Skip to content

[PyTorch] 透過給予 Loss 權重,試圖解決資料不平衡的情況

Last Updated on 2021-07-05 by Clay

在這裡紀錄我自己在調適模型的一些經驗,對於熟練者、高手大神們來說可能微不足道,但是或許可以參考一下。

今天我想討論的就是在訓練過程中,『資料不平衡』的狀況。資料不平衡是件相當恐怖的事情,以二分類來舉例,可能我 Label_A 的資料有 1000 筆,然而 Label_B 的資料卻只有 10 筆。那這時候我們建立一個分類器模型,會有什麼樣的訓練結果呢?

是的,我們的模型恐怕是只會一面倒地將所有的分類結果都猜是 Label_A,畢竟從 Loss function 來看這樣的誤差就很低了,不會特別再改動模型的權重。

這樣當然不是我們想要的結果。我在實際訓練模型時碰到這樣的狀況,在網路上查詢過後大致有兩種比較明確的處理方法,在下面紀錄我測試的心得。

順帶一提,這篇文章中提及的方法都為 PyTorch 的框架下使用的,但我相信其他機器學習、深度學習的框架也有著同樣的處理方法。


一、資料採樣

對手頭上的資料進行採樣可能是很直觀的辦法:簡單來說,我們有 1000 筆 Label_A 的資料、有 10 筆 Label_B 的資料,直接進行訓練的話會導致模型傾向完全猜 A。

那麼,我們只隨機取 Label_A 的 10 筆資料不就好了?這樣一來,兩邊的資料就平衡了。

不過這樣的缺點也一目了然:假設我們的資料過少,那麼模型就相當難收斂,可能就只會亂猜 —— 這樣的話,可能會比一面倒地猜 A 還要糟糕。

另外,就算模型在當前的測試資料集上分數很高,可能也缺乏某種特定特徵的分辨能力 (畢竟某部份訓練資料被排除了)。

不過當資料都很多的情況下,我覺得還是值得一試的。


二、給予 Loss 不同的權重

這就是我今天主要想紀錄的主題:通過給予 Loss 不同標籤的權重,達成讓模型也懂得猜另外一種標籤的目標。

就這樣說好了,今天模型是父母,膝下有一對姊弟。姊姊向來在課業上表現優秀、弟弟則頑劣不堪,成日與朋友鬼混,絲毫沒有用心在課業上。

今天,倆姊弟同時考糟了。父母對於一向用功的姊姊大發雷霆、對於平日渾渾噩噩的弟弟則嘆了一口氣就算了。

這就是『權重』。 (以上舉例,與真實世界人、事、時、地、物均無關。)

今天我們將模型猜錯 Label_A 的權重保持不變、可是在模型猜錯 Label_B 的時候 Loss 乘上一個係數 —— 這樣一來,為了能降低 Loss ,在模型回頭去更新權重網路時就會自動修正成要『猜對 Label_B』,而這也剛好就是我們想要達成的結果。

我順帶在這裡紀錄 PyTorch 當中 Binary Cross Entropy 的權重給予方法:

可以看到,我們可以直接設定 Weight 輸入 BCELoss 當中。

像我就會在訓練過程中直接設定 Weight。在這裡,我設定 label == 1 時權重為 4、然而 label == 0 時權重為 1。

直接放入 BECLoss() 當中就可以正常發揮作用了。

不過要小心的是,權重該調多少可能跟資料集中標籤的比例有很大的關係,甚至有可能影響到真正的分類結果。這點上我也沒有什麼好的答案,只能實際試試看來決定權重了。


追述

事實上,在面對不平衡的資料時還有許多可以嘗試的方法。比如說使用 GAN 生成資料 (對於 NLP 可能不一定合適)、比如說使用 Ensemble 的方法來提昇分類效果 ......

總地來說,不平衡的資料會是是訓練模型過程中非常麻煩的困境,有時候甚至得多取得一些特徵才能很好地進行分類。

網路上很多的說法是將其認定為『瑕疵檢測』的任務來處理,不過我認為可能對於圖像處理比較適合、對於不平衡標籤的文字資料來說可能這個概念有點模型。若我的想法有任何謬誤之處,還請不吝指出。

希望大家都可以訓練好自己的模型,因為我也希望我的模型能有好的結果。


Reference


Read More

Leave a Reply