【Vitis AI】 Vitis AI 通过迁移学习训练自定义模型
测评计划:
一、开箱报告,KV260通过网线共享PC网络
二、Zynq超强辅助-PYNQ配置,并使用XVC(Xilinx Virtual Cable)调试FPGA逻辑
三、硬件加速之—使用PL加速FFT运算(Vivado)
四、硬件加速之—使用PL加速矩阵乘法运算(Vitis HLS)
五、Vitis AI 构建开发环境,并使用inspector检查模型
六、Vitis AI 进行模型校准和来量化
七、Vitis AI 通过迁移学习训练自定义模型
八、Vitis AI 将自定义模型编译并部署到KV260中
本文目的
使用迁移学习的方法,将预训练的resnet18模型从原来的1000类分类任务,改造为适应自定义的30类分类任务。
ResNet18介绍
ResNet18是一种基于深度残差网络(ResNet)的卷积神经网络模型,由何凯明等人于2015年提出。ResNet的核心思想是通过引入残差块(Residual Block),解决了深度网络中的梯度消失和退化问题,使得网络可以更深更有效地学习特征。
ResNet18是ResNet系列中最简单的一个模型,共有18层,其中包括:
迁移学习
根据不同的任务和数据集,迁移学习有以下几种常见的方法:
首先导入所需的模块:
#!pip install -i <https://pypi.tuna.tsinghua.edu.cn/simple> torchsummary
# torchsummary是一个用于查看网络结构,非必须
from torchsummary import summary
import torch, torchvision, random
from pytorch_nndct.apis import Inspector, torch_quantizer
import torchvision.transforms as transforms
from torchvision import models
from tqdm import tqdm
然后导入预训练模型,并查看网络结构:
model = models.resnet18(pretrained=True) # 载入预训练模型
summary(model, (3, 224, 224))
---以下为执行结果
----------------------------------------------------------------
Layer (type) Output Shape Param #
================================================================
Conv2d-1 [-1, 64, 112, 112] 9,408
BatchNorm2d-2 [-1, 64, 112, 112] 128
ReLU-3 [-1, 64, 112, 112] 0
MaxPool2d-4 [-1, 64, 56, 56] 0
Conv2d-5 [-1, 64, 56, 56] 36,864
BatchNorm2d-6 [-1, 64, 56, 56] 128
ReLU-7 [-1, 64, 56, 56] 0
Conv2d-8 [-1, 64, 56, 56] 36,864
BatchNorm2d-9 [-1, 64, 56, 56] 128
ReLU-10 [-1, 64, 56, 56] 0
BasicBlock-11 [-1, 64, 56, 56] 0
Conv2d-12 [-1, 64, 56, 56] 36,864
BatchNorm2d-13 [-1, 64, 56, 56] 128
ReLU-14 [-1, 64, 56, 56] 0
Conv2d-15 [-1, 64, 56, 56] 36,864
BatchNorm2d-16 [-1, 64, 56, 56] 128
ReLU-17 [-1, 64, 56, 56] 0
BasicBlock-18 [-1, 64, 56, 56] 0
Conv2d-19 [-1, 128, 28, 28] 73,728
BatchNorm2d-20 [-1, 128, 28, 28] 256
ReLU-21 [-1, 128, 28, 28] 0
Conv2d-22 [-1, 128, 28, 28] 147,456
BatchNorm2d-23 [-1, 128, 28, 28] 256
Conv2d-24 [-1, 128, 28, 28] 8,192
BatchNorm2d-25 [-1, 128, 28, 28] 256
ReLU-26 [-1, 128, 28, 28] 0
BasicBlock-27 [-1, 128, 28, 28] 0
Conv2d-28 [-1, 128, 28, 28] 147,456
BatchNorm2d-29 [-1, 128, 28, 28] 256
ReLU-30 [-1, 128, 28, 28] 0
Conv2d-31 [-1, 128, 28, 28] 147,456
BatchNorm2d-32 [-1, 128, 28, 28] 256
ReLU-33 [-1, 128, 28, 28] 0
BasicBlock-34 [-1, 128, 28, 28] 0
Conv2d-35 [-1, 256, 14, 14] 294,912
BatchNorm2d-36 [-1, 256, 14, 14] 512
ReLU-37 [-1, 256, 14, 14] 0
Conv2d-38 [-1, 256, 14, 14] 589,824
BatchNorm2d-39 [-1, 256, 14, 14] 512
Conv2d-40 [-1, 256, 14, 14] 32,768
BatchNorm2d-41 [-1, 256, 14, 14] 512
ReLU-42 [-1, 256, 14, 14] 0
BasicBlock-43 [-1, 256, 14, 14] 0
Conv2d-44 [-1, 256, 14, 14] 589,824
BatchNorm2d-45 [-1, 256, 14, 14] 512
ReLU-46 [-1, 256, 14, 14] 0
Conv2d-47 [-1, 256, 14, 14] 589,824
BatchNorm2d-48 [-1, 256, 14, 14] 512
ReLU-49 [-1, 256, 14, 14] 0
BasicBlock-50 [-1, 256, 14, 14] 0
Conv2d-51 [-1, 512, 7, 7] 1,179,648
BatchNorm2d-52 [-1, 512, 7, 7] 1,024
ReLU-53 [-1, 512, 7, 7] 0
Conv2d-54 [-1, 512, 7, 7] 2,359,296
BatchNorm2d-55 [-1, 512, 7, 7] 1,024
Conv2d-56 [-1, 512, 7, 7] 131,072
BatchNorm2d-57 [-1, 512, 7, 7] 1,024
ReLU-58 [-1, 512, 7, 7] 0
BasicBlock-59 [-1, 512, 7, 7] 0
Conv2d-60 [-1, 512, 7, 7] 2,359,296
BatchNorm2d-61 [-1, 512, 7, 7] 1,024
ReLU-62 [-1, 512, 7, 7] 0
Conv2d-63 [-1, 512, 7, 7] 2,359,296
BatchNorm2d-64 [-1, 512, 7, 7] 1,024
ReLU-65 [-1, 512, 7, 7] 0
BasicBlock-66 [-1, 512, 7, 7] 0
AdaptiveAvgPool2d-67 [-1, 512, 1, 1] 0
Linear-68 [-1, 1000] 513,000
================================================================
Total params: 11,689,512
Trainable params: 11,689,512
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.57
Forward/backward pass size (MB): 62.79
Params size (MB): 44.59
Estimated Total Size (MB): 107.96
----------------------------------------------------------------
可以原始看到最后一层有1000个特征输出,对应1000分类。我们要做的,就是使用特征提取方法,修改最后一层(FC),实现一个30分类的特征输出。
修改全链接层,然后查看修改结果:
print('Original output layer:')
print(model.fc)
#输入特征数(in_features)保持不变,输出特征数(out_features)设置为10
model.fc = torch.nn.Linear(model.fc.in_features, 30)
print('New output layer:')
print(model.fc)
---以下为执行结果
Original output layer:
Linear(in_features=512, out_features=1000, bias=True)
New output layer:
Linear(in_features=512, out_features=30, bias=True)
配置优化器,只微调输出层(FC),然后执行训练:
# 只微调训练最后一层全连接层的参数,其它层冻结
optimizer = optim.Adam(model.fc.parameters())
# 遍历每个 EPOCH
for epoch in tqdm(range(EPOCHS)):
model.train()
for images, labels in train_loader: # 获取训练集的一个 batch,包含数据和标注
images = images.to(device)
labels = labels.to(device)
outputs = model(images) # 前向预测,获得当前 batch 的预测结果
loss = criterion(outputs, labels) # 比较预测结果和标注,计算当前 batch 的交叉熵损失函数
optimizer.zero_grad()
loss.backward() # 损失函数对神经网络权重反向传播求梯度
optimizer.step() # 优化更新神经网络权重
---以下为执行结果
100%|██████████| 20/20 [03:04<00:00, 9.24s/it]
在测试集的准确度为:85.900 %
注:本文不详解如何构建数据集加载器,以及测试部分相关代码,只保留关键代码以演示使用迁移学习过程,需要读者自行补齐机器学习相关知识。
导出迁移学习后的结果模型:
torch.save(model, 'resnet18_out30.pth')
将在当前工作目录下,生成resnet18_out30.pth文件。
量化配置文件
这些参数是量化配置文件的重点,下面作详细解释:
全局量化设置的部分:
量化参数的部分:
Vitis AI默认的量化配置:
"convert_relu6_to_relu": 关闭,
"include_cle": 启用,
"keep_first_last_layer_accuracy": 关闭,
"keep_add_layer_accuracy": 关闭,
"include_bias_corr": 开,
"target_device": "DPU",
"quantizable_data_type": ["input", "weights", "bias", "activation"],
"bit_width": 8,
"method": "diffs",
"round_mode": "std_round",
"symmetry": 启用,
"per_channel": 关闭,
"signed": 启用,
"narrow_range": 关闭,
"scale_type": "power_of_two",
"calib_statistic_method": "modal"
配置完毕后,需要按照上一讲的内容,进行校准和量化:
【KV260视觉入门套件试用体验】Vitis AI 进行模型校准和来量化
https://bbs.elecfans.com/jishu_2383101_1_1.html
config_file= "./int8_config.json"
quantizer= torch_quantizer(quant_mode=quant_mode,
module=model,
input_args=(input),
device=device,
quant_config_file=config_file)
唯一的不同,是以上代码部分需要引用新配置的json文件。
模型编译:
vai_c_xir -x /PATH/TO/quantized.xmodel \\\\
-a /PATH/TO/arch.json \\\\
-o /OUTPUTPATH \\\\
-n netname
编译模型,只需这一条指令。
附:查看支持的型号
!ls -l /opt/vitis_ai/compiler/arch/
---
total 24
drwxr-xr-x 4 root root 4096 Jun 12 2022 DPUCADF8H
drwxr-xr-x 8 root root 4096 Jun 12 2022 DPUCAHX8H
drwxr-xr-x 5 root root 4096 Jun 12 2022 DPUCAHX8L
drwxr-xr-x 3 root root 4096 Jun 12 2022 DPUCVDX8G
drwxr-xr-x 6 root root 4096 Jun 12 2022 DPUCVDX8H
drwxr-xr-x 5 root root 4096 Jun 12 2022 DPUCZDX8G
附:查看DPUCZDX8G支持的板卡
!ls -l /opt/vitis_ai/compiler/arch/DPUCZDX8G
---
total 12
drwxr-xr-x 2 root root 4096 Jun 12 2022 KV260
drwxr-xr-x 2 root root 4096 Jun 12 2022 ZCU102
drwxr-xr-x 2 root root 4096 Jun 12 2022 ZCU104
执行完毕编译过程,就可以在对应目录中得到*.xmodel文件了~
总结
本文主要介绍使用Vitis AI工具创建自定义的Xmodol,难点并不在工具本身,而是需要了解很多机器学习的知识。一个很好的出发点是使用Vitis Model Zoo库,是一个包含了大量预训练模型的资源库,这些模型涵盖了多种AI应用领域,如图像分类、目标检测、语义分割、人脸识别、自然语言处理等。我们可以利用这些模型作为一个起点,快速入门并开发自己的应用。这些是由Xilinx官方提供的经过优化和验证的模型,可以直接在Xilinx硬件平台上部署和运行。在熟悉自己的业务的需求,并建立数据集后,我们可以定制的模型。
下一讲,我们使用自定义的模型运行在KV260的DPU上,并进行适当的后处理。
更多回帖