1、背景
Python语言中的Keras库搭建深度学习模型非常便捷,但有时需要在 C++ 中调用训练好的模型,得到测试集的结果。比如将模型部署于FPGA,中间的一个步骤则需要用C++构建模型。但 Keras库没有提供 C++ API,其中一种解决方法是使用 TensorFlow 的 C++ API,但编译过程非常繁琐,难以成功,而另一种方法,如果不是必须要使用 GPU,frugally-deep是一个不错的选择。
2、介绍
frugally-deep是一个用C++实现的库,只依赖于三个头文件库 FunctionalPlus、Eigen、json,它可以将 Keras 保存的 .h5 文件直接转为 C++ 中可调用的 .json 文件,同时它也是线程安全的,可以很方便的在多 CPU 上进行前向传播。
3、准备工作
(1)支持 C++14 的编译器:Visual Studio 2019
(2)python版本在 3.7 或以上,TensorFlow 2.1.1(可使用pip install TensorFlow下载 )
(3)下载源码:分别前往frugally-deep, FunctionalPlus , Eigen 和 json 点击右侧的 Code,再点击 Download ZIP 下载这些源码,
- frugally-deep:https://github.com/Dobiasd/frugally-deep
- FunctionalPlus :https://github.com/Dobiasd/FunctionalPlus
- Eigen :https://gitlab.com/libeigen/eigen#
- Json:https://github.com/nlohmann/json
(4)也可以直接到该网盘连接下载:
链接:https://pan.baidu.com/s/1HX_tPZxmOhr2BHCwu9Mp8A
提取码:1x7e
4、使用过程:以下过程是在以上工作准备就绪后进行
(1)在 Python 中训练好模型后,model.save('....h5', include_optimizer=False) 保存模型,比如frugally-deep 主页上的例子。创建create_model.py,运行 create_model.py 后,当前目录下生成了 keras_model.h5
# create_model.pyimport numpy as npfrom tensorflow.keras.layers import Input, Densefrom tensorflow.keras.models import Modelinputs = Input(shape=(4,))x = Dense(5, activation='relu')(inputs)predictions = Dense(3, activation='softmax')(x)model = Model(inputs=inputs, outputs=predictions)model.compile(loss='categorical_crossentropy', optimizer='nadam')model.fit(np.asarray([[1, 2, 3, 4], [2, 3, 4, 5]]),np.asarray([[1, 0, 0], [0, 0, 1]]), epochs=10)model.save('keras_model.h5', include_optimizer=False)
(2)解压frugally-deep、FunctionalPlus、Eigen、json,将frugally-deep-master文件夹下的keras_export文件复制到create_model.py同一个目录下
(3)打开cmd命令窗口(linux系统打开一个终端),使用命令“python keras_export/convert_model.py keras_model.h5 keras_model.json”将模型的.h文件转为c++可直接调用的.json文件,执行命令后同一个目录下出现keras_model.json文件。
转换过程中,frugally-deep 会自动对模型进行测试,验证相同的输入下,模型在 Python 和 C++ 中的输出是否相同。若输出不同会直接报错,则不必担心转换出错。
(4)用vs创建一个空共项目,在项目中创建一个main.cpp文件,在main.cpp文件所在的项目文件夹中创建一个include文件夹。
将 frugally-deep-master文件夹中的include 文件夹中的fdeep文件夹、FunctionalPlus-master文件夹中的include 文件夹中的 fplus 文件夹、将 json-develop 文件夹中的include 文件夹中的nlohmann 文件夹、eigen-master文件夹中的Eigen 文件夹复制到刚创建的include空文件夹内。
// main.cpp#include <fdeep/fdeep.hpp>int main(){const auto model = fdeep::load_model("fdeep_model.json");const auto result = model.predict({fdeep::tensor(fdeep::tensor_shape(static_cast<std::size_t>(4)),{1, 2, 3, 4})});std::cout << fdeep::show_tensors(result) << std::endl;}
(5)在VS创建的项目中,右键点击“解决方案资源管理器”中的项目名称,选择属性 -> 配置属性 -> C/C++ -> 常规,在右侧的附加包含目录中填上 $(ProjectDir)include; 若使用的是 gcc 编译器,要在编译时加上参数 -Iinclude。
(6)运行main.cpp,输出:
5、注意点
如果要预测多个tensor的值,可增加一个循环,如下示例,内部的两层循环是给tensor赋值,最外层循环是控制多个tensor的预测
6、参考网址:该作者已经写的很详细了,学习后,结合自己的项目模型重新理解的写了一下
在 C++ 中调用 keras | iqhy's Blog
C++中用frugally-deep读取keras的模型并进行预测(详细)_1037号森林里一段干木头的博客-CSDN博客