TensorFlow 1.13.1在VS2015编译报错及模型节点获取咨询
解决TensorFlow 1.13.1 C++接口编译错误并获取模型输入输出节点信息
首先,你遇到的这些未解析外部符号问题,根源是没有正确链接Google Protobuf的库文件——TensorFlow依赖Protobuf来序列化/反序列化GraphDef,VS2015在链接阶段找不到对应的Protobuf实现。下面一步步解决:
一、修复编译链接错误
1. 关联正确的依赖库
打开VS2015项目属性,依次进入链接器 -> 输入 -> 附加依赖项,添加以下内容:
- TensorFlow官方提供的
tensorflow.lib(如果是Debug版本,对应tensorflowd.lib,务必和项目的Debug/Release配置匹配) - 对应版本的Protobuf库(TensorFlow 1.13.1适配的是Protobuf 3.6.1,必须用TensorFlow编译时配套的Protobuf库,不要用单独安装的其他版本)
2. 配置包含目录和库目录
- 在VC++目录 -> 包含目录中添加:
- TensorFlow的
include文件夹路径 - Protobuf的
include文件夹路径(如果是TensorFlow自带的,路径一般是tensorflow/include/google/protobuf的上级目录)
- TensorFlow的
- 在VC++目录 -> 库目录中添加:
- TensorFlow的
lib文件夹路径 - Protobuf的
lib文件夹路径
- TensorFlow的
3. 匹配Runtime Library配置
VS2015中,项目的C/C++ -> 代码生成 -> Runtime Library要和TensorFlow、Protobuf编译时的配置一致:
- 预编译的TensorFlow库一般用
/MD(多线程DLL)或/MDd(Debug多线程DLL),不要改成/MT或/MTd,否则会出现链接不兼容问题
二、正确获取模型输入输出节点信息
原来的PrintDebugString()依赖Protobuf的日志组件,容易触发链接问题,换用直接访问节点成员的方式更可靠,还能精准筛选输入输出节点:
修改后的完整代码示例:
#include <tensorflow/core/framework/graph.pb.h> #include <tensorflow/core/platform/env.h> #include <iostream> #include <string> #include <map> using namespace tensorflow; int main(int argc, char* argv[]) { std::string modelPath = "your_model_path.pb"; // 替换为你的模型绝对路径 GraphDef graph_def; Status status = ReadBinaryProto(Env::Default(), modelPath, &graph_def); if (!status.ok()) { std::cerr << "ReadBinaryProto Status:" << status.ToString() << std::endl; return -1; } std::cout << "Successfully loaded model." << std::endl; int node_count = graph_def.node_size(); std::cout << "Total nodes in model: " << node_count << std::endl; for (int i = 0; i < node_count; ++i) { const auto& node = graph_def.node(i); std::cout << "\nNode Index: " << i << std::endl; std::cout << "Node Name: " << node.name() << std::endl; std::cout << "Node Op Type: " << node.op() << std::endl; // 打印该节点的所有输入 std::cout << "Input Nodes: "; for (const std::string& input : node.input()) { std::cout << input << " "; } std::cout << std::endl; // 识别输入节点(通常Op为Placeholder) if (node.op() == "Placeholder") { std::cout << "⚠️ This is an INPUT node" << std::endl; // 提取输入形状信息 if (node.attr().count("shape")) { const auto& shape = node.attr().at("shape").shape(); std::cout << "Input Shape: "; for (int j = 0; j < shape.dim_size(); ++j) { // -1表示动态维度,用?代替显示 std::cout << (shape.dim(j).size() == -1 ? "?" : std::to_string(shape.dim(j).size())) << " "; } std::cout << std::endl; } } // 识别输出节点(根据你的模型实际Op判断,比如Softmax、Identity等) // 这里以常见输出Op为例,你可以根据自己的模型调整 if (node.op() == "Softmax" || node.op() == "Identity" || node.op() == "ArgMax") { std::cout << "⚠️ This is a potential OUTPUT node" << std::endl; } std::cout << "----------------------------------------" << std::endl; } return 0; }
额外说明:
- 如果你的模型是SavedModel格式,不能用
ReadBinaryProto,需要改用LoadSavedModel接口加载,再从MetaGraphDef中提取节点信息 - 输出节点的判断条件需要根据你的模型结构调整,比如自定义模型的最后一层Op可能是其他类型
内容的提问来源于stack exchange,提问作者carlton
相关产品推荐
相关产品推荐

