1.项目介绍:
生肖也称为属相,共有十二种生肖,分别是鼠、牛、虎、兔、龙、蛇、马、羊、猴、鸡、狗、猪,每个生肖都有其独特的寓意和象征意义,是中国传统文化中的一种记年方式,是一种十二年一个循环的纪年系统,每年用一种动物来代表,每隔十二年循环一次。十二生肖起源于中国古代天文历法中的十二地支,对应子、丑、寅、卯、辰、巳、午、未、申、酉、戌、亥,形成了现在的生肖记年法。生肖是中国传统文化中的重要组成部分,它不仅是一种纪年方式,也是对古代中国时间、自然、文化方面的总结和反映,具有文化和历史价值。十二生肖是中国文化的重要符号之一,它已经被广泛运用于绘画、雕塑、陶瓷、民间传说、戏曲、游戏、影视、动画、书籍、旅游各种文化载体,十二生肖也被广泛应用于商业文化中,例如在中国的年货市场上,各种与生肖相关的商品,如手工艺品、玩具、书籍、饰品、绘画作品等都备受欢迎。
在当今世界中,机器学习,深度学习,计算机视觉等技术日新月异,在不断飞速发展的同时也使得图像识别技术等AI技术也在我们的生活中大放异彩。我认为通过图像识别检测十二生肖,可以让人们更好的了解到生肖,更好的了解中国传统文化。因此本项目的目标是基于图像识别等技术,利用MAX78000开发板完成日常生活中生肖的检测任务,使用板卡上的摄像头采集图像,并使用AI技术判断图像中是否有十二生肖,并显示其中十二生肖的名称。
图1-1 生肖龙
图1-2 生肖虎
图1-3 生肖羊
2.项目设计思路:
项目设计思路如下图所示:
图2-1 十二生肖检测仪项目设计思路
3.搜集素材的思路:
3.1 生肖数据收集
本项目中用到的十二生肖数据集本来来源于一个网站:https://www.kaggle.com/datasets/elderyouth/chinese-zodiac-signs/data,其包含了十二生肖共8508张图像。但是后续发现该数据集中的图片类型有些问题,其中龙生肖中有一半图片来自于西方龙,并不符合十二生肖的设定,而其他生肖的图片几乎都来自于真实的动物,没有包含其他艺术文化形式的图片类型,如:剪纸,美术形式。所以我把数据集中的西方龙的图片删除,加上自己在百度,谷歌,必应等平台上搜集了一些其他艺术类型的生肖图片,每种类别收集了几十张,然后对这些图片做了剪切等处理,合并进了原本的数据集之中,最终得到的新的数据集,其中训练集占比80%,验证集占比10%,测试集占比10%。
图3-1 训练集内容图
3.2 生成数据集
生成数据集采用pytorch的ImageFolder类读取图片并进行处理,训练集和测试集都采用此方法进行生成。由于网络处理的图片需要拥有统一的图片尺寸,而原始数据集中的图片尺寸不一样,所以我们需要把所有图片进行尺寸变换,统一将图片大小都设置为128×128。即使本项目训练集数据很丰富,我们依旧需要对训练集进行数据增强以提高训练精度,提升不同场景下的鲁棒性并防止过拟合,最后需要将图片变换成pytorch张量并进行归一化,将数据从[0,1]变换至[-128,127]。生成数据集代码如下:
train_transform = transforms.Compose([
transforms.RandomAffine(degrees=10, translate=(0.05, 0.05), shear=5),
transforms.RandomPerspective(distortion_scale=0.3, p=0.2),
transforms.RandomHorizontalFlip(),
transforms.ColorJitter(brightness=0.7),
transforms.Resize((128, 128)),
transforms.ToTensor(),
ai8x.normalize(args=args),
])
将数据集分成分成train,test和valid三类并放置到目录ai8x-training/data下, 然后在ai8x-training/datasets下新建一个文件shenxiao.py,用于编写读取数据集的代码,读取和生成数据集的具体代码如下:
import os
from torchvision import transforms
from torchvision.datasets import ImageFolder
import ai8x
def shenxiao_get_datasets(data, load_train=True, load_test=True):
(data_dir, args) = data
if load_train:
train_transform = transforms.Compose([
transforms.RandomAffine(degrees=10, translate=(0.05, 0.05), shear=5),
transforms.RandomPerspective(distortion_scale=0.3, p=0.2),
transforms.RandomHorizontalFlip(),
transforms.ColorJitter(brightness=0.7),
transforms.Resize((128, 128)),
transforms.ToTensor(),
ai8x.normalize(args=args),
])
train_dataset = ImageFolder(root=os.path.join(data_dir, 'train'), transform=train_transform)
else:
train_dataset = None
if load_test:
test_transform = transforms.Compose([
transforms.Resize((128, 128)),
transforms.ToTensor(),
ai8x.normalize(args=args),
])
test_dataset = ImageFolder(root=os.path.join(data_dir, 'test'), transform=test_transform)
else:
test_dataset = None
return train_dataset, test_dataset
datasets = [
{
'name': 'shenxiao',
'input': (3, 128, 128),
'output': ('rat', 'ox', 'tiger', 'rabbit', 'dragon', 'snake', 'horse', 'goat', 'monkey', "rooster", "dog", "pig"),
'loader': shenxiao_get_datasets,
},
]
4.预训练实现过程:
预训练主要参照官方 AI 文档:https://github.com/MaximIntegratedAI/MaximAI_Documentation
MAX78000 中使用 AI 算法主要有 training、synthesis、deployment 三个步骤
ai8x-training仓库,用于在电脑上训练神经网络:https://github.com/MaximIntegratedAI/ai8x-training
ai8x-synthesis仓库,用于把训练好的模型文件转换成c语言代码:https://github.com/MaximIntegratedAI/ai8x-synthesis
msdk仓库,用于编写单片机程序:https://github.com/Analog-Devices-MSDK/msdk
4.1 环境搭建:
本次项目的环境要求如下所示:
CPU: 64-bit amd64/x86_64 “PC” with Ubuntu Linux 20.04 LTS GPU for hardware acceleration (optional but highly recommended): Nvidia with CUDA 11 PyTorch 1.8.1 (LTS) on Python 3.8.x
4.1.1 安装MSDK(需要科学上网)
首先需要下载安装MaximMicrosSDK,官网地址如下:https://www.maximintegrated.com/en/design/software-description.html/swpart=SFW0010820A
具体安装流程参考:https://blog.csdn.net/VOR234/article/details/128061754
4.1.2 下载ai8x-training和ai8x-synthesis仓库(需要科学上网)
下载地址如下:
ai8x-training:https://github.com/MaximIntegratedAI/ai8x-training.git
ai8x-synthesis:https://github.com/MaximIntegratedAI/ai8x-synthesis.git
4.1.3 安装Anaconda3
Anaconda的下载地址:https://www.anaconda.com/download/
具体安装流程参考:https://blog.csdn.net/weixin_37766087/article/details/100742198
4.1.4 虚拟环境搭建
虚拟环境搭建教程参考:https://blog.csdn.net/m0_62648611/article/details/131731563
如果下载太慢,可以使用国内镜像源,ai8x_training环境的构建代码如下:
> conda create -n ai8x_training python=3.8.11
> D:
> cd MAX78000\AI\ai8x-training
> conda activate ai8x_training
> pip3 install -r requirements-win-cu11.txt -i https://mirrors.aliyun.com/pypi/simple/
ai8x-synthesis环境的构建和ai8x-training同理,构建代码如下:
> conda create -n ai8x_synthesis python=3.8.11
> D:
> cd MAX78000\AI\ai8x-synthesis
> conda activate ai8x_synthesis
> pip3 install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/
4.1.5 安装pycharm配置环境
pycharm下载地址:https://www.jetbrains.com/pycharm/download/
具体安装流程参考:https://blog.csdn.net/2301_78077589/article/details/130723662
给pycharm配置anaconda构建的虚拟环境的教程:
图4-1 给pycharm配置anaconda构建的虚拟环境流程图
对ai8x-training文件夹和ai8x-synthesis文件夹分别配置ai8x-training环境和ai8x-synthesis环境。
4.2 模型选择和优化
本项目分别使用了基于ai85net-cd模型,精简的res模型和ai85net-simplenet-wide2x模型修改而来的模型进行训练,经过了反复训练和测试,基于精简的res模型修改的模型得到的模型训练结果如下:
2023-12-09 18:59:47,007 - Training epoch: 7011 samples (240 per mini-batch)
2023-12-09 19:00:18,161 - Epoch: [314][ 10/ 30] Overall Loss 1.343042 Objective Loss 1.343042 LR 0.000040 Time 3.115309
2023-12-09 19:00:31,913 - Epoch: [314][ 20/ 30] Overall Loss 1.356508 Objective Loss 1.356508 LR 0.000040 Time 2.245153
2023-12-09 19:00:44,211 - Epoch: [314][ 30/ 30] Overall Loss 1.346136 Objective Loss 1.346136 Top1 57.388316 Top5 93.470790 LR 0.000040 Time 1.906669
2023-12-09 19:00:44,647 - --- validate (epoch=314)-----------
2023-12-09 19:00:44,648 - 779 samples (240 per mini-batch)
2023-12-09 19:01:06,109 - Epoch: [314][ 4/ 4] Loss 1.547752 Top1 49.550706 Top5 87.804878
2023-12-09 19:01:06,530 - ==> Top1: 49.551 Top5: 87.805 Loss: 1.548
2023-12-09 19:01:06,532 - ==> Best [Top1: 51.733 Top5: 87.291 Sparsity:0.00 Params: 80734 on epoch: 222]
2023-12-09 19:01:06,532 - Saving checkpoint to: logs\2023.12.09-115000\qat_checkpoint.pth.tar
基于ai85net-simplenet-wide2x模型修改得到的模型训练结果如下:
2023-12-10 18:47:46,369 - Training epoch: 7003 samples (240 per mini-batch)
2023-12-10 18:48:26,924 - Epoch: [149][ 10/ 30] Overall Loss 2.022833 Objective Loss 2.022833 LR 0.000016 Time 4.055343
2023-12-10 18:48:46,152 - Epoch: [149][ 20/ 30] Overall Loss 2.029027 Objective Loss 2.029027 LR 0.000016 Time 2.989004
2023-12-10 18:49:02,771 - Epoch: [149][ 30/ 30] Overall Loss 2.042283 Objective Loss 2.042283 Top1 28.975265 Top5 73.851590 LR 0.000016 Time 2.546633
2023-12-10 18:49:03,299 - --- validate (epoch=149)-----------
2023-12-10 18:49:03,299 - 778 samples (240 per mini-batch)
2023-12-10 18:49:26,286 - Epoch: [149][ 4/ 4] Loss 2.069062 Top1 26.221080 Top5 72.107969
2023-12-10 18:49:26,714 - ==> Top1: 26.221 Top5: 72.108 Loss: 2.069
2023-12-10 18:49:26,717 - ==> Best [Top1: 30.334 Top5: 73.008 Sparsity:0.00 Params: 708232 on epoch: 128]
2023-12-10 18:49:26,717 - Saving checkpoint to: logs\2023.12.10-143357\qat_checkpoint.pth.tar
2023-12-10 18:49:26,744 - --- test ---------------------
2023-12-10 18:49:26,745 - 757 samples (240 per mini-batch)
2023-12-10 18:49:47,459 - Test: [ 4/ 4] Loss 2.138329 Top1 28.533686 Top5 71.202114
2023-12-10 18:49:47,885 - ==> Top1: 28.534 Top5: 71.202 Loss: 2.138
基于ai85net-cd模型修改得到的模型训练结果如下:
2023-12-08 15:44:14,170 - Training epoch: 7011 samples (240 per mini-batch)
2023-12-08 15:44:48,694 - Epoch: [99][ 10/ 30] Overall Loss 1.120448 Objective Loss 1.120448 LR 0.000200 Time 3.452330
2023-12-08 15:45:01,504 - Epoch: [99][ 20/ 30] Overall Loss 1.088512 Objective Loss 1.088512 LR 0.000200 Time 2.366598
2023-12-08 15:45:17,432 - Epoch: [99][ 30/ 30] Overall Loss 1.079984 Objective Loss 1.079984 Top1 64.604811 Top5 95.876289 LR 0.000200 Time 2.108631
2023-12-08 15:45:17,882 - --- validate (epoch=99)-----------
2023-12-08 15:45:17,882 - 779 samples (240 per mini-batch)
2023-12-08 15:45:41,735 - Epoch: [99][ 4/ 4] Loss 1.341696 Top1 53.016688 Top5 88.703466
2023-12-08 15:45:42,193 - ==> Top1: 53.017 Top5: 88.703 Loss: 1.342
2023-12-08 15:45:42,194 - ==> Best [Top1: 55.712 Top5: 88.447 Sparsity:0.00 Params: 68015 on epoch: 86]
2023-12-08 15:45:42,195 - Saving checkpoint to: logs\2023.12.08-131828\qat_checkpoint.pth.tar
2023-12-08 15:45:42,209 - --- test ---------------------
2023-12-08 15:45:42,209 - 757 samples (240 per mini-batch)
2023-12-08 15:46:01,734 - Test: [ 4/ 4] Loss 1.527895 Top1 51.387054 Top5 88.375165
2023-12-08 15:46:02,194 - ==> Top1: 51.387 Top5: 88.375 Loss: 1.528
由上述三个模型的训练结果对比,发现依旧还是基于ai85net-cd模型修改而来的模型进行训练效果最佳,但是虽然该模型的top5能够达到88%,top1却只有51%,为了增加该模型的准确率,我使用了增加训练循环次数,增加网络模型深度和添加残差连接,等方法对训练进行修改,但效果均不理想。增加训练循环次数的训练结果如下:
2023-12-08 19:31:33,422 - Training epoch: 7012 samples (256 per mini-batch)
2023-12-08 19:32:11,261 - Epoch: [149][ 10/ 28] Overall Loss 1.159092 Objective Loss 1.159092 LR 0.000016 Time 3.783916
2023-12-08 19:32:25,817 - Epoch: [149][ 20/ 28] Overall Loss 1.179319 Objective Loss 1.179319 LR 0.000016 Time 2.619768
2023-12-08 19:32:40,621 - Epoch: [149][ 28/ 28] Overall Loss 1.184086 Objective Loss 1.184086 Top1 63.764045 Top5 93.258427 LR 0.000016 Time 2.399973
2023-12-08 19:32:41,085 - --- validate (epoch=149)-----------
2023-12-08 19:32:41,086 - 779 samples (256 per mini-batch)
2023-12-08 19:33:03,846 - Epoch: [149][ 4/ 4] Loss 1.397416 Top1 52.118100 Top5 88.318357
2023-12-08 19:33:04,336 - ==> Top1: 52.118 Top5: 88.318 Loss: 1.397
2023-12-08 19:33:04,337 - ==> Confusion:
[[33 1 6 5 11 3 5 11 7 2 0 2]
[ 0 11 1 1 1 0 1 0 0 7 8 2]
[ 8 0 27 6 2 3 3 5 1 2 5 1]
[ 4 1 4 34 1 8 2 2 2 1 0 1]
[10 1 4 1 46 2 10 4 5 0 1 1]
[ 2 1 2 9 0 36 2 0 3 3 1 1]
[ 7 1 5 0 4 6 42 0 2 2 2 2]
[ 6 2 5 2 4 1 4 20 8 4 9 0]
[ 2 1 3 1 3 2 10 10 20 2 4 3]
[ 0 2 0 0 1 2 2 1 5 50 4 3]
[ 2 7 2 1 2 0 1 2 6 2 29 2]
[ 0 5 1 0 2 0 1 0 0 1 0 58]]
2023-12-08 19:33:04,339 - ==> Best [Top1: 53.273 Top5: 87.035 Sparsity:0.00 Params: 68016 on epoch: 127]
2023-12-08 19:33:04,340 - Saving checkpoint to: logs\2023.12.08-155241\qat_checkpoint.pth.tar
2023-12-08 19:33:04,355 - --- test ---------------------
2023-12-08 19:33:04,355 - 757 samples (256 per mini-batch)
2023-12-08 19:33:23,253 - Test: [ 3/ 3] Loss 1.602395 Top1 48.745046 Top5 84.412153
2023-12-08 19:33:23,713 - ==> Top1: 48.745 Top5: 84.412 Loss: 1.602
增加网络模型深度和添加残差连接的训练结果如下:
2023-12-10 08:19:42,518 - Training epoch: 7004 samples (240 per mini-batch)
2023-12-10 08:20:17,673 - Epoch: [149][ 10/ 30] Overall Loss 1.288790 Objective Loss 1.288790 LR 0.000016 Time 3.515372
2023-12-10 08:20:29,793 - Epoch: [149][ 20/ 30] Overall Loss 1.294369 Objective Loss 1.294369 LR 0.000016 Time 2.363632
2023-12-10 08:20:44,590 - Epoch: [149][ 30/ 30] Overall Loss 1.290687 Objective Loss 1.290687 Top1 56.338028 Top5 89.436620 LR 0.000016 Time 2.068950
2023-12-10 08:20:45,015 - --- validate (epoch=149)-----------
2023-12-10 08:20:45,015 - 778 samples (240 per mini-batch)
2023-12-10 08:21:06,590 - Epoch: [149][ 4/ 4] Loss 1.547520 Top1 48.071979 Top5 85.475578
2023-12-10 08:21:07,050 - ==> Top1: 48.072 Top5: 85.476 Loss: 1.548
2023-12-10 08:21:07,052 - ==> Best [Top1: 51.157 Top5: 86.504 Sparsity:0.00 Params: 72880 on epoch: 91]
2023-12-10 08:21:07,052 - Saving checkpoint to: logs\2023.12.10-044317\qat_checkpoint.pth.tar
2023-12-10 08:21:07,069 - --- test ---------------------
2023-12-10 08:21:07,070 - 757 samples (240 per mini-batch)
2023-12-10 08:21:25,761 - Test: [ 4/ 4] Loss 1.626634 Top1 47.820343 Top5 85.468956
2023-12-10 08:21:26,189 - ==> Top1: 47.820 Top5: 85.469 Loss: 1.627
因此最终选择由SDK中自带的ai85net-cd猫狗分类模型修改得到本项目的十二生肖检测模型,该模型被用于十二分类任务,输入为尺寸128×128×3的RGB图像,共包含了6个卷积层,除最后一个卷积层外,每个卷积层后还包含批归一化操作和ReLU激活层。
4.3 模型训练
在pycharm打开ai8x-training文件夹搭建训练模型,在ai8x-training/models下新建一个文件ai85net-shenxiao.py进行模型搭建,模型的具体内容如下:
from torch import nn
import ai8x
class AI85Net_Shenxiao(nn.Module):
def __init__(self, num_classes=12, num_channels=3, dimensions=(128, 128),
fc_inputs=16, bias=False, **kwargs):
super().__init__()
assert dimensions[0] == dimensions[1]
dim = dimensions[0]
self.conv1 = ai8x.FusedConv2dReLU(num_channels, 16, 3,
padding=1, bias=bias, **kwargs)
pad = 2 if dim == 28 else 1
self.conv2 = ai8x.FusedMaxPoolConv2dReLU(16, 32, 3, pool_size=2, pool_stride=2,
padding=pad, bias=bias, **kwargs)
dim //= 2
if pad == 2:
dim += 2
self.conv3 = ai8x.FusedMaxPoolConv2dReLU(32, 64, 3, pool_size=2, pool_stride=2, padding=1,
bias=bias, **kwargs)
dim //= 2
self.conv4 = ai8x.FusedMaxPoolConv2dReLU(64, 32, 3, pool_size=2, pool_stride=2, padding=1,
bias=bias, **kwargs)
dim //= 2
self.conv5 = ai8x.FusedMaxPoolConv2dReLU(32, 32, 3, pool_size=2, pool_stride=2, padding=1,
bias=bias, **kwargs)
dim //= 2
self.conv6 = ai8x.FusedConv2dReLU(32, fc_inputs, 3, padding=1, bias=bias, **kwargs)
self.fc = ai8x.Linear(fc_inputs*dim*dim, num_classes, bias=True, wide=True, **kwargs)
for m in self.modules():
if isinstance(m, nn.Conv2d):
nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
def forward(self, x): # pylint: disable=arguments-differ
x = self.conv1(x)
x = self.conv2(x)
x = self.conv3(x)
x = self.conv4(x)
x = self.conv5(x)
x = self.conv6(x)
x = x.view(x.size(0), -1)
x = self.fc(x)
return x
def ai85net_shenxiao(pretrained=False, **kwargs):
assert not pretrained
return AI85Net_Shenxiao(**kwargs)
models = [
{
'name': 'ai85net_shenxiao',
'min_input': 1,
'dim': 2,
},
]
然后在ai8x-training/policies下新建文件schedule-shenxiao.py,填写learning rate schedule配置文件如下:
lr_schedulers:
training_lr:
class: MultiStepLR
milestones: [40, 60, 80]
gamma: 0.25
policies:
- lr_scheduler:
instance_name: training_lr
starting_epoch: 0
ending_epoch: 100
frequency: 1
最后把模型训练参数设置为100epoch,batchsize128,学习率0.001,优化器为Adam,并随着训练进度阶梯式调整学习率来使模型得到充分训练,具体训练脚本如下:
python train.py --epochs 100 --optimizer Adam --lr 0.001 --wd 0.001 --batch-size 240 --gpus 0 --deterministic --compress policies/schedule-shenxiao.yaml --model ai85net_shenxiao --dataset shenxiao --param-hist --pr-curves --embedding --device MAX78000
把该脚本直接放入pycharm终端运行即可。
图4-2 pycharm运行训练脚本过程图
训练输出结果如下:
2023-12-08 13:18:28,764 - Log file for this run: D:\MAX7800\12sx\shenxiao\ai8x-training\logs\2023.12.08-131828\2023.12.08-131828.log
2023-12-08 13:18:29,901 - Optimizer Type: <class 'torch.optim.adam.Adam'>
2023-12-08 13:18:29,901 - Optimizer Args: {'lr': 0.001, 'betas': (0.9, 0.999), 'eps': 1e-08, 'weight_decay': 0.001, 'amsgrad': False}
2023-12-08 13:18:30,032 - Dataset sizes:
training=7011
validation=779
test=757
2023-12-08 13:18:30,033 - Reading compression schedule from: policies/schedule-shenxiao.yaml
2023-12-08 13:18:30,036 -
2023-12-08 13:18:30,036 - Training epoch: 7011 samples (240 per mini-batch)
2023-12-08 13:19:09,478 - Epoch: [0][ 10/ 30] Overall Loss 2.473655 Objective Loss 2.473655 LR 0.001000 Time 3.944174
2023-12-08 13:19:19,970 - Epoch: [0][ 20/ 30] Overall Loss 2.464135 Objective Loss 2.464135 LR 0.001000 Time 2.496557
2023-12-08 13:19:38,074 - Epoch: [0][ 30/ 30] Overall Loss 2.455299 Objective Loss 2.455299 Top1 14.776632 Top5 55.670103 LR 0.001000 Time 2.267841
2023-12-08 13:19:38,526 - --- validate (epoch=0)-----------
2023-12-08 13:19:38,526 - 779 samples (240 per mini-batch)
2023-12-08 13:20:00,477 - Epoch: [0][ 4/ 4] Loss 2.425305 Top1 11.810013 Top5 54.942234
2023-12-08 13:20:00,922 - ==> Top1: 11.810 Top5: 54.942 Loss: 2.425
2023-12-08 13:20:00,924 - ==> Best [Top1: 11.810 Top5: 54.942 Sparsity:0.00 Params: 68016 on epoch: 0]
2023-12-08 13:20:00,924 - Saving checkpoint to: logs\2023.12.08-131828\checkpoint.pth.tar
2023-12-08 13:20:00,940 -
2023-12-08 13:20:00,940 - Training epoch: 7011 samples (240 per mini-batch)
2023-12-08 13:20:35,171 - Epoch: [1][ 10/ 30] Overall Loss 2.408739 Objective Loss 2.408739 LR 0.001000 Time 3.422906
2023-12-08 13:20:49,266 - Epoch: [1][ 20/ 30] Overall Loss 2.386310 Objective Loss 2.386310 LR 0.001000 Time 2.416246
2023-12-08 13:21:05,251 - Epoch: [1][ 30/ 30] Overall Loss 2.367534 Objective Loss 2.367534 Top1 17.182131 Top5 61.855670 LR 0.001000 Time 2.143635
2023-12-08 13:21:05,694 - --- validate (epoch=1)-----------
2023-12-08 13:21:05,694 - 779 samples (240 per mini-batch)
2023-12-08 13:21:28,242 - Epoch: [1][ 4/ 4] Loss 2.367832 Top1 17.715019 Top5 57.637997
2023-12-08 13:21:28,684 - ==> Top1: 17.715 Top5: 57.638 Loss: 2.368
2023-12-08 13:21:28,685 - ==> Best [Top1: 17.715 Top5: 57.638 Sparsity:0.00 Params: 68016 on epoch: 1]
2023-12-08 13:21:28,686 - Saving checkpoint to: logs\2023.12.08-131828\checkpoint.pth.tar
2023-12-08 13:21:28,701 -
................
2023-12-08 15:44:14,170 - Training epoch: 7011 samples (240 per mini-batch)
2023-12-08 15:44:48,694 - Epoch: [99][ 10/ 30] Overall Loss 1.120448 Objective Loss 1.120448 LR 0.000200 Time 3.452330
2023-12-08 15:45:01,504 - Epoch: [99][ 20/ 30] Overall Loss 1.088512 Objective Loss 1.088512 LR 0.000200 Time 2.366598
2023-12-08 15:45:17,432 - Epoch: [99][ 30/ 30] Overall Loss 1.079984 Objective Loss 1.079984 Top1 64.604811 Top5 95.876289 LR 0.000200 Time 2.108631
2023-12-08 15:45:17,882 - --- validate (epoch=99)-----------
2023-12-08 15:45:17,882 - 779 samples (240 per mini-batch)
2023-12-08 15:45:41,735 - Epoch: [99][ 4/ 4] Loss 1.341696 Top1 53.016688 Top5 88.703466
2023-12-08 15:45:42,193 - ==> Top1: 53.017 Top5: 88.703 Loss: 1.342
2023-12-08 15:45:42,194 - ==> Best [Top1: 55.712 Top5: 88.447 Sparsity:0.00 Params: 68015 on epoch: 86]
2023-12-08 15:45:42,195 - Saving checkpoint to: logs\2023.12.08-131828\qat_checkpoint.pth.tar
2023-12-08 15:45:42,209 - --- test ---------------------
2023-12-08 15:45:42,209 - 757 samples (240 per mini-batch)
2023-12-08 15:46:01,734 - Test: [ 4/ 4] Loss 1.527895 Top1 51.387054 Top5 88.375165
2023-12-08 15:46:02,194 - ==> Top1: 51.387 Top5: 88.375 Loss: 1.528
2023-12-08 15:46:02,198 -
2023-12-08 15:46:02,198 - Log file for this run: D:\MAX7800\12sx\shenxiao\ai8x-training\logs\2023.12.08-131828\2023.12.08-131828.log
可以看到,经过训练在测试集上的Top1准确率可以达到51%,Top5准确率可以达到88%,说明网络可以对十二生肖图片进行较为有效的识别。
训练结束之后,训练结果会被保存在ai8x-training/logs下,以便于查看训练记录找到训练记录。
4.4 模型量化
为了让模型成功部署在MAX78000上,需要对模型的网络参数进行量化,对于中间层每个参数以2bit量化,两边层用4bit或者8bit量化,首先需要将训练好的模型qat_best.pth.tar从ai8x-training/logs目录下拷贝到ai8x-synthesis/trained目录下,并把名字改成ai8x-shenxiao-qat8.pth.tar。训练结果中的qat_best.pth.tar模型是保存的最好的训练结果,并且是在训练时被量化的结果,经过实验验证,使用这个模型来量化能得到最好的量化结果。
图4-3 qat_best.pth.tar位置图
然后再在pycharm打开ai8x-synthesis文件夹,在终端中运行以下代码实现模型量化,具体量化脚本如下:
python quantize.py trained/ai8x-shenxiao-qat8.pth.tar trained/ai8x-shenxiao-qat8-q.pth.tar --device MAX78000 -v
量化完成的结果如下:
图4-4 量化完成结果图
完成这一步之后会在ai8x-synthesis/trained目录下生成一个文件ai8x-shenxiao-qat8-q.pth.tar。
4.5 模型评估
在pycharm打开ai8x-training文件夹,输入以下代码进行模型评估,具体评估脚本如下:
python train.py --model ai85net_shenxiao --dataset shenxiao --confusion --evaluate --exp-load-weights-from ../ai8x-synthesis/trained/ai8x-shenxiao-qat8-q.pth.tar -8 --device MAX78000
模型评估结果如下图所示:
图4-5 模型评估结果图
测试精度与训练时的测试结果差别不大,说明模型大体上满足要求。
4.6 模型转换
模型量化后,我的下一个目标是把原本的模型转化成可以在MAX78000上运行的c语言代码,生成该项目主要需要三个文件:量化后的模型, 测试样本文件和网络描述文件。我已经在之前得到了量化后的模型,接下来得到测试样本文件和网络描述文件就可以实现模型转化。
生成测试样本文件:
还是在pycharm打开ai8x-training文件夹,首先需要进行测试样本生成,在终端中输入以下指令生成的测试样本用于模型转换的时候生成MAX78000的测试工程。生成测试样本的具体脚本如下:
python ./train.py --model ai85net_shenxiao --save-sample 10 --dataset shenxiao --evaluate --exp-load-weights-from ../ai8x-synthesis/trained/ai8x-shenxiao-qat8-q.pth.tar -8 --device MAX78000
测试样本生成的结果如下图所示:
图4-6 测试样本生成结果图
把生成的样本文件sample_shenxiao.npy移动到ai8x-synthesis/tests目录中去。
编写网络描述文件:
之后在pycharm打开ai8x-synthesis文件夹,在ai8x-synthesis/networks目录下新建一个文件shenxiao.yaml,指定编辑描述网络的yaml文件,该文件的编写方法可以参考:https://github.com/MaximIntegratedAI/MaximAI_Documentation/blob/master/Guides/YAML%20Quickstart.md,具体编辑内容如下:
---
# HWC (big data) configuration for Cats and Dogs image classification
arch: ai85net_shenxiao
dataset: shenxiao
# Define layer parameters in order of the layer sequence
layers:
- pad: 1
activate: ReLU
out_offset: 0x1000
processors: 0x0000000000000007
data_format: HWC
operation: Conv2d
streaming: true
- max_pool: 2
pool_stride: 2
pad: 1
activate: ReLU
out_offset: 0x2000
processors: 0x000ffff000000000
operation: Conv2d
streaming: true
- max_pool: 2
pool_stride: 2
pad: 1
activate: ReLU
out_offset: 0x0000
processors: 0x00000000ffffffff
operation: Conv2d
- max_pool: 2
pool_stride: 2
pad: 1
activate: ReLU
out_offset: 0x2000
processors: 0xffffffffffffffff
operation: Conv2d
- max_pool: 2
pool_stride: 2
pad: 1
activate: ReLU
out_offset: 0x0000
processors: 0x00000000ffffffff
operation: Conv2d
- pad: 1
activate: ReLU
out_offset: 0x2000
processors: 0xffffffff00000000
operation: Conv2d
- op: mlp
flatten: true
out_offset: 0x1000
output_width: 32
processors: 0x000000000000ffff
activate: None
得到了输入样本文件和网络描述文件后,就可以进行模型转换了。
在pycharm打开ai8x-synthesis文件夹,在终端输入以下代码即可实现模型转换。具体模型转换脚本如下:
python ./ai8xize.py --verbose --test-dir demos --prefix ai8x-shenxiao --checkpoint-file trained/ai8x-shenxiao-qat8-q.pth.tar --config-file networks/shenxiao.yaml --device MAX78000 --compact-data --mexpress --softmax --fifo --sample-input tests/sample_shenxiao.npy --overwrite
模型转换生成模型代码以及测试Demo工程的结果如下图所示:
图4-7 模型转换结果图
4.7 demo模型代码烧录
在进行上一步模型转换之后,可在ai8x-synthesis\demos\ai8x-shenxiao目录下找到自动生成的项目,该项目可以通过vscode直接下载到MAX78000中,当我们打开vscode,打开ai8x-synthesis\demos\ai8x-shenxiao目录,在电脑连接了MAX78000的情况下,按shift+ctrl+B,即可打开以下列表。如下如图所示:
图4-8 烧录列表图
其中clean是清理文件,build是生成文件,flash&run是烧录并运行程序,依次进行这三步,即可完成代码烧录,为将输入样本送给网络得到输出,并通过串口打印结果。
至此,我们得到了可以部署在MAX78000上的十二生肖模型,完成了十二生肖分类的任务。但该模型只会对固定的输入样本进行分类,不能实现我们所需要的现实中检测的功能。所以接下来就需要实现在现实中检测的功能。
4.8 编写图像采集代码
为实现能够在现实中进行十二生肖检测的功能,待分类的十二生肖图片应该由MAX78000的板载摄像头直接采集,而并非像之前的demo那样直接写进代码中,因此我们需要编写图像采集代码。图像采集代码主要参考了官方提供的例程cats-dogs_demo,该例程包含了相机模块初始化、拍照、图像处理和导入模型等步骤,正好符合要求。
我们首先把之前生成的ai8x-synthesis\demos\ai8x-shenxiao目录下的除了main.c和project.mk的文件全部复制,粘贴替换到MSDK\Examples\MAX78000\CNN\cats-dogs_demo目录下,再把cats-dogs_demo文件夹改名成ai8x-shenxiao。此时main.c中就包含了图像采集所需要的capture_process_camera()函数和cnn_load_input()函数,其中capture_process_camera()函数)负责逐行读取图像、将图像转换为0x00bbggrr格式提供给模型作为输入、将图像转换为RGB565格式提供给TFT显示屏模块进行显示等操作,cnn_load_input()函数负责把图像导入进模型中。
4.9 编写图像显示代码
为了实现在显示屏上显示图像,我们需要用vscode打开MSDK\Examples\MAX78000\CNN\ai8x-shenxiao文件夹,根据自己的模型对main.c,settings.json,project.mk进行更新与编写,具体更新代码如下所示:
//工程vscode配置文件 :vscode/settings.json
"target":"MAX78000",
"board":"FTHR_RevA",
//工程配置文件:project.mk
BOARD=FTHR_RevA
//主程序设置RESET、BLK控制引脚:main.c
#ifdef BOARD_FTHR_REVA
#ifdef ENABLE_TFT
/* Initialize TFT display */
mxc_gpio_cfg_t tft_reset_pin = {MXC_GPIO0, MXC_GPIO_PIN_19, MXC_GPIO_FUNC_OUT, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIOH};
mxc_gpio_cfg_t tft_blen_pin = {MXC_GPIO0, MXC_GPIO_PIN_9, MXC_GPIO_FUNC_OUT, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIOH};
MXC_TFT_Init(MXC_SPI0, 1, &tft_reset_pin, &tft_blen_pin);
// MXC_TFT_Init(MXC_SPI0, 1, NULL, NULL);
TFT_Feather_test();
#endif
#endif // #ifdef BOARD_FTHR_REVA
更新完成后,按照电路连线图连接MAX78000和显示屏,最后再和上步demo烧录过程一样,在vscode中打开MSDK\Examples\MAX78000\CNN\ai8x-shenxiao文件夹烧录即可。烧录结果如下:
图4-9 十二生肖检测模型烧录图
实现启动之后会显示作品信息,按下SW1开始启动十二生肖检测器识别摄像头采集到的图片中的生肖,软件采用实时刷新,摄像头会一直采集图像信息,再次按下SW1后会停止采集图像然后对当前图像进行检测,并通过LCD显示出现相似度最高的类别的生肖;相似率前五名的生肖会显示在LCD屏最右部分;再次按下SW1,摄像头会继续采集图像信息,并清除右侧的生肖相似率。
具体的main.c代码过长,便放置在文章末尾的整合包中。
4.9 硬件连接
本项目使用的显示屏为ILI9341驱动的TFT LCD显示屏,分辨率为240×320,使用SPI协议与MAX78000进行通讯。显示屏和MAX78000的具体连接方式如下图所示:
图4-10 电路连接图
5.实验结果展示:
6.遇到的问题以及解决方法:
6.1 GitHub网页加载错误
解决方法:使用科学上网
6.2 下载ai8x_training的支持包出错,没有Microsoft C++
图6-1 ai8x_training的支持包出错图
解决方法:打开红框中的网址:https://visualstudio.microsoft.com/zh-hans/visual-cpp-build-tools/,下载Microsoft C++生成工具,具体安装流程参考:https://blog.csdn.net/xianjianwu1/article/details/129908678
6.3 训练无后续,无法继续进行训练
图6-2 训练卡住无后续
解决方法:cpu和gpu的python第三方库有冲突,不要两个同时安装。重新安装虚拟环境即可。
6.4 无法点亮显示屏
解决方法:对main.c,settings.json,project.mk进行更新与编写,正确编写RESET,BLK引脚的相关代码,并对MAX78000和显示屏正确连线。
6.5 识别准确率问题
本次使用了多种网络模型进行十二生肖检测的训练,但是由于十二生肖中动物的种类和外观形象过多,导致训练效果都不太理想,此外由MAX78000板载摄像头所拍摄到的图片画面颜色相比数据集中的图片和实际画面有较大差异,清晰度也较差,导致模型有时无法准确识别拍摄图片中的生肖。
解决办法:调整网络架构,继续寻找更加适合十二生肖检测的模型,对MAX78000拍摄到的图像进行处理,可以使用直方图均衡等方法突出特征,便于模型检测。
7.总结
我在这次的比赛之中收益匪浅,这是我第一次使用嵌入式AI开发板,也是我第一次个人完整的进行全流程的ai训练与单片机运行。在人工智能领域中,我还是一个小白,虽然这次ai的训练成果不是非常理想,直到时间截至,我也依旧没有找到我想要的最佳检测结果,但是,在这次比赛中,我依旧被ai的魅力深深折服,我非常感谢官方提供的丰富板卡相关说明与例程,以及每一位参赛者在比赛中对我的帮助,没有这一双双援手,我无法走到最后一步,无法完成这次比赛,对此我再次表示我的感激之情。这次比赛,我看到了ai和单片机相互结合所产生的美妙火花,看到了单片机全新的未来,相信在未来,ai一定会越来越好,我也会继续努力,不断追赶时代前进的浪潮。
最后感谢电子森林,Maxim硬禾与ADI给予的这次机会,希望Maxim能够继续将边缘计算发扬光大,做大做强!