使用TensorFlow服务进行预测时,Tensor名称没有形状信息错误

时间:2019-08-19 09:01:20

标签: tensorflow tensorflow-serving

我正在使用tensorflow服务来保存一个模型。我有两个签名:第一个输出keras model.output和第二个输出model.output的后处理。当我尝试在张量流上预测第二个签名的调用时,它给我一个错误{ "error": "Tensor name: prediction has no shape information " }

这是构建保存的模型的代码

    shape1 = 92
    shape2 = 92
    reg=0.000001
    learning_rate=0.001

    sess = tf.Session()
    K.set_session(sess)
    K._LEARNING_PHASE = tf.constant(0)
    K.set_learning_phase(0)


    #preprocessing
    x_input = tf.placeholder(tf.string, name='x_input', shape=[None])
    reshaped = tf.reshape(x_input, shape=[])
    image = tf.image.decode_jpeg(reshaped, channels=3)
    image2 = tf.expand_dims(image,0)
    resized = tf.image.resize_images(image2, (92,92))
    meaned = tf.math.subtract(resized, tf.constant(116.0))
    normalized = tf.math.divide(meaned, tf.constant(66.0))

    #keras model
    model = tf.keras.Sequential()
    model.add(InputLayer(input_tensor=normalized))
    model.add(Conv2D(32, (3, 3), padding='same', activation='relu', kernel_regularizer=l2(reg)))
    model.add(Conv2D(32, (3, 3), padding='same', activation='relu', kernel_regularizer=l2(reg)))
    model.add(MaxPooling2D(pool_size=(2, 2)))

    model.add(Conv2D(64, (3, 3), padding='same', activation='relu', kernel_regularizer=l2(reg)))
    model.add(Dropout(0.1))
    model.add(Conv2D(64, (3, 3), padding='same', activation='relu', kernel_regularizer=l2(reg)))
    model.add(Dropout(0.1))
    model.add(MaxPooling2D(pool_size=(2, 2)))

    model.add(Conv2D(128, (3, 3), padding='same', activation='relu', kernel_regularizer=l2(reg)))
    model.add(Dropout(0.2))
    model.add(Conv2D(128, (3, 3), padding='same', activation='relu', kernel_regularizer=l2(reg)))
    model.add(Dropout(0.2))
    model.add(MaxPooling2D(pool_size=(2, 2)))

    model.add(Conv2D(256, (3, 3), padding='same', activation='relu', kernel_regularizer=l2(reg)))
    model.add(Dropout(0.3))
    model.add(Conv2D(256, (3, 3), padding='same', activation='relu', kernel_regularizer=l2(reg)))
    model.add(Dropout(0.3))
    model.add(MaxPooling2D(pool_size=(2, 2)))

    model.add(Flatten())
    model.add(Dense(256, activation='relu', kernel_regularizer=l2(reg)))
    model.add(Dropout(0.5))

    model.add(Dense(256, activation='relu', kernel_regularizer=l2(reg)))
    model.add(Dropout(0.5))

    model.add(Dense(1))
    model.add(Activation('sigmoid'))

    model.compile(loss='binary_crossentropy',
                    optimizer=tf.train.RMSPropOptimizer(learning_rate=learning_rate),
                    metrics=['accuracy'])

    #post processing to output label
    pred = tf.gather_nd(model.output, (0,0))
    label = tf.cond(pred > 0.5, lambda: tf.constant('Dog', shape=[]), lambda: tf.constant('Cat', shape=[]))

    model.load_weights(r'./checkpoints/4.ckpt')
    export_path = './saved_models/1'


    init_op = tf.group(tf.global_variables_initializer(), tf.local_variables_initializer())
    sess.run(init_op)
    model.load_weights(r'./checkpoints/4.ckpt')

    if os.path.isdir(export_path):
        print('\nAlready saved a model, cleaning up\n')
        print(subprocess.run(['rm', '-r', export_path]))

    #first signature(this works)
    x_info = tf.saved_model.utils.build_tensor_info(x_input)
    y_info = tf.saved_model.utils.build_tensor_info(model.output)
    sigmoid_signature = build_signature_def(inputs={"image": x_info}, outputs={"prediction":y_info}, method_name='tensorflow/serving/predict')

    #2nd signature(this doesn't work)
    x_info = tf.saved_model.utils.build_tensor_info(x_input)
    y_info = tf.saved_model.utils.build_tensor_info(label)
    label_signature = build_signature_def(inputs={"image": x_info}, outputs={"prediction":y_info}, method_name='tensorflow/serving/predict')

    builder = tf.saved_model.builder.SavedModelBuilder(export_path)

    legacy_init_op = tf.group(tf.tables_initializer(), name='legacy_init_op')

    builder.add_meta_graph_and_variables(sess=sess,
                                     tags=["serve"],
                                     signature_def_map={'sigmoid': sigmoid_signature, 'label': label_signature})
    builder.save()

这是调用tf服务的代码

imgs = ['./Dog/' + img for img in imgs]
img = open('./Dog/3.jpg', 'rb').read()

img = base64.b64encode(img).decode('utf-8')

data = json.dumps(
        {"signature_name": "label",
         "instances": [
                 {'image': {'b64': img}}
                 ]
        }
)
json_response = requests.post('http://localhost:8501/v1/models/pet:predict', data=data)
print(json_response.text)

我没有得到{"predictions": "Dog"}的响应,而是得到了错误{ "error": "Tensor name: prediction has no shape information " }

2 个答案:

答案 0 :(得分:0)

我设法解决了这个问题。我在要输出的内容上使用了tf.reshape并将其传递给签名生成器。

#post processing to output label
    pred = tf.gather_nd(model.output, (0,0))
    label = tf.cond(pred > 0.5, lambda: tf.constant('Dog', shape=[]), lambda: tf.constant('Cat', shape=[]))
    label_reshaped = tf.reshape(label, [None])

...

#2nd signature(this doesn't work)
    x_info = tf.saved_model.utils.build_tensor_info(x_input)
    y_info = tf.saved_model.utils.build_tensor_info(label_reshaped)
    label_signature = build_signature_def(inputs={"image": x_info}, outputs={"prediction":y_info}, method_name='tensorflow/serving/predict')

答案 1 :(得分:0)

阅读 tensorflow serving documentation,您会看到有两种方法可以在您的请求中指定输入张量,行格式(使用 instances 就像您的示例)和列格式(使用 { {1}})。

由于行格式要求所有输入和输出具有相同的第 0 维,如果您没有导出具有显式输出形状的模型,则不能使用行格式。

因此,在您的情况下(无需像其他答案提供的那样通过显式重塑重新导出模型),您可以改为发送此有效负载

inputs

另一方面,请记住,如果您确实想发送多个 b64 编码的图像,最好的办法是使用具有多个实例的行格式(例如,如果您想对多个图像运行批量预测) .