6.1.6.2. 分类模型训练

这篇教程主要是告诉大家如何利用HAT在 ImageNet 上训练一个state-of-art的浮点模型。 ImageNet 是图像分类里用的最多的数据集,很多最先进的图像分类研究都会优先基于这个数据集做好验证。 虽然有很多方法在社区或者其他途径里可以获取到 state-of-art 的分类模型,但从头训一个state-of-art的分类模型仍然不是一个简单的任务。 本篇教程将会重点讲叙从数据集准备开始如何在 ImageNet 上训练出一个state-of-art的模型,包括浮点、量化和定点三种模式。

其中 ImageNet 数据集可以从 ImageNet官网 进行下载。下载之后的数据集格式为:

ILSVRC2012_img_train.tar
ILSVRC2012_img_val.tar
ILSVRC2012_devkit_t12.tar.gz

这里我们使用 VargConvNet 的例子来详细介绍整个分类的流程。

6.1.6.2.1. 训练流程

如果你只是想简单的使用HAT的接口来进行简单的实验,那么首先阅读一下这一小节的内容是个不错的选择。 对于所有的训练和评测的任务,HAT统一采用 tools + config 的形式来完成。 在准备好原始数据集之后,通过以下的流程,我们可以方便的完成整个训练的流程。

6.1.6.2.1.1. 数据集准备

首先是数据集打包,打包数据集与原始数据集在处理速度上有明显的优势,这里我们选择与 PyTorch 一脉相承的 LMDB 的打包方法, 当然由于HAT在处理 dataset 上的灵活性,其他形式的数据集打包和读取形式,如 MXRecord 也是可以独立支持的。

tools/datasets 目录下提供了 cityscapesimagenetvocmscoco 这些常见数据集的打包脚本。 例如 imagenet2lmdb 的脚本,可以利用 torchvision 提供的默认公开数据集处理方法直接将原始的公开 ImageNet 数据 集转成 Numpy 或者 Tensor 的格式,最后将得到的数据统一用 msgpack 的方法压缩到 LMDB 的文件中。

这个过程可以很方便通过下面的脚本完成数据集打包:

python3 tools/datasets/imagenet_packer.py --src-data-dir ${src-data-dir} --target-data-dir ${target-data-dir} --split-name train --num-workers 10 --pack-type lmdb

python3 tools/datasets/imagenet_packer.py --src-data-dir ${src-data-dir} --target-data-dir ${target-data-dir} --split-name val --num-workers 10 --pack-type lmdb

在完成数据集打包之后,可以得到含有 ImageNetLMDB 数据集。下一步就可以开始训练。

6.1.6.2.1.2. 模型训练

以下以vargconvnet模型为例。在网络训练开始之前,你可以使用以下命令先测试一下网络的计算量和参数数量:

python3 tools/calops.py --config configs/classification/vargconvnet.py --input-shape "1,3,224,224"

准备打包好数据集之后,便可以开始训练模型。只需要运行下面的命令就可以启动训练:

python3 tools/train.py --step "float" --config configs/classification/vargconvnet.py

如果想要验证已经训练好的模型精度,运行下面的命令即可:

python3 tools/train.py --step float --config configs/classification/vargconvnet.py --val-ckpt float-checkpoint-best.pth.tar --val-only

如果想要导出onnx模型, 运行下面的命令即可:

python3 tools/export_onnx.py --config configs/classification/vargconvnet.py --ckpt float-checkpoint-best.pth.tar --onnx-name vargconvnet.onnx

由于HAT算法包使用了一种巧妙的注册机制,使得每一个训练任务都可以按照这种 train.py 加上 config 配置文件的形式启动。 train.py 是统一的训练脚本,与任务无关,我们需要训练什么样的任务、使用什么样的数据集以及训练相关的超参数设置都在指定的 config 配置文件里面。 config 文件里面提供了模型构建、数据读取等关键的 dict

6.1.6.2.1.3. 量化训练

关于量化训练中的关键步骤,比如准备浮点模型、算子替换、插入量化和反量化节点、设置量化参数以及算子的融合等,请阅读 量化感知训练 章节的内容。这里主要讲一下HAT的分类中如何定义和使用量化模型。

在模型准备的好情况下,包括量化已有的一些模块完成之后,HAT在训练脚本中统一使用下面的脚本将浮点模型映射到定点模型上来。

qconfig_manager.set_qconfig_mode(qconfig_manager.QconfigMode.QAT)
model.set_qconfig()
model = horizon.quantization.prepare_qat_fx(model)

量化训练的策略并不统一,这里简单描述分类模型训练中的常见策略。

量化训练的整体策略可以直接沿用浮点训练的策略,但学习率和训练长度需要适当调整。因为有浮点预训练模型,所以量化训练的学习率 Lr 可以很小, 一般可以从0.001或0.0001开始,并可以搭配 StepLrUpdater 做1-2次 scale=0.1Lr 调整;同时训练的长度不用很长。 此外 weight decay 也会对训练结果有一定影响。

6.1.6.2.1.4. 模型检查编译和仿真上板精度验证

对于HAT来说,量化模型的意义在于可以在 BPU 上直接运行。因此,对于量化模型的检查和编译是必须的。 前文提到的 compile_perf 脚本也可以让用户定义好量化模型之后,先检查能否在 BPU 上正常运行, 并可通过 align_bpu_validation 脚本获取模型上板精度。用法同前文。

6.1.6.2.1.5. 结果可视化

如果你希望可以看到训练出来的模型对于单张图片的检测效果,我们的tools文件夹下面同样提供了单张图片预测及可视化的脚本,你只需要运行以下脚本即可:

python3 tools/infer.py --config configs/classification/vargconvnet.py --dataset imagenet --input-size 224x224x3 --input-images ${img-path} --input-format yuv --is-plot