低成本AIoT硬件部署TensorLayer 深度学习模型实战

低成本AIoT硬件部署TensorLayer 深度学习模型实战

相信大家对TensorLayer等深度学习框架已经很熟悉了,但是平时大家都是在PC端运行自己的模型,

或者可能尝试过在树莓派上运行一些tflite格式的小型模型,但是速度一般只有几帧。。

今天给大家带来的实战笔记是,在低成本(百元内)AIoT硬件 Maix Bit上部署运行TensorLayer的MobileNet模型。

准备工作

软件环境

首先准备一台 安装有TensorLayer 2.1.0或以上版本的Ubuntu PC或虚拟机

安装嵌入式模型转换器 Maix-EMC:


pip install dissect.cstruct

git clone https://github.com/sipeed/Maix-EMC.git

cd Maix-EMC

pip install .

Maix-EMC是一款针对边缘计算的嵌入式深度学习模型转换器

可以将TensorLayer训练所得的FP32模型量化为端侧常用的INT8模型,

并将需要较复杂解析过程的PC端模型结构,扁平化为 嵌入式端可以直接载入内存运行的紧凑模型文件。

硬件环境

这里选用开源硬件公司Sipeed出品的 低成本AIoT硬件 Maix-Bit 套件,(某宝有售)

10美金左右的价格,RISC-V 64GC双核,1TOPS@0.5W,自带200W像素摄像头,可以直插面包板DIY,

image

并配有图形化IDE,方便小白上手,

Sipeed为其提供了便捷的MaixPy环境,使用大家熟悉的python进行快速开发

https://github.com/sipeed/MaixPy

https://maixpy.sipeed.com/zh/

MobileNet模型准备

我们以典型的MobileNetV1模型为例,讲解部署过程。

TensorLayer内置了一个MobileNetV1的实现demo,并附上了预训练的权重文件:


/usr/local/lib/python3.6/dist-packages/tensorlayer/models/mobilenetv1.py

模型修改

针对目标硬件平台的一些特性限制,我们需要对原始的TL提供的网络描述文件做两处修改:

  1. 由于TL使用TF作为后端,而TF默认的stride后的padding方式是 右下角padding, 与我们的目标硬件平台的padding方式不同(Maix的padding方式是与caffe一致的四圈padding),所以我们在stride=(2,2)的层之前手工padding一圈:

if strides != (1, 1):

n = ZeroPad2d(padding=((1, 1), (1, 1)), name=name + '.pad')(n)

padding_type = 'VALID'

else:

padding_type = 'SAME'

  1. 原始的TL提供的模型不支持MobileNet的alpha超参数设置,使用了默认的1.0, 生成的模型文件较大,所以我们为它加上alpha超参数支持。(简单地说alpha参数就是裁剪了通道数)

n_filter = int(n_filter*alpha)

修改完成的py文件在:

模型权重系数获取

MobileNetV1的模型尺寸,精度与alpha的关系可以查阅下表:

alpha size(MB) Top-1 Accuracy Top-5 Accuracy
1.0 4.24 70.9 89.9
0.75 2.59 68.4 88.2
0.5 1.34 63.3 84.9
0.25 0.47 49.8 74.2

可以看到0.75系数时,精度下降不明显,但是体积明显减小,所以我们选取0.75的配置

这里我们使用Keras提供的预训练权重系数:


base_model=keras.applications.mobilenet.MobileNet(input_shape=(224, 224, 3), alpha = 0.75,depth_multiplier = 1, dropout = 0.001, pooling='avg',include_top = True, weights = "imagenet", classes = 1000)

params = np.array(base_model.get_weights())

np.savez('mbnetv1_0.75.npz', params=params)

(保存脚本在:https://github.com/sipeed/Maix-EMC/blob/master/example/mbnetv1/models/save_keras_weight.py)

由于我们在前面修改了padding方式,理论上需要重新微调网络参数来适应更改,

但是经过测试,直接使用原始的权重系数,搭配新的结构,其精度损失不明显,作为我们demo演示已经足够,

所以这里我们就不重新训练微调了。

MobileNet模型转换

由于PC端训练的模型是FP32的权重系数,需要进行量化,我们要提供一些图片样本给转换器进行量化矫正。

我们随机找几十张ImageNet数据集里的图片,放到EMC example/mbnetv1/mbnetv1_dataset目录下。

然后,,短短两行代码就可以转换出嵌入式端使用的模型文件啦!惊不惊喜,意不意外!


# build the model network

mobilenetv1 = MobileNetV1(pretrained=True, alpha=0.75)

# save the model into kmodel:

emc.save_kmodel(mobilenetv1, kmodel_name, './mbnetv1_dataset', dataset_func='img_0_1', quant_func='minmax', quant_bit=8, version=3, sm_flag=True)

(完整文件见:https://github.com/sipeed/Maix-EMC/blob/master/example/mbnetv1/mbnetv1_to_kmodel.py)

这里简单介绍下EMC转换器的API接口:


save_kmodel(network, filepath, dataset_dir, dataset_func='img_0_1', quant_func='minmax', quant_bit=8, version=3, sm_flag=False)

Parameter Intro
network TL model network
filepath output kmodel’s filepath
dataset_dir the path you store pictures for quantization
dataset_func the dataset loader function, convert image to 0~1, or -1~1, or 0~255
quant_func quantization functions, choose from minmax, kld
quant_bit default 8bit, optional 16bit
version kmodel version, default 3
sm_flag add softmax layer at the end.

在Maix板卡上运行kmodel

为方便大家测试,相关的资源文件已打包在此:https://bbs.sipeed.com/uploads/short-url/3CgfAbT7fD4gjV01qHM6hdQOgLF.zip

烧录MaixPy固件及模型文件

在这里下载烧录软件kflash_gui:

烧录maixpy_emc.bin固件 及mbnetv1.kfpkg模型文件 :

下载安装MaixPy IDE

http://dl.sipeed.com/MAIX/MaixPy/ide/v0.2.3/

如速度慢,请使用梯子,或者使用页面里的CDN链接

安装完成之后,使用IDE的上传功能传输labels.txt到板子的文件系统:https://maixpy.sipeed.com/zh/get_started/upload_script.html

image

运行示例代码:

使用IDE或者任意的终端,执行mbnet_test.py里的示例代码

(注意,使用终端的话,按Ctrl+E进入粘贴模式,粘贴完成,按Ctrl+D运行)


import sensor, image, lcd, time

import KPU as kpu

lcd.init()

sensor.reset()

sensor.set_pixformat(sensor.RGB565)

sensor.set_framesize(sensor.QVGA)

sensor.set_windowing((224, 224))

sensor.set_vflip(1)

sensor.run(1)

lcd.clear()

lcd.draw_string(100,96,"MobileNet Demo")

lcd.draw_string(100,112,"Loading labels...")

f=open('labels.txt','r')

labels=f.readlines()

f.close()

lcd.draw_string(100,128,"Done!")

task = kpu.load(0xa00000)

clock = time.clock()

while(True):

img = sensor.snapshot()

clock.tick()

fmap = kpu.forward(task, img)

fps=clock.fps()

plist=fmap[:]

pmax=max(plist)

max_index=plist.index(pmax)

a = lcd.display(img, oft=(0,0))

lcd.draw_string(0, 224, "%.2f:%s "%(pmax, labels[max_index].strip()))

print(fps)

a = kpu.deinit(task)

把Maix-Bit的摄像头对准待识别的物体或图片,就可以在配套LCD或者IDE终端上看到识别信息啦:

image

参考演示视频:https://www.bilibili.com/video/av46664014

我们可以在终端上看到识别速度在20fps+, 实际上通过调整摄像头和CPU、KPU速率,最高可以达到30fps+

小小的Maix-Bit,实战起来比树莓派还要快将近一个数量级呢~

MobileNet的部署实战到此为止了,小伙伴们也可以尝试转换自己的模型到Maix板卡上运行,有什么问题的话欢迎甩issue来Maix-EMC:https://github.com/sipeed/Maix-EMC

小结

使用Maix-EMC工具可以便捷地将TensorLayer的小型静态模型部署到嵌入式端运行,为TensorLayer的工业化部署提供了一个良好的范例。

Maix-EMC项目仍在不断完善迭代中,有兴趣的小伙伴可以参与一起开发(联系support@sipeed.com),参与者皆免费获赠Maix板卡一套哦~

1 Like