TensorFlow 2 C++部署saved_model.pb预测时出现越界错误求助
问题:TensorFlow C++加载SavedModel时出现维度越界错误
我在C++中使用训练好的saved_model.pb,以文本为输入获取预测类别ID和分数时,出现如下错误:W tensorflow/core/framework/op_kernel.cc:1767] OP_REQUIRES failed at strided_slice_op.cc:108 : Invalid argument: slice index 0 of dimension 0 out of bounds.
环境:TensorFlow 2.5,模型由Python训练得到。
saved_model_cli输出的SignatureDef信息:
MetaGraphDef with tag-set: 'serve' contains the following SignatureDefs: signature_def['classification']: The given SavedModel SignatureDef contains the following input(s): inputs['inputs'] tensor_info: dtype: DT_STRING shape: (-1) name: Placeholder:0 The given SavedModel SignatureDef contains the following output(s): outputs['classes'] tensor_info: dtype: DT_STRING shape: (-1, 74) name: head/Tile:0 outputs['scores'] tensor_info: dtype: DT_FLOAT shape: (-1, 74) name: head/predictions/probabilities:0 Method name is: tensorflow/serving/classify signature_def['predict']: The given SavedModel SignatureDef contains the following input(s): inputs['content'] tensor_info: dtype: DT_STRING shape: (-1) name: Placeholder:0 The given SavedModel SignatureDef contains the following output(s): outputs['all_class_ids'] tensor_info: dtype: DT_INT32 shape: (-1, 74) name: head/predictions/Tile:0 outputs['all_classes'] tensor_info: dtype: DT_STRING shape: (-1, 74) name: head/predictions/Tile_1:0 outputs['class_ids'] tensor_info: dtype: DT_INT64 shape: (-1, 1) name: head/predictions/ExpandDims:0 outputs['classes'] tensor_info: dtype: DT_STRING shape: (-1, 1) name: head/predictions/hash_table_Lookup/LookupTableFindV2:0 outputs['logits'] tensor_info: dtype: DT_FLOAT shape: (-1, 74) name: add:0 outputs['probabilities'] tensor_info: dtype: DT_FLOAT shape: (-1, 74) name: head/predictions/probabilities:0 Method name is: tensorflow/serving/predict signature_def['serving_default']: The given SavedModel SignatureDef contains the following input(s): inputs['inputs'] tensor_info: dtype: DT_STRING shape: (-1) name: Placeholder:0 The given SavedModel SignatureDef contains the following output(s): outputs['classes'] tensor_info: dtype: DT_STRING shape: (-1, 74) name: head/Tile:0 outputs['scores'] tensor_info: dtype: DT_FLOAT shape: (-1, 74) name: head/predictions/probabilities:0 Method name is: tensorflow/serving/classify
我的C++代码:
// run the model std::string test(const char *modelPath, const char *text) { tensorflow::SavedModelBundle model; tensorflow::Status status = tensorflow::LoadSavedModel( tensorflow::SessionOptions(), tensorflow::RunOptions(), modelPath, {"serve"}, &model); TF_CHECK_OK(status); // Provide input data. tensorflow::Tensor tensor(tensorflow::DT_STRING, tensorflow::TensorShape()); tensor.scalar<tensorflow::tstring>()() = tensorflow::tstring(text); // Link the data with some tags so tensorflow know where to put those data entries. std::vector<std::pair<std::string, tensorflow::Tensor>> feedInputs = {{"Placeholder:0", tensor}}; std::vector<std::string> fetches = {"head/Tile:0", "head/predictions/probabilities:0"}; // We need to store the results somewhere. std::vector<tensorflow::Tensor> outputs; // Let's run the model... status = model.GetSession()->Run(feedInputs, fetches, {}, &outputs); TF_CHECK_OK(status); for (const auto& output : outputs) { // TODO:: } return ""; }
我已尝试修改C代码中的输入输出名称,但似乎当前使用的名称是正确的。我对TensorFlow C API不太熟悉,希望得到帮助。
解决方法
错误原因
输入张量维度不匹配:从saved_model_cli的输出可知,输入Placeholder:0的shape是(-1)(一维批量输入),但代码中创建的是0维标量张量(TensorShape()为空),模型期望的是至少一维的张量(哪怕是单样本,shape也应为[1]),导致维度越界错误。
修改步骤
- 调整输入张量的形状为一维,匹配模型的批量输入要求
- 优先使用SignatureDef定义的输入输出名称(而非直接用张量名),提升代码健壮性
- 如果需要直接获取类别ID,推荐使用
predict签名,它直接输出class_ids和probabilities,无需额外处理
修改后的代码
// run the model std::string test(const char *modelPath, const char *text) { tensorflow::SavedModelBundle model; tensorflow::Status status = tensorflow::LoadSavedModel( tensorflow::SessionOptions(), tensorflow::RunOptions(), modelPath, {"serve"}, &model); TF_CHECK_OK(status); // 1. 创建一维张量,shape为[1],对应单样本批量输入 tensorflow::Tensor tensor(tensorflow::DT_STRING, tensorflow::TensorShape({1})); tensor.flat<tensorflow::tstring>()(0) = tensorflow::tstring(text); // 2. 使用predict签名的输入名称(更健壮,避免张量名变化) std::vector<std::pair<std::string, tensorflow::Tensor>> feedInputs = {{"content", tensor}}; // 3. 获取predict签名的输出:类别ID和概率分数 std::vector<std::string> fetches = {"class_ids", "probabilities"}; std::vector<tensorflow::Tensor> outputs; status = model.GetSession()->Run(feedInputs, fetches, {}, &outputs); TF_CHECK_OK(status); // 解析输出结果 if (outputs.size() >= 2) { // 类别ID:shape (-1,1),取第一个样本的ID int64_t class_id = outputs[0].flat<tensorflow::int64>()(0); // 概率分数:shape (-1,74),取对应类别的分数 float score = outputs[1].flat<float>()(class_id); // 示例输出 std::cout << "类别ID: " << class_id << ", 分数: " << score << std::endl; } return ""; }
补充说明
- 如果坚持使用
serving_default或classification签名,只需将输入名称改为inputs,输入张量形状保持[1]即可 - 若要处理多样本输入,只需调整张量形状为
[N](N为样本数量),并填充对应文本即可
内容的提问来源于stack exchange,提问作者Sina KH
相关产品推荐
相关产品推荐

