使用C ++中加载的tensorflow模型运行推理

时间:2018-06-19 02:27:55

标签: python c++ tensorflow

此示例的我的tensorflow模型很简单,已成功加载。我的问题是,要进行推理,我应该通过tf :: Session?如何创建提及here的feedDict以及我的" outputOps"?

这是python中的模型:

model = tf.keras.Sequential([
tf.keras.layers.Convolution2D(filters, (5, 5), input_shape=(BoardDepth, BoardLength, BoardLength), data_format='channels_first', name='Input'),
tf.keras.layers.Activation('relu', name='Relu'),
tf.keras.layers.MaxPooling2D(pool_size=(2,2), name='Pool'),
tf.keras.layers.Flatten(name="Flatten"),
tf.keras.layers.Dense(BoardSize, activation='softmax', name='Output'),
])

optimizer = tf.train.AdamOptimizer(learning_rate=0.0018)

model.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics=['accuracy']) 

这里是用于训练模型的方法,该模型使用生成器来提供图像:

earlyExit = keras.callbacks.EarlyStopping(monitor='val_acc', min_delta=0, patience=0)

# Train the model
history = model.fit_generator(generator=gen.generator(),
                steps_per_epoch=gen.stepsPerEpoch(),
                validation_data=valGen.generator(),
                validation_steps=valGen.stepsPerEpoch(),
                epochs=numEpochs, 
                verbose=2, workers=1, callbacks=[earlyExit])

以下是用于保存模型的方法:

K.set_learning_phase(0)
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    saver = tf.train.Saver(tf.trainable_variables())
    saver.save(sess, './models/test/latestModel')

如果你没有按照上面的链接进行推理,那应该是这样的:

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

我尝试过关注示例here,但似乎无法弄清楚我需要传递什么作为outputOps。我是否只需要传递输出节点的名称,还是需要传递模型中的每个操作?到目前为止,我尝试过的不同配置还没有奏效。

到目前为止我的代码看起来像这样:

auto shape = tf::TensorShape({ BoardDepth, BoardSize, BoardSize});

// Placeholder until we're using actual input data
float inData[inputSize] = { 0.0 };

tf::Tensor input(tf::DT_FLOAT, shape);
std::copy_n(inData, inputSize, input.flat<float>().data());

std::vector<std::pair<std::string, tf::Tensor>> inputs = {
    { "Input/Conv2D", input },
};

std::vector<std::string> outOps = { "Output/bias:0"};

std::vector<tf::Tensor> outputs;

status = session->Run(inputs, outOps, {}, &outputs);

输入/输出名称只是设置为我可以找到的不会抛出错误的名称。我真的不知道我应该将它们设置为什么,以便模型在训练时发挥作用。

2 个答案:

答案 0 :(得分:1)

它与存储库中给定的example.py完全相同。

在python中你写道:

import tensorflow as tf
import numpy as np
sess = tf.Session()

from keras import backend as K
K.set_session(sess)

img = tf.placeholder(tf.float32, shape=(None, 2), name='input_plhdr')

model = tf.keras.Sequential([
    tf.keras.layers.Dense(10, activation='relu', name='Intermediate'),
    tf.keras.layers.Dense(2, activation='softmax', name='Output'),
])

M = model(img)
print('input', img.name)
print('output', M.name)
sess.run(tf.global_variables_initializer())
print('result', sess.run(M, {img: np.array([[42, 43.]], dtype=np.float32)}))

saver = tf.train.Saver(tf.global_variables())
saver.save(sess, './exported/my_model')
tf.train.write_graph(sess.graph, '.', "./exported/graph.pb", as_text=False)

print('input', img.name)  # ('input', u'input_plhdr:0')
print('output', M.name)   # ('output', u'sequential/Output_1/Softmax:0')

告诉您输入和输出的名称。调整inference_cc.cc只需要填写正确的名称:

// same as in python file
auto data_ = data.flat<float>().data();
data_[0] = 42;
data_[1] = 43;

tensor_dict feed_dict = {
  { "input_plhdr", data },
};

std::vector<tensorflow::Tensor> outputs;
TF_CHECK_OK(sess->Run(feed_dict, {"sequential/Output_1/Softmax:0"}, {}, &outputs));

std::cout << "input           " << data.DebugString() << std::endl;
std::cout << "output          " << outputs[0].DebugString() << std::endl;

在Python中我得到了

Using TensorFlow backend.
('input', u'input_plhdr:0')
('output', u'sequential/Output_1/Softmax:0')
('result', array([[1.0000000e+00, 1.8979743e-11]], dtype=float32))

C ++返回

input           Tensor<type: float shape: [1,2] values: [42 43]>
output          Tensor<type: float shape: [1,2] values: [1 1.89797431e-11]>

答案 1 :(得分:0)

打印输出张量名称作为Patwie的答案显示了如何解决一半问题。 keras的输入张量名称似乎是您的第一层名称+ _input,因此在我的情况下,我的输入名称为Input_input。