簡介
這一節主要是為模型打補丁,在這之前筆者已經介紹並實現了幾種典型的機器學習模型,比如線性回歸、logistic回歸、最大熵、感知機、svm等,但目前它們都有一個共性,那就是構造的損失函數對每個樣本都是“一視同仁”的,即每個樣本在損失函數中權重都是一樣的,為了方便,可以將它們的損失函數做如下抽象:
這里\(L(\cdot)\)表示整體的損失函數,\(l(w,x_i,y_i)\)表示第\(i\)個樣本的損失函數,樣本量為\(N\),對具體情況有:
線性回歸有:
對logistic回歸:
對感知機:
對最大熵模型:
對svm:
代價敏感
如果對所有樣本的損失函數都考慮一樣的權重其實是有問題的,比如對於離群點、異常點這樣的數據,其實可以忽略掉其損失函數;特別地,對於類別不平衡分類問題,我們可以給少數類樣本更高的權重,而對於多數類更低的權重;另外對於像adaboost這樣的集成學習方法,我們可以迭代調整每個樣本點的權重以組合得到一個不錯的強分類器;所以在損失函數中考慮樣本權重,在某些場景下其實很有必要,簡單來說考慮樣本權重后,損失函數可以更新如下:
這里\(\alpha_i\)表示樣本\(i\)的權重
代碼實現
代碼實現其實很easy,根據目前的情況可以分為兩類:
(1)若采用的隨機梯度下降,可以對每次更新時的梯度\(dw\)乘以\(\alpha_i\);
(2)若采用對偶方式求解,則對其拉格朗日乘子做調整
具體地,我們為fit
函數添加一個參數sample_weight
以指定每個樣本的權重(對各模型的更新代碼就不帖了,見ml_models),接下來我們用svm測試不平衡分類的效果
from sklearn.datasets import make_classification
import matplotlib.pyplot as plt
import numpy as np
import os
os.chdir('../')
from ml_models import utils
from ml_models.svm import SVC
%matplotlib inline
X, y = make_classification(n_samples=500, n_features=2,
n_informative=2,n_redundant=0,
n_repeated=0, n_classes=2,
n_clusters_per_class=1,weights=[0.05, 0.95],
class_sep=3,flip_y=0.05, random_state=0)
svc_without_sample_weight=SVC(kernel='rbf',gamma=2.0,tol=0.01)
svc_without_sample_weight.fit(X,y)
utils.plot_decision_function(X=X,y=y,clf=svc_without_sample_weight)
#然后我們加大少數類的權重
weights=np.where(y==0,20,1)
svc_with_sample_weight=SVC(kernel='rbf',gamma=2.0,tol=0.01)
svc_with_sample_weight.fit(X,y,sample_weight=weights)
utils.plot_decision_function(X=X,y=y,clf=svc_with_sample_weight)