查看原文
其他

模型自动压缩工具实战:YOLOv7模型缩小75%,部署加速163%!

将AI进行到底的 百度AI 2022-12-19


众所周知,YOLO 系列算法在检测场景中获得了广泛应用,但是工程师追求“更准、更小、更快”的效率能力永无止境。本文为大家介绍一个低成本、高收益的 AI 模型自动压缩工具(ACT, Auto Compression Toolkit),在 YOLO 系列模型上利用基于知识蒸馏的量化训练方法,无需修改训练源代码,通过几十分钟量化训练,即可获得非常好的收益。举例来看:该方法在 YOLOv7 上模型体积降低75%,GPU 上推理速度可提升163%。


图1 自动压缩工具在 YOLO 系列模型上的模型压缩和速度提升


【测试环境与补充说明】


1、测试数据与指标:mAP 的指标均在 COCO val2017 数据集中评测得到。

2、测试环境:Tesla T4 的 GPU 环境下开启 TensorRT 8.4.1,batch_size=1 测试获取

3、测试模型输入图像尺寸:640*640;

注:YOLOv6 原论文精度 Baseline 是 mAP43.1%,由于模型导出是固定 shape,所以导成 ONNX 后有掉点(-0.7%),实测精度42.4%;YOLOv7 在原论文 Baseline mAP 51.2%,导成 ONNX 后实测精度51.1%。


本文将从以下五个方面进一步技术解读,全文大约2300字,预计阅读时长3分钟。


  • 模型自动压缩工具-动机和思考
  • 模型自动压缩工具-量化蒸馏训练技术解析
  • 模型自动压缩工具-量化蒸馏训练技术实战(以 YOLOv7 为例)
  • 模型自动压缩工具-推理部署
  • 未来工作展望


传送门:

https://github.com/PaddlePaddle/PaddleSlim/tree/develop/example/auto_compression/pytorch_yolo_series


 模型自动压缩工具 


动机与思考


模型量化是提升模型推理速度的手段之一,实际使用中有如下几点困难:


▌模型参数分布不均匀,导致量化误差大


过度训练是导致参数分布不均匀的原因之一。例如在 YOLOv6s 迭代过程中,为了让模型更好地收敛,通常需要延长模型训练周期。但随之也会带来一些隐患,比如模型在 COCO 数据集上出现了过拟合,某些层的数值分布极端化,这些状况增加了量化的噪声,我们分析了 YOLOvs6 每层 Conv 的量化精度,发现某些层精度下降的特别严重,由此导致了 YOLOv6s 模型离线量化后在验证集上的精度下降了10%,无法达到业务要求。


图2 YOLOv6s 卷积层量化损失评估


我们对比分析了 YOLOv6s 的权重分布情况,发现量化损失较小的层数值分布相对平稳,数值处于-0.25到0.25之间,而量化损失较大的层数值分布非常极端,绝大部分值趋近于0,且数值处于-0.1到0.1之间,尽管看上去都是正太分布,但大量数值为0不利于量化统计 scale 值。


图3 权重数值分布对比


任务复杂度高,模型精度受量化误差的影响大


任务复杂度越高,模型量化带来的精度损失越大。目标检测融合了目标定位和目标分类两种任务,整体的复杂度相对较高,因此它的精度受量化的影响更大。普通的离线量化无法改变模型激活值的数值分布,只会让量化 scale 适应该分布。遇到数值分布不均匀的激活值,离线量化的量化误差会很大。


▌量化训练需修改训练代码,难度大,技术门槛高


相比离线量化(Post Training Quantization),量化训练能减少离线量化的精度掉点程度。量化训练方法在训练过程中,可以不断地调整激活的数值分布,使激活的分布更适合量化。但是,量化训练使用成本比较高,体现在以下两方面:


  • 一方面是人力成本高:为了实现量化训练,需要修改模型的组网和训练代码,插入模拟量化操作;

  • 另一方面时间成本高:训练时需要加载完整训练集做训练。


量化蒸馏训练技术解析


本文介绍的自动压缩工具(ACT)针对 YOLO 系列模型,利用知识蒸馏技术,自动为推理模型添加训练逻辑;无需修改训练代码,仅拿训练好的模型和部分无标注数据,训练几十分钟,即可达到预期效果。具体步骤包括如下3步,详细过程如下图所示。


▌构造教师模型


加载推理模型文件,并将推理模型在内存中复制一份,作为知识蒸馏中的教师模型,待量化模型则作为学生模型。


▌添加loss


自动地分析模型结构,寻找适合添加蒸馏 loss 的层,一般是最后一个带可训练参数的层。比如,检测模型 head 有多个分支的话,会将每个 head 最后一个 conv 作为蒸馏节点。


▌蒸馏训练


教师模型通过蒸馏 loss 监督原模型的稀疏训练或量化训练,完成模型压缩的过程。



ACT 还支持更多功能,包括离线量化超参搜索、算法自动组合和硬件感知等。功能详情以及 ACT 在更多场景的应用,请参加自动压缩工具首页介绍。


近期我们会将自动压缩代码提到 YOLOv5、YOLOv6、YOLOv7、PP-YOLOE 的官方 repo 中,这样大家在原模型项目中也可使用该能力。


 量化蒸馏训练技术实战(以 YOLOv7 为例)


准备预测模型 导出 ONNX 模型。


git clone https://github.com/WongKinYiu/yolov7.git
cd yolov7
python export.py --weights yolov7-tiny.pt --grid

准备训练数据&定义 DataLoader

准备 COCO 或者 VOC 格式的数据。定义数据预处理模块,其中,数据预处理Reader的设置如下:

class COCOValDataset(paddle.io.Dataset):
    def  __init__(self, 
                 dataset_dir=None,
                 image_dir=None,
                 anno_path=None,
                 img_size=[640, 640])
:
        self.dataset_dir = dataset_dir
        self.image_dir = image_dir
        self.img_size = img_size
        self.ann_file = os.path.join(dataset_dir, anno_path)
        self.coco = COCO(self.ann_file)
        self.ids = list(sorted(self.coco.imgs.keys()))

    def __getitem__(self, idx):
        img_id = self.ids[idx]
        img = self._get_img_data_from_img_id(img_id)
        img, scale_factor = self.image_preprocess(img, self.img_size)
        return {'image': img, 'im_id': np.array([img_id]), 'scale_factor': scale_factor}

    def __len__(self):
        return len(self.ids)

定义评估接口
为了在压缩过程中实时评估量化模型的精度,需要定义一个 eval_function 来做模型推理效果评估。这一步是可选的,如果没有 eval_function 也不会影响量化训练的过程。
def eval_function(exe, compiled_test_program, test_feed_names, test_fetch_list):
    bboxes_list, bbox_nums_list, image_id_list = [], [], []
    for data in val_loader:
        data_all = {k: np.array(v) for k, v in data.items()}
        outs = exe.run(compiled_test_program,
                       feed={test_feed_names[0]: data_all['image']},
                       fetch_list=test_fetch_list,
                       return_numpy=False)
        postprocess = YOLOv7PostProcess(
            score_threshold=0.001, nms_threshold=0.65, multi_label=True)
        res = postprocess(np.array(outs[0]), data_all['scale_factor'])
        bboxes_list.append(res['bbox'])
        bbox_nums_list.append(res['bbox_num'])
        image_id_list.append(np.array(data_all['im_id']))
    map_res = coco_metric(anno_file, bboxes_list, bbox_nums_list, image_id_list)
    return map_res[0]
定义配置文件

定义量化训练的配置文件,Distillation 表示蒸馏参数配置,Quantization 表示量化参数配置,TrainConfig 表示训练时的训练轮数、优化器等设置。具体超参的设置可以参考 ACT 超参设置文档。

Distillation: # 蒸馏参数设置
  alpha: 1.0 # 蒸馏loss所占权重
  loss: soft_label

Quantization:  # 量化参数设置
  use_pact: true  # 是否使用PACT量化算法
  activation_quantize_type: 'moving_average_abs_max'   # 激活量化方式,选择'moving_average_abs_max'即可
  quantize_op_types:   # 需要量化的OP类型,可以是conv2d、depthwise_conv2d、mul、matmul_v2等
  - conv2d
  - depthwise_conv2d

TrainConfig:   # 训练的配置
  train_iter: 3000   # 训练的轮数
  eval_iter: 1000    # 训练中每次评估精度的间隔轮数
  learning_rate: 0.00001  # 训练学习率
  optimizer_builder:  # 优化器设置
    optimizer: 
      type: SGD
    weight_decay: 4.0e-05
开始运行
少量代码就可以开始 ACT 量化训练。启动 ACT 时,需要传入模型文件的路径(model_dir)、模型文件名(model_filename)、参数文件名称(params_filename)、压缩后模型存储路径(save_dir)、压缩配置文件(config)、dataloader 和评估精度的 eval_callback。

‍from paddleslim.auto_compression import AutoCompression
ac = AutoCompression(
        model_dir=global_config["model_dir"],
        model_filename=global_config["model_filename"],
        params_filename=global_config["params_filename"],
        save_dir=FLAGS.save_dir,
        config=all_config,
        train_dataloader=train_loader,
        eval_callback=eval_function)
ac.compress()
以上是精简后的关键代码,如果想快速体验,可以根据下方链接中的示例文档及代码进行体验:
https://github.com/PaddlePaddle/PaddleSlim/tree/develop/example/auto_compression/pytorch_yolo_series

训练完成后会在 save_dir 路径下产出 model.pdmodel 和 model.pdiparams 文件。至此,完成了模型训练压缩工作,推理部署参考下一节内容。

推理部署

完成量化训练后的模型,支持 Paddle Inference TensorRT 部署(以下简称Paddle TensorRT)。

在 YOLO 系列模型上测试, Paddle TensorRT 的性能与直接使用 TensorRT 基本持平,如下图所示(在 YOLOv5s、PP-YOLOE-s、YOLOv7 上,Paddle TensorRT 性能优于 TensorRT),相关推理部署代码已经集成到了自动压缩工具开源项目,可以直接下载体验。

图4 YOLO 系列模型在 Paddle TensorRT 和 TensorRT 上的速度对比
# FP32
./build/trt_run --model_file yolov7_infer/model.pdmodel --params_file yolov7_infer/model.pdiparams --run_mode=trt_fp32
# FP16
./build/trt_run --model_file yolov7_infer/model.pdmodel --params_file yolov7_infer/model.pdiparams --run_mode=trt_fp16
# INT8
./build/trt_run --model_file yolov7_quant/model.pdmodel --params_file yolov7_quant/model.pdiparams --run_mode=trt_int8
⭐Star 收藏⭐
这么好的项目,欢迎大家点 star 鼓励并前来体验!

https://github.com/PaddlePaddle/PaddleSlim/tree/develop/example/auto_compression/pytorch_yolo_series

未来工作展望

ACT 自动化压缩工具将支持更多 AI 模型的压缩;支持 YOLO 系列模型剪枝、非结构化稀疏等压缩方法;升级 ACT 能力,加入更多前沿压缩算法;支持完善更多部署方法,包括 ONNX Runtime、OpenVINO 等,进一步助力 AI 模型工程落地。

 直播预告 

想了解 YOLO 系列模型压缩策略,了解更多自动压缩工具的算法和能力,快快扫码加群关注我们的直播间吧!

直播时间:2022.08.22(周一)19:00-20:00。
欢迎大家扫码报名!


项目地址
  • GitHub:
https://github.com/PaddlePaddle/PaddleSlim
  • Gitee:
https://gitee.com/paddlepaddle/PaddleSlim

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存