1. PyTorch模型量化工具學習

        共 5378字,需瀏覽 11分鐘

         ·

        2020-09-02 18:25

        ↑ 點擊藍字?關注極市平臺

        作者丨Ironboy@知乎
        來源丨h(huán)ttps://zhuanlan.zhihu.com/p/144025236
        編輯丨極市平臺

        極市導讀

        ?

        通過減少原始模型參數(shù)的數(shù)量或比特數(shù),模型量化技術(shù)能降低深度學習對內(nèi)存和計算的需求。本文主要介紹了這種量化技術(shù)的方法、流程和工具,并預測了數(shù)個有潛力的研究方向。


        官方教程(英文)
        https://pytorch.org/docs/stable/quantization.htmlpytorch.org
        官方教程(中文)
        https://pytorch.apachecn.org/docs/1.4/88.htmlpytorch.apachecn.org
        目前很多高精度的深度學習模型所需內(nèi)存、計算量和能耗巨大,并不適合部署在一些低成本的嵌入式設備中。為了解決這個矛盾,模型壓縮技術(shù)應運而生,其主要是通過減少原始模型參數(shù)的數(shù)量或比特數(shù)來實現(xiàn)對內(nèi)存和計算需求的降低,從而進一步降低能耗。目前性能最穩(wěn)定的就是INT8的模型量化技術(shù),相對于原始模型的FP32計算相比,INT8量化可將模型大小減少 4 倍,并將內(nèi)存帶寬要求減少 4 倍,對 INT8 計算的硬件支持通???2 到 4 倍。值得注意的是量化主要是一種加速前向推理的技術(shù),并且絕大部分的量化算子僅支持前向傳遞。
        注:目前PyTorch的量化工具僅支持1.3及以上版本。

        應用范圍

        數(shù)據(jù)類型:
        • weight的8 bit量化 :data_type = qint8,數(shù)據(jù)范圍為[-128, 127]
        • activation的8 bit量化:data_type = quint8,數(shù)據(jù)范圍為[0, 255]
        bias一般是不進行量化操作的,仍然保持float32的數(shù)據(jù)類型,還有一個需要提前說明的,weight在浮點模型訓練收斂之后一般就已經(jīng)固定住了,所以根據(jù)原始數(shù)據(jù)就可以直接量化,然而activation會因為每次輸入數(shù)據(jù)的不同,導致數(shù)據(jù)范圍每次都是不同的,所以針對這個問題,在量化過程中專門會有一個校準過程,即提前準備一個小的校準數(shù)據(jù)集,在測試這個校準數(shù)據(jù)集的時候會記錄每一次的activation的數(shù)據(jù)范圍,然后根據(jù)記錄值確定一個固定的范圍。
        支持后端:
        • 具有 AVX2 支持或更高版本的 x86 CPU:fbgemm
        • ARM CPU:qnnpack
        通過如下方式進行設置:
        q_backend = "qnnpack" # qnnpack or fbgemmtorch.backends.quantized.engine = q_backendqconfig = torch.quantization.get_default_qconfig(q_backend)
        打印輸出可得:
        QConfig(activation=functools.partial(, reduce_range=False), weight=functools.partial(, dtype=torch.qint8, qscheme=torch.per_tensor_symmetric))
        可以看出qnnpack 的量化方式:activation量化的數(shù)據(jù)范圍是通過記錄每次運行數(shù)據(jù)的最大最小值的統(tǒng)計直方圖導出的,weight為per-layer的對稱量化,整型數(shù)據(jù)范圍為[-128,127],直接用最后收斂的浮點數(shù)據(jù)的最大最小值作為范圍進行量化,其他信息僅從這個打印信息暫時還得不到。

        量化方法

        1、Post Training Dynamic Quantization:這是最簡單的一種量化方法,Post Training指的是在浮點模型訓練收斂之后進行量化操作,其中weight被提前量化,而activation在前向推理過程中被動態(tài)量化,即每次都要根據(jù)實際運算的浮點數(shù)據(jù)范圍每一層計算一次scale和zero_point,然后進行量化;
        2、Post Training Static Quantization:第一種不是很常見,一般說的Post Training Quantization指的其實是這種靜態(tài)的方法,而且這種方法是最常用的,其中weight跟上述一樣也是被提前量化好的,然后activation也會基于之前校準過程中記錄下的固定的scale和zero_point進行量化,整個過程不存在量化參數(shù)_(_scale和zero_point)的再計算;
        3、Quantization Aware Training:對于一些模型在浮點訓練+量化過程中精度損失比較嚴重的情況,就需要進行量化感知訓練,即在訓練過程中模擬量化過程,數(shù)據(jù)雖然都是表示為float32,但實際的值的間隔卻會受到量化參數(shù)的限制。
        至于為什么不在一開始訓練的時候就模擬量化操作是因為8bit精度不夠容易導致模型無法收斂,甚至直接使用16bit進行from scrach的量化訓練都極其容易導致無法收斂,不過目前已經(jīng)有了一些tricks去緩解這個問題,但不在本文討論之列。

        量化流程

        以最常用的Post Training (Static) Quantization為例:
        1、準備模型:準備一個訓練收斂了的浮點模型,用QuantStub和DeQuantstub模塊指定需要進行量化的位置;
        2、模塊融合將一些相鄰模塊進行融合以提高計算效率,比如conv+relu或者conv+batch normalization+relu,最常提到的BN融合指的是conv+bn通過計算公式將bn的參數(shù)融入到weight中,并生成一個bias;
        3. 確定量化方案:這一步需要指定量化的后端(qnnpack/fbgemm/None),量化的方法(per-layer/per-channel,對稱/非對稱),activation校準的策略(最大最小/移動平均/L2Norm(這個不太清楚,是類似TensorRT的校準方式嗎???));
        4. activation校準:利用torch.quantization.prepare() 插入將在校準期間觀察激活張量的模塊,然后將校準數(shù)據(jù)集灌入模型,利用校準策略得到每層activation的scale和zero_point并存儲;
        5. 模型轉(zhuǎn)換:使用 torch.quantization.convert()函數(shù)對整個模型進行量化的轉(zhuǎn)換。這其中包括:它量化權(quán)重,計算并存儲要在每個激活張量中使用的scale和zero_point,替換關鍵運算符的量化實現(xiàn);

        量化工具

        torch.quantization:最基礎的量化庫,里面包含模型直接轉(zhuǎn)換函數(shù)torch.quantization.quantize,量化訓練函數(shù)torch.quantization.quantize_qat,準備校準函數(shù)torch.quantization.prepare等一系列工具
        quantize_per_tensor():per-ayer量化,需要手動指定scale, zero_point和數(shù)據(jù)類型dtype;
        quantize_per_channel():per-channel量化,除了需要指定上述三個參數(shù)之外,還需要額外指定執(zhí)行per-channel量化的維度;
        torch.nn.intrinsic.quantized:提供了很多已經(jīng)融合好的模塊,如ConvBn2d,ConvBnReLU2d,直接對這些模型進行量化
        其余的如torch.nn.quantized,torch.nn.quantized.functional......

        Quantization-Aware Training相關模塊

        torch.nn.qat:支持全連接和二維卷積操作;
        torch.nn.intrinsic.qat:對融合好的層進行量化訓練;
        torch.nn.qat:可以實現(xiàn)在float32數(shù)據(jù)中模仿量化的操作,即量化+反量化折騰一下。

        總結(jié)

        以上這些工具感覺是不同團隊做的,有點冗余和混亂,使用上不是很(非常不)友好,限制很多,而且整套量化過程手動部分比較多,每換一個模型都需要事先對模型的細節(jié)了解非常清楚,包括需要進行融合模塊的名字。然而實際生產(chǎn)過程需要的是一套可以針對特定硬件平臺自動進行量化,并且結(jié)合相應的深度學習編譯器進行優(yōu)化,最終部署到移動端/嵌入式設備中,在保證精度要求的前提下有加速效果(最好能達到實時)。之前因為組里的項目需要也自己寫了一套自動的量化工程,當時的計劃是只需要給我提供pth文件我就能給你量化后的pth
        然而在實際研究和coding過程中發(fā)現(xiàn)了各種問題,比如:
        pth在沒有model類定義的情況下是無法單獨load的,即使是torch.save的完整模型,這個和TensorFlow的pb文件還不一樣,之前TensorFlow用的多,所以不太了解這部分,夸下了只需要pth文件的???;
        BN的自動融合很難cover所有的模型,因為不從底層計算圖上進行conv層和bn層的融合都需要去自動識別兩個模塊,然后將兩層參數(shù)進行融合計算,原始conv層變成一個有bias的conv層,bn層變成identity(不能完全去掉),因為編程方式的不同,所以這種自動識別十分困難,我目前實現(xiàn)的只能覆蓋pytorchcv這個庫里面的模型(歡迎嘗試)
        https://github.com/Ironteen/Batch-Normalization-fusiongithub.com
        我嘗試添加適應不同方式,但是發(fā)現(xiàn)很難做到,Captain Jack大佬對這個有一些比較好的理解:https://zhuanlan.zhihu.com/p/143664360
        很難自動去做qat,即量化感知訓練,我自己寫了一個Conv+BN融合的層,并加入了模仿量化的操作,暫時命名為Conv_Bn_Quant,但是給我一個官方預訓練好的pth和模型類定義文件,我需要對每個模塊做個name的映射才能將原始參數(shù)load進我寫好的Conv_Bn_Quant中,這一步基本上就要非常了解這個模型的名字細節(jié)然后手動寫了(說好的智能呢,怎么還停留在人工的階段)。
        總的來說,模型的8bit量化在學術(shù)研究上剩余空間已經(jīng)不多了,因為一些模型在per-layer無法達到很好結(jié)果時,per-channel往往可以解決這個問題,當硬件不支持per-channel操作時,用qat訓練一下量化模型就行,所以目前再去研究如何提升量化后的精度就很難了,但在實際工程部署上面發(fā)現(xiàn)實現(xiàn)問題比較多,很難做一套完全自動化的流程,實現(xiàn)絕大多數(shù)模型的快速部署。
        我根據(jù)查閱的資料和自己閱讀過的論文,覺得以下方向還可以繼續(xù)進行研究(肯定不全面而且理解上存在一定誤區(qū),希望大佬多多指點):
        8bit的from scracth訓練,這樣就可以實現(xiàn)訓練加速,前段時間研讀了商湯的一篇相關論文,很有意思;
        full-quantized method,去掉中間大量的quantize和de-quantize操作,bias也進行量化,這樣不可避免會喪失一定的靈活性(研究一下add這塊怎么對scale進行對齊就能感受到),但整個過程中沒有float32參與了,硬件運行是更高效的,尤其對于FPGA這種對float不是很友好的硬件;
        將乘除法用移位來代替,在保證精度的前提下進一步提升硬件運行效率;這個論文目前比較多,之前在ICCV2019的poster現(xiàn)場看到不少。
        無需提供數(shù)據(jù)或只需極少量數(shù)據(jù)就能對每一層的activation進行校準,這一步對精度影響還是蠻大的,但是對于一些比較隱私的數(shù)據(jù)(如醫(yī)學),提供數(shù)據(jù)還是比較難的,所以如果能夠從模型本身獲取得到activation相關的信息然后進行校準是很有意義的,前段時間看過CVPR一篇論文就是解決這個問題,立意很好:
        https://arxiv.org/abs/2001.00281
        模型量化向其他任務上的遷移,如目標檢測,語義分割,人體位姿檢測,NLP任務,如何在不進行量化訓練的前提下保持較高精度(可以實現(xiàn)快速部署)。


        推薦閱讀



        添加極市小助手微信(ID : cvmart2),備注:姓名-學校/公司-研究方向-城市(如:小極-北大-目標檢測-深圳),即可申請加入極市目標檢測/圖像分割/工業(yè)檢測/人臉/醫(yī)學影像/3D/SLAM/自動駕駛/超分辨率/姿態(tài)估計/ReID/GAN/圖像增強/OCR/視頻理解等技術(shù)交流群:月大咖直播分享、真實項目需求對接、求職內(nèi)推、算法競賽、干貨資訊匯總、與?10000+來自港科大、北大、清華、中科院、CMU、騰訊、百度等名校名企視覺開發(fā)者互動交流~

        △長按添加極市小助手

        △長按關注極市平臺,獲取最新CV干貨

        覺得有用麻煩給個在看啦~??


        瀏覽 188
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
          
          

            1. 稀缺精品怮呦泬专区 | 国产欧美日韩免费看aⅴ视频 | 嫩草研究院 国产 | 99色色 | 青青草大香蕉在线 |