Tensorflow 在 C 中导出和运行图的不同方法

新手上路,请多包涵

要将训练有素的网络导入 C++,您需要导出网络才能执行此操作。经过大量搜索,几乎没有找到关于它的信息,明确了我们应该使用 freeze_graph() 才能做到这一点。

感谢新的 0.7 版本的 Tensorflow,他们添加了它的 文档

查看文档后,我发现几乎没有类似的方法,您能说出 freeze_graph() 和: tf.train.export_meta_graph 之间有什么区别,因为它具有相似的参数,但似乎也可以用于将模型导入 C++ (我只是猜想不同之处在于,使用这种方法输出的文件只能使用 import_graph_def() 还是其他?)

Also one question about how to use write_graph() : In documentations the graph_def is given by sess.graph_def but in examples in freeze_graph() it is sess.graph.as_graph_def() 。这两者有什么区别?

这个问题与 这个问题有关。

谢谢!

原文由 Hamed MP 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 701
1 个回答

这是我利用 TF 0.12 中引入的 V2 检查点的解决方案。

无需将所有变量转换为常量或 冻结图形

为清楚起见,V2 检查点在我的目录 models 中如下所示:

 checkpoint  # some information on the name of the files in the checkpoint
my-model.data-00000-of-00001  # the saved weights
my-model.index  # probably definition of data layout in the previous file
my-model.meta  # protobuf of the graph (nodes and topology info)

Python部分(保存)

 with tf.Session() as sess:
    tf.train.Saver(tf.trainable_variables()).save(sess, 'models/my-model')

如果您使用 Saver 创建 tf.trainable_variables() ,您可以节省一些头痛和存储空间。但也许一些更复杂的模型需要保存所有数据,然后将此参数删除到 Saver ,只需确保在创建图表 创建 Saver 。为所有变量/层赋予唯一名称也是非常明智的,否则您可能会遇到 不同的问题

Python部分(推理)

 with tf.Session() as sess:
    saver = tf.train.import_meta_graph('models/my-model.meta')
    saver.restore(sess, tf.train.latest_checkpoint('models/'))
    outputTensors = sess.run(outputOps, feed_dict=feedDict)

C++部分(推理)

请注意, checkpointPath 不是任何现有文件的路径,只是它们的公共前缀。如果您错误地将 .index 文件的路径放在那里,TF 不会告诉您这是错误的,但由于未初始化的变量,它会在推理过程中死亡。

 #include <tensorflow/core/public/session.h>
#include <tensorflow/core/protobuf/meta_graph.pb.h>

using namespace std;
using namespace tensorflow;

...
// set up your input paths
const string pathToGraph = "models/my-model.meta"
const string checkpointPath = "models/my-model";
...

auto session = NewSession(SessionOptions());
if (session == nullptr) {
    throw runtime_error("Could not create Tensorflow session.");
}

Status status;

// Read in the protobuf graph we exported
MetaGraphDef graph_def;
status = ReadBinaryProto(Env::Default(), pathToGraph, &graph_def);
if (!status.ok()) {
    throw runtime_error("Error reading graph definition from " + pathToGraph + ": " + status.ToString());
}

// Add the graph to the session
status = session->Create(graph_def.graph_def());
if (!status.ok()) {
    throw runtime_error("Error creating graph: " + status.ToString());
}

// Read weights from the saved checkpoint
Tensor checkpointPathTensor(DT_STRING, TensorShape());
checkpointPathTensor.scalar<std::string>()() = checkpointPath;
status = session->Run(
        {{ graph_def.saver_def().filename_tensor_name(), checkpointPathTensor },},
        {},
        {graph_def.saver_def().restore_op_name()},
        nullptr);
if (!status.ok()) {
    throw runtime_error("Error loading checkpoint from " + checkpointPath + ": " + status.ToString());
}

// and run the inference to your liking
auto feedDict = ...
auto outputOps = ...
std::vector<tensorflow::Tensor> outputTensors;
status = session->Run(feedDict, outputOps, {}, &outputTensors);

原文由 Martin Pecka 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题