使用TF Serving部署叶片分类模型后POST请求返回400错误求助
排查TF Serving预测请求400错误的解决方法
以下是导致400错误的核心问题及修复方案:
1. 错误的请求头设置
你的请求头content-type被错误设置为serving_default,TF Serving要求JSON格式请求的content-type必须为application/json。
2. 输入数据格式不匹配
问题点:
instances字段需要是批量数据结构(即使单张图片也要包裹在列表中),你直接传入了单张图片的数组,不符合TF Serving的请求格式。tf.keras.applications.mobilenet.preprocess_input输出的是float32类型数据(范围-1到1),你强制转成uint8会丢失精度,且与模型训练时的输入类型不匹配。- CV2默认读取图片为BGR格式,但Mobilenet训练时用的是RGB格式,格式不匹配也会间接导致请求不符合模型要求。
3. 验证模型输入签名(关键前置步骤)
先确认模型的输入要求,运行以下命令查看导出模型的签名信息:
saved_model_cli show --dir /home/bhargavpatel/Desktop/Image_Classification_tfx/Image_Classification/tfx/pipelines/leaf_classification_native_keras_8/Pusher/pushed_model/1 --all
重点关注signature_def['serving_default']下的输入形状、数据类型(通常是float32,形状为[None, 224, 224, 3])。
修复后的预测代码
import json import numpy as np import cv2 import requests import tensorflow as tf import pprint SERVER_URL = "http://localhost:8501/v1/models/leaf_classification_native_keras_8:predict" IMAGE_PATH = "/home/bhargavpatel/Desktop/Image_Classification_tfx/Image_Classification/raw_data/test/healthy/healthy_test.0.jpg" def main(): # 修正请求头 headers = {"content-type": "application/json"} # 图片预处理(严格匹配训练流程) img = cv2.imread(IMAGE_PATH, cv2.IMREAD_COLOR) img = cv2.resize(img, (224, 224), interpolation=cv2.INTER_AREA) # CV2转RGB格式,匹配Mobilenet训练输入 img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) img = tf.keras.applications.mobilenet.preprocess_input(img) # 保留float32类型,不做uint8转换 image_content = img.tolist() # 构造符合TF Serving要求的请求数据 data = { "signature_name": "serving_default", "instances": [image_content] # 单样本包裹在列表中,符合批量格式 } # 测试请求 for _ in range(3): response = requests.post(SERVER_URL, json=data, headers=headers) pprint.pprint(response.json()) # 批量测试并计算延迟 total_time = 0 num_requests = 10 for _ in range(num_requests): response = requests.post(SERVER_URL, json=data, headers=headers) response.raise_for_status() total_time += response.elapsed.total_seconds() prediction = response.json()["predictions"][0] print(f"Prediction class: {np.argmax(prediction)}, avg latency: {(total_time * 1000) / num_requests:.2f} ms") if __name__ == "__main__": main()
额外优化提示
- 使用
requests.post的json参数时,无需手动调用json.dumps,直接传入Python字典即可,内部会自动完成序列化。 - 如果仍有问题,可以查看TF Serving容器日志,运行
docker logs tfserving_leaf_classification,日志会明确提示请求错误的具体原因(比如输入形状不匹配、数据类型错误等)。
内容的提问来源于stack exchange,提问作者Bhargav Patel
相关产品推荐
相关产品推荐

