化實(shí)踐指南)
量化方案選型這個(gè)話題我過去幾年里被問到的次數(shù)特別多。不少團(tuán)隊(duì)拿著模型優(yōu)化需求來找我開口就問“哪個(gè)量化方案效果好”但聊到最后發(fā)現(xiàn)真正有意思的從來不是選哪個(gè)庫、用哪條命令而是整個(gè)團(tuán)隊(duì)怎么理解精度和性能之間的這筆賬。這篇東西我就結(jié)合自己這些年做模型壓縮和推理優(yōu)化的實(shí)際經(jīng)歷把量化方案選型這件事從需求拆解、原理辨析、落地對比到問題排查完整梳理一遍。1. 量化方案選型為什么是個(gè)系統(tǒng)工程1.1 先搞清楚量化到底解決什么問題模型量化說白了就是把深度學(xué)習(xí)模型里的高精度浮點(diǎn)數(shù)參數(shù)和中間激活值從FP32、FP16降到INT8甚至更低比特從而縮小模型體積、減少內(nèi)存帶寬占用、加速推理計(jì)算。這套技術(shù)到今天已經(jīng)很成熟了主流的推理引擎都支持算法側(cè)也有大量論文支撐。但落到具體業(yè)務(wù)里量化常常不是“跑通就行”而是要同時(shí)滿足模型精度損失在可接受范圍、推理延遲達(dá)標(biāo)、部署硬件兼容這三個(gè)約束。這三者就像是三角關(guān)系你很難同時(shí)把三個(gè)邊都做到最長。我之前遇到過一個(gè)典型的項(xiàng)目要做一批邊緣設(shè)備上的圖像分類任務(wù)目標(biāo)設(shè)備只有不到2GB內(nèi)存算力大概是手機(jī)中端芯片的水平幀率要求不低于15FPS。模型已經(jīng)選好了一個(gè)結(jié)構(gòu)比較重的CNN網(wǎng)絡(luò)直接跑原始FP32權(quán)重體積大約是120MB左右單幀推理延遲在60毫秒上下。這時(shí)候模型體積和延遲都壓不下來就只剩量化和剪枝這兩條路。很多人以為量化就是把權(quán)重直接四舍五入成INT8那么簡單其實(shí)不是。一個(gè)完整可用的量化方案要處理權(quán)重量化、激活量化、量化尺度計(jì)算、反量化邏輯、量化感知訓(xùn)練、校準(zhǔn)數(shù)據(jù)選取、硬件算子適配等多層問題。每一層都會(huì)影響最終效果而且這些因素彼此耦合一旦某一層沒處理好前面的努力可能全白費(fèi)。1.2 常見的認(rèn)知誤區(qū)量化不是“一鍵優(yōu)化”我在不少技術(shù)交流群和社區(qū)里經(jīng)??吹接腥税蚜炕枋龀伞爸恍枰恍写a”的優(yōu)化操作。確實(shí)現(xiàn)成的工具鏈簡化了大量細(xì)節(jié)比如直接調(diào)用某個(gè)推理框架的量化接口模型丟進(jìn)去跑一下校準(zhǔn)出來一個(gè)量化后的模型。但是這種“一鍵量化”往往只適用于寬容錯(cuò)場景比如一些非關(guān)鍵路徑上的文本分類、粗粒度目標(biāo)檢測。真正棘手的場景是模型精度非常敏感或者模型結(jié)構(gòu)里有大量結(jié)構(gòu)特殊的算子比如帶有動(dòng)態(tài)shape的循環(huán)、自定義的標(biāo)準(zhǔn)化層、需要保持高精度的后處理模塊。在這些情況里單純依賴默認(rèn)量化接口精度掉得可能讓你懷疑人生。我見過不止一個(gè)團(tuán)隊(duì)量化之后精度掉了兩三個(gè)點(diǎn)甚至更多然后來來回回排查發(fā)現(xiàn)就是校準(zhǔn)數(shù)據(jù)選取不當(dāng)或者某個(gè)算子被強(qiáng)制量化成了低精度導(dǎo)致數(shù)值崩潰。所以選型的第一步不是比工具而是把復(fù)雜問題拆開你當(dāng)前卡在哪里你的約束條件是什么你愿意用多大的時(shí)間成本去換取多少性能提升。沒有這個(gè)前置分析后面所有的技術(shù)選型都會(huì)非常被動(dòng)。2. 主流量化方案的分類與應(yīng)用邊界2.1 訓(xùn)練后量化PTQ與感知量化訓(xùn)練QAT量化方案從執(zhí)行時(shí)機(jī)上大體可以分成兩類訓(xùn)練后量化Post-Training QuantizationPTQ和量化感知訓(xùn)練Quantization-Aware TrainingQAT。PTQ的做法是模型先按照正常流程訓(xùn)練到收斂然后拿一批校準(zhǔn)數(shù)據(jù)統(tǒng)計(jì)各層激活值的數(shù)值分布計(jì)算出合適的量化參數(shù)最后把浮點(diǎn)權(quán)重映射成低比特整數(shù)。這種方案最大的優(yōu)勢就是快不需要重新訓(xùn)練模型大大節(jié)省了算力成本。對于很多成熟模型只要校準(zhǔn)數(shù)據(jù)有代表性精度損失通常可以控制在幾個(gè)百分點(diǎn)甚至更低。QAT則是在訓(xùn)練過程中就模擬量化的誤差讓模型在前向計(jì)算時(shí)使用模擬量化的權(quán)重和激活值反向傳播時(shí)仍然保持浮點(diǎn)梯度。這樣模型在訓(xùn)練階段就適應(yīng)了量化帶來的噪聲推理時(shí)再切換成真正的低比特計(jì)算精度往往比PTQ好不少尤其對于小模型和分布比較復(fù)雜的模型QAT的提升會(huì)比較明顯。但QAT的訓(xùn)練成本高、周期長而且需要調(diào)整原始訓(xùn)練代碼對團(tuán)隊(duì)的工程能力要求比較高。我在實(shí)際選型中有一條經(jīng)驗(yàn)如果模型規(guī)模不大且PTQ結(jié)果精度損失低于業(yè)務(wù)容忍閾值那就直接用PTQ。如果PTQ掉點(diǎn)嚴(yán)重再考慮對特定層做敏感度分析做混合精度量化而不是一上來就上QAT。QAT一旦啟用訓(xùn)練流程、超參數(shù)、數(shù)據(jù)增強(qiáng)策略都可能需要重新調(diào)工作量和坑都會(huì)成倍增加。2.2 按工具鏈劃分從算法原語到跨平臺(tái)框架另一個(gè)劃分維度是工具鏈的層級。底層一些的量化方案通常由編譯器或推理引擎直接提供比如ONNX Runtime的量化工具、TensorFlow Lite的量化轉(zhuǎn)換器、PyTorch的torch.quantization模塊以及各硬件廠商自帶的推理SDK里的量化接口。這些工具通常封裝得比較完整支持PTQ和QAT并且在特定硬件上有深度優(yōu)化。更高一層的方案是模型優(yōu)化工具鏈比如基于XLA或TVM這類編譯優(yōu)化的方案。這類方案往往不只是做量化還會(huì)做算子融合、內(nèi)存規(guī)劃、自動(dòng)調(diào)優(yōu)等。對開發(fā)者來說使用門檻更高但換來的性能上限也更高。選這種方案的團(tuán)隊(duì)一般都有專門的推理優(yōu)化工程師至少得有人能看懂底層算子實(shí)現(xiàn)。我在給團(tuán)隊(duì)做方案建議時(shí)常會(huì)畫一條簡單的分界線如果你們的模型最終部署平臺(tái)是固定的、并且官方工具鏈支持得比較好優(yōu)先用平臺(tái)官方的量化方案如果模型需要跨平臺(tái)部署且性能要求很高那么編譯優(yōu)化的方案更合適如果只是算法驗(yàn)證階段想做快速評估那么先用手上的深度學(xué)習(xí)框架自帶的量化API就夠了別急著上重型工具鏈。3. 實(shí)用決策框架從需求到量化方案落地的全流程3.1 第一步明確量化目標(biāo)與約束邊界我給你講一個(gè)實(shí)際指導(dǎo)過的選型過程。項(xiàng)目背景是這樣的某智能硬件團(tuán)隊(duì)需要把一個(gè)語音喚醒模型部署到低功耗芯片上要求模型權(quán)重壓縮到原來的四分之一以下喚醒延遲要從原來的200毫秒降到50毫秒以內(nèi)誤喚醒率不能超過基線水平。團(tuán)隊(duì)之前完全沒有量化的經(jīng)驗(yàn)剛開始走了一些彎路后來找我一起梳理。我讓他們做的第一件事不是挑方案而是把需求量化成具體的技術(shù)指標(biāo)。首先是模型體積當(dāng)前模型FP32是50MB要求部署后不超過12MB相當(dāng)于壓縮4倍以上單靠量化到INT8是不夠的可能還需要結(jié)合剪枝或者蒸餾。其次是延遲指標(biāo)50毫秒是硬指標(biāo)但具體要從哪個(gè)環(huán)節(jié)算起是從音頻進(jìn)入DSP開始還是從模型推理開始這要提前定義清楚。再就是精度要求誤喚醒率不能突破某個(gè)數(shù)值這是業(yè)務(wù)紅線。這三個(gè)指標(biāo)列清楚之后每個(gè)候選方案能不能滿足基本就能淘汰掉一半了。比如有些量化方案只支持特定層類型如果模型里剛好有不支持的算子那整個(gè)方案就得重新評估。3.2 第二步盤點(diǎn)模型結(jié)構(gòu)和算子組成選型的下一步是對模型做一次結(jié)構(gòu)審計(jì)。我習(xí)慣用一段腳本把模型里的所有算子類型、數(shù)量、參數(shù)大小、激活形狀都統(tǒng)計(jì)出來尤其在準(zhǔn)備用PTQ之前。因?yàn)镻TQ方案能否順利落地很大程度上取決于模型里是否有大量對量化不友好的算子。import torch # 偽代碼示意統(tǒng)計(jì)模型算子類型與參數(shù)分布 model load_model(path/to/model.pt) layer_summary {} def count_layer(module, prefix): for name, child in module.named_children(): layer_name f{prefix}.{name} if prefix else name layer_type type(child).__name__ if layer_type not in layer_summary: layer_summary[layer_type] {count: 0, params: 0} layer_summary[layer_type][count] 1 layer_summary[layer_type][params] sum( p.numel() for p in child.parameters() ) count_layer(child, layer_name) count_layer(model) for layer_type, info in layer_summary.items(): print(layer_type, info[count], info[params])算子審計(jì)的價(jià)值在于預(yù)警。我遇到過不只一次模型里有自定義的動(dòng)態(tài)向量查找操作標(biāo)準(zhǔn)量化工具根本不識(shí)別最后只能把這一層排除在量化范圍外或者手工模擬量化邏輯這種額外工作量要在選型之初就納入評估。另外激活值的動(dòng)態(tài)范圍也很重要。有些網(wǎng)絡(luò)層輸出的數(shù)值在不同輸入樣本下分布差異極大這意味著量化尺度的選擇會(huì)很困難。這時(shí)候就需要考慮粒度更細(xì)的量化策略比如分通道量化、分組量化或者把這一層單獨(dú)保持浮點(diǎn)。3.3 第三步建立候選方案并做小規(guī)模驗(yàn)證候選方案不用選太多挑兩到三個(gè)即可。一個(gè)比較穩(wěn)的組合是官方推理框架內(nèi)置量化方案、獨(dú)立模型壓縮工具鏈、手動(dòng)模擬量化的工程實(shí)現(xiàn)。這三個(gè)方案的梯度和代價(jià)是遞增的精度可控性也是遞增的。每個(gè)候選方案都要用同一套評估腳本去做對比評估。評估內(nèi)容包括量化后模型體積、單次推理時(shí)間、峰值內(nèi)存占用、在測試集上的精度指標(biāo)。這些結(jié)果整理成一張對照表選型就清晰很多了。我在這個(gè)階段從來不直接看工具鏈文檔里宣稱的加速倍數(shù)因?yàn)橛布h(huán)境、模型結(jié)構(gòu)、線程設(shè)置都會(huì)影響最終結(jié)果。自己跑一遍用同一臺(tái)機(jī)器、同一個(gè)輸入數(shù)據(jù)、同樣的并發(fā)度和預(yù)熱操作出來的數(shù)字才有比較意義。3.4 第四步全鏈路回歸測試與灰度驗(yàn)證選型不能止步于離線跑幾個(gè)指標(biāo)。量化之后模型要接入完整的業(yè)務(wù)鏈路做回歸測試。因?yàn)樵谡鎸?shí)業(yè)務(wù)中模型前面往往有預(yù)處理邏輯后面有后處理邏輯量化誤差和預(yù)處理誤差可能會(huì)疊加引發(fā)意料之外的連鎖變化。比如有一個(gè)目標(biāo)檢測場景量化后的模型在離線測試集上精度幾乎不掉但在真實(shí)視頻流里小目標(biāo)的召回率明顯下降。最后定位發(fā)現(xiàn)問題不在檢測模型本身而是預(yù)處理階段的下采樣算法在低算力設(shè)備上被替換成了更快但精度更低的版本導(dǎo)致輸入圖像細(xì)節(jié)丟失嚴(yán)重量化后的模型對小目標(biāo)更加敏感。這種問題如果不做全鏈路測試很難被發(fā)現(xiàn)。所以我的建議是量化方案選型的驗(yàn)證流程至少要覆蓋四個(gè)環(huán)節(jié)單模型離線評估、前后處理鏈路聯(lián)調(diào)、真實(shí)設(shè)備灰度測試、持續(xù)監(jiān)控線上指標(biāo)回看。缺少任何一個(gè)環(huán)節(jié)都可能留下隱患。4. 不同硬件平臺(tái)上的量化方案對比與選型要點(diǎn)4.1 通用GPU推理場景的方案特征在通用GPU場景做量化邏輯相對簡單。GPU上的算子大部分都有比較成熟的實(shí)現(xiàn)INT8計(jì)算在CUDA等平臺(tái)上支持得不錯(cuò)。選型重點(diǎn)通常集中在推理框架的版本、TensorRT的算子兼容性、動(dòng)態(tài)shape的支持程度、以及多batch吞吐量的調(diào)優(yōu)。TensorRT相對常用它的量化校準(zhǔn)器做得比較完善支持多種校準(zhǔn)算法。選它的時(shí)候要注意版本匹配關(guān)系因?yàn)門ensorRT和PyTorch之間經(jīng)常出現(xiàn)版本不兼容同一個(gè)模型在不同版本上量化出來的行為可能有差異。另外TensorRT對動(dòng)態(tài)shape支持得不算友好如果你的業(yè)務(wù)里有頻繁變化的輸入尺寸要在選型階段就明確是否能用固定shape繞過去。我個(gè)人的經(jīng)驗(yàn)是在GPU平臺(tái)做量化優(yōu)先考慮TensorRT的INT8方案如果模型結(jié)構(gòu)比較復(fù)雜或者算子兼容性有問題再考慮兼容性更強(qiáng)的ONNX Runtime量化鏈路。不要為了追求極致的推理速度在通用GPU場景引入過重的自定義編譯方案維護(hù)成本會(huì)顯著上升。4.2 移動(dòng)端和邊緣設(shè)備場景的方案特征移動(dòng)端和邊緣設(shè)備是量化收益最大的場景也是坑最深的場景。這類設(shè)備通常內(nèi)存帶寬受限、算力有限量化帶來的收益非??捎^但不同芯片廠商的指令集和算子實(shí)現(xiàn)差異很大。在移動(dòng)端常見的量化方案包括各移動(dòng)端推理框架提供的INT8量化模型轉(zhuǎn)換能力。這類框架對ARM架構(gòu)優(yōu)化得比較好支持CPU和GPU的異構(gòu)調(diào)度。如果你要在不同品牌的手機(jī)上部署需要特別留意不同SoC對INT8算子支持程度的差異比如有些芯片在NPU上只支持特定形式的對稱量化不支持非對稱那么你在量化時(shí)就得選擇對稱量化的配置。在邊緣設(shè)備上情況更復(fù)雜。有些設(shè)備用的是自研DSP或者NPU它的量化工具鏈?zhǔn)欠忾]的只接受特定格式的模型輸入比如量化參數(shù)必須手動(dòng)指定或者要求模型以固定的拓?fù)浣Y(jié)構(gòu)輸入。這種時(shí)候通用方案基本失效你需要圍繞廠商提供的SDK來做定制量化流程。針對這類場景我的建議是用例先行。先把一個(gè)最小可用的模型用廠商SDK完整跑通一遍量化到部署的流程再做規(guī)?;瘮U(kuò)展。如果廠商的工具鏈能順利支持你們的主模型再全面鋪開如果在最小模型上就出現(xiàn)嚴(yán)重問題那這個(gè)方案可以直接淘汰不用等深入之后才暴露問題。4.3 多平臺(tái)部署時(shí)的統(tǒng)一與分治策略如果團(tuán)隊(duì)負(fù)責(zé)的產(chǎn)品需要同時(shí)部署在多個(gè)平臺(tái)比如服務(wù)器端GPU、移動(dòng)端芯片、邊緣設(shè)備我就會(huì)建議采用“統(tǒng)一訓(xùn)練分質(zhì)量化”的策略。意思是模型結(jié)構(gòu)和算法訓(xùn)練流程完全統(tǒng)一訓(xùn)練結(jié)束后導(dǎo)出同一份浮點(diǎn)基線模型然后在各個(gè)目標(biāo)平臺(tái)分別做量化和調(diào)優(yōu)。這樣做的原因在于不同平臺(tái)上的硬件算子、編譯器優(yōu)化策略和數(shù)值行為差異很大強(qiáng)行用一套量化配置去適配多平臺(tái)往往會(huì)導(dǎo)致某個(gè)平臺(tái)的精度特別差或者速度不達(dá)標(biāo)。分質(zhì)量化雖然增加了工作量但每個(gè)平臺(tái)都有獨(dú)立的優(yōu)化空間。為了控制成本可以先把精力集中在核心平臺(tái)其他平臺(tái)先沿用默認(rèn)量化配置后續(xù)再持續(xù)優(yōu)化。這種策略也有代價(jià)就是模型在多個(gè)平臺(tái)上的行為可能不完全一致給測試和故障排查帶來一些麻煩。所以我在項(xiàng)目里通常會(huì)搭一套跨平臺(tái)的自動(dòng)化測試腳本對不同平臺(tái)量化后的模型跑同一批輸入數(shù)據(jù)然后逐一對比輸出差異這樣很快就能定位各平臺(tái)之間的偏差來源。5. 量化方案落地中的性能調(diào)優(yōu)與精度回退5.1 精度掉點(diǎn)后的第一排查順序哪怕選擇了一個(gè)理論上很合適的量化方案實(shí)操中仍然會(huì)遇到精度掉點(diǎn)。我處理過好幾種典型情況也總結(jié)出一套排查順序供你參考第一先檢查校準(zhǔn)數(shù)據(jù)集是否覆蓋了真實(shí)的輸入分布。這是最常見的掉點(diǎn)原因。有些人圖省事直接用訓(xùn)練集里隨機(jī)抽的幾十張圖做校準(zhǔn)結(jié)果量化參數(shù)被某些異常樣本帶偏。正確做法是校準(zhǔn)數(shù)據(jù)要和線上真實(shí)數(shù)據(jù)分布盡量一致保證數(shù)量充足且覆蓋各種邊界條件。一個(gè)經(jīng)驗(yàn)值是至少準(zhǔn)備512到1000個(gè)代表性樣本。第二檢查哪些層對量化最敏感??梢杂弥饘用舾卸确治龅姆椒▽⒚恳粚臃謩e設(shè)為浮點(diǎn)其他層保持量化觀察精度變化找出主要的掉點(diǎn)來源。敏感度分析可以在小規(guī)模測試集上快速執(zhí)行定位到敏感層之后再結(jié)合層融合、混合精度或者重設(shè)計(jì)結(jié)構(gòu)來決定方案。第三檢查激活值的分布形態(tài)。如果某一層的激活值存在長尾分布那么默認(rèn)的量化范圍計(jì)算方式可能會(huì)讓大部分?jǐn)?shù)據(jù)落在極少的量化區(qū)間里導(dǎo)致大量信息丟失。這時(shí)候需要手動(dòng)調(diào)整量化范圍或者使用更精細(xì)的量化粒度。import numpy as np # 示意用KL散度或百分位數(shù)計(jì)算更好的量化邊界 def calibrate_scale(activations, percentile99.99): # activations: 校準(zhǔn)集在該層的激活輸出 abs_vals np.abs(activations) threshold np.percentile(abs_vals, percentile) scale threshold / 127.0 return scale第四檢查后處理和業(yè)務(wù)邏輯是否對量化誤差過于敏感。很多模型在離線評測時(shí)精度不錯(cuò)但真實(shí)業(yè)務(wù)里表現(xiàn)異常就是因?yàn)樵械暮筇幚硭惴ㄊ菄@浮點(diǎn)模型的數(shù)值特性設(shè)計(jì)的量化后數(shù)值分布發(fā)生了輕微偏移后處理閾值就不再匹配了。這種情況下重新標(biāo)定后處理的閾值比改量化方案有效得多。5.2 量化后推理速度不達(dá)標(biāo)的瓶頸定位精度問題解決了速度又不達(dá)標(biāo)這是另一個(gè)常見困境。推理變慢的原因通常有兩類一類是量化算子沒有被硬件正確調(diào)用模型雖然在網(wǎng)絡(luò)結(jié)構(gòu)上是INT8實(shí)際運(yùn)行時(shí)卻被回退到了浮點(diǎn)算子另一類是數(shù)據(jù)搬運(yùn)的開銷過大量化雖然減少了計(jì)算量但頻繁的量化反量化操作反而增加了內(nèi)存拷貝耗時(shí)。排查第一類問題最簡單的方法是啟用推理框架的算子信息打印查看運(yùn)行時(shí)每個(gè)算子實(shí)際執(zhí)行的指令類型和精度。如果發(fā)現(xiàn)模型中大量算子仍然以FP32執(zhí)行那多半是框架不支持這些算子的量化版本。解決途徑有替換算子實(shí)現(xiàn)、修改模型結(jié)構(gòu)、或降級到浮點(diǎn)數(shù)計(jì)算。排查第二類問題則需要從內(nèi)存布局出發(fā)。通常模型內(nèi)部如果存在量化層和浮點(diǎn)層的混用每一次跨精度傳遞都需要做額外的格式轉(zhuǎn)換。這類開銷在小模型上格外明顯。這時(shí)可以考慮整層量化策略盡量減少精度切換點(diǎn)?;蛘哂盟阕尤诤鲜侄伟严噜彽木矸e、批歸一化、激活函數(shù)融合成一個(gè)算子減少內(nèi)存訪問次數(shù)。5.3 一版可用的量化項(xiàng)目實(shí)測流程參考這里我梳理一個(gè)通用的量化方案落地流程可以直接作為團(tuán)隊(duì)內(nèi)部的技術(shù)方案模板第一步模型準(zhǔn)備確定模型結(jié)構(gòu)、訓(xùn)練權(quán)重和評估基準(zhǔn)。先把浮點(diǎn)模型的精度基線固定下來后續(xù)所有調(diào)優(yōu)都以這個(gè)基線為參照。第二步硬件與工具鏈調(diào)研明確目標(biāo)部署設(shè)備的算力特性、現(xiàn)有推理框架的量化算子支持能力、以及社區(qū)內(nèi)相關(guān)的踩坑經(jīng)驗(yàn)。第三步最小可行性驗(yàn)證選一個(gè)小規(guī)模模型或子網(wǎng)絡(luò)完成從浮點(diǎn)到量化的完整鏈路驗(yàn)證工具鏈可用性。第四步全模型PTQ評估完成全模型的量化記錄精度和性能指標(biāo)和浮點(diǎn)基線對比。第五步精度敏感度分析和混合精度量化定位敏感算子層嘗試混合精度方案或者應(yīng)用QAT作為后備。第六步端側(cè)集成與回歸把量化后的模型集成進(jìn)業(yè)務(wù)代碼進(jìn)行真實(shí)數(shù)據(jù)回歸測試和灰度驗(yàn)證。第七步線上監(jiān)控與持續(xù)優(yōu)化量化不是一次性的工作模型要隨著業(yè)務(wù)數(shù)據(jù)的變化做周期性重校準(zhǔn)和評估。這套流程我在多個(gè)項(xiàng)目里都驗(yàn)證過能減少很多不必要的返工。尤其是第三步很多人覺得麻煩總想直接上全模型量化結(jié)果一旦出現(xiàn)問題排查成本反而更高?;▋扇炫芡ㄗ钚℃溌泛竺婢蜁?huì)順很多。6. 典型問題與經(jīng)驗(yàn)速查表6.1 經(jīng)典問題的直觀呈現(xiàn)在積累了多個(gè)項(xiàng)目的量化落地經(jīng)驗(yàn)后我整理出一張常見問題速查表。遇到問題先對照這張表能省去大量排查時(shí)間。問題現(xiàn)象常見原因優(yōu)先排查方法解決方向精度整體掉點(diǎn)超過2%校準(zhǔn)數(shù)據(jù)分布偏差、敏感層較多檢查校準(zhǔn)集代表性和覆蓋度更換校準(zhǔn)集、逐層敏感度分析大目標(biāo)正常但小目標(biāo)漏檢激活值長尾分布小數(shù)值區(qū)間信息丟失查看小目標(biāo)相關(guān)的特征層分布調(diào)整量化邊界、細(xì)粒度量化特定badcase完全崩潰極值異常樣本導(dǎo)致數(shù)值溢出復(fù)現(xiàn)輸入并打印各層輸出增加截?cái)嗖呗?、排除離群樣本模型體積符合預(yù)期但推理延遲高算子未真正量化、數(shù)據(jù)搬運(yùn)開銷大打印算子實(shí)際執(zhí)行精度算子替換、算子融合、減少精度切換同一套配置在不同設(shè)備上效果差異大不同SoC算子實(shí)現(xiàn)差異對比各設(shè)備算子支持矩陣分設(shè)備量化、硬件特定調(diào)優(yōu)量化后輸出完全錯(cuò)亂模型包含自定義算子且未處理檢查自定義算子的量化邏輯手寫量化函數(shù)或保持該層浮點(diǎn)這張表不完全覆蓋所有場景但在多數(shù)項(xiàng)目中已經(jīng)能解決80%的常規(guī)問題。剩下的20%往往需要深入具體硬件的文檔或者向廠商的技術(shù)支持尋求幫助這時(shí)候你手里有了一份詳細(xì)的排查記錄溝通效率會(huì)高很多。6.2 校準(zhǔn)數(shù)據(jù)選取的經(jīng)驗(yàn)與細(xì)節(jié)關(guān)于校準(zhǔn)數(shù)據(jù)我特別想再展開說一下因?yàn)檫@是影響PTQ效果最關(guān)鍵的因素偏偏又最容易被忽略。校準(zhǔn)數(shù)據(jù)的選擇要遵循三個(gè)原則數(shù)量適中、覆蓋充分、貼近真實(shí)分布。數(shù)量太少統(tǒng)計(jì)出來的激活分布可能不穩(wěn)定數(shù)量太多校準(zhǔn)耗時(shí)增加還可能把訓(xùn)練集里的噪聲特征引入量化參數(shù)。我一般會(huì)從驗(yàn)證集或線上抽樣日志中隨機(jī)選取大約500到1000個(gè)樣本作為校準(zhǔn)集。如果模型類別多按類別比例抽樣確保每個(gè)類別的樣本都有覆蓋。另外校準(zhǔn)數(shù)據(jù)的預(yù)處理流程必須和訓(xùn)練時(shí)完全一致包括歸一化方式、輸入尺寸、通道順序。我見過有人直接用原始圖片文件做校準(zhǔn)沒有經(jīng)過任何預(yù)處理導(dǎo)致量化參數(shù)完全偏離真實(shí)情況。這種低級錯(cuò)誤排查起來很費(fèi)時(shí)間。還有一種情況值得注意如果你的業(yè)務(wù)數(shù)據(jù)分布會(huì)隨著時(shí)間漂移那么校準(zhǔn)集也要定期更新。比如一個(gè)售貨柜上的商品識(shí)別模型換季時(shí)商品包裝換了原有校準(zhǔn)集可能就不適用了。這時(shí)候要做周期性的模型重校準(zhǔn)否則線上的精度會(huì)肉眼可見地下降。6.3 量化方案選型中的團(tuán)隊(duì)協(xié)作與文檔沉淀最后再說一說選型過程中的團(tuán)隊(duì)協(xié)作問題。量化方案選型不只是算法工程師一個(gè)人的事它涉及算法、后端、客戶端、測試等多個(gè)角色。算法工程師負(fù)責(zé)模型精度評估后端或推理工程師負(fù)責(zé)性能和兼容性驗(yàn)證測試同學(xué)負(fù)責(zé)全鏈路回歸產(chǎn)品經(jīng)理則要明確業(yè)務(wù)容忍邊界。如果缺少跨角色協(xié)作很容易出現(xiàn)各管一段、銜接不暢的情況。一個(gè)很有用的做法是讓團(tuán)隊(duì)成員共同維護(hù)一份量化選型文檔記錄候選方案、測試結(jié)果、踩坑記錄和最終決策依據(jù)。這份文檔不僅是當(dāng)下項(xiàng)目的沉淀也是后續(xù)做類似項(xiàng)目時(shí)的第一手參考資料。我自己平時(shí)做技術(shù)方案時(shí)也會(huì)刻意記錄那些實(shí)驗(yàn)數(shù)據(jù)中反直覺的部分比如某個(gè)量化配置在測試集上明明很好但真實(shí)設(shè)備上卻表現(xiàn)不佳。這種記錄可能比最終結(jié)論更有價(jià)值。7. 我當(dāng)時(shí)踩過的幾個(gè)坑和現(xiàn)在的處理方法量化選型這條路上我也交過不少學(xué)費(fèi)。有一個(gè)項(xiàng)目印象特別深當(dāng)時(shí)團(tuán)隊(duì)為了追求極致的推理速度選了一個(gè)編譯優(yōu)化非常激進(jìn)、對開發(fā)者并不友好的方案。方案本身性能確實(shí)強(qiáng)但模型里正好有個(gè)結(jié)構(gòu)特殊的注意力模塊編譯優(yōu)化時(shí)被錯(cuò)誤地融合了導(dǎo)致模型輸出開始出現(xiàn)偶發(fā)性的錯(cuò)亂。這類問題極難排查因?yàn)樗皇欠€(wěn)定復(fù)現(xiàn)的而是和輸入數(shù)據(jù)有關(guān)。后來我們花了整整兩周時(shí)間定位到問題根源最終決定還是把這部分特殊的計(jì)算子圖單獨(dú)拎出來用浮點(diǎn)實(shí)現(xiàn)繼續(xù)保持其他模塊量化。整體性能雖然比全量化版本差一些但穩(wěn)定性和精度都恢復(fù)了。從那以后我在做量化選型時(shí)多了一個(gè)原則穩(wěn)定性和可維護(hù)性的優(yōu)先級永遠(yuǎn)高于理論峰值性能。一個(gè)需要團(tuán)隊(duì)持續(xù)投入大量精力去維護(hù)的優(yōu)化方案即便推理速度更快從整體項(xiàng)目回報(bào)來看也不一定劃算。另外一個(gè)值得分享的技巧是在量化方案里做好版本管理。量化后的模型和浮點(diǎn)模型一樣需要版本管理但同時(shí)還要記錄完整的量化配置信息包括校準(zhǔn)數(shù)據(jù)集、量化算法、縮放參數(shù)、混合精度設(shè)定等。否則過了幾個(gè)月量化模型出現(xiàn)問題了你可能連當(dāng)初是怎么量化出來的都查不到了。我在項(xiàng)目里會(huì)要求每次量化產(chǎn)出一個(gè)配置文件記錄完整的參數(shù)和數(shù)據(jù)集哈希值并把配置文件也納入版本管理。這個(gè)做法成本很低但能在后續(xù)排查問題時(shí)省下大量時(shí)間。你也可以試試。