TensorFlow 0.12 模型文件

TensorFlow 0.12 Model Files

我训练模型并使用以下方法保存它:

saver = tf.train.Saver()
saver.save(session, './my_model_name')

除了 checkpoint 文件,它仅包含指向模型最新检查点的指针,这会在当前路径中创建以下 3 个文件:

  1. my_model_name.meta
  2. my_model_name.index
  3. my_model_name.data-00000-of-00001

我想知道每个文件包含什么。

我想用 C++ 加载这个模型并 运行 推理。 label_image 示例使用 ReadBinaryProto() 从单个 .bp 文件加载模型。我想知道如何从这 3 个文件加载它。下面的 C++ 等价物是什么?

new_saver = tf.train.import_meta_graph('./my_model_name.meta')
new_saver.restore(session, './my_model_name')

我目前正在为此苦苦挣扎,我发现目前做起来并不是很简单。关于该主题的两个最常被引用的教程是: https://medium.com/jim-fleming/loading-a-tensorflow-graph-with-the-c-api-4caaff88463f#.goxwm1e5jhttps://medium.com/@hamedmp/exporting-trained-tensorflow-models-to-c-the-right-way-cf24b609d183#.g1gak956i

相当于

new_saver = tf.train.import_meta_graph('./my_model_name.meta')
new_saver.restore(session, './my_model_name')

只是

Status load_graph_status = LoadGraph(graph_path, &session);

假设您 "frozen the graph"(使用脚本将图形文件与检查点值结合起来)。 另外,请参阅此处的讨论:Tensorflow Different ways to Export and Run graph in C++

您的保护程序创建的内容称为 "Checkpoint V2" 并在 TF 0.12 中引入。

我让它工作得很好(尽管 C++ 部分的文档很糟糕,所以我花了一天时间来解决)。有人建议 converting all variables to constants or freezing the graph,但实际上需要 none。

Python部分(节省)

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

如果您使用 tf.trainable_variables() 创建 Saver,您可以省去一些麻烦和存储空间 space。但也许一些更复杂的模型需要保存所有数据,然后将此参数删除到 Saver,只需确保您正在创建 Saver after 您的图表被建造。给所有variables/layers唯一的名字也是非常明智的,否则你可以在不同的问题中运行

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);

为了完整起见,这里是 Python 等价物:

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)