Tensorflow在C ++中导出和运行图的不同方法
c++
python
tensorflow
6
0

要将训练有素的网络导入C ++,您需要导出网络才能这样做。经过大量搜索并且几乎没有找到有关它的信息之后,我们澄清了应该使用freeze_graph()来做到这一点。

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

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

还有一个有关如何使用write_graph() :在文档中, graph_defsess.graph_def给出,但是在freeze_graph()示例中为sess.graph.as_graph_def() 。两者有什么区别?

这个问题与此问题有关

谢谢!

参考资料:
Stack Overflow
收藏
评论
共 2 个回答
高赞 时间 活跃

为了进行预测(以及其他所有操作),您可以执行以下操作:

首先,在python中,您应该命名变量或操作以供将来使用

self.init = tf.initialize_variables(tf.all_variables(), name="nInit")

训练后,在分配变量时对so ..的计算将遍历所有变量并将其另存为常量到图形中。 (使用该冻结工具几乎可以完成,但是我通常是自己完成,请在下面的py和cpp中检查“ name = nWeights”)

def save(self, filename):
    for variable in tf.trainable_variables():
        tensor = tf.constant(variable.eval())
        tf.assign(variable, tensor, name="nWeights")

    tf.train.write_graph(self.sess.graph_def, 'graph/', 'my_graph.pb', as_text=False)

现在去c ++并加载我们的图形并从保存的常量中加载变量:

void load(std::string my_model) {
        auto load_graph_status =
                ReadBinaryProto(tensorflow::Env::Default(), my_model, &graph_def);

        auto session_status = session->Create(graph_def);

        std::vector<tensorflow::Tensor> out;
        std::vector<string> vNames;

        int node_count = graph_def.node_size();
        for (int i = 0; i < node_count; i++) {
            auto n = graph_def.node(i);

            if (n.name().find("nWeights") != std::string::npos) {
                vNames.push_back(n.name());
            }
        }

        session->Run({}, vNames, {}, &out);

现在,您已加载了所有神经网络权重或其他变量。

同样,您可以执行其他操作(还记得名称吗?);制作适当大小的输入和输出张量,用数据填充输入张量并运行会话,如下所示:

auto operationStatus = session->Run(input, {"put_your_operation_here"}, {}, &out);
收藏
评论

这是我利用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')

如果使用tf.trainable_variables()创建Savertf.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);
收藏
评论
新手导航
  • 社区规范
  • 提出问题
  • 进行投票
  • 个人资料
  • 优化问题
  • 回答问题

关于我们

常见问题

内容许可

联系我们

@2020 AskGo
京ICP备20001863号