要将经过训练的网络导入 C++,您需要导出网络才能执行此操作。经过大量搜索,几乎没有找到关于它的信息,明确了我们应该使用freeze_graph()。能够做到。
感谢新的 0.7 版 Tensorflow,他们添加了 documentation其中。
查看文档后,我发现类似的方法很少,你能说出 freeze_graph()
和有什么区别:
tf.train.export_meta_graph
因为它具有相似的参数,但它似乎也可以用于将模型导入C++(我只是猜测不同之处在于,使用这种方法输出的文件你只能使用 import_graph_def()
还是其他?)
还有一个关于如何使用write_graph()
的问题:
在文档中,graph_def
由 sess.graph_def
给出,但在 freeze_graph()
的示例中,它是 sess.graph.as_graph_def()
。这两者有什么区别?
此问题与 this issue. 有关
谢谢!
最佳答案
这是我利用 TF 0.12 中引入的 V2 检查点的解决方案。
无需将所有变量转换为常量或freeze the graph .
为了清楚起见,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')
如果您使用 tf.trainable_variables()
创建 Saver
,您可以为自己节省一些头痛和存储空间。但可能一些更复杂的模型需要保存所有数据,然后将此参数删除到 Saver
,只要确保您创建的是 Saver
after 您的图表已创建。给所有变量/层赋予唯一的名称也是非常明智的,否则你可以在 different problems 中运行.
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
不是任何现有文件的路径,只是它们的公共(public)前缀。如果你错误地将 .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);
关于python - Tensorflow 在 C++ 中导出和运行图的不同方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35508866/