【问题标题】:Weights saved in (Python) tensorflow not loaded in C++ tf保存在(Python)张量流中的权重未在 C++ tf 中加载
【发布时间】:2018-12-05 19:19:49
【问题描述】:

我一直关注链接的帖子,最终设法将我训练有素的 tensorflow 模型的图形+权重加载到 C++ 中,而不会向我抛出错误,但它似乎没有正确加载权重。我可能错过了一步,很可能是在推理部分。

我在下面包含了一个功能齐全的最小工作示例。为了运行它,您(可能)需要 Python + 1.4.0

将“训练”模型并保存它的 Python 代码 + 权重,如 here 所示:

from __future__ import absolute_import, division, print_function
import os
import tensorflow as tf
import numpy as np
import random
import keras
from keras import backend as K

# Set it manually so C++ interface can use mem growth
config = tf.ConfigProto()
config.gpu_options.allow_growth = True
sess = tf.Session(config=config)
K.set_session(sess)

model = tf.keras.Sequential([
    tf.keras.layers.Convolution2D(64, (5, 5), input_shape=(7, 19, 19), data_format='channels_first', name='Input'),
    tf.keras.layers.ZeroPadding2D(padding =(4, 4), data_format='channels_first', name='Pad0'),
    tf.keras.layers.BatchNormalization(axis=1, momentum=0.99, name='Norm0'), 
    tf.keras.layers.Dropout(0.25, name='Drop0'),
    tf.keras.layers.Flatten(name='Flatten0'),
    tf.keras.layers.Dense(361, activation='softmax', name='Output'),
])

X = np.ones((25, 7, 19, 19))
Y = np.zeros((25, 361))

optimizer = tf.train.AdamOptimizer(learning_rate=0.0018)
model.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics=['accuracy'])

x = np.zeros((1, 7, 19, 19))
print(model.predict(x))

model.fit(X, Y, 1, 5, 2)
print(model.predict(x)) # Just to verify output is different after training

K.set_learning_phase(0)
sess.run(tf.global_variables_initializer())

saver = tf.train.Saver(tf.global_variables())
saver.save(sess, save_path='./models/myModel')
// Just used to look at graph structure
tf.train.write_graph(sess.graph, '.', './models/graph.pb', as_text=True)

还有C++代码,目前使用的是tf 1.5.0:

加载模型的代码如图here

#define _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS
#define COMPILER_MSVC
#define NOMINMAX
#include <iomanip>
#include <tensorflow\core\public\session.h>
#include <tensorflow\core\protobuf\meta_graph.pb.h>
#include <tensorflow\core\framework\tensor.h>
#include <tensorflow\cc\ops\standard_ops.h>

namespace tf = tensorflow;
tf::Status status;
tf::Session* session;
tf::SessionOptions options;
tf::MetaGraphDef graphDef;
std::string pathToGraph = "models/myModel.meta";
std::string pathToCheckpoint = "models/myModel";

int main()
{
    options.config.mutable_gpu_options()->set_allow_growth(true);
    options.config.mutable_gpu_options()->set_per_process_gpu_memory_fraction(1.0);

    session = tf::NewSession(options);
    if (!session)
         throw std::runtime_error("Could no create Tensorflow Session!");

    // Read in the protobuf
    status = tf::ReadBinaryProto(tf::Env::Default(), pathToGraph, &graphDef);
    if (!status.ok())
        throw std::runtime_error("Error reading graph: " + status.ToString());

    status = session->Create(graphDef.graph_def());
    if (!status.ok())
        throw std::runtime_error("Error creating graph: " + status.ToString());

    // Read the weights
    tf::Tensor checkpointPathTensor(tf::DT_STRING, tf::TensorShape());
    checkpointPathTensor.scalar<std::string>()() = pathToCheckpoint;

    const auto fileTensorName = graphDef.saver_def().filename_tensor_name();
    const auto restoreOpName = graphDef.saver_def().restore_op_name();

    status = session->Run(
        { { fileTensorName, checkpointPathTensor }, },
        {},
        { restoreOpName },
        nullptr
    );

    if (!status.ok())
        throw std::runtime_error("Error loading checkpoint from " + pathToCheckpoint + ": " + status.ToString());

    ...

随后是代码以使用加载/训练的模型运行推理

    float inData[2527] = { 0.f };

    static const std::string inputName = "Input_input";
    static const std::string outputName = "Output/Softmax";

    static const auto shape = tf::TensorShape({ 1, 7, 19, 19});
    tf::Tensor input(tf::DT_FLOAT, shape);
    std::copy_n(inData, 2527, input.flat<float>().data());

    std::vector<tf::Tensor> outputs;
    status = session->Run({ { inputName, input } }, { outputName }, {}, &outputs);

    tf::TTypes<float>::Flat flatOut = outputs[0].flat<float>();

    for (int i = 0; i < 361; ++i)
    {
        if (i % 19 == 0)
            std::cout << '\n';
        std::cout << std::setw(8) << std::fixed << std::setprecision(8) << flatOut(i) << ", ";
    }

    std::cout << '\n';

}

对我来说,当我运行它时,在 Python 部分中一切正常,但在 C++ 部分中静默地无法加载经过训练的图(或执行类似的操作)。运行 C++ 部分时,模型输出与未经训练的 Python 模型完全相同的输出。我在这里缺少一些步骤吗?

模型训练前的 Python 输出示例:

[[0.00277008 0.00277008 0.00277008 0.00277008 0.00277008 0.00277008 
0.00277008 0.00277008 0.00277008 0.00277008 0.00277008  ...etc ]]

在 Python 中训练后的示例输出:

.00387822 0.00228055 0.0018196  0.0014322  0.00266262 0.00234695 
0.0026182  0.00322318 0.00252047 0.00353322 0.00342526 ...etc ]]

加载模型并使用相同输入在 C++ 中运行后的示例输出:

0.00277008, 0.00277008, 0.00277008, 0.00277008, ... etc

理想情况下,我希望看到与训练后的 Python 输出相同的 C++ 输出!

【问题讨论】:

    标签: python c++ tensorflow keras


    【解决方案1】:

    您可以从 tf_label_image_example 项目中修改 main.cc。

    但是,我在使用 CMake 构建 tensorflow 时设置了 tensorflow_BUILD_CC_EXAMPLE=ON。

    你可以参考这个http://www.stefanseibert.com/2017/10/tensorflow-as-dll-into-your-windows-c-project-with-gpu-support-and-cmake-v1-3/

    另外,我构建了一个与 tf_label_image_example_project 类似的 Visual Studio Project(VS 2015 x64 Release)。

    其实我是用Visual Studio打开tf_label_image_example_project,把很多配置复制到我的项目里。最重要的是,*.vcxproj 和 *.vcxproj.filters 中的对象库。

    【讨论】:

      猜你喜欢
      • 2021-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-26
      • 2017-12-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多