化實(shí)踐)
前陣子幫某團(tuán)隊(duì)把一個(gè)圖像分類模型往嵌入式設(shè)備上搬模型在服務(wù)器上跑得飛快一上板子就露餡內(nèi)存直接頂滿跑一幀要兩秒多。問題根本不是精度不夠而是模型太大、計(jì)算太重。這時(shí)候能想到的第一個(gè)手段就是模型量化——把 FP32 的權(quán)重和激活從 32 位浮點(diǎn)壓到 8 位整數(shù)模型體積直接縮到四分之一推理速度能提好幾倍。這篇內(nèi)容就把模型量化這塊最基礎(chǔ)的知識(shí)一次性講清楚包括它解決什么問題、有哪些關(guān)鍵概念、實(shí)際落地怎么做、又會(huì)踩到哪些坑。不管你是剛接觸部署優(yōu)化的同學(xué)還是已經(jīng)在做端側(cè)推理但一直沒系統(tǒng)梳理過量化原理的工程師這篇都適合當(dāng)一份入門地圖來用。1. 為什么模型越跑越慢量化要解決的問題1.1 部署現(xiàn)場(chǎng)的三個(gè)老大難模型訓(xùn)練的時(shí)候大家關(guān)心的是精度、收斂速度、顯存占用模型一旦要部署問題就完全變了。我見過很多項(xiàng)目在服務(wù)器上表現(xiàn)挺好一換到手機(jī)、攝像頭、機(jī)器人控制器這些端側(cè)設(shè)備立刻遇到三個(gè)攔路虎內(nèi)存不夠、算力吃緊、帶寬卡脖子。先說內(nèi)存。一個(gè)常見的分類模型如果權(quán)重是 FP32那就是每個(gè)參數(shù)占 4 個(gè)字節(jié)。模型不大還好一旦涉及到檢測(cè)、分割這類大模型動(dòng)輒幾百兆字節(jié)很多嵌入式設(shè)備根本裝不下更別說還要給激活值、中間緩存留空間。再說算力大部分端側(cè)芯片的浮點(diǎn)計(jì)算單元和整數(shù)計(jì)算單元數(shù)量差距懸殊同一個(gè)芯片上 INT8 的運(yùn)算速度往往是 FP32 的好幾倍這也是為什么量化之后“跑得快”。最后是帶寬模型推理時(shí)要把權(quán)重從內(nèi)存搬到計(jì)算單元內(nèi)存帶寬越窄搬運(yùn)時(shí)間越長(zhǎng)。如果你把 4 字節(jié)的參數(shù)壓成 1 字節(jié)搬運(yùn)量直接變成原來的四分之一很多存儲(chǔ)帶寬瓶頸一下子就解開了。這三個(gè)問題量化都能從根上緩解。所以它不只是“省內(nèi)存的小技巧”而是端側(cè)部署繞不開的核心手段。1.2 量化的本質(zhì)一次帶精度的“單位換算”量化聽起來高大上其實(shí)本質(zhì)就是一次單位換算。我用一個(gè)生活化的類比FP32 相當(dāng)于一臺(tái)高精度電子秤能精確到 0.1 克INT8 相當(dāng)于一把帶刻度的量杯只有 256 個(gè)刻度。你不可能用量杯稱出電子秤那么精細(xì)的值但只要量程設(shè)計(jì)得合理絕大多數(shù)東西都能量個(gè)八九不離十。數(shù)學(xué)上量化就是把浮點(diǎn)數(shù)值映射到整數(shù)。假設(shè)浮點(diǎn)數(shù)的范圍是 [r_min, r_max]目標(biāo)整數(shù)范圍是 [q_min, q_max]比如 INT8 就是 [-128, 127]。量化公式長(zhǎng)這樣q clamp(round(r / S) Z, q_min, q_max)其中 S 是縮放因子Z 是零點(diǎn)。反量化則是r ≈ S * (q - Z)S 和 Z 怎么算也很好理解S (r_max - r_min) / (q_max - q_min) Z round(q_min - r_min / S)舉一個(gè)具體例子。假設(shè)某層權(quán)重范圍是 [-1.28, 1.27]要量化到 INT8那么 S (1.27 - (-1.28)) / (127 - (-128)) 2.55 / 255 ≈ 0.01Z round(-128 - (-1.28) / 0.01) 0。 這時(shí)候權(quán)重里的 0.14 就會(huì)變成 q round(0.14 / 0.01) 0 14反量化回來就是 0.14。整個(gè)過程相當(dāng)于確定了“1 個(gè)整數(shù)刻度代表多大的浮點(diǎn)數(shù)”然后做一次四舍五入。這里的核心矛盾在于量化一定會(huì)引入精度損失因?yàn)?round 這一步把信息丟了。好的量化方案就是要讓這個(gè)損失盡量不影響最終任務(wù)指標(biāo)。1.3 換來的收益和付出的代價(jià)量化帶來的收益非常直接。模型體積通常能變成原來的四分之一因?yàn)?32 位變 8 位推理延遲在很多整數(shù)加速單元上能降低一半甚至更多內(nèi)存占用和能耗也會(huì)顯著下降。這些收益在端側(cè)設(shè)備上比在服務(wù)器上更突出因?yàn)榉?wù)器本身算力富裕省下來的時(shí)間未必明顯但芯片資源緊缺時(shí)差距就是“能跑”和“跑不動(dòng)”的區(qū)別。代價(jià)也沒法回避。首先是精度可能掉點(diǎn)尤其對(duì)于小模型、檢測(cè)任務(wù)或者分布特別集中的層掉點(diǎn)會(huì)更明顯。其次是量化得做額外的工作至少你得準(zhǔn)備校準(zhǔn)數(shù)據(jù)、做精度對(duì)比實(shí)驗(yàn)。最后是兼容性不是每一層、每個(gè)算子都能被量化工具無縫處理有些層的計(jì)算在整數(shù)域里很麻煩可能需要回退到浮點(diǎn)。所以我的建議是不要一上來就把量化當(dāng)銀彈。先搞清楚瓶頸在內(nèi)存、算力還是帶寬再?zèng)Q定要不要量化、量化到多少位。2. 先別急著動(dòng)手量化方案和關(guān)鍵概念怎么選2.1 PTQ 與 QAT訓(xùn)練后量化還是量化感知訓(xùn)練量化方案按“什么時(shí)候做”分成兩大類訓(xùn)練后量化 PTQ 和量化感知訓(xùn)練 QAT。理解這兩者是邁過量化的第一道門檻。PTQ 的做法是模型已經(jīng)訓(xùn)練好了我不動(dòng)訓(xùn)練過程只拿一部分?jǐn)?shù)據(jù)做“校準(zhǔn)”統(tǒng)計(jì)出每一層權(quán)重的數(shù)值分布算出 S 和 Z然后把模型轉(zhuǎn)成整數(shù)版本。優(yōu)點(diǎn)是快通常幾十分鐘就能跑完缺點(diǎn)是精度損失相對(duì)不可控如果模型原本就很敏感可能掉點(diǎn)嚴(yán)重。這里說的校準(zhǔn)意指用一小批真實(shí)數(shù)據(jù)在模型里跑一遍前向記錄每層激活值的分布范圍——激活范圍是從數(shù)據(jù)里統(tǒng)計(jì)出來的不能憑空猜。QAT 則在訓(xùn)練階段就模擬量化誤差。做法是在模型里插入“偽量化節(jié)點(diǎn)”前向傳播時(shí)把權(quán)重和激活先量化再反量化讓模型在訓(xùn)練過程中逐漸適應(yīng)這種精度損失權(quán)重會(huì)被優(yōu)化得更加“抗量化”。精度通常比 PTQ 好不少但需要你有訓(xùn)練流程、GPU 資源和時(shí)間成本。我自己的選型經(jīng)驗(yàn)是模型比較大、任務(wù)指標(biāo)容忍度高的場(chǎng)景先試 PTQ如果精度損失在可接受范圍就直接用如果是小模型或者部署到安全敏感的場(chǎng)景直接做好 QAT 的心理準(zhǔn)備。先量化一個(gè)副本跑對(duì)比實(shí)驗(yàn)再?zèng)Q定投不投入訓(xùn)練成本這是最穩(wěn)妥的順序。2.2 對(duì)稱量化與非對(duì)稱量化零點(diǎn)“歸不歸零”的差別另一組繞不開的概念是對(duì)稱量化和非對(duì)稱量化。區(qū)別就在零點(diǎn)上。對(duì)稱量化把浮點(diǎn)范圍映射成對(duì)稱的整數(shù)范圍零點(diǎn) Z 強(qiáng)制等于 0公式變成q clamp(round(r / S), q_min, q_max)它的好處是實(shí)現(xiàn)簡(jiǎn)單很多硬件原生支持壞處是如果數(shù)據(jù)分布不對(duì)稱比如激活值經(jīng)過 ReLU 之后全是非負(fù)數(shù)范圍 [0, 6.2]對(duì)稱量化卻要把 [-6.2, 6.2] 的一段范圍白白浪費(fèi)掉整數(shù)刻度的利用率就低了。非對(duì)稱量化則允許零點(diǎn)不為 0可以讓量化范圍貼著真實(shí)數(shù)據(jù)的分布走比如激活范圍 [0, 6.2] 會(huì)映射到 [-128, 127] 的完整區(qū)間量化分辨率更高。代價(jià)是實(shí)現(xiàn)復(fù)雜一點(diǎn)推理時(shí)多一步零點(diǎn)偏移的計(jì)算。實(shí)際落地時(shí)有個(gè)很常見的配置組合權(quán)重用對(duì)稱量化激活用非對(duì)稱量化。為什么因?yàn)闄?quán)重分布通常圍繞 0 上下展開對(duì)稱量化浪費(fèi)很少而激活經(jīng)過各種激活函數(shù)之后往往帶偏移用非對(duì)稱量化更合適。當(dāng)然這只是經(jīng)驗(yàn)配比具體要對(duì)齊目標(biāo)硬件支持情況。2.3 校準(zhǔn)粒度per-tensor、per-channel 與 per-group很多人第一次接觸量化時(shí)不理解為什么還要區(qū)分 per-tensor 和 per-channel。說白了就是一個(gè)網(wǎng)絡(luò)層里是一整套參數(shù)共用一個(gè) S還是每個(gè)輸出通道單獨(dú)用一個(gè) S。per-tensor 最簡(jiǎn)單整層權(quán)重算一個(gè)統(tǒng)計(jì)范圍計(jì)算量小硬件實(shí)現(xiàn)也方便。問題是卷積層的不同輸出通道權(quán)重?cái)?shù)值分布可能差異很大。想象一下一個(gè)通道權(quán)重范圍是 [-1.28, 1.27]另一個(gè)通道范圍是 [-0.01, 0.01]如果共用同一個(gè) S第二通道的小數(shù)值會(huì)幾乎全部被“壓”成同一個(gè)整數(shù)信息幾乎全丟。per-channel 則是每個(gè)輸出通道計(jì)算自己的 S 和 Z相當(dāng)于給每個(gè)通道單獨(dú)配了一把刻度合適的“量尺”精度會(huì)好很多這是目前 CNN 量化里非常實(shí)用的做法。代價(jià)是部分硬件不支持或者在某些算子實(shí)現(xiàn)里會(huì)引入額外的計(jì)算開銷。后來還有個(gè)折中方案 per-group即把參數(shù)分成幾個(gè)組每組一個(gè)量化刻度。它比 per-tensor 精細(xì)比 per-channel 靈活在部分低比特量化場(chǎng)景里很流行。選粒度的時(shí)候先看硬件支持列表再看精度對(duì)比結(jié)果別只看理論精度。2.4 校準(zhǔn)方法min-max、百分位與 KL 散度剛才一直提到校準(zhǔn)其實(shí)就是確定浮點(diǎn)范圍 [r_min, r_max] 的過程。范圍選得越準(zhǔn)量化精度越好。這個(gè)環(huán)節(jié)常用三種辦法。min-max 最簡(jiǎn)單直接取校準(zhǔn)數(shù)據(jù)里觀測(cè)到的最大值和最小值。它的弱點(diǎn)是對(duì)離群點(diǎn)非常敏感如果某個(gè)樣本的激活值突然冒出一個(gè)超大值整個(gè)量化范圍被拉寬大部分?jǐn)?shù)據(jù)的分辨率就會(huì)被稀釋。百分位法比 min-max 穩(wěn)一些取觀測(cè)分布的第 0.01 或 0.001 百分位作為邊界主動(dòng)忽略極端異常值減少離群點(diǎn)的影響。代價(jià)是需要緩存足夠的統(tǒng)計(jì)量計(jì)算分布。KL 散度法更講究它的思路是在給定整數(shù)精度下找一個(gè)最優(yōu)截?cái)嚅撝底屃炕昂蟮姆植疾町愖钚?。很多主流工具的校?zhǔn)方式就是基于 KL 散度。使用它的時(shí)候校準(zhǔn)數(shù)據(jù)集和分布選擇對(duì)結(jié)果影響更大樣本越有代表性效果越好。我個(gè)人的理解是min-max 適合快速驗(yàn)證百分位法適合直覺調(diào)整KL 散度適合作為默認(rèn)選擇。在實(shí)操里可以在同一份校準(zhǔn)集上分別跑一遍比較驗(yàn)證集精度來定。3. 實(shí)操記錄從 FP32 到 INT8 的完整流程3.1 先搭最小驗(yàn)證閉環(huán)講完概念接下來是動(dòng)手環(huán)節(jié)。我強(qiáng)烈建議不要一上來就接項(xiàng)目里的完整生產(chǎn)鏈路而是先搭一個(gè)最小驗(yàn)證閉環(huán)模型、校準(zhǔn)集、量化工具、評(píng)估腳本四樣?xùn)|西齊了就開跑。我這里以某開源深度學(xué)習(xí)框架配合常見推理工具鏈為例主要用示意圖代碼表達(dá)流程因?yàn)椴煌姹?API 名稱會(huì)有差異但步驟高度一致。整體流程就是加載 FP32 模型 → 準(zhǔn)備校準(zhǔn)數(shù)據(jù) → 配置量化參數(shù) → 跑校準(zhǔn) → 導(dǎo)出量化模型 → 對(duì)比評(píng)估。model load_model(model.pth) # 加載原始 FP32 模型 calib_loader build_calib_loader(data_dir, count500) # 準(zhǔn)備校準(zhǔn)數(shù)據(jù) quant_model prepare_ptq(model, calib_loader) # 進(jìn)入量化模式 quant_model.calibrate() # 執(zhí)行校準(zhǔn)統(tǒng)計(jì)范圍 quant_model.export(formatint8) # 導(dǎo)出量化模型 fp32_metric evaluate(model, val_loader) int8_metric evaluate(quant_model, val_loader) print(FP32 top-1:, fp32_metric[top1]) print(INT8 top-1:, int8_metric[top1])這段流程短但信息量不少。prepare_ptq 不只是把模型“變成”量化模式它還會(huì)把一些算子融合比如把卷積和后面的 ReLU 合并成一個(gè)算子減少計(jì)算和內(nèi)存訪問calibrate 階段會(huì)跑幾次前向統(tǒng)計(jì)每層的激活分布并據(jù)此確定縮放因子。3.2 校準(zhǔn)集準(zhǔn)備別用訓(xùn)練集硬湊校準(zhǔn)集就是用來統(tǒng)計(jì)激活值分布的那一批數(shù)據(jù)很多人在這里翻車。第一不要直接拿訓(xùn)練集來校準(zhǔn)。訓(xùn)練集和真實(shí)推理場(chǎng)景的數(shù)據(jù)分布不一定一致而且訓(xùn)練集通常做了大量數(shù)據(jù)增強(qiáng)統(tǒng)計(jì)出來的分布會(huì)“更寬”導(dǎo)致量化分辨率被稀釋。我一般從驗(yàn)證集里均勻抽 500 到 1000 張圖片或樣本盡量覆蓋真實(shí)場(chǎng)景中的各種典型情況。第二樣本數(shù)量不用太多但要足夠“雜”。有人覺得越多越好其實(shí)校準(zhǔn)數(shù)據(jù)和訓(xùn)練不一樣它只統(tǒng)計(jì)分布范圍。500 張代表性樣本通常就夠了再多意義不大。關(guān)鍵是覆蓋面要廣比如明暗、大小、遠(yuǎn)近、不同類別都要有。如果校準(zhǔn)集只有“晴天”的圖片部署時(shí)來了“雨夜”的數(shù)據(jù)分布一偏量化精度就會(huì)出問題。第三校準(zhǔn)前要把數(shù)據(jù)預(yù)處理流程對(duì)齊推理時(shí)的流程。歸一化參數(shù)、尺寸縮放這些不一致的話校準(zhǔn)出來的是另一個(gè)分布。3.3 量化與導(dǎo)出一天內(nèi)跑通第一個(gè)量化模型跑通第一個(gè)量化模型的目標(biāo)應(yīng)該是一天內(nèi)完成不要拖。對(duì) PTQ 來說大多數(shù)配置都有默認(rèn)參數(shù)我的建議是先用“比較穩(wěn)”的一組默認(rèn)參數(shù)跑通per-channel 權(quán)重量化、非對(duì)稱激活量化、KL 散度校準(zhǔn)。先不管極致精度拿到量化前后精度對(duì)比再說。導(dǎo)出模型時(shí)注意兩個(gè)事情。一是要確認(rèn)工具鏈導(dǎo)出的是不是“真量化”。有些時(shí)候?qū)С龅哪P椭皇前褭?quán)重從浮點(diǎn)轉(zhuǎn)成了整數(shù)但計(jì)算時(shí)還是會(huì)“反量化回浮點(diǎn)來算”這種叫偽量化速度提升非常有限。真正的整數(shù)推理是整個(gè)計(jì)算圖盡量都保持在整數(shù)域里運(yùn)算。你可以通過工具鏈的 profile 功能看每一層實(shí)際執(zhí)行的數(shù)據(jù)類型一眼就能識(shí)別。二是保留 FP32 的原始模型不要覆蓋。量化模型只是部署產(chǎn)物后續(xù)調(diào)參、定位問題都需要原模型。我見過有人把原模型直接覆蓋掉最后只能從 git 歷史里翻非常被動(dòng)。3.4 精度評(píng)估量化前后到底差多少評(píng)估是量化流程里最容易糊弄的環(huán)節(jié)。這里的核心是必須用和上線一致的數(shù)據(jù)和指標(biāo)來對(duì)比。分類任務(wù)看 top-1、top-5檢測(cè)任務(wù)看 mAP分割任務(wù)看 mIoU如果是特征提取模型可以看特征向量的余弦相似度。不要只用 loss 值判斷l(xiāng)oss 的絕對(duì)值下降看不出任務(wù)層面的影響。評(píng)估時(shí)還要注意FP32 和 INT8 模型要跑同一份驗(yàn)證集、同樣的預(yù)處理、同樣的 batch size。我曾見過同事對(duì)比時(shí)一個(gè)用了原始尺寸一個(gè)用了縮放后的尺寸結(jié)果精度差異根本不是量化造成的。如果量化前后指標(biāo)差距在 0.5% 以內(nèi)通常直接上線超過 1%就要去做敏感層定位了??梢园蚜炕`差大的層單獨(dú)回退到 FP32看指標(biāo)能否恢復(fù)借此找到需要混合精度的層。4. 摸爬滾打后總結(jié)的常見坑位4.1 精度掉點(diǎn)到底是誰的鍋精度掉點(diǎn)是最常見的現(xiàn)象但背后的原因五花八門。我排查時(shí)有個(gè)固定順序先看校準(zhǔn)集再看敏感層最后看量化配置。校準(zhǔn)集不代表性是最容易出問題的地方。如果校準(zhǔn)數(shù)據(jù)和真實(shí)數(shù)據(jù)分布存在差異統(tǒng)計(jì)出的范圍就不準(zhǔn)。簡(jiǎn)單驗(yàn)證方法是換一批校準(zhǔn)數(shù)據(jù)重新跑一遍如果精度波動(dòng)很大說明校準(zhǔn)集沒選好。敏感層問題也常見。有些網(wǎng)絡(luò)層對(duì)量化特別不友好比如檢測(cè)任務(wù)里的回歸頭、分割任務(wù)的上采樣層、注意力機(jī)制里的 Softmax 與矩陣乘這些層稍微量化一下就會(huì)放大誤差。定位方法很簡(jiǎn)單逐層或者逐塊做量化回退實(shí)驗(yàn)把某一層保留 FP16其他層量化看誰對(duì)精度影響最大。找到敏感層之后配合混合精度方案解決。還有一種情況是量化配置本身不合理。比如激活用對(duì)稱量化、權(quán)重用非對(duì)稱量化又比如 per-tensor 在通道差異大的層上用了都會(huì)造成額外損失。把配置切換成 per-channel 權(quán)重、非對(duì)稱激活通常就能改善。4.2 校準(zhǔn)集和真實(shí)場(chǎng)景分布不一致這個(gè)問題在部署后才會(huì)暴露——量化時(shí)驗(yàn)證集精度挺正常一上真實(shí)環(huán)境就掉點(diǎn)。典型的例子是圖像分類模型在校準(zhǔn)時(shí)只用了室內(nèi)光線數(shù)據(jù)上線后遇到戶外強(qiáng)光、夜間低光分布直接漂移。解決思路有兩個(gè)方向。一是讓校準(zhǔn)集更貼近真實(shí)分布盡量從線上日志或代表性場(chǎng)景里采集樣本如果做不到考慮做一定程度的數(shù)據(jù)增強(qiáng)再校準(zhǔn)。二是給模型保留少量“靈活性”比如把輸入輸出層或?qū)Ψ植济舾械膶恿粼诟呔茸屨w模型對(duì)分布漂移不那么敏感。另外提醒一句量化模型的分布漂移比 FP32 模型更劇烈。因?yàn)楦↑c(diǎn)模型對(duì)輸入分布的容忍度高量化后每個(gè)值都經(jīng)過了刻度映射分布一偏就可能導(dǎo)致大量值落在一個(gè)較差的量化區(qū)間里。4.3 量化后速度反而更慢很多人第一次量化后會(huì)困惑模型變小了為什么推理時(shí)間沒有變短甚至更長(zhǎng)了這種情況通常是“量化沒有真正落地”。第一種可能是硬件不支持整數(shù)加速算子。有些平臺(tái)對(duì) INT8 卷積有優(yōu)化但對(duì) INT8 的某些激活函數(shù)、上采樣、拼接操作沒有原生支持于是推理引擎只能把數(shù)據(jù)“反量化回浮點(diǎn)”來計(jì)算算完再“量化回去”。來回轉(zhuǎn)換的開銷可能比省下來的還大。方案是檢查 target 平臺(tái)的算子支持表盡量把不支持算子回退到 FP16而不是跟著整個(gè)網(wǎng)絡(luò)一起轉(zhuǎn) INT8。第二種可能是模型太小帶寬收益不明顯。對(duì)于已經(jīng)很小或計(jì)算量很低的模型量化的主要收益是體積和內(nèi)存推理速度未必有質(zhì)的提升。量化一個(gè)非常輕量的分類模型經(jīng)常出現(xiàn) INT8 和 FP32 差不多的情況因?yàn)楹臅r(shí)大頭可能在預(yù)處理或者數(shù)據(jù)搬運(yùn)。第三種可能是高層 API 默認(rèn)配置不適合當(dāng)前芯片。有些推理引擎需要手動(dòng)指定“推理設(shè)備”和“精度策略”如果默認(rèn)策略是 FP32你量化了個(gè)寂寞。性能調(diào)優(yōu)時(shí)必須看 profiler 輸出確認(rèn)實(shí)際跑起來的每一層是什么精度。4.4 算子不支持導(dǎo)致的“偽量化”偽量化是一個(gè)隱蔽的坑。從模型文件看權(quán)重是 INT8 了但推理引擎拿到之后先把權(quán)重反量化成浮點(diǎn)再用 FP32 計(jì)算最后輸出。表面上是量化模型實(shí)際上計(jì)算沒有省。出現(xiàn)這種情況往往是不支持某些自定義算子、某些動(dòng)態(tài)形狀的分支、或者注意力類算子。排查辦法就是前面提過的 profiler看每一層的實(shí)際執(zhí)行精度。如果發(fā)現(xiàn)某幾層全部是 FP32那它們就是干掉性能的元兇。處理方式分為幾類一是用算子融合把不支持的算子合并到支持的操作里二是把不支持的層調(diào)度到浮點(diǎn)通道混合執(zhí)行三是修改模型結(jié)構(gòu)用更友好的算子替換。多數(shù)情況下混合精度方案足夠解決問題不必為了讓整個(gè)模型“全 INT8”而大改結(jié)構(gòu)。5. 進(jìn)階玩法混合精度與量化邊界5.1 混合精度讓敏感層留在高精度當(dāng)全模型 INT8 精度不達(dá)標(biāo)時(shí)下一步通常就是混合精度也就是讓某些層保持 FP16 甚至 FP32其余層走 INT8。相比全量化混合量化通常在精度和速度之間取得比較好的平衡。怎么決定哪些層保留高精度我的經(jīng)驗(yàn)是先對(duì)關(guān)鍵層做精度實(shí)驗(yàn)再結(jié)合 profiler 看哪些層延遲占比高。延遲占比高、量化誤差小的層優(yōu)先量化延遲占比低、但對(duì)精度影響大的層就保留高精度。理論上這樣性價(jià)比最高。輸入輸出層也值得單獨(dú)考慮。輸入層的通道數(shù)少、計(jì)算量小量化與否對(duì)速度影響不大但保留 FP32 往往能讓模型對(duì)輸入分布變化更穩(wěn)健。輸出層同理直接決定最終數(shù)值質(zhì)量。另外混合精度方案的“整數(shù)/浮點(diǎn)切換”會(huì)產(chǎn)生一定的轉(zhuǎn)換開銷所以不要把模型切得太碎。一般以模塊為單位切比如某個(gè)殘差塊整體走 INT8某個(gè)檢測(cè)頭整體走 FP16減少切換次數(shù)。5.2 量化和剪枝、蒸餾怎么配合在部署優(yōu)化這個(gè)領(lǐng)域量化經(jīng)常不是單獨(dú)使用的。模型壓縮有三大件剪枝、蒸餾、量化它們可以疊加使用。剪枝是把不重要的連接或通道刪掉減少計(jì)算量量化是在剩余結(jié)構(gòu)上進(jìn)一步降低精度。這兩者疊加時(shí)有個(gè)順序問題一般建議先剪枝再量化。剪完的模型更小量化后的精度損失也可能更小但剪枝比例過大會(huì)讓模型變得過于脆弱量化掉點(diǎn)反而更嚴(yán)重。蒸餾則是用一個(gè)大模型“教”一個(gè)小模型。如果蒸餾和量化一起用可以在訓(xùn)練階段就讓小模型適應(yīng)量化誤差通常做法是teacher 是 FP32 大模型student 是量化感知訓(xùn)練的小模型這樣訓(xùn)練出來的模型精度往往比“先普通訓(xùn)練再量化”好很多。如果你做 QAT可以順便把蒸餾損失加上幾乎不增加太多訓(xùn)練成本但精度提升明顯。5.3 低比特量化的現(xiàn)實(shí)約束INT8 是目前最主流的量化位寬因?yàn)榻^大多數(shù)硬件對(duì)其支持最成熟。但最近 INT4、甚至混合的 INT4/INT8 方案也逐漸變多主要是為了進(jìn)一步壓內(nèi)存和帶寬。INT4 帶來的體積收益更誘人但現(xiàn)實(shí)約束不小。一是硬件支持參差不齊很多平臺(tái)對(duì) INT4 乘法的加速能力有限甚至根本沒有二是精度損失顯著一般需要更強(qiáng)的 QAT 手段和更復(fù)雜的混合精度策略來兜底。有人會(huì)在權(quán)重上試 INT4在激活上保留 INT8也算一種折中方案。我個(gè)人建議除非目標(biāo)硬件明確支持且你的任務(wù)精度寬容度很高否則先老老實(shí)實(shí)把 INT8 做扎實(shí)。低比特是優(yōu)化方向不是默認(rèn)選項(xiàng)。先把 INT8 的校準(zhǔn)、混合精度、算子融合這些都調(diào)明白了再去試低比特才有意義。最后分享一點(diǎn)個(gè)人體會(huì)。量化這件事入門門檻并不高幾行配置就能跑通一個(gè) PTQ但真正把它調(diào)好需要對(duì)模型結(jié)構(gòu)、數(shù)據(jù)分布和底層硬件都有理解。我踩過最深的坑從來不是公式看不懂而是校準(zhǔn)集隨便準(zhǔn)備、量化配置照抄默認(rèn)、評(píng)估不做對(duì)齊——這三個(gè)問題不解決量化結(jié)果就是碰運(yùn)氣。如果你正在做部署項(xiàng)目建議花點(diǎn)時(shí)間把“校準(zhǔn)集怎么選”“敏感層怎么找”“profile 怎么看”這三件事挨個(gè)實(shí)踐一遍之后遇到量化問題都會(huì)順很多。