Ham*_* MP 27 c++ python tensorflow
要将训练有素的网络导入C++,您需要导出网络才能执行此操作.经过大量搜索并几乎找不到有关它的信息后,我们明白应该使用freeze_graph()来做到这一点.
感谢Tensorflow的新0.7版本,他们添加了它的文档.
在查看文档之后,我发现几乎没有类似的方法,你能说出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().这两者有什么区别?
这个问题与这个问题有关.
谢谢!
Mar*_*cka 35
这是我使用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)
Run Code Online (Sandbox Code Playgroud)
Python部分(保存)
with tf.Session() as sess:
tf.train.Saver(tf.trainable_variables()).save(sess, 'models/my-model')
Run Code Online (Sandbox Code Playgroud)
如果你创建了Saverwith 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)
Run Code Online (Sandbox Code Playgroud)
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);
Run Code Online (Sandbox Code Playgroud)
小智 18
对于预测(以及所有其他操作),您可以执行以下操作:
首先在python中,您应该为变量或操作命名以备将来使用
self.init = tf.initialize_variables(tf.all_variables(), name="nInit")
Run Code Online (Sandbox Code Playgroud)
训练之后,如果你已经分配了变量,那么计算得到了所有这些变量并将其作为常量保存到图表中.(几乎可以使用该冻结工具完成相同的操作,但我通常自己做,请在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)
Run Code Online (Sandbox Code Playgroud)
现在转到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);
Run Code Online (Sandbox Code Playgroud)
现在你已经加载了所有的神经净重或其他变量.
同样,您可以执行其他操作(记住名称?); 制作适当大小的输入和输出张量,用数据填充输入张量并运行会话,如下所示:
auto operationStatus = session->Run(input, {"put_your_operation_here"}, {}, &out);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
24234 次 |
| 最近记录: |