You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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]),导致维度越界错误。

修改步骤

  1. 调整输入张量的形状为一维,匹配模型的批量输入要求
  2. 优先使用SignatureDef定义的输入输出名称(而非直接用张量名),提升代码健壮性
  3. 如果需要直接获取类别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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 08:55:37