Tensorflow Serving 在预训练的 Keras ResNet50 模型上返回始终相同的预测
Tensorflow Serving on pretrained Keras ResNet50 model returning always same predictions
我正在使用以下代码将预训练的 ResNet50 keras 模型导出到 tensorflow,用于 tensorflow-serving:
import tensorflow as tf
sess = tf.Session()
from keras import backend as K
K.set_session(sess)
K.set_learning_phase(0)
# Modelo resnet con pesos entrenados en imagenet
from keras.applications.resnet50 import ResNet50
model = ResNet50(weights='imagenet')
# exportar en tensorflow
import os
version_number = max([ int(x) for x in os.listdir('./resnet-classifier') ]) + 1
export_path = './resnet-classifier/{}'.format(version_number)
with tf.keras.backend.get_session() as sess:
init_op = tf.global_variables_initializer()
sess.run(init_op)
tf.saved_model.simple_save(sess, export_path,
inputs=dict(input_image=model.input),
outputs={t.name:t for t in model.outputs}
)
我尝试了上述的一些变体,所有这些都具有相同的结果(由 tensorflow 服务提供相同的预测)。
然后我 运行 tensorflow-serving 就像:
docker run -p 8501:8501 \
-v ./resnet-classifier:/models/resnet-classifier \
-e MODEL_NAME=resnet-classifier -e MODEL_BASE_PATH=/models \
-t tensorflow/serving
最后,我使用以下函数对 tensorflow 服务进行预测:
def imagepath_to_tfserving_payload(img_path):
import numpy as np
from keras.preprocessing import image
from keras.applications.resnet50 import preprocess_input
img = image.img_to_array(image.load_img(img_path, target_size=(224, 224)))
X = np.expand_dims(img, axis=0).astype('float32')
X = preprocess_input(X)
payload = dict(instances=X.tolist())
payload = json.dumps(payload)
return payload
def tfserving_predict(image_payload, url=None):
import requests
if url is None:
url = 'http://localhost:8501/v1/models/resnet-classifier:predict'
r = requests.post(url, data=image_payload)
pred_json = json.loads(r.content.decode('utf-8'))
from keras.applications.resnet50 import decode_predictions
predictions = decode_predictions(np.asarray(pred_json['predictions']), top=3)[0]
return predictions
然后我使用上面的两个函数,从 ipython shell 到 select 来自 imagenet 的 val 集的随机图像,我已经在本地存储了。问题是 tensorflow 服务总是对我发送的所有图像返回相同的预测。
每次我使用上面的第一个脚本导出模型时,我都会变得略有不同 classes,第一个 class 的置信度为“1”,其他的置信度为“0”,例如:
# Serialization 1, in ./resnet-classifier/1 always returning:
[
[
"n07745940",
"strawberry",
1.0
],
[
"n02104029",
"kuvasz",
1.4013e-36
],
[
"n15075141",
"toilet_tissue",
0.0
]
]
# Serialization 2, in ./resnet-classifier/2 always returning:
[
[
"n01530575",
"brambling",
1.0
],
[
"n15075141",
"toilet_tissue",
0.0
],
[
"n02319095",
"sea_urchin",
0.0
]
]
这可能与 Tensorflow : serving model return always the same prediction 有关,但我不知道那里的答案(没有被接受的答案)有何帮助。
有人知道上面出了什么问题吗?如何解决?
我有时会在忘记规范化图像时遇到这种问题。我认为 resnet 接受 0. 和 1.(或者 -1. 到 1.)之间的浮点数格式的图像。我不知道 preprocess_input 函数的作用,但您可以检查它是否 returns 数组以预期的格式。
我发现调用 sess.run(tf.global_variables_initializer()) 会覆盖预训练的权重,线索在 http://zachmoshe.com/2017/11/11/use-keras-models-with-tf.html。
我的解决方案非常简单,只需将原始问题中的第一段代码更改为以下代码,即调用 tf.global_variables_initializer() before 模型实例化/ 负重:
import tensorflow as tf
sess = tf.Session()
sess.run(tf.global_variables_initializer())
from keras import backend as K
K.set_session(sess)
K.set_learning_phase(0)
# Modelo resnet con pesos entrenados en imagenet
from keras.applications.resnet50 import ResNet50
model = ResNet50(weights='imagenet')
# exportar en tensorflow
import os
versions = [ int(x) for x in os.listdir('./resnet-classifier') ]
version_number = max(versions) + 1 if versions else 1
export_path = './resnet-classifier/{}'.format(version_number)
tf.saved_model.simple_save(sess, export_path,
inputs=dict(input_image=model.input),
outputs={t.name:t for t in model.outputs}
)
我正在使用以下代码将预训练的 ResNet50 keras 模型导出到 tensorflow,用于 tensorflow-serving:
import tensorflow as tf
sess = tf.Session()
from keras import backend as K
K.set_session(sess)
K.set_learning_phase(0)
# Modelo resnet con pesos entrenados en imagenet
from keras.applications.resnet50 import ResNet50
model = ResNet50(weights='imagenet')
# exportar en tensorflow
import os
version_number = max([ int(x) for x in os.listdir('./resnet-classifier') ]) + 1
export_path = './resnet-classifier/{}'.format(version_number)
with tf.keras.backend.get_session() as sess:
init_op = tf.global_variables_initializer()
sess.run(init_op)
tf.saved_model.simple_save(sess, export_path,
inputs=dict(input_image=model.input),
outputs={t.name:t for t in model.outputs}
)
我尝试了上述的一些变体,所有这些都具有相同的结果(由 tensorflow 服务提供相同的预测)。
然后我 运行 tensorflow-serving 就像:
docker run -p 8501:8501 \
-v ./resnet-classifier:/models/resnet-classifier \
-e MODEL_NAME=resnet-classifier -e MODEL_BASE_PATH=/models \
-t tensorflow/serving
最后,我使用以下函数对 tensorflow 服务进行预测:
def imagepath_to_tfserving_payload(img_path):
import numpy as np
from keras.preprocessing import image
from keras.applications.resnet50 import preprocess_input
img = image.img_to_array(image.load_img(img_path, target_size=(224, 224)))
X = np.expand_dims(img, axis=0).astype('float32')
X = preprocess_input(X)
payload = dict(instances=X.tolist())
payload = json.dumps(payload)
return payload
def tfserving_predict(image_payload, url=None):
import requests
if url is None:
url = 'http://localhost:8501/v1/models/resnet-classifier:predict'
r = requests.post(url, data=image_payload)
pred_json = json.loads(r.content.decode('utf-8'))
from keras.applications.resnet50 import decode_predictions
predictions = decode_predictions(np.asarray(pred_json['predictions']), top=3)[0]
return predictions
然后我使用上面的两个函数,从 ipython shell 到 select 来自 imagenet 的 val 集的随机图像,我已经在本地存储了。问题是 tensorflow 服务总是对我发送的所有图像返回相同的预测。
每次我使用上面的第一个脚本导出模型时,我都会变得略有不同 classes,第一个 class 的置信度为“1”,其他的置信度为“0”,例如:
# Serialization 1, in ./resnet-classifier/1 always returning:
[
[
"n07745940",
"strawberry",
1.0
],
[
"n02104029",
"kuvasz",
1.4013e-36
],
[
"n15075141",
"toilet_tissue",
0.0
]
]
# Serialization 2, in ./resnet-classifier/2 always returning:
[
[
"n01530575",
"brambling",
1.0
],
[
"n15075141",
"toilet_tissue",
0.0
],
[
"n02319095",
"sea_urchin",
0.0
]
]
这可能与 Tensorflow : serving model return always the same prediction 有关,但我不知道那里的答案(没有被接受的答案)有何帮助。
有人知道上面出了什么问题吗?如何解决?
我有时会在忘记规范化图像时遇到这种问题。我认为 resnet 接受 0. 和 1.(或者 -1. 到 1.)之间的浮点数格式的图像。我不知道 preprocess_input 函数的作用,但您可以检查它是否 returns 数组以预期的格式。
我发现调用 sess.run(tf.global_variables_initializer()) 会覆盖预训练的权重,线索在 http://zachmoshe.com/2017/11/11/use-keras-models-with-tf.html。
我的解决方案非常简单,只需将原始问题中的第一段代码更改为以下代码,即调用 tf.global_variables_initializer() before 模型实例化/ 负重:
import tensorflow as tf
sess = tf.Session()
sess.run(tf.global_variables_initializer())
from keras import backend as K
K.set_session(sess)
K.set_learning_phase(0)
# Modelo resnet con pesos entrenados en imagenet
from keras.applications.resnet50 import ResNet50
model = ResNet50(weights='imagenet')
# exportar en tensorflow
import os
versions = [ int(x) for x in os.listdir('./resnet-classifier') ]
version_number = max(versions) + 1 if versions else 1
export_path = './resnet-classifier/{}'.format(version_number)
tf.saved_model.simple_save(sess, export_path,
inputs=dict(input_image=model.input),
outputs={t.name:t for t in model.outputs}
)