通用目標檢測開源框架YOLOv6在美團的量化部署實戰

語言: CN / TW / HK

基於美團目標檢測模型開源框架 YOLOv6,本文提供了一種通用的量化部署方案,在保持精度的同時大幅提升了檢測的速度,為通用檢測的工業化部署探索出一條可行之路,希望能給大家帶來一些啟發或者幫助。

1. 背景和難點

YOLOv6 是美團釋出的一款開源的面向工業應用的 2D 目標檢測模型 [1],主要特點是速度快、精度高、部署友好,在美團眾多視覺業務場景中都有著廣泛的應用。通過量化(Quantization)提升推理速度是實際工業應用中的基本操作,但由於 YOLOv6 系列模型採用了大量的重引數化模組,如何針對 YOLOv6 進行高效和高精度的量化成為一個亟待解決的問題。本文旨在解決 YOLOv6 量化方面的難題,並以 YOLOv6s 模型為例,從訓練後量化(Post-Training Quantization, PTQ)和量化感知訓練(Quantization-Aware Training, QAT)兩個方面進行分析,探索出了一條切實可行的量化方案。

YOLOv6 採用了多分支的重引數化結構 [2](如圖 1A 所示),通過在網路結構層面加入人工先驗可以在訓練階段讓模型更好收斂。在推理階段,多分支可以等價合併為單路,從而提升執行速度。但現有的訓練後量化方法,不能很好應對多分支結構帶來的劇烈變動的數值範圍,導致量化後產生嚴重的精度損失 [3]。另外,如何針對多分支結構設計量化感知訓練(QAT)方法也面臨著較大的挑戰。蒸餾常被用來輔助 QAT 提升效能,但如何應用 2D 目標檢測的蒸餾方法來輔助 YOLOv6 模型的量化,也需要設計合理的方案在實際應用中進行檢驗。

圖1 多分支結構重引數化過程(A)結構變化(B)引數變化 (來源:[2])

2. 量化方案實戰

2.1 重引數化優化器

YOLOv6 網路中大量使用重引數化結構,在提高模型訓練精度的同時能夠顯著降低模型部署推理延時,但也帶來了模型量化部署方面的難題。對重引數化網路的直接量化一般會帶來不可接受的精度損失,例如 RepVGG-B1 [2] 網路在 ImageNet 資料集上的浮點精度為 78.42%,採用 TensorRT 後量化(PTQ)的量化模型精度則降低為 54.55%。

此外,由於重引數化結構在訓練和部署時結構不同,因此無法直接適配現有的量化感知訓練(QAT)方法,如何使用 QAT 方法來提高 YOLOv6 量化模型的精度,同樣存在著挑戰。近期,一篇重引數化優化器的工作 RepOpt [3] 較好地解決了重引數化結構的量化問題。

2.1.1 RepOpt

RepOpt [3] 對重引數化結構量化困難的問題進行了研究,發現重引數結構的分支融合操作,顯著放大了權重引數分佈的標準差。異常的權重分佈產生了過大的網路啟用層數值分佈,進一步導致該層量化損失過大,因此模型精度損失嚴重。

鑑於此,我們統計了基於 RepVGG 結構的 YOLOv6 模型(YOLOv6s_repvgg)各層的權重及啟用數值分佈,分析了 YOLOv6 中的重引數化層的資料分佈。下圖 2 以 “Rep_p4.block.0.rbr_reparam” 層為例,給出其特徵圖數值分佈直方圖,我們發現其數值廣泛分佈在 [0, 57] 的區間內。顯然,採用現有的 INT8 量化方法,無論怎樣選擇量化縮放參數 (scale),都會產生較大的量化誤差。

圖2 YOLOv6 網路使用 RepVGGBlock 和 RepOptBlock 版本的單層啟用值資料分佈

為解決這一問題,RepOpt 提出了一種基於優化器的重引數化設計(如下圖 3 所示),通過梯度掩碼(Gradient Mask)的方式在網路訓練反向傳播的過程中加入先驗,保證了訓練精度可達到 RepVGG 相近的水平,而網路結構則在訓練和推理階段始終保持普通的 VGG 結構,這種訓練方法請參考 RepOpt [3]。該工作中提出的 RepOpt-B1 網路模型,在浮點精度與 RepVGG-B1基本一致的情況下,量化模型精度提升超過 20%,極大地改善了重引數化網路的量化掉點問題。此外,RepOpt模型的訓練速度快,記憶體佔用也比較低。

圖3 RepVGG 和 RepOpt 結構示意圖

2.1.2 RepOpt 版本的 PTQ

我們實現了 RepOpt 版本的 YOLOv6s網路(YOLOv6s_repopt),達到了與 YOLOv6s_repvgg 一致的浮點精度 42.4%(300 epochs),兩個版本的網路結構在部署階段保持一致。我們首先分析了 YOLOv6s_repopt 模型的資料分佈特徵。

如圖 2 所示,給出了“Rep_p4.block.0.rbr_reparam” 層的特徵圖數值分佈直方圖,可以看到數值緊密分佈在 [0, 10] 的區間內,相比 YOLOv6s_repvgg 的數值分佈對於量化操作更加友好。進一步採用 TRT 的後量化方法進行模型量化部署,可以看到 YOLOv6s_repvgg 的量化網路精度降低了 7.4%,在實際工程中基本不可用。而 YOLOv6s_repopt 網路的量化模型精度為 40.9%,精度損失僅為 1.5%,相比原版模型有了極大的改善。

表1 使用 RepOpt 在標準分類和檢測任務上的 INT8 精度提升

2.1.3 RepOpt 版本的 QAT

此外,使用 RepOpt 結構解決了原本的 RepVGG 網路無法直接使用現有量化感知訓練的問題。對於結構重引數化的 RepVGG 網路,如何使用 QAT 來恢復量化模型精度,我們一直存有困擾。如下圖 4(左)所示,如果對重引數化操作之前的多分支網路進行 QAT,對每個分支分別新增偽量化運算元進行量化感知訓練,由於每個分支的量化引數不同,導致多分支結構無法等效融合進行高效能部署;如果對重引數化操作之後的單分支網路進行 QAT, 由於網路中不再有 BN 層,使用 QAT 方法進行微調並不容易恢復到浮點精度。而對於 RepOpt 結構網路則不存在這一問題,因為 RepOpt 在訓練和部署中網路結構是保持一致的。

圖4 RepVGG 和 RepOpt 結構的 QAT 過程示意圖

如圖 4 (右)所示,對 RepOpt 的卷積等運算元加入偽量化節點進行量化感知訓練,提升量化模型精度,然後直接部署該量化模型,而不需要再進行模型融合的操作。後文,我們將給出具體的 QAT 演算法及對模型精度的提升結果。

2.2 基於量化敏感度分析的部分量化

YOLOv6s_repopt 在 PTQ 後的 mAP 達到了 40.9%,雖然比之前的 35.0% 有了很大的改善,但仍然有 1.5% 的精度損失,還無法滿足業務需求。因此,我們採用了部分量化(Partial PTQ),一種使網路中的部分量化敏感層恢復浮點計算,來快速恢復量化模型精度的方法。首先需要對網路中的每一層都進行量化敏感度分析。

我們在 YOLOv6s-repopt 網路上對常用的敏感度分析方法均方誤差(MSE)、信噪比(SNR)、餘弦相似度(Cosine Similarity)進行了對比測試。量化校準(calibration)測試使用 4 個 batch 的資料,敏感度計算用 1 個 batch,batch 大小設定為 32。

測試時,每次只對一層進行量化,獲取該層的啟用資料後計算敏感度數值,代表了該層的量化敏感度。作為對比,我們可以直接計算網路在 COCO val 資料集上的 mAP,使用檢測精度作為該層的量化敏感度,即檢測精度越高,該層敏感度越低(下文稱為 mAP 方法)。

表2  常用的量化敏感度計算方法及含義

測試結果如下圖 5 所示,我們對測試結果進行歸一化後,從不同敏感度分析結果中選擇敏感性最高的 6 層跳過,計算部分量化精度。

圖5 YOLOv6s_repopt 各層敏感度對比

部分量化精度如下表 3 所示,可以看到:mAP 方法取得了最好的效果,能夠有效代表 YOLOv6 敏感度分析結果。但由於 mAP 方法需要頻繁地計算驗證集精度,耗時太久且容易過擬合驗證集,因此在實際專案中為了追求效率,我們建議使用 MSE 方法。

表3 使用不同量化敏感指標得到的 Top-6 敏感層及部分量化精度對比

2.3 基於通道蒸餾的量化感知訓練

至此,我們優化後的 PTQ 的精度達到了 42.0%,進一步提高模型精度需要引入量化感知訓練( QAT)。量化感知訓練(Quantization Aware Training, QAT)可以改善 PTQ 量化精度損失,通過在訓練過程中對卷積等運算元加入偽量化操作(如圖 4 所示),使得網路引數能更好地適應量化帶來的資訊損失,從而顯著降低量化後的精度損失。

模型蒸餾作為一種有效的提升小模型精度的方法,在 QAT 過程中被廣泛使用,來提升量化模型的精度。以下,我們將探索針對 YOLOv6 網路的量化感知訓練方法。

2.3.1 通道蒸餾

傳統的分類網路在蒸餾時,往往對最後一層輸出的 logits 進行蒸餾;但是在檢測網路中一般採用“特徵圖”蒸餾的方法,直接讓學生網路(student)輸出的特徵圖擬合教師網路(teacher)輸出的特徵圖(一般不會選取整個特徵圖,而是一些感興趣區域)。

這種方法的缺陷是特徵圖中的每個 pixel 對蒸餾的損失貢獻相同。我們採用了每通道分佈蒸餾 [6],即讓 student 輸出的每個通道的分佈擬合 teacher 輸出的每個通道的分佈。兩種方法的區別如下圖 6 所示:

圖6 使用空間維度蒸餾和通道維度蒸餾的對比示意

2.3.2 YOLOv6 量化感知蒸餾框架

針對 YOLOv6s,我們選擇對 Neck(Rep-PAN)輸出的特徵圖進行通道蒸餾(channel-wise distillation, CW)。另外,我們採用“自蒸餾”的方法,教師模型是 FP32 精度的 YOLOv6s,學生模型是 INT8 精度的 YOLOv6s。下圖 7 是一個簡化示意圖,只畫出了 Neck 的一個分支:

圖7 應用於 YOLOv6s 的通道蒸餾方案示意圖

如下表 4 所示,在 Partial QAT 中引入通道蒸餾方案(CW),量化精度進一步提升了 0.3%。

表4 Partial QAT 使用通道蒸餾提升對比

3. 部署時優化

3.1 圖優化

量化部署時,可以直接利用 TensorRT 的 PTQ 介面進行生成量化引擎,但是這種方法往往精度損失較大。因此,一般要先進行 QAT,使量化模型精度滿足業務需求,然後匯出帶有“Quant”、“DeQuant”節點的 ONNX,最後再利用 TensorRT 構建量化引擎。我們發現這兩種方案最終生成的圖結構並不相同,導致部署模型的實際執行效率存在很大的差異,通常 QAT 方法生成的模型效率更低。

我們在 NVIDIA T4 機器上對量化模型進行了對比測試(見下表 5)。儘管 QAT INT8 模型的 QPS 比 FP16 高了~27%,但是離 PTQ INT8 還有較大差距。我們對此現象進行了細緻的分析,發現原因是 QAT 引入的“Quant”,“DeQuant”節點打破了原有 TensorRT 的融合策略,導致了很多運算元無法融合,從而影響了最終量化引擎的效能。在這一節中,我們以 YOLOv6s_repopt 為例,展示一種定位具體瓶頸的圖優化方法。在量化實踐中,圖優化是一個很實用的手段,我們可以依法炮製,提升模型的 QPS。

表5 PTQ 和 QAT 模型的 QPS 對比

3.1.1 效能分析

首先,我們利用 nsys 工具 [5] 對 QAT INT8 的模型和 PTQ INT8 模型進行了效能分析,如下表所示:

表6 PTQ/QAT 節點的 Kernel 執行時間分析

從中我們發現,QAT INT8 有 10.8% 的 kernel 執行了 permutationKernelPLC3 操作,這些操作對應 quantize_scale_node 節點,如下圖 8 所示:

圖8 permutationKernelPLC3 操作定位

3.1.2 圖結構分析

為什麼 QAT INT8會有大量的 permutationKernelPLC3 操作?我們利用 trtexec 和 pltEngine 工具,畫出了 PTQ INT8 和 QAT INT8 的計算圖,並進行了仔細的分析。下圖 9 是其中一個子圖的對比:

圖9 PTQ 與 QAT 子圖區別

QAT INT8 計算圖中 neck.reduce_layer1.conv 融合節點輸出精度是 FP32,並且跟了 2 個 quantize_scale_node 節點,而 PTQ INT8 圖中的 neck.reduce_layer1.conv 融合節點輸出的是 INT8。很顯然,QAT 圖中 FP32 和 INT8 之間的轉換會帶來額外的開銷。我們又利用 Netron 來分析 QAT INT8 的 ONNX 圖結構,找到了 neck.reduce_layer1.conv 這個位置,圖 10 給出該節點示意。

圖10 因 Scale 不同而產生了雙分支

通過分析 ONNX 圖結構,我們發現了QAT INT8 引擎中 neck.reduce_layer1.conv 輸出為 FP32,並且為兩個分支保留了quantize_scale_node 的原因。因為 neck.upsample1.upsample_transpose 分支的輸入量化 scale 為 0.083,而 neck.Rep_n3.conv1 分支的輸入量化 scale 為 0.105,這兩個節點輸入尺度是不同的,導致 neck.reduce_layer1.conv 無法直接輸出為 INT8。

可以看出,對於同一個輸出,輸入到多路分支後為何 scale 不同的,原因是右邊的分支經過了 concat 操作,會導致輸出的資料分佈發生變化,再進行啟用校準(Activation Calibration)時,會得到的不同的最佳截斷值 (Activaition Max)。

3.1.3 圖結構優化

根據上面的分析,如果一個節點的輸出,輸入到不同的分支節點中,並且分支節點的量化 scale 不同,則 quantize_scale_node 節點無法融合,進而導致了額外的開銷。如何解決這個問題?我們使用了一個簡單的方法,就是強制使所有分支節點的量化 scale 相同(根據經驗,在同一數量級上的 scale 可以安全合併),即直接修改 QAT 網路中的 Quantizer 節點的引數。

我們整理了 YOLOv6s_repopt 中所有需要進行 scale 融合的節點(如表 7 所示),由於 TensorRT 的 8 bit 的量化範圍是[-127,127],所以只需要將多路分支的 Activation Amax 設為同一個值,一般取多路分支中的最大值。

表7 需要融合 Scale 的節點列表

3.1.4 效能測試

經過以上的多路分支的 scale 融合後,我們再次利用 trtexec 和 pltEngine 工具,畫出了 QAT INT8 進行優化前後的圖結構。可以發現,quantize_scale_node 節點已經全部被融合。

圖11 圖優化後 INT8 圖節點變化

我們測試了經過圖優化的 QAT 模型,QPS 達到了 528,效能非常接近 PTQ 的 556,而且 mAP 依然保持優化前的 42.1%。

表8 圖優化後 QPS 對比

3.2 線上服務優化

我們在 NVIDIA T4 伺服器上進行了端到端的吞吐測試,利用“多例項”併發處理的技術,YOLOv6s_repopt INT8 QPS 達到了 552,相較 FP16 提升了~40%。我們對伺服器的各項指標進行了監測,發現此時 T4 GPU 的利用率只有 95%,還有壓榨空間,而 16 核 CPU 利用率已經超過了 1500%,幾乎滿負荷運轉。我們推測整個線上服務的“瓶頸”可能在 CPU,而圖片預處理會使用大量 CPU 資源。

表9 伺服器資源配置

3.2.1 DALI 預處理

為了解決 CPU 預處理帶來的“瓶頸”,我們採用了 NVIDIA 的 DALI 庫,將預處理直接放到 GPU 中運算。該庫可以在 GPU 上對二進位制圖片進行解碼和預處理,極大的緩解 CPU 瓶頸,下圖 12 為 DALI 的經典流程。

圖12 DALI 加速影象預處理流程

3.2.2 吞吐測試

如下圖 13 所示,INT8 + DALI 的吞吐達到了 1182 imgs/s,比 INT8 吞吐提升了 1.14 倍。引入 DALI 預處理後,T4 GPU 利用率達到了100%,而 16 核 CPU 的利用率則下降到了 1100% 左右,部分 CPU 資源得到了“解放”。另外,我們也測試 FP16 + DALI 的吞吐,反而有略微的下降。我們推測是 DALI 搶佔了部分 GPU 計算資源,而 FP16 服務的瓶頸在 GPU,所以對整體效能產生了負面影響。

圖13 使用 DALI 後吞吐測試提升對比

4. 總結

綜上所述,本文基於 YOLOv6 V1.0 版本,以 YOLOv6s 為例探討了基於重引數化結構設計的 2D 檢測模型的量化難點和具體方案,在模型精度基本保持的前提下,通過量化加速,提升了約 40% 的 QPS。部署時的預處理優化則額外提升了 214%,極大地提升了工業部署吞吐能力。下表列出了本文嘗試的方法及疊加效果。

表10 本文使用的量化方案及效果對比

本文使用的速度測試環境見表 11, 測試輸入 batch size 為 1,尺寸為 640x640。

表11 速度測試環境

YOLOv6 版本更新

近日,YOLOv6 已經更新了 V2.0 版本,並新增了中大型網路,對輕量級和小網路的效能進行了全面升級,進一步提升綜合性能,量化效果也得到大幅提升,其中 YOLOv6-S 量化模型達到了 43.3mAP 和 869 FPS (TensorRT 8.4)。更多詳細內容請關注官方出品的技術報告 [7]。

表12 YOLOv6-S V2.0 量化效果

我們希望通過分享本文的實踐,進一步推動最新通用目標檢測演算法的落地。未來,我們會和業界同行一道,探索更優的量化方案,持續提升量化精度和推理速度,助力降本增效,深化業務價值。

5. 參考文獻

  • [1]YOLOv6:又快又準的目標檢測框架開源啦
  • [2] RepVGG: Making VGG-style ConvNets Great Again,https://arxiv.org/abs/2101.03697
  • [3] ReOpt: Re-parameterizing Your Optimizers rather than Architectures
  • [4] SNR: https://github.com/openppl-public/ppq/blob/8a849c9b14bacf2a5d0f42a481dfa865d2b75e66/ppq/quantization/measure/norm.py
  • [5] Nsight-systems: https://docs.nvidia.com/nsight-systems/UserGuide/index.html
  • [6] Channel-wise Knowledge Distillation for Dense Prediction, https://arxiv.org/abs/2011.13256
  • [7] YOLOv6: A Single-Stage Object Detection Framework for Industrial Applications, https://arxiv.org/abs/2209.02976

6. 本文作者

慶源、李亮、奕鐸、張勃、王新、祥祥等,來自美團基礎研發平臺數據科學與平臺部和視覺智慧部。

閱讀美團技術團隊更多技術文章合集

前端 | 演算法 | 後端 | 資料 | 安全 | 運維 | iOS | Android | 測試

| 在公眾號選單欄對話方塊回覆【2021年貨】、【2020年貨】、【2019年貨】、【2018年貨】、【2017年貨】等關鍵詞,可檢視美團技術團隊歷年技術文章合集。

| 本文系美團技術團隊出品,著作權歸屬美團。歡迎出於分享和交流等非商業目的轉載或使用本文內容,敬請註明“內容轉載自美團技術團隊”。本文未經許可,不得進行商業性轉載或者使用。任何商用行為,請傳送郵件至[email protected]申請授權。