如何使 TensorFlow Hub 模型为 TensorFlow Serving REST 请求做好准备(使用 base64 编码图像)?
Posted
技术标签:
【中文标题】如何使 TensorFlow Hub 模型为 TensorFlow Serving REST 请求做好准备(使用 base64 编码图像)?【英文标题】:How to make a TensorFlow Hub model ready for TensorFlow Serving REST requests (with base64 encoded images)? 【发布时间】:2020-01-31 05:30:16 【问题描述】:按照以下建议,我在旧的 keras ResNet50-ImageNet-Classifier 上进行了一些手术以从 TensorFlow Serving 中获得预测,并取得了一些成功:
How to a make a model ready for TensorFlow Serving REST interface with a base64 encoded image?
保存模型(使用 tensorflow 1.14)...
from keras.applications.resnet50 import ResNet50
from keras.preprocessing import image
from keras.applications.resnet50 import preprocess_input, decode_predictions
import numpy as np
import sys
model = ResNet50(weights='imagenet')
from keras import optimizers
sgd = optimizers.SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='mean_squared_error', optimizer=sgd)
save_here='/Users/alexryan/.keras/models/hd5/model-and-weights.hd5'
model.save(save_here)
编辑模型(使用 tensorflow 2)...
import os
import shutil
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()
h5_model_path = '/Users/alexryan/.keras/models/hd5/model-and-weights.hd5'
tf_model_path = '/Users/alexryan/.keras/models/tf'
export_path = '/Users/alexryan/.keras/models/json_b64'
version = '1'
CHANNELS = 3
estimator = tf.keras.estimator.model_to_estimator(
keras_model_path=h5_model_path,
model_dir=tf_model_path)
def serving_input_receiver_fn():
def prepare_image(image_str_tensor):
image = tf.image.decode_jpeg(image_str_tensor, channels=CHANNELS)
# return image_preprocessing(image)
return image
input_ph = tf.placeholder(tf.string, shape=[None])
images_tensor = tf.map_fn(
prepare_image, input_ph, back_prop=False, dtype=tf.uint8)
images_tensor = tf.image.convert_image_dtype(images_tensor, dtype=tf.float32)
return tf.estimator.export.ServingInputReceiver(
'input_1': images_tensor,
'image_bytes': input_ph)
export_path = os.path.join(export_path, version)
if os.path.exists(export_path): # clean up old exports with this version
shutil.rmtree(export_path)
estimator.export_savedmodel(
export_path,
serving_input_receiver_fn=serving_input_receiver_fn)
但是,当我尝试使用相同的代码编辑从 TensorFlow Hub 获得的模型时,尝试将模型保存为 .hd5 模型时出错,这似乎是进行编辑所必需的。
classifier.save(save_here, save_format='h5') => RuntimeError: Unable to create link (name already exists)
具体来说,这段代码...
from __future__ import absolute_import, division, print_function, unicode_literals
import tensorflow as tf
import tensorflow_hub as hub
from tensorflow.keras import layers
import numpy as np
import PIL.Image as Image
import sys
classifier_url ="https://tfhub.dev/google/tf2-preview/mobilenet_v2/classification/2" #@param type:"string"
IMAGE_SHAPE = (224, 224)
classifier = tf.keras.Sequential([
hub.KerasLayer(classifier_url, input_shape=IMAGE_SHAPE+(3,))
])
save_here='/Users/alexryan/.keras/models/hd5-tf2/model-and-weights.hd5'
classifier.save(save_here, save_format='h5')
产生这个错误...
(tf2) ???? >./save_model.sh
MODEL_DIR=|/Users/alexryan/.keras/models/hd5-tf2|
/Users/alexryan/.keras/models/hd5-tf2
0 directories, 0 files
2019-10-01 12:11:10.060958: E tensorflow/core/platform/hadoop/hadoop_file_system.cc:132] HadoopFileSystem load error: dlopen(libhdfs.dylib, 6): image not found
2019-10-01 12:11:12.099867: I tensorflow/core/platform/cpu_feature_guard.cc:142] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
2019-10-01 12:11:12.123701: I tensorflow/compiler/xla/service/service.cc:168] XLA service 0x7fefd12f07d0 initialized for platform Host (this does not guarantee that XLA will be used). Devices:
2019-10-01 12:11:12.123722: I tensorflow/compiler/xla/service/service.cc:176] StreamExecutor device (0): Host, Default Version
Traceback (most recent call last):
File "save_model.py", line 19, in <module>
classifier.save(save_here, save_format='h5')
File "/Users/alexryan/miniconda3/envs/tf2/lib/python3.7/site-packages/tensorflow_core/python/keras/engine/network.py", line 986, in save
signatures, options)
File "/Users/alexryan/miniconda3/envs/tf2/lib/python3.7/site-packages/tensorflow_core/python/keras/saving/save.py", line 112, in save_model
model, filepath, overwrite, include_optimizer)
File "/Users/alexryan/miniconda3/envs/tf2/lib/python3.7/site-packages/tensorflow_core/python/keras/saving/hdf5_format.py", line 109, in save_model_to_hdf5
save_weights_to_hdf5_group(model_weights_group, model_layers)
File "/Users/alexryan/miniconda3/envs/tf2/lib/python3.7/site-packages/tensorflow_core/python/keras/saving/hdf5_format.py", line 631, in save_weights_to_hdf5_group
param_dset = g.create_dataset(name, val.shape, dtype=val.dtype)
File "/Users/alexryan/miniconda3/envs/tf2/lib/python3.7/site-packages/h5py/_hl/group.py", line 139, in create_dataset
self[name] = dset
File "/Users/alexryan/miniconda3/envs/tf2/lib/python3.7/site-packages/h5py/_hl/group.py", line 373, in __setitem__
h5o.link(obj.id, self.id, name, lcpl=lcpl, lapl=self._lapl)
File "h5py/_objects.pyx", line 54, in h5py._objects.with_phil.wrapper
File "h5py/_objects.pyx", line 55, in h5py._objects.with_phil.wrapper
File "h5py/h5o.pyx", line 202, in h5py.h5o.link
RuntimeError: Unable to create link (name already exists)
MODEL_DIR=|/Users/alexryan/.keras/models/hd5-tf2|
/Users/alexryan/.keras/models/hd5-tf2
└── model-and-weights.hd5
是否有另一种方法可以直接进行相同的编辑,而无需从已保存的模型恢复为 .hd5 模型?
【问题讨论】:
【参考方案1】:正如Github Issue 中所述,有两种方法可以解决此问题。
1.使用最新版本的Mobilenet,版本4。代码如下:
from __future__ import absolute_import, division, print_function, unicode_literals
import tensorflow as tf
import tensorflow_hub as hub
from tensorflow.keras import layers
import numpy as np
import PIL.Image as Image
import sys
classifier_url = "https://tfhub.dev/google/tf2-preview/mobilenet_v2/classification/4"
IMAGE_SHAPE = (224, 224)
classifier = tf.keras.Sequential([
hub.KerasLayer(classifier_url, input_shape=IMAGE_SHAPE+(3,))
])
save_here='/content/Classifier_Saved_Model.h5'
classifier.save(save_here, save_format='h5')
2.使用save_format='tf'
代替save_format='h5'
。相同的代码如下所示:
from __future__ import absolute_import, division, print_function, unicode_literals
import tensorflow as tf
import tensorflow_hub as hub
from tensorflow.keras import layers
import numpy as np
import PIL.Image as Image
import sys
classifier_url = "https://tfhub.dev/google/tf2-preview/mobilenet_v2/classification/2"
IMAGE_SHAPE = (224, 224)
classifier = tf.keras.Sequential([
hub.KerasLayer(classifier_url, input_shape=IMAGE_SHAPE+(3,))
])
save_here='/content/Classifier_Saved_Model'
classifier.save(save_here, save_format='tf')
【讨论】:
以上是关于如何使 TensorFlow Hub 模型为 TensorFlow Serving REST 请求做好准备(使用 base64 编码图像)?的主要内容,如果未能解决你的问题,请参考以下文章
剑指TensorFlow,PyTorch Hub官方模型库一行代码复现主流模型
利用 TensorFlow Hub 中的预处理模型简化 BERT
“史上最强”BigGAN公开TensorFlow Hub demo!
如何配置 Tensorflow Serving 以服务来自 HDFS 的模型?
如何从 python 中的预训练模型中获取权重并在 tensorflow 中使用它?
在 Tensorflow 中,将 Google 的 BigTransfer 模型转换为 Tensorflow Lite 时出现错误