不均衡分類問題 之 class weight & sample weight

分類問題中,當不同類別的樣本量差異很大,即類分佈不平衡時,很容易影響分類結果。因此,需要進行對預測概率進行校正。

sklearn的做法是加權,加權就要涉及到class_weight和sample_weight,當不設置該參數時,默認所有類別的權值爲1。

類型權重 class_weight

字典類型,將類索引映射到權重值。對訓練集裏的每個類別加權,作用於損失函數(僅在訓練過程中)。從而使模型更加關注樣本數量少的類別。如果某類別的樣本數多,那麼它的權重就低,反之則權重就高.

應用場景
第一種是誤分類的代價很高。比如對合法用戶和非法用戶進行分類,將非法用戶分類爲合法用戶的代價很高,我們寧願將合法用戶分類爲非法用戶,這時可以人工再甄別,但是卻不願將非法用戶分類爲合法用戶。這時,我們可以適當提高非法用戶的權重class_weight={0:0.9, 1:0.1}。

第二種是樣本是高度失衡的,比如我們有合法用戶和非法用戶的二元樣本數據10000條,裏面合法用戶有9995條,非法用戶只有5條,如果我們不考慮權重,則我們可以將所有的測試集都預測爲合法用戶,這樣預測準確率理論上有99.95%,但是卻沒有任何意義。這時,我們可以選擇balanced(scikit-learn 邏輯迴歸類庫使用小結),讓類庫自動提高非法用戶樣本的權重。

參數設置
那麼應該如何設置class_weight呢?

  1. 通過字典形式傳入權重參數,如二分類問題y{0,1}y \in \{0,1\},class_weight={0:0.9, 1:0.1}
  2. 設置class_weight = 'balanced’
    此時,會自動調用from sklearn.utils.class_weight import compute_class_weight計算權重,平衡輸入樣本中各類別之間的權重。其計算公式爲:
    weight=n_samples/(n_classesnp.bincount(y))weight = n\_samples / (n\_classes * np.bincount(y))
import numpy as np

y = [0,0,0,0,0,0,0,0,1,1,1,1,1,1,2,2]  #標籤值,一共16個樣本

a = np.bincount(y)  # array([8, 6, 2], dtype=int64) 計算每個類別的樣本數量
aa = 1/a  #倒數 array([0.125     , 0.16666667, 0.5       ])
print(aa)

from sklearn.utils.class_weight import compute_class_weight 
class_weight = 'balanced'
classes = np.array([0, 1, 2])  #標籤類別
weight = compute_class_weight(class_weight, classes, y)
print(weight) # [0.66666667 0.88888889 2.66666667]

print(0.66666667*8)  #5.33333336
print(0.88888889*6)  #5.33333334
print(2.66666667*2) #5.33333334
# 這三個值非常接近
# 'balanced'計算出來的結果很均衡,使得懲罰項和樣本量對應

這種方式在原始的損失函數的基礎上乘以對應的sample_weight來計算最終的損失。這樣計算而來的損失函數不會因爲樣本不平衡而被“推向”樣本量偏少的類別中

樣本權重 sample_weight

numpy權重數組。對每個樣本加權(僅在訓練過程中),思路和類別權重類似,即樣本數多的類別樣本權重低,反之樣本權重高

應用場景
樣本不平衡,導致樣本不是總體樣本的無偏估計,從而可能導致我們的模型預測能力下降。遇到這種情況,我們可以通過調節樣本權重來嘗試解決這個問題。調節樣本權重的方法有兩種,第一種是在class_weight使用balanced。第二種是在調用fit函數時,通過sample_weight來自己調節每個樣本權重。

注意事項:

  1. 在sklearn中的邏輯迴歸時,如果上面兩種方法都用到了,那麼樣本的真正權重是class_weight * sample_weight.
    原理:樣本或類別的權重在訓練模型最終通過損失函數實現(以邏輯迴歸爲例):
    算法會把每個樣本的訓練損失乘以它的權重class_weight*sample_weight,損失函數爲:

    J(θ)=βln(θ)=βi=1m(y(i)log(hθ(x(i)))+(1y(i))log(1hθ(x(i))))J(\theta) =-\beta*\ln(\theta) = −\beta∑_{i=1}^m(y^{(i)}log(h_θ(x^{(i)}))+(1−y^{(i)})log(1−h_θ{(x^{(i)})}))

    其中,β=(class_weightsample_weight)\beta = (class\_weight∗sample\_weight)

    應用:做受衆選擇(人羣擴展、人羣定向)模型,若種子包括目標商品轉化和行爲用戶(購買較少,加入線上加購、收藏作爲正樣本),可考慮加大轉化用戶的樣本權重。

  2. 如果僅僅是類不平衡,則使用class_weight;
    如果類內樣本之間還不平衡,則使用sample_weights。

  3. 如果class_weight選擇balanced,那麼類庫會根據訓練樣本量來計算權重。某種類型樣本量越多,則權重越低,樣本量越少,則權重越高。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章