蒸餾原理與實(shí)戰(zhàn):讓輕量模型繼承大模型智慧)
1. 先搞清楚知識(shí)蒸餾到底解決了什么問題1.1 大模型的“能”與“不能”這兩年被聊得最多的一個(gè)詞就是“大模型”。參數(shù)規(guī)模從幾億漲到幾千億效果確實(shí)好但部署起來也真頭疼。我自己在某個(gè)項(xiàng)目里試過把一套較大規(guī)模的模型落到普通服務(wù)器上光是顯存占用就讓人頭疼——推理一張圖的延遲到了幾百毫秒更別說同時(shí)承載多路請(qǐng)求了。你辛辛苦苦訓(xùn)練出一個(gè)效果很好的模型真正到了業(yè)務(wù)側(cè)往往面臨的現(xiàn)實(shí)是機(jī)器不夠、預(yù)算有限、延遲要求又高。這就像一個(gè)滿腹經(jīng)綸的教授什么都懂但他行動(dòng)遲緩、要住在高規(guī)格的套房里你總不能讓他天天跑一線去干體力活吧。所以行業(yè)里自然就有一條很清晰的需求能不能讓一個(gè)身材小、吃得少、跑得快的模型盡可能學(xué)會(huì)那個(gè)大而全的模型的本事知識(shí)蒸餾Knowledge Distillation干的就是這件事。它本質(zhì)上是一種模型壓縮和知識(shí)遷移的方法用一個(gè)訓(xùn)練好的大模型當(dāng)“老師”去教一個(gè)小模型當(dāng)“學(xué)生”。學(xué)生不需要從頭開始瞎摸索而是直接從老師那里接過已經(jīng)提煉好的經(jīng)驗(yàn)快速達(dá)到一個(gè)非常接近老師的水平。先說結(jié)論在圖像分類、目標(biāo)檢測(cè)、自然語(yǔ)言理解這些常見任務(wù)上一個(gè)設(shè)計(jì)得當(dāng)?shù)膶W(xué)生模型往往能壓縮老師模型80%~90%的參數(shù)量同時(shí)保住老師90%以上的精度——這個(gè)性價(jià)比在實(shí)際工程里是非常誘人的。1.2 蒸餾的本質(zhì)不是復(fù)制而是傳承很多人第一次接觸蒸餾時(shí)腦子里往往有個(gè)誤解蒸餾不就是讓大模型把答案告訴小模型嗎那真值標(biāo)簽直接給不就行了還用得著多此一舉問題就出在這里。傳統(tǒng)訓(xùn)練里我們用硬標(biāo)簽one-hot標(biāo)簽告訴模型“這張圖是貓”。模型學(xué)到的是一個(gè)唯一的正確答案它并不知道“這張圖為什么是貓它和狗有什么相似之處”。這就像你告訴學(xué)生一個(gè)事實(shí)但沒有告訴他推理過程。學(xué)生記住了一個(gè)孤立的答案遇到新題目照樣不會(huì)舉一反三。而知識(shí)蒸餾的核心是讓老師模型把自己對(duì)每個(gè)類別的“判斷傾向”告訴學(xué)生。還是拿貓舉例。一個(gè)訓(xùn)練好的大模型看到一張貓的照片它輸出的概率分布往往不全是“貓0.99”而是“貓0.92、老虎0.03、狗0.02、狐貍0.01”。這種分布里的那些微小的、看似無關(guān)的概率其實(shí)藏著大模型對(duì)物體相似性的理解貓和老虎都是貓科動(dòng)物所以它在特征空間上離得近。這個(gè)信息硬標(biāo)簽是完全丟掉的。知識(shí)蒸餾保留的正是這些“模糊地帶”的信息它們才是經(jīng)驗(yàn)里最有價(jià)值的部分。把大模型輸出的這份概率分布也叫軟標(biāo)簽?zāi)贸鰜懋?dāng)作小模型的監(jiān)督信號(hào)小模型就能學(xué)會(huì)老師那種對(duì)類別的細(xì)膩判斷。它的泛化能力往往比直接用原始數(shù)據(jù)硬訓(xùn)出來的同體型模型好上一截。我打一個(gè)更生活化的比方新手學(xué)做菜如果只看菜譜的最終步驟大概率做出來味道不對(duì)但如果在一位老師傅旁邊看著他調(diào)鹽、看火候、聞香氣哪怕老師傅什么都不說你也能慢慢摸到那種“手感”。知識(shí)蒸餾就是把老師傅的“手感”盡量數(shù)字化、傳遞下去。2. 蒸餾的三種主流玩法與選型2.1 離線蒸餾最經(jīng)典也最穩(wěn)妥離線蒸餾是最常見的蒸餾方式流程非常簡(jiǎn)單清晰先用完整數(shù)據(jù)訓(xùn)練或者直接拿開源預(yù)訓(xùn)練好的一個(gè)教師模型凍結(jié)教師模型參數(shù)讓它對(duì)訓(xùn)練數(shù)據(jù)輸出軟標(biāo)簽用這些軟標(biāo)簽通常會(huì)結(jié)合硬標(biāo)簽一起去訓(xùn)練學(xué)生模型。學(xué)生模型全程接觸不到教師模型的內(nèi)部結(jié)構(gòu)和參數(shù)它只看到一個(gè)黑盒輸出的結(jié)果。好處是解耦老師和學(xué)生可以是完全不同的網(wǎng)絡(luò)結(jié)構(gòu)甚至可以用不同框架訓(xùn)練。你既可以把Transformer蒸餾成CNN也可以把集成模型蒸餾成單模型。這一步在實(shí)際操作里幾乎沒有坑唯一要做的就是提前把教師模型的預(yù)測(cè)結(jié)果保存下來避免每次訓(xùn)練都重復(fù)跑一遍推理。很多同學(xué)圖省事直接邊訓(xùn)學(xué)生邊調(diào)教師結(jié)果一個(gè)epoch幾十分鐘一半時(shí)間浪費(fèi)在重復(fù)計(jì)算上。比較推薦的做法是**先離線把教師模型對(duì)全部訓(xùn)練集的軟標(biāo)簽預(yù)測(cè)出來存成文件訓(xùn)練學(xué)生模型時(shí)直接讀取。**這個(gè)文件可以當(dāng)成一種“預(yù)計(jì)算特征”既能省時(shí)間又能避免訓(xùn)練過程中教師和學(xué)生的耦合帶來的不確定性。2.2 在線蒸餾當(dāng)數(shù)據(jù)本身也是稀缺資源離線蒸餾的前提是你手里有一套高質(zhì)量的訓(xùn)練數(shù)據(jù)并且能承擔(dān)兩階段的訓(xùn)練開銷。但有些場(chǎng)景里數(shù)據(jù)本身就是稀缺品比如醫(yī)療影像、工業(yè)缺陷檢測(cè)——標(biāo)注樣本就那么幾百?gòu)埬氵B教師模型都訓(xùn)練不出好效果更別說蒸餾了。這時(shí)候可以試試在線蒸餾。在線蒸餾的核心思路是讓教師模型和學(xué)生模型協(xié)同訓(xùn)練兩個(gè)模型一起看數(shù)據(jù)互相學(xué)習(xí)甚至教師模型本身也在持續(xù)更新。其中最出名的一種做法是“互蒸餾”兩個(gè)結(jié)構(gòu)不同的模型互相從對(duì)方的預(yù)測(cè)中學(xué)習(xí)最后把它們?nèi)诤铣梢粋€(gè)更強(qiáng)的模型。這種方式相當(dāng)于老師和學(xué)生一起成長(zhǎng)單看誰都不是最終的權(quán)威但兩者互相糾正之后最終收斂出來的效果往往能超過任何單個(gè)模型直接訓(xùn)練的結(jié)果。在線蒸餾我個(gè)人用的不算多但它確實(shí)能解決一個(gè)很現(xiàn)實(shí)的痛點(diǎn)當(dāng)你的數(shù)據(jù)量不夠訓(xùn)練一個(gè)足夠強(qiáng)的教師模型時(shí)別再死磕離線蒸餾了不如讓兩個(gè)模型在訓(xùn)練過程中互相拉一把用集體的智慧頂替單個(gè)權(quán)威。2.3 特征蒸餾在細(xì)節(jié)里摳收益如果你盯著的目標(biāo)不是分類任務(wù)而是目標(biāo)檢測(cè)、語(yǔ)義分割這類對(duì)空間信息很敏感的任務(wù)那么只蒸logits輸出層的得分向量往往不太夠用。道理也很直白這些任務(wù)最終輸出的是一個(gè)框、一張分割圖模型中間層提取出來的特征才是關(guān)鍵。那些邊緣、紋理、語(yǔ)義區(qū)域的表達(dá)光靠最后輸出的概率分布沉淀不下來。特征蒸餾的做法是把學(xué)生模型中間層的特征圖拉向教師模型對(duì)應(yīng)層的特征圖讓兩者的特征表達(dá)盡量一致。聽起來直接但實(shí)際操作有一點(diǎn)門檻師生模型的通道數(shù)很可能對(duì)不上你得先加一層適配模塊去對(duì)齊維度另外中間層特征圖的數(shù)值尺度也千差萬別直接算均方誤差很可能讓訓(xùn)練爆炸。一個(gè)比較實(shí)用的小技巧是在算特征蒸餾損失之前先對(duì)教師和學(xué)生特征圖分別做一次歸一化。如果還想更寬松一點(diǎn)可以只對(duì)通道維度做全局平均池化再把兩者拉近也就是所謂的“蒸餾要的不是像素級(jí)對(duì)齊而是語(yǔ)義級(jí)對(duì)齊”——作為老師教會(huì)學(xué)生抓住重點(diǎn)就足夠了沒必要連細(xì)枝末節(jié)的紋理都一一復(fù)刻。3. 核心參數(shù)背后的原理溫度T、軟標(biāo)簽與損失函數(shù)3.1 溫度T到底在調(diào)什么知識(shí)蒸餾里有個(gè)繞不開的參數(shù)溫度T。公式也不復(fù)雜就是在softmax里加一個(gè)溫度系數(shù)。相比普通的softmax蒸餾版softmax把每個(gè)logit除以T再做歸一化。當(dāng)T等于1的時(shí)候就是普通的softmax當(dāng)T大于1時(shí)輸出的概率分布就會(huì)變得更加平滑各類別之間的差距被縮小那些原本很小但不為零的概率會(huì)被放大出來。這一放大藏在“錯(cuò)誤答案”里的相似性信息就浮現(xiàn)了。實(shí)際操作里怎么選T我看過不少新手上來就設(shè)一個(gè)50、100的大數(shù)值結(jié)果學(xué)生模型怎么訓(xùn)都訓(xùn)不好。原因很好理解溫度越高分布越平到最后所有類別都趨向同一個(gè)概率等于把老師的判斷完全抹平成噪音了學(xué)生什么有效信息都學(xué)不到。我自己的經(jīng)驗(yàn)是T取2到6之間比較穩(wěn)妥。分類任務(wù)里T4左右往往能兼顧“軟化”和“信息量”檢測(cè)或更復(fù)雜的任務(wù)T2的效果我體感更好。說到底溫度只是一個(gè)手段讓概率分布里的“暗信息”被放大到學(xué)生模型能感知到的程度就夠了。你可以跑一個(gè)小批量先對(duì)比一下T在2、3、4、5下的loss走勢(shì)再?zèng)Q定用哪個(gè)值。3.2 軟標(biāo)簽為什么比硬標(biāo)簽更好教這一點(diǎn)我前面簡(jiǎn)單提過但值得再展開說幾句。傳統(tǒng)訓(xùn)練里模型拿到的監(jiān)督信號(hào)是硬標(biāo)簽——“圖片上就是貓”沒有任何商量的余地。硬標(biāo)簽信息量有限它對(duì)“這張圖的難點(diǎn)在哪”一無所知。而軟標(biāo)簽包含的是教師模型對(duì)輸入的全部判斷它有0.9以上的把握說這是貓又留了一點(diǎn)可能性給老虎和狐貍。學(xué)生模型收到這種帶梯度信息的監(jiān)督等于是拿到了“為什么這題選C”的完整解析過程。換個(gè)角度看學(xué)會(huì)硬標(biāo)簽?zāi)P椭皇钦业搅艘粋€(gè)分類邊界學(xué)會(huì)軟標(biāo)簽?zāi)P偷扔诶斫饬祟悇e在特征空間里的相對(duì)關(guān)系。這種相對(duì)關(guān)系才是泛化能力的來源。這里還有一個(gè)訓(xùn)練上的實(shí)際收益軟標(biāo)簽帶來的“暗知識(shí)”客觀上起到了一種正則化的效果。學(xué)生模型不會(huì)為了強(qiáng)行壓到0和1去學(xué)習(xí)尖銳的決策面而是學(xué)著老師那種“留有余地”的判斷風(fēng)格對(duì)噪聲和擾動(dòng)自然更穩(wěn)健一些。3.3 蒸餾損失與交叉熵?fù)p失怎么搭配工程上常用的蒸餾損失拆成兩部分第一部分是蒸餾損失。把教師和學(xué)生模型的logits分別除以溫度T再各自做softmax計(jì)算兩者的KL散度。注意這里KL散度是有方向性的一般把教師的分布當(dāng)作目標(biāo)學(xué)生的分布當(dāng)作預(yù)測(cè)讓學(xué)生的分布去擬合教師的分布。第二部分是常規(guī)的交叉熵?fù)p失。直接用學(xué)生模型的logits對(duì)真實(shí)硬標(biāo)簽計(jì)算。千萬別丟掉這部分因?yàn)榻處煹念A(yù)測(cè)不見得永遠(yuǎn)正確硬標(biāo)簽是“標(biāo)準(zhǔn)答案”能在教師判斷失誤的時(shí)候給學(xué)生兜底。總損失一般寫成加權(quán)和的形式。權(quán)重系數(shù)alpha取多少?zèng)]有一個(gè)萬能答案。alpha偏大學(xué)生學(xué)習(xí)教師風(fēng)格更多但可能繼承教師的錯(cuò)誤alpha偏小學(xué)生更依賴硬標(biāo)簽蒸餾的特色就變淡了。我個(gè)人做圖像任務(wù)時(shí)習(xí)慣把蒸餾損失權(quán)重放在0.7附近交叉熵權(quán)重在0.3附近先跑幾輪看收斂情況再微調(diào)。另外提醒一下最終蒸餾損失計(jì)算時(shí)KL散度部分記得乘上T的平方。原因在于除以T之后logits的梯度整體縮小了T倍乘回T的平方能把梯度尺度恢復(fù)回來不然溫度一高蒸餾損失的影響會(huì)被稀釋到幾乎不起作用。4. 實(shí)操?gòu)牧闩芡ㄒ粋€(gè)圖像分類蒸餾項(xiàng)目4.1 環(huán)境準(zhǔn)備與數(shù)據(jù)劃分說了一堆原理不如直接上一份能跑的實(shí)操。我用一個(gè)經(jīng)典的圖像分類數(shù)據(jù)集做演示你換成自己的業(yè)務(wù)數(shù)據(jù)流程一模一樣。環(huán)境方面推薦直接用深度學(xué)習(xí)框架PyTorch不需要裝任何額外庫(kù)所有蒸餾需要的操作用框架自帶接口就能實(shí)現(xiàn)。數(shù)據(jù)劃分上有一個(gè)小建議教師模型的訓(xùn)練集和學(xué)生模型的訓(xùn)練集最好是同一份數(shù)據(jù)但學(xué)生模型訓(xùn)練時(shí)隨機(jī)增強(qiáng)策略可以比教師訓(xùn)練時(shí)更激進(jìn)一些。原因在于教師模型輸出的是樣本在當(dāng)前增強(qiáng)下的軟標(biāo)簽學(xué)生模型如果能從不同視角的增強(qiáng)里學(xué)習(xí)泛化能力會(huì)更強(qiáng)。很多同學(xué)直接把教師訓(xùn)練用的那份增強(qiáng)原樣搬到學(xué)生訓(xùn)練里效果也沒問題但會(huì)錯(cuò)過這部分額外收益。4.2 搭建教師和學(xué)生模型教師模型選一個(gè)結(jié)構(gòu)相對(duì)深、參數(shù)量大的網(wǎng)絡(luò)。為了直觀我選一個(gè)預(yù)訓(xùn)練好的殘差網(wǎng)絡(luò)直接用torchvision里的接口加載權(quán)重學(xué)生模型則用手寫一個(gè)輕量網(wǎng)絡(luò)只保留三層卷積加一個(gè)全連接層參數(shù)量大約是教師的十分之一。這里有個(gè)很重要的實(shí)操細(xì)節(jié)**教師模型一定要先凍結(jié)參數(shù)。**之前有人問我蒸餾訓(xùn)練時(shí)為什么學(xué)生模型越訓(xùn)越差排查了半天發(fā)現(xiàn)是教師模型的梯度開關(guān)沒關(guān)導(dǎo)致優(yōu)化器順帶更新了教師參數(shù)。凍結(jié)教師模型很簡(jiǎn)單把參數(shù)requires_grad設(shè)為False再把模型切到eval模式確保BatchNorm和Dropout在推理時(shí)表現(xiàn)穩(wěn)定。學(xué)生模型沒有任何預(yù)訓(xùn)練權(quán)重就是一個(gè)從零開始訓(xùn)練的小網(wǎng)絡(luò)。你甚至可以給學(xué)生模型加上一個(gè)和教師模型結(jié)構(gòu)無關(guān)的自定義頭驗(yàn)證一下“結(jié)構(gòu)無關(guān)”這個(gè)特性。4.3 蒸餾訓(xùn)練的核心代碼先定義兩個(gè)計(jì)算函數(shù)一個(gè)是帶溫度系數(shù)的softmax一個(gè)是蒸餾損失。import torch import torch.nn as nn import torch.nn.functional as F def softmax_with_temperature(logits, temperature): return F.softmax(logits / temperature, dim1) def distillation_loss(student_logits, teacher_logits, temperature): student_soft softmax_with_temperature(student_logits, temperature) teacher_soft softmax_with_temperature(teacher_logits, temperature) # KL散度注意log概率在下目標(biāo)分布在上 return F.kl_div( torch.log(student_soft 1e-8), teacher_soft, reductionbatchmean ) * (temperature ** 2)隨后定義一個(gè)訓(xùn)練循環(huán)每次迭代里同時(shí)計(jì)算兩份損失def train_one_epoch(student_model, teacher_model, dataloader, optimizer, device, temperature, alpha): student_model.train() teacher_model.eval() total_loss 0.0 for images, labels in dataloader: images images.to(device) labels labels.to(device) optimizer.zero_grad() # 教師模型只走前向不計(jì)算梯度 with torch.no_grad(): teacher_logits teacher_model(images) # 學(xué)生模型正常前向 student_logits student_model(images) # 蒸餾損失學(xué)生對(duì)老師的軟標(biāo)簽 loss_distill distillation_loss(student_logits, teacher_logits, temperature) # 標(biāo)準(zhǔn)交叉熵學(xué)生對(duì)硬標(biāo)簽 loss_ce nn.CrossEntropyLoss()(student_logits, labels) # 組合損失 loss alpha * loss_distill (1 - alpha) * loss_ce loss.backward() optimizer.step() total_loss loss.item() return total_loss / len(dataloader)有幾個(gè)變量需要根據(jù)原項(xiàng)目調(diào)temperature4.0alpha0.7優(yōu)化器用SGD或者Adam都行學(xué)習(xí)率從一個(gè)常規(guī)的0.001開始跑。如果發(fā)現(xiàn)loss一直不降可以把學(xué)習(xí)率降到原來的十分之一試試。另外CrossEntropyLoss本身自帶softmax行為student_logits在算CE時(shí)不需要手動(dòng)做softmax而蒸餾損失里我們自己做了帶溫度的softmax千萬別再加一層否則梯度就亂了。4.4 評(píng)估與推理部署訓(xùn)練結(jié)束后學(xué)生模型直接進(jìn)入常規(guī)流程推理時(shí)不再需要教師模型也不用任何額外分支模型就是標(biāo)準(zhǔn)的輕量網(wǎng)絡(luò)。在驗(yàn)證集上如果數(shù)據(jù)不是特別復(fù)雜學(xué)生模型通常能穩(wěn)定達(dá)到教師精度的95%以上。這個(gè)環(huán)節(jié)我建議做一個(gè)對(duì)照實(shí)驗(yàn)?zāi)孟嗤Y(jié)構(gòu)的輕量網(wǎng)絡(luò)完全不加蒸餾只用硬標(biāo)簽從零訓(xùn)練。對(duì)比下來你會(huì)發(fā)現(xiàn)蒸餾過的學(xué)生在精度上大概率超過硬訓(xùn)版本而且收斂速度也更快。這個(gè)對(duì)照結(jié)果很有說服力是向團(tuán)隊(duì)展示蒸餾價(jià)值的最直觀證據(jù)。部署方面學(xué)生模型因?yàn)閰?shù)量和計(jì)算量都小可以直接走FNNDI原諒我這里說順嘴了是ONNX導(dǎo)出或者直接量化到FP16甚至INT8。蒸餾和量化剪枝并不沖突它們是可以疊加的壓縮手段。我見過不少方案是“先蒸餾、再剪枝、最后量化”三者疊加起來模型體積能壓縮到原來的幾十分之一。5. 用在哪里最劃算適用場(chǎng)景與邊界5.1 高價(jià)值落地場(chǎng)景知識(shí)蒸餾在幾個(gè)特定方向上性價(jià)比極高我梳理成表格方便對(duì)照?qǐng)鼍巴纯帱c(diǎn)蒸餾的收益移動(dòng)端App設(shè)備算力受限、電池電量敏感小模型保精度延遲從數(shù)百毫秒降到幾十毫秒邊緣設(shè)備推理內(nèi)存和算力雙緊蒸餾后可省下大塊內(nèi)存甚至跑在MCU級(jí)別設(shè)備上高并發(fā)在線服務(wù)GPU資源有限、算力成本高單卡并發(fā)數(shù)翻倍吞吐提升且精度勉強(qiáng)不掉多任務(wù)學(xué)習(xí)多個(gè)模型部署占資源用一套學(xué)生模型承接多個(gè)教師的能力另外還有一種非常有價(jià)值的玩法把一個(gè)強(qiáng)集成模型比如多個(gè)模型投票的結(jié)果蒸餾成單個(gè)模型。集成模型的精度通常高于單模型但部署成本也高好幾倍。用蒸餾讓一個(gè)輕量學(xué)生模型去模仿集成模型的輸出分布最終效果往往遠(yuǎn)超任何一個(gè)單獨(dú)模型成本還只有一份。5.2 不適合硬上的場(chǎng)景我也得潑點(diǎn)冷水不是所有任務(wù)都適合蒸餾。如果你的數(shù)據(jù)本身質(zhì)量很差噪聲大、標(biāo)簽錯(cuò)得離譜那老師教的東西也未必對(duì)。硬標(biāo)簽還能靠模型自己糾錯(cuò)軟標(biāo)簽反而會(huì)把這些錯(cuò)誤傾向一并復(fù)制給學(xué)生。這種情況優(yōu)先做數(shù)據(jù)清洗別急著蒸餾。如果教師模型本身就欠擬合比如準(zhǔn)確率連及格線都沒到那你蒸餾出來的學(xué)生也不可能好到哪去。巧婦難為無米之炊老師都一知半解學(xué)生再聰明也學(xué)不到真本事。還有一類情況是預(yù)算實(shí)在緊張連訓(xùn)練一個(gè)大模型的時(shí)間和算力都拿不出來。那老老實(shí)實(shí)直接訓(xùn)練一個(gè)規(guī)模適中的模型就好沒必要硬湊蒸餾的形勢(shì)——蒸餾本身的訓(xùn)練開銷雖然不大但前期的教師模型訓(xùn)練成本是不能回避的。6. 避坑指南與經(jīng)驗(yàn)分享6.1 高頻踩坑點(diǎn)快查我整理了這半年被問到最多的問題做成一張速查表看到同款癥狀就能快速對(duì)癥下藥現(xiàn)象可能原因解決思路學(xué)生模型loss不降溫度T過大軟標(biāo)簽過于平滑調(diào)低溫度從T2開始重試學(xué)生模型精度低于硬訓(xùn)教師模型本身效果差或是alpha過高先檢查教師指標(biāo)再降低蒸餾損失權(quán)重蒸餾后精度反而上升了但推理變慢對(duì)“蒸餾”和“壓縮”概念混淆蒸餾不改變模型結(jié)構(gòu)耗時(shí)取決于模型本身學(xué)生模型訓(xùn)練震蕩明顯KL散度梯度尺度沒恢復(fù)確認(rèn)是否乘了T的平方并適當(dāng)調(diào)低學(xué)習(xí)率特征蒸餾不work特征圖直接算損失尺度不一致先對(duì)特征做歸一化再加一層適配器另外還有一個(gè)很隱蔽的坑有些框架里KL散度接口接收的輸入是log概率有些直接接收概率。如果你不確認(rèn)接口行為建議先在兩個(gè)隨機(jī)張量上手動(dòng)驗(yàn)證一下梯度方向。小小一個(gè)環(huán)節(jié)錯(cuò)了能讓整個(gè)訓(xùn)練曲線徹底亂掉。6.2 我的幾條實(shí)操心得做蒸餾做到現(xiàn)在我覺得最容易被低估、但影響最大的操作有兩個(gè)。第一**教師模型的預(yù)測(cè)不要直接拿來用先做一次置信度篩查。**如果某張樣本在教師模型那里的最大預(yù)測(cè)概率只有0.3說明教師自己都拿不準(zhǔn)這張樣本的軟標(biāo)簽里含的有效信息極少甚至可能是噪聲。把這類低置信度樣本從蒸餾訓(xùn)練集里剔除掉學(xué)生模型學(xué)得更干凈。我在某個(gè)業(yè)務(wù)場(chǎng)景里做過實(shí)驗(yàn)剔除10%低置信度樣本之后學(xué)生精度反而提升了0.3到0.5個(gè)點(diǎn)訓(xùn)練穩(wěn)定度也更高了。第二訓(xùn)練過程中可以動(dòng)態(tài)調(diào)整溫度T和alpha。前幾百個(gè)迭代先用較大T去學(xué)教師的大局觀等到loss下降趨緩再把溫度調(diào)低讓學(xué)生關(guān)注更精細(xì)的類別邊界。這個(gè)操作類似于先學(xué)框架再摳細(xì)節(jié)效果比我見過的固定參數(shù)方案都要穩(wěn)。6.3 蒸餾之后還能做什么把蒸餾做完相當(dāng)于你已經(jīng)拿到一個(gè)“小而強(qiáng)”的基座模型。接下來還想進(jìn)一步壓縮可以往兩個(gè)方向延伸。一是配合結(jié)構(gòu)化剪枝把學(xué)生模型里冗余通道裁掉。因?yàn)檎麴s后的模型對(duì)特征的集中度更高剪枝后精度掉得往往比普通模型更慢。先蒸后剪算是一條經(jīng)過驗(yàn)證的組合拳。二是做量化感知訓(xùn)練。在蒸餾階段就同步開啟偽量化操作讓模型在訓(xùn)練過程中適應(yīng)低精度表達(dá)這么一來最終導(dǎo)出的INT8模型損失會(huì)明顯更小。我之前的項(xiàng)目里同樣一個(gè)模型蒸餾后做INT8量化比直接量化精度回升了接近1個(gè)點(diǎn)。最后說一句掏心窩的話知識(shí)蒸餾不是那種“花里胡哨但用不上”的技術(shù)。它解決的是現(xiàn)實(shí)中每天都在發(fā)生的矛盾——模型越來越大機(jī)器卻永遠(yuǎn)不夠用。與其寄希望于還沒影兒的輕薄大模型不如認(rèn)認(rèn)真真把蒸餾這套成熟方法用起來讓大模型的智慧真正落地到每一臺(tái)普普通通的設(shè)備上。