将Keras模型转换为C++

68

我正在使用Keras(与Theano一起)训练我的CNN模型。 有谁知道如何在我的C ++应用程序中使用它吗? 有人尝试过类似的事情吗? 我想编写一些Python代码,以生成具有网络功能的C ++代码 - 对此有什么建议吗?

我在这里找到了一个类似的问题如何在C ++中使用Tensorflow Keras模型,但没有答案。


@akarsakov 您需要哪些详细信息? - 1''
@1 对不起,我选择了错误的悬赏原因。我想找到更直接或更适合在C++代码中使用Keras模型的方法。 - akarsakov
1
@1 "这样的解决方案很难分发。我们需要部署所有包括Keras等Python环境。" - akarsakov
@akarsakov,请查看我的编辑后的答案。 - 1''
@1'' 谢谢!这是一个不错的选择。但我希望找到一种不依赖于Python的方法。 - akarsakov
显示剩余2条评论
7个回答

67
为了回答自己的问题并找到解决方案,我编写了一个名为keras2cpp的纯C++解决方案(其代码可在GitHub上获得)。
在这个解决方案中,您可以存储网络架构(以json格式)和权重(以hdf5格式)。然后,您可以使用提供的脚本将网络转储到纯文本文件中。您可以在纯C++代码中使用获取的文本文件与网络进行交互。它不依赖于Python库或hdf5。它应该适用于theano和tensorflow后端。

抱歉,我没有意识到您想要部署已经训练好的模型。在这种情况下,这是一个很好的解决方案。 - 1''

19

我发现自己处于类似的情况,需要在C++中支持顺序Keras模型的前向传递,还需要支持使用功能API构建的更复杂的模型。

因此,我编写了一个名为frugally-deep的新库。您可以在GitHub上找到它,并且它是在MIT许可下发布的:https://github.com/Dobiasd/frugally-deep

除了支持许多常见的层类型外,它还可以跟上(有时甚至超过)单个CPU上TensorFlow的性能。您可以在repo中找到一些常见模型的最新基准结果。

通过自动测试,frugally-deep保证在C++中使用它的模型的输出与在Python中使用Keras运行的输出完全相同。


你的库是否支持推断使用 tensorflow.keras 训练的模型? - off99555
@off99555 是的,它可以。 :) - Tobias Hermann

8
如果你的Keras模型是使用tensorflow后端训练的,你可以按照以下代码将Keras模型保存为tensorflow模型: https://github.com/amir-abdi/keras_to_tensorflow 以下是代码的简短版本:
from keras import backend as K
from tensorflow.python.framework import graph_util
from tensorflow.python.framework import graph_io

weight_file_path = 'path to your keras model'
net_model = load_model(weight_file_path)
sess = K.get_session()

constant_graph = graph_util.convert_variables_to_constants(sess, sess.graph.as_graph_def(), 'name of the output tensor')
graph_io.write_graph(constant_graph, 'output_folder_path', 'output.pb', as_text=False)
print('saved the constant graph (ready for inference) at: ', osp.join('output_folder_path', 'output.pb'))

6
您可以尝试这个链接:https://github.com/gosha20777/keras2cpp Keras2cpp是一个小型库,用于在没有任何依赖项的情况下从C++应用程序中运行训练过的Keras模型。
支持的Keras层: - Dense(全连接层) - Convolution1D(一维卷积层) - Convolution2D(二维卷积层) - Convolution3D(三维卷积层) - Flatten(扁平化层) - ELU(指数线性单元激活函数层) - Activation(激活函数层) - MaxPooling2D(二维最大池化层) - Embedding(嵌入层) - LocallyConnected1D(一维局部连接层) - LocallyConnected2D(二维局部连接层) - LSTM(长短时记忆网络层) - GRU(门控循环单元层) - CNN(卷积神经网络层) - BatchNormalization(批量归一化层)
支持的激活函数: - linear(线性激活函数) - relu(修正线性激活函数) - softplus(软正激活函数) - tanh(双曲正切激活函数) - sigmoid(Sigmoid激活函数) - hard_sigmoid(硬Sigmoid激活函数) - elu(指数线性单元激活函数) - softsign(软符号激活函数) - softmax(Softmax激活函数)
设计目标:
  • 与使用TensorFlow后端生成的Keras网络兼容。
  • 仅支持CPU。
  • 无外部依赖项,使用标准库和C++17。
  • 模型存储在内存中。

2
欢迎来到Stack Overflow!虽然我们感谢您想要贡献答案,但请确保问题首先符合网站的主题范围。这是一个关于外部资源的请求,因此不应该回答参见:是否应该建议处理与主题无关的问题? - E net4
2
你好,欢迎来到 Stack Overflow。看起来你正在链接到自己的 GitHub 库。如果你没有适当地披露这个事实,你的答案可能会被删除。请花点时间阅读 SO 关于自我推广的指导。SO's guidance on self-promotion - Michael Dodd

4

我有一个类似的需求——我想在C++应用程序中嵌入Keras模型——于是决定编写自己的库:Kerasify

Kerasify的设计目标:

  • 与使用Theano后端生成的图像处理Sequential网络兼容。 (如果您切换矩阵列/行顺序,则可以使用Tensorflow)。
  • 没有外部依赖项,标准库,支持C++11特性。
  • 以二进制格式存储在磁盘上的模型可以快速读取。
  • 在内存中以连续块存储的模型可以获得更好的缓存性能。
  • 不会抛出异常,仅在错误时返回bool值。
  • 仅支持CPU,不支持GPU。

示例代码,单元测试等详见github链接。 它并没有完全完成,只支持我使用的Keras函数的狭窄子集,但稍加努力即可扩展。


4
这里提供的解决方案相当不错,但如果您的模型有一些这些库不支持的不同类型的层,请按照以下步骤操作:
  • 将Keras模型转换为TensorFlow模型。
  • 冻结模型并使用TensorFlow提供的Transform Graph工具(您需要使用bazel从源代码构建它)。
  • 编译C++ API TensorFlow库以在项目中使用它。
  • 使用C++ API TensorFlow库并将库链接到您的项目。

如果您想使用与bazel不同的编译器(例如g++),可以按照这个很棒的教程进行操作:

http://tuatini.me/building-tensorflow-as-a-standalone-project/


2
小补充:Bazel 不是编译器,而是一个构建工具(可能使用像 g++ 这样的编译器,但不会替代它)。 - Evert Heylen
很好,修改了答案。 - TFreitas

3
最简单的方法可能是通过系统调用Python脚本,将预测结果写入二进制或HDF5文件中,然后在C++中读取。你也可以{{link2:直接将Python集成到C++} }中。
如果您需要轻松部署和分发,可以考虑自包含的Python安装,例如Anaconda,但您最好避免使用Keras并使用Caffe或Tensorflow的C++接口。我不建议使用Tensorflow,因为从C++中使用它并不标准;请参见此讨论。Caffe可以说是第二流行的深度学习库,所以您不会错。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接