口袋中的人工智能 --- 嵌入式AI编程实践系列笔记
疫情高峰过后,又逢清明假期,有空把最近开始做的一些嵌入式的AI开发笔记整理一下.
清明早上外出,晨光中些许感慨,参照于右任先生"望故乡"词阙,赋诗一首,歌以咏志:
沐朝霞兮,登高坡; 遥望远兮,叹蹉跎; 凤凰涅槃兮,天佑中国; 天苍苍,野茫茫; 山之上,国有殇. 2020 清明有感
好了,抒情完毕,切入正题,开始我的学习之旅.
0. 背景
我们这几年一直在做一些深度学习相关的东西,无论模型的设计和训练,模型推理和部署,都是在GPU服务器上实现的.近期,随着边缘计算的兴起,推理和部署渐渐倾向使用前端的AI芯片完成比较耗算力的工作,后端完成一些技术难度更高或者综合推理的工作.这种模式的兴起是随着嵌入式的AI芯片的发展而且来的.可以预见,在不久的将来更多的算法:目标检测,图像分类等基础的算法都会移植到前端的小芯片上,这样我们身边的设备像摄像头,玩具,小家电,办公设备等等不仅是智能化了,而且是具备了深度学习能力,不仅可以看见,听见还可以看明白和听明白,我确信这些会很快实现.
我前期也做了一些探索,使用过没有深度学习的Arduino和Esp32等芯片,也是用过raspberry pi这样的基于arm的主板做些项目.一般作为前端采集和预处理,把图像发送给GPU服务器,有服务器计算完成再把结果返回来. raspberry pi有一定的计算能力,可以运行 opencv和 tensorflow,只是做速度太慢,无法满足实时处理的要求.后来尝试使用raspberry pi + NCS2(intel公司的第二代神经棒)和 jetson tx2和jetson nano(英伟达的基于GPU的嵌入式主板). raspberry pi + NCS2的实测效果和我的目前使用的笔记本速度差不多(mac air 2012年款),jetson tx2基本上达到了 Nvidia的入门级显卡的速度(GTX960). 价格上NCS2不到800元,jetson tx2就比较贵差不多4000多元吧,jetson nano是简化版的这个价格更加亲民,开发板应该在800元.
10.png1.新视野
最近偶然的机会开始接触一款K210的芯片,这跨芯片是原来做阿瓦隆矿机团队做的,这个币圈的朋友应该知道.挖矿消耗的算力其实和深度学习的算法是一样的,都是大量的张量运算.这款芯片无论是算力合适价格真的把上面的秒杀了! 芯片号称只有5美金.
12.png俗话说的好"是骡子是马,拉出去溜溜",我入手了2款基于K210的开发板,汐速科技的Maix Go和Maix Dock. 开始了我的嵌入式AI开发之路.
Maix Go属于豪华配置,外设配的很全:主板,屏幕,电池,喇叭,摄像头,触屏一应俱全,属于写上代码马上就能部署的东西,价格在250元左右吧. Maix Dock应该跟适合做产品的内核,包括显卡,屏幕和主板,价格在150元左右吧.
17.png
3.启程
这2款开发板,都可以使用MaixPy编程,其实真的很容易上手. MaixPy其实就是整合了 micropython和openmv的开发语言.如果熟悉python和opencv的,可以很小的代价转移到嵌入式设备的开发. micropython是python针对迁入设备的一个子集,而openmv是对opencv做了简化后的一个嵌入式的库. 具体可以参照MAIXP的手册,应该是写的很详细了.
(https://maixpy.sipeed.com/zh/
对于初学的建议使用sd卡存储程序和模型,主要是主板flash容量太小,另外传输也不是很方便,使用sd卡就可以节约很多时间.
嵌入式系统使用了MaixPy,启动时候会把flask中一段3M的空间加载为:/flash,把sd可加载为: /sd,这样我们就可以直接使用这样的空间工作.
micropython会默认调用 boot.py和main.py这2个文件,优先调用sd目录.一般boot.py是一些参数初始化,main.py写主代码.这些可以参照文档
其实这种主板最核心的东西就是AI芯片的使用,这一点上MaixPy做的非常好,使用起来也非常简单. k210芯片的AI芯片定义为 KPU.
KPU是通用的神经网络处理器,它可以在低功耗的情况下实现卷积神经网络计算,时时获取被检测目标的大小、坐标和种类,对人脸或者物体进行检测和分类。
KPU 具备以下几个特点:
- 支持主流训练框架按照特定限制规则训练出来的定点化模型
- 对网络层数无直接限制,支持每层卷积神经网络参数单独配置,包括输入输出通道数目、输入输 出行宽列高
- 支持两种卷积内核 1x1 和 3x3
- 支持任意形式的激活函数
- 实时工作时最大支持神经网络参数大小为 5.5MiB 到 5.9MiB
- 非实时工作时最大支持网络参数大小为(Flash 容量-软件体积)
加载模型
从flash或者文件系统中加载模型
import KPU as kpu
task = kpu.load(offset or file_path)
参数
-
offtset
: 模型在 flash 中的偏移大小,如0xd00000
表示模型烧录在13M起始的地方 -
file_path
: 模型在文件系统中为文件名, 如“/sd/xxx.kmodel”
返回
-
kpu_net
: kpu 网络对象
初始化yolo2网络
为yolo2网络模型传入初始化参数
import KPU as kpu
task = kpu.load(offset or file_path)
anchor = (1.889, 2.5245, 2.9465, 3.94056, 3.99987, 5.3658, 5.155437, 6.92275, 6.718375, 9.01025)
kpu.init_yolo2(task, 0.5, 0.3, 5, anchor)
参数
-
kpu_net
: kpu 网络对象 -
threshold
: 概率阈值 -
nms_value
: box_iou 门限 -
anchor_num
: 锚点数 -
anchor
: 锚点参数与模型参数一致
例程
运行人脸识别demo
import sensor
import image
import lcd
import KPU as kpu
lcd.init()
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.run(1)
task = kpu.load('/sd/face_model.kmodel') # face_model.kmodel为人脸识别模型
anchor = (1.889, 2.5245, 2.9465, 3.94056, 3.99987, 5.3658, 5.155437, 6.92275, 6.718375, 9.01025)
a = kpu.init_yolo2(task, 0.5, 0.3, 5, anchor)
while(True):
img = sensor.snapshot()
code = kpu.run_yolo2(task, img)
if code:
for i in code:
print(i)
a = img.draw_rectangle(i.rect())
a = lcd.display(img)
a = kpu.deinit(task)
运行效果
Gif-2020-46-05-12-46-24.gif4.动手做几个小项目
已经做了几个小项目,回头整理一下笔记,后续会分享出来.
Gif-2020-59-05-12-59-45.gif
网友评论