在STM32F103中使用NNoM部署CNN神经网络进行CIFAR-10图像(灰度)分类

        在上一个示例中,我们使用NNoM提供的示例完整的进行了神经网络的训练、部署并在单片机中本地推理,通过这个实例我们对全流程已经有了一个初步的认识,而在本章中我们将从0搭建训练自己的模型,实现对CIFAR-10图像的分类。

一、准备工作

       如果你可以顺利的训练上一章中示例里的神经网络,那么你的训练环境就已经配置无误了,因为在这一章中我们的训练环境保持不变。依然会使用TensorFlow-cpu在pycharm中搭建神经网络进行训练。

         在示例中使用的是MNIST手写体数据集,他的尺寸是28x28x1的,1代表单通道即灰度图像,我们要用到的数据集CIFAR-10是包含有包括飞机、鸟、汽车等十种类型的彩色图像,其尺寸为32x32x3,但是我已经踩过坑了,因为单片机性能的限制与TensorFlow-cpu没有cuda加速的原因,通道数增加后在训练时速度很慢,提取特征的模型过于庞大,部署在单片机后推理时间令人难以接受,所以在训练模型与推理时将使用单通道的灰度图像,接下来在文章中出现的CIFAR-10数据集同一指代单通道灰度图。可能有些标题党了哈哈^_^。

        接下来我们的任务就是,使用CIFAR-10数据集进行训练,保存准确率表现最佳的模型,将其转换成NNoM头文件的格式,并从CIFAR-10验证集中随机挑选10张图像将其转变成二值图。 接下来就要在pycharm中敲代码,逐个完成上述的功能,源码我会上传,所以这里只着重介绍神经网络部分。

二、训练模型

        

        这是我设计的一个简单的CNN网络结构,输入为32x32x1的尺寸,相较于主流的那些只能说十分简陋了,只有四个卷积块,每一层只是先卷积,进BN层归一化,然后激活函数,再卷积,dropout防止过拟合,经过四个卷积块之后以2x2x128的尺寸在Flatten中展平为一维向量特征融合,输出每个类别的得分并在softmax中将得分转换为高绿分布,输出10x1的维度表示CIFAR-10中的类别,目前这个尺寸的神经网络是接近在stm32f103zet6上部署的极限了。

        这是部署在单片机后,通过串口打印出的模型具体的尺寸,如果模型过大就会无法分配足够的内存产生memory out的报错,在修改模型时可以参考网络各层的尺寸还是很方便的。在训练时我使用的batch size大小为64,训练30次。但是在训练时会产生模型在训练集上的准确率还在升高,但是在验证集上的准确率停留在0.7附近不再变化,这可能是学习率过大的问题导致的模型陷入局部最优解的情况,于是我引入了余弦退火学习率动态的调整,

        加入了这项之后,在30轮训练后,验证集上的准确率会提升到80%,但是在训练集上的准确率已经来到了93%,并且没有发生过拟合的现象。并且从最终结果来看,模型在stm32上推理的准确度是与在验证集上的准确率相似的。但是我还没有想到在既不提升模型的大小的同时提升在验证集上的表现,我也试图引入了如注意力机制或分组卷积等,但是都没有效果,使用数据增强则直接会给我的模型干到准确率停留在0.2,也是很无奈了。如果可以把在验证集上的准确率提升到90%就好了。除了神经网络部分我还增加了一些函数,比如保存表现最好的模型而不是最后一个,图像处理,生成image.h与weights.h等头文件等,基本上与示例中的代码类似,选择的图片我另外保存在了其他文件夹中方便更直观的了解,这里就不多介绍了。

        在训练好模型之后,我希望可以在电脑上推理模型检测一下效果,待检测的图片就是上面的这些从验证集中选出来的10张与在网上随便搜到的一些,猫、飞机什么的。所以还要写一个加载模型进行推理检测的代码。

        

         首先要将图片变成32x32x1的尺寸,然后再由模型推理检测,最后输出结果,并且有一个可视化的结果。经过对代码的一些缝缝补补,最终就可以看见检测后的图是这个效果:

        至此我们就完成了搭建一个简单的神经网络并训练,下一步就可以将生成的weights.h与image.h文件移植到单片机中,在单片机中进行推理了。        

三、在STM32F103ZET6上部署

        这里的移植操作与上一章的一样,只需要更改一下内存分配的大小,简单地说将所有MNIST的28x28修改为32x32后,替换weights.h与image.h文件后运行,就可以在串口中看到输出的内容了,不过我手边正好有一块320x240的lcd屏幕,我希望将检测信息打印在屏幕上方便观察,所以新增了一些函数。

        读取image.h中的灰度值,将灰度值转换为RGB565格式的颜色值,然后使用下面的for循环将尺寸变大,并在lcd上显示出来。

        

        最终运行的结果就是这个样子:

        Tru label为图片存在image.h中正确的标签,Pre label为推理预测出的标签,Time为7387毫秒。经过我又手动挑选的20张图片,在这上面推理结果的准确度与在验证集上相似,为80%左右,识别错误的总是猫,哈基米坏事做尽。虽然检测时间达到了7秒多,但是他只是个zet6,所以我感觉效果还是不错的。至此我们就完成了从头搭建神经网络到使用NNoM部署的全过程了。

       总结一下,首先这个使用的CNN模型还有很多值得优化的地方,我只是简单的在各个卷积块中不断地扩大通道数以提取特征,但是应该会有其他办法继续提升模型的能力;

        其次,我认为这也说明基础的stm32也是有一定的部署神经网络的能力的,CIFAR-10数据集包含的背景信息还是较为复杂的,提取特征有一定的难度,但是对于一些输入参数较少,实时性要求不高的场合使用这种低成本的stm32部署个神经网络进去我觉得还是有一定的可行性的。

四、番外

        刚好手边有一块f407,移植过去看了一下检测时间索缩短了十倍不止,来到了500毫秒,性能差距居然这么

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值