0%

ncnn如何加载keras模型?

我们通常会遇到想让ncnn加载tensorflow、pytorch训练的深度学习模型,但实际上,ncnn是无法直接加载tensorflow或者pytorch模型的

但我们可以通过一种变通的手段让ncnn加载它们,方法就是先将tensorflow、pytorch训练的模型转成通用深度学习模型onnx,然后再利用ncnn工具onnx2ncnn将onnx格式的模型转成ncnn模型。

下面我们以keras训练的模型(.keras)为例,向你详细介绍一下具体的操作步骤。

keras模型转onnx

将keras模型转onnx还是比较简单的,首先我们安装tf2onnx包,命令如下:

1
pip install tf2onnx

之后我们写一段python代码,如下:

1
2
3
4
5
6
7
8
9
10
11
12
import tf2onnx
import onnx
import tensorflow as tf

#加载keras模型
model = tf.keras.models.load_model('tf/mnist.keras')

#转成onnx模型
onnx_model = tf2onnx.convert.from_keras(model)

#将onnx保存成文件
onnx.save_model(onnx_model[0], 'tf/model.onnx')

上面这段代码非常简单, 它首先加载.keras模型,之后调用tf2onnx中convert类的from_keras(…)方法将keras模型转成onnx模型,最后调用onnx.save_model(…)将onnx格式模型保存成文件。

代码中唯一要注意的是,onnx_model是一个二元组,其中第一项才是真正的model,因此我们在将其保存成文件时,要通过[0]找到真正的模型。

至此,我们就将keras模型转成了onnx模型。接下来,咱们来看看如何将onnx转成ncnn模型。

onnx转ncnn

其实,onnx转ncnn也比较简单,ncnn就给我们提供了相应的工具,叫作onnx2ncnn。下面,我们就来看一下具体该如何操作:

第一,我们需要从git上下载ncnn源码,命令如下:

1
git clone https://github.com/Tencent/ncnn.git

代码下载好后,接下来咱们来安装依赖库。要想将onnx2ncnn编译出来,我们需要安装几个依赖包,如opencv、protobuf等。

具体的安装命令如下所示:

1
apt install libopencv-dev libprotobuf-dev protobuf-compiler

当依赖库安装好后,我们就可以编译onnx2ncnn了,编译指令如下:

1
2
3
4
5
6
cd ncnn
mkdir build
cd build
cmake ..
make
make install

上面命令行中,第一步是进行到ncnn源码中,然后创建build子目录,执行cmake .. 生成Makefile,然后执行make进行编译,最终将编译好的程序安装到默认目录下(build下的tools目录)。

不出意外的话,此时我们就可以在build/install/bin中看到onnx2ncnn工具了。

接下来,我们可以使用onnx2ncnn将onnx模型转成ncnn可以识别的模型,命令如下:

1
./onnx2ncnn /tf/model.onnx /tf/ncnn_model.param /tf/ncnn_model.bin

这条命令非常简单,onnx2ncnn的第一个参数是要转换的onnx模型,而第二个参数是转换后的ncnn模型参数,而第三个参数是转换后的权重。

现在有了ncnn模型,后面我们就可以使用ncnn加载这个模型,然后进行预测了。

加载ncnn模型

总的来说,我觉得ncnn有些接口定义的确实不中pytorch和keras友好,咱们来看看ncnn是如何加载网络,并进行推理的吧!

首先我们先装好ncnn包,命令如下:

1
pip install ncnn

接下来,咱们来看一下如何加载模型,代码如下:

1
2
3
4
5
6
7
8
9
import ncnn
model = ncnn.Net()

model.load_param('/tf/ncnn_model.param')
model.load_model('/tf/ncnn_model.bin')

#读取图片并进行预处理
...
preprocess_img = ...

模型加载好后,接下来使用加载好的模型做下推理吧!代码如下:

1
2
3
4
5
6
7
8
9
10
ex = model.create_extractor()
ncnn_img = ncnn.Mat.from_pixels(preprocess_img.data,
ncnn.Mat.PixelType.PIXEL_GRAY,
preprocess_img.shape[1],
preprocess_img.shape[0]
)
ex.input("flatten_input", ncnn_img)
output = ncnn.Mat()
ex.extract("dense_1", output)
print(output)

咱们来看一下这段代码中每一行的含义是什么:

  • ex = model.create_extractor(): 这一行创建了一个 ncnn 模型的提取器(Extractor)。提取器用于设置模型的输入、执行推理,并获取输出。
  • ncnn_img = ncnn.Mat.from_pixels(preprocess_img.data, ncnn.Mat.PixelType.PIXEL_GRAY, preprocess_img.shape[1], preprocess_img.shape[0]): 这一行将经过预处理的图像数据转换为 ncnn::Mat 对象。from_pixels 方法用于从原始像素数据创建一个 ncnn::Mat,并指定像素类型为 PIXEL_GRAY,表示单通道黑白图像。
  • ex.input(“flatten_input”, ncnn_img): 这一行将转换后的图像数据设置为模型的输入。”flatten_input” 是模型中定义的输入 blob 的名称,您需要确保与模型中的实际输入名称一致。
  • output = ncnn.Mat(): 这一行创建了一个空的 ncnn::Mat 对象,用于存储模型的输出结果。
  • ex.extract(“dense_1”, output): 这一行执行模型推理,将输入传递给模型并获取输出。”dense_1” 是模型中定义的输出 blob 的名称,您需要确保与模型中的实际输出名称一致。

总的来说,在推理这块ncnn的API确实不够简练!

小结

本文简要的向你介绍了如何让ncnn加载keras模型,从中你可以知道ncnn是无法直接加载keras模型的,必须要绕一下,先将keras模型转成通用模型onnx,然后再利用ncnn工具将onnx转成ncnn模型,这样才能加载。

欢迎关注我的其它发布渠道