分类问题后处理技巧CAN,近乎零成本获取效果提升
文 | 蘇劍林
編 | 智商掉了一地
單位 | 追一科技
思想樸素卻不平凡的分類問題后處理技巧,淺顯易懂的講解,拿來吧你!
顧名思義,本文將會介紹一種用于分類問題的后處理技巧——CAN(Classification with Alternating Normalization)。經(jīng)過筆者的實測,CAN確實多數(shù)情況下能提升多分類問題的效果,而且?guī)缀鯖]有增加預(yù)測成本,因為它僅僅是對預(yù)測結(jié)果的簡單重新歸一化操作。
有趣的是,其實CAN的思想是非常樸素的,樸素到每個人在生活中都應(yīng)該用過同樣的思想。然而,CAN的論文卻沒有很好地說清楚這個思想,只是純粹形式化地介紹和實驗這個方法。本文的分享中,將會盡量將算法思想介紹清楚。
論文標(biāo)題:
When in Doubt: Improving Classification Performance with Alternating Normalization
論文鏈接:
https://arxiv.org/abs/2109.13449
思想例子
假設(shè)有一個二分類問題,模型對于輸入給出的預(yù)測結(jié)果是,那么我們就可以給出預(yù)測類別為;接下來,對于輸入,模型給出的預(yù)測結(jié)果是,這時候處于最不確定的狀態(tài),我們也不知道輸出哪個類別好。
但是,假如我告訴你:
類別必然是0或1其中之一;
兩個類別的出現(xiàn)概率各為0.5。
在這兩點先驗信息之下,由于前一個樣本預(yù)測結(jié)果為1,那么基于樸素的均勻思想,我們是否更傾向于將后一個樣本預(yù)測為0,以得到一個滿足第二點先驗的預(yù)測結(jié)果?
這樣的例子還有很多,比如做10道選擇題,前9道你都比較有信心,第10題完全不會只能瞎蒙,然后你一看發(fā)現(xiàn)前9題選A、B、C的都有就是沒有一個選D的,那么第10題在蒙的時候你會不會更傾向于選D?
這些簡單例子的背后,有著跟CAN同樣的思想,它其實就是用先驗分布來校正低置信度的預(yù)測結(jié)果,使得新的預(yù)測結(jié)果的分布更接近先驗分布。
2 不確定性
準(zhǔn)確來說,CAN是針對低置信度預(yù)測結(jié)果的后處理手段,所以我們首先要有一個衡量預(yù)測結(jié)果不確定性的指標(biāo)。常見的度量是“熵”[1],對于,定義為:
然而,雖然熵是一個常見選擇,但其實它得出的結(jié)果并不總是符合我們的直觀理解。比如對于和,直接套用公式得到,但就我們的分類場景而言,顯然我們會認(rèn)為比更不確定,所以直接用熵還不夠合理。
一個簡單的修正是只用前top-個概率值來算熵,不失一般性,假設(shè)是概率最高的個值,那么
其中。為了得到一個0~1范圍內(nèi)的結(jié)果,我們?nèi)樽罱K的不確定性指標(biāo)。
算法步驟
現(xiàn)在假設(shè)我們有個樣本需要預(yù)測類別,模型直接的預(yù)測結(jié)果是個概率分布,假設(shè)測試樣本和訓(xùn)練樣本是同分布的,那么完美的預(yù)測結(jié)果應(yīng)該有:
其中是類別的先驗分布,我們可以直接從訓(xùn)練集估計。也就是說,全體預(yù)測結(jié)果應(yīng)該跟先驗分布是一致的,但受限于模型性能等原因,實際的預(yù)測結(jié)果可能明顯偏離上式,這時候我們就可以人為修正這部分。
具體來說,我們選定一個閾值,將指標(biāo)小于的預(yù)測結(jié)果視為高置信度的,而大于等于的則是低置信度的,不失一般性,我們假設(shè)前個結(jié)果屬于高置信度的,而剩下的個屬于低置信度的。我們認(rèn)為高置信度部分是更加可靠的,所以它們不用修正,并且可以用它們來作為“標(biāo)準(zhǔn)參考系”來修正低置信度部分。
具體來說,對于,我們將與高置信度的一起,執(zhí)行一次 “行間標(biāo)準(zhǔn)化 :
這里的,其中乘除法都是element-wise的。不難發(fā)現(xiàn),這個標(biāo)準(zhǔn)化的目的是使得所有新的的平均向量等于先驗分布,也就是促使式(3)的成立。然而,這樣標(biāo)準(zhǔn)化之后,每個就未必滿足歸一化了,所以我們還要執(zhí)行一次 行內(nèi)標(biāo)準(zhǔn)化 :
理論上,這兩步可以交替迭代幾次(不過實驗結(jié)果顯示一次的效果就挺好了)。最后,我們只保留最新的作為原來第個樣本的預(yù)測結(jié)果,其余的均棄之不用。
注意,這個過程需要我們遍歷每個低置信度結(jié)果執(zhí)行,也就是說是逐個樣本進(jìn)行修正,而不是一次性修正的,每個都借助原始的高置信度結(jié)果組合來按照上述步驟迭代,雖然迭代過程中對應(yīng)的都會隨之更新,但那只是臨時結(jié)果,最后都是棄之不用的,每次修正都是用原始的。
參考實現(xiàn)
這是筆者給出的參考實現(xiàn)代碼:
#?預(yù)測結(jié)果,計算修正前準(zhǔn)確率 y_pred?=?model.predict(valid_generator.fortest(),?steps=len(valid_generator),?verbose=True ) y_true?=?np.array([d[1]?for?d?in?valid_data]) acc_original?=?np.mean([y_pred.argmax(1)?==?y_true]) print('original?acc:?%s'?%?acc_original)#?評價每個預(yù)測結(jié)果的不確定性 k?=?3 y_pred_topk?=?np.sort(y_pred,?axis=1)[:,?-k:] y_pred_topk?/=?y_pred_topk.sum(axis=1,?keepdims=True) y_pred_uncertainty?=?-(y_pred_topk?*?np.log(y_pred_topk)).sum(1)?/?np.log(k)#?選擇閾值,劃分高、低置信度兩部分 threshold?=?0.9 y_pred_confident?=?y_pred[y_pred_uncertainty?<?threshold] y_pred_unconfident?=?y_pred[y_pred_uncertainty?>=?threshold] y_true_confident?=?y_true[y_pred_uncertainty?<?threshold] y_true_unconfident?=?y_true[y_pred_uncertainty?>=?threshold]#?顯示兩部分各自的準(zhǔn)確率 #?一般而言,高置信度集準(zhǔn)確率會遠(yuǎn)高于低置信度的 acc_confident?=?(y_pred_confident.argmax(1)?==?y_true_confident).mean() acc_unconfident?=?(y_pred_unconfident.argmax(1)?==?y_true_unconfident).mean() print('confident?acc:?%s'?%?acc_confident) print('unconfident?acc:?%s'?%?acc_unconfident)#?從訓(xùn)練集統(tǒng)計先驗分布 prior?=?np.zeros(num_classes) for?d?in?train_data:prior[d[1]]?+=?1.prior?/=?prior.sum()#?逐個修改低置信度樣本,并重新評價準(zhǔn)確率 right,?alpha,?iters?=?0,?1,?1 for?i,?y?in?enumerate(y_pred_unconfident):Y?=?np.concatenate([y_pred_confident,?y[None]],?axis=0)for?j?in?range(iters):Y?=?Y**alphaY?/=?Y.sum(axis=0,?keepdims=True)Y?*=?prior[None]Y?/=?Y.sum(axis=1,?keepdims=True)y?=?Y[-1]if?y.argmax()?==?y_true_unconfident[i]:right?+=?1#?輸出修正后的準(zhǔn)確率 acc_final?=?(acc_confident?*?len(y_pred_confident)?+?right)?/?len(y_pred) print('new?unconfident?acc:?%s'?%?(right?/?(i?+?1.))) print('final?acc:?%s'?%?acc_final)實驗結(jié)果
那么,這樣的簡單后處理,究竟能帶來多大的提升呢?原論文給出的實驗結(jié)果是相當(dāng)可觀的:
▲原論文的實驗結(jié)果之一筆者也在CLUE上的兩個中文文本分類任務(wù)上做了實驗,顯示基本也有點提升,但沒那么可觀(驗證集結(jié)果):
| BERT | 60.06% | 56.80% |
| BERT + CAN | 60.52% | 56.86% |
| RoBERTa | 60.64% | 58.06% |
| RoBERTa + CAN | 60.95% | 58.00% |
大體上來說,類別數(shù)目越多,效果提升越明顯,如果類別數(shù)目比較少,那么可能提升比較微弱甚至?xí)陆?#xff08;當(dāng)然就算下降也是微弱的),所以這算是一個“幾乎免費的午餐”了。超參數(shù)選擇方面,上面給出的中文結(jié)果,只迭代了1次,的選擇為3、的選擇為0.9,經(jīng)過簡單的調(diào)試,發(fā)現(xiàn)這基本上已經(jīng)是比較優(yōu)的參數(shù)組合了。
還有的讀者可能想問前面說的“高置信度那部分結(jié)果更可靠”這個情況是否真的成立?至少在筆者的兩個中文實驗上它是明顯成立的,比如IFLYTEK任務(wù),篩選出來的高置信度集準(zhǔn)確率為0.63+,而低置信度集的準(zhǔn)確率只有0.22+;TNEWS任務(wù)類似,高置信度集準(zhǔn)確率為0.58+,而低置信度集的準(zhǔn)確率只有0.23+。
個人評價
最后再來綜合地思考和評價一下CAN。
首先,一個很自然的疑問是為什么不直接將所有低置信度結(jié)果跟高置信度結(jié)果拼在一起進(jìn)行修正,而是要逐個進(jìn)行修正?筆者不知道原論文作者有沒有對比過,但筆者確實實驗過這個想法,結(jié)果是批量修正有時跟逐個修正持平,但有時也會下降。其實也可以理解,CAN本意應(yīng)該是借助先驗分布,結(jié)合高置信度結(jié)果來修正低置信度的,在這個過程中,如果摻入越多的低置信度結(jié)果,那么最終的偏差可能就越大,因此理論上逐個修正會比批量修正更為可靠。
說到原論文,讀過CAN論文的讀者,應(yīng)該能發(fā)現(xiàn)本文介紹與CAN原論文大致有三點不同:
不確定性指標(biāo)的計算方法不同。按照原論文的描述,它最終的不確定性指標(biāo)計算方式應(yīng)該是
也就是說,它也是top-個概率算熵的形式,但是它沒有對這個概率值重新歸一化,并且它將其壓縮到0~1之間的因子是而不是(因為它沒有重新歸一化,所以只有除才能保證0~1之間)。經(jīng)過筆者測試,原論文的這種方式計算出來的結(jié)果通常明顯小于1,這不利于我們對閾值的感知和調(diào)試。
對CAN的介紹方式不同。原論文是純粹數(shù)學(xué)化、矩陣化地陳述CAN的算法步驟,而且沒有介紹算法的思想來源,這對理解CAN是相當(dāng)不友好的。如果讀者沒有自行深入思考算法原理,是很難理解為什么這樣的后處理手段就能提升分類效果的,而在徹底弄懂之后則會有一種故弄玄虛之感。
CAN的算法流程略有不同。原論文在迭代過程中還引入了參數(shù),使得式(4)變?yōu)?/p>
也就是對每個結(jié)果進(jìn)行次方后再迭代。當(dāng)然,原論文也沒有對此進(jìn)行解釋,而在筆者看來,該參數(shù)純粹是為了調(diào)參而引入的(參數(shù)多了,總能把效果調(diào)到有所提升),沒有太多實際意義。而且筆者自己在實驗中發(fā)現(xiàn),基本已經(jīng)是最優(yōu)選擇了,精調(diào)也很難獲得是實質(zhì)收益。
文章小結(jié)
本文介紹了一種名為CAN的簡單后處理技巧,它借助先驗分布來將預(yù)測結(jié)果重新歸一化,幾乎沒有增加多少計算成本就能提高分類性能。經(jīng)過筆者的實驗,CAN確實能給分類效果帶來一定提升,并且通常來說類別數(shù)越多,效果越明顯。
后臺回復(fù)關(guān)鍵詞【入群】
加入賣萌屋NLP/IR/Rec與求職討論群
后臺回復(fù)關(guān)鍵詞【頂會】
獲取ACL、CIKM等各大頂會論文集!
?
[1] ?蘇劍林. (Dec. 1, 2015). 《“熵”不起:從熵、最大熵原理到最大熵模型(一)》[Blog post]. Retrieved from https://kexue.fm/archives/3534
總結(jié)
以上是生活随笔為你收集整理的分类问题后处理技巧CAN,近乎零成本获取效果提升的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 以jieba为首的主流分词工具总结
- 下一篇: 算法工程师思维导图—数据结构与算法