预训练的Keras ResNet50模型上的Tensorflow Serving返回始终相同的预测 [英] Tensorflow Serving on pretrained Keras ResNet50 model returning always same predictions

查看:632
本文介绍了预训练的Keras ResNet50模型上的Tensorflow Serving返回始终相同的预测的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用以下代码将经过预训练的ResNet50 keras模型导出到tensorflow,以进行tensorflow服务:

I'm using the following code to export a pre-trained ResNet50 keras' model to tensorflow, for 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服务提供的预测相同).

I tried some variations of the above, all of them with the same results (same prediction while served by tensorflow serving).

然后我像这样运行tensorflow-serving:

Then i run tensorflow-serving like:

docker run -p 8501:8501 \
  -v ./resnet-classifier:/models/resnet-classifier \
  -e MODEL_NAME=resnet-classifier -e MODEL_BASE_PATH=/models \
  -t tensorflow/serving

最后,我使用以下函数对张量流服务进行预测:

Finally, i'm using the following function to make predictions against tensorflow serving:

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中使用以上两个函数,从imagenet的val集中选择随机imagenes,我已将其存储在本地.问题在于,tensorflow服务对于我发送的所有图像总是返回相同的预测.

Then i use both functions above from an ipython shell to select random imagenes from imagenet's val set, which i've stored locally. The problem is that tensorflow serving is always returning the same prediction for all images i send.

每次我使用上面的第一个脚本导出模型时,我得到的类都会稍有不同,例如,第一类的置信度为"1",其他类的置信度为"0",例如:

Each time i export the model with the first script above, i'm getting slightly different classes, with '1' confidence for the first class and '0' for others, for example:

# 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:服务模型返回始终相同预测,但我不知道那里的答案(没有被接受的答案)可能会有帮助.

This might be related with Tensorflow : serving model return always the same prediction, but i don't know how the answers there (no accepted one) may help.

任何人都知道上面有什么问题以及如何解决?

Anybody knows what's wrong above, and how to fix it?

推荐答案

我发现调用sess.run(tf.global_variables_initializer())会覆盖预训练的权重,线索可在

I've found that calling sess.run(tf.global_variables_initializer()) overrides pretrained weights, clue found at http://zachmoshe.com/2017/11/11/use-keras-models-with-tf.html.

对我来说,解决方案非常简单,只需在以下问题中更改原始问题中的第一段代码,即调用tf.global_variables_initializer()之前模型实例化/权重负载:

The solution for me was really simple, just change the first block of code in the original question by the following, which calls tf.global_variables_initializer() before model instantiation / weight load:

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}
)

这篇关于预训练的Keras ResNet50模型上的Tensorflow Serving返回始终相同的预测的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆