當數據預處理完成后,我們需要選擇有意義的特征輸入機器學習的算法和模型進行訓練。通常來說,從兩個方面考慮來選擇特征:
·
特征是否發散:如果一個特征不發散,例如方差接近於0,也就是說樣本在這個特征上基本上沒有差異,這個特征對於樣本的區分並沒有什么用。
·
特征與目標的相關性:這點比較顯見,與目標相關性高的特征,應當優選選擇。除方差法外,本文介紹的其他方法均從相關性考慮。
特征選擇主要包括:Filter Method 過濾法, Wrapper Method 包裝法和Embedded Method 嵌入法。本文結合sklearn中的feature_selection庫來進行特征選擇的詳細介紹。
1 Filter Method 過濾法
通過統計學的方法對每個feature給出一個score, 通過score對特征進行排序,然后從中選取score最高的子集. 這種方法僅僅是對每個feature進行獨立考慮,沒有考慮到feature之間的依賴性或相關性. 常用的方法有: 卡方檢驗,信息增益等。
1.1 方差選擇法
使用方差選擇法,先要計算各個特征的方差,然后根據閾值,選擇方差大於閾值的特征。
使用feature_selection庫的VarianceThreshold類來選擇特征的代碼如下:
from sklearn.feature_selection import VarianceThreshold #方差選擇法,返回值為特征選擇后的數據 #參數threshold為方差的閾值 VarianceThreshold(threshold=3).fit_transform(iris.data)
1.2 相關系數法
使用相關系數法,先要計算各個特征對目標值的相關系數以及相關系數的P值。
用feature_selection庫的SelectKBest類結合相關系數來選擇特征的代碼如下:
from sklearn.feature_selection import SelectKBest from scipy.stats import pearsonr #選擇K個最好的特征,返回選擇特征后的數據 #第一個參數為計算評估特征是否好的函數,該函數輸入特征矩陣和目標向量,輸出二元組(評分,P值)的數組,數組第i項為第i個特征的評分和P值。在此定義為計算相關系數 #參數k為選擇的特征個數 SelectKBest(lambda X, Y: array(map(lambda x:pearsonr(x, Y), X.T)).T, k=2).fit_transform(iris.data, iris.target)
1.3 卡方檢驗
經典的卡方檢驗是檢驗定性自變量對定性因變量的相關性。假設自變量有N種取值,因變量有M種取值,考慮自變量等於i且因變量等於j的樣本頻數的觀察值與期望的差距,構建統計量:
這個統計量的含義簡而言之就是自變量對因變量的相關性。
用feature_selection庫的SelectKBest類結合卡方檢驗來選擇特征的代碼如下:
from sklearn.feature_selection import SelectKBest from sklearn.feature_selection import chi2 #選擇K個最好的特征,返回選擇特征后的數據 SelectKBest(chi2, k=2).fit_transform(iris.data, iris.target)
1.4 互信息法
經典的互信息也是評價定性自變量對定性因變量的相關性的,互信息計算公式如下:
為了處理定量數據,最大信息系數法被提出,使用feature_selection庫的SelectKBest類結合最大信息系數法來選擇特征的代碼如下:
from sklearn.feature_selection import SelectKBest from minepy import MINE #由於MINE的設計不是函數式的,定義mic方法將其為函數式的,返回一個二元組,二元組的第2項設置成固定的P值0.5 def mic(x, y): m = MINE() m.compute_score(x, y) return (m.mic(), 0.5) #選擇K個最好的特征,返回特征選擇后的數據 SelectKBest(lambda X, Y: array(map(lambda x:mic(x, Y), X.T)).T, k=2).fit_transform(iris.data, iris.target)
2 Wrapper Method 包裝法
和filter method 相比, wrapper method 考慮到了feature 之間的相關性, 通過考慮feature的組合對於model性能的影響. 比較不同組合之間的差異,選取性能最好的組合. 比如recursive feature selection。
2.1 遞歸特征消除法
遞歸消除特征法使用一個基模型來進行多輪訓練,每輪訓練后,消除若干權值系數的特征,再基於新的特征集進行下一輪訓練。使用feature_selection庫的RFE類來選擇特征的代碼如下:
from sklearn.feature_selection import RFE from sklearn.linear_model import LogisticRegression #遞歸特征消除法,返回特征選擇后的數據 #參數estimator為基模型 #參數n_features_to_select為選擇的特征個數 RFE(estimator=LogisticRegression(), n_features_to_select=2).fit_transform(iris.data, iris.target)
3 Embedded Method 嵌入法
結合前面二者的優點, 在模型建立的時候,同時計算模型的准確率. 最常見的embedded method 是 regularization methods(簡單來說就是通過增加penalization coefficients來約束模型的復雜度)。
3.1 基於懲罰項的特征選擇法
使用帶懲罰項的基模型,除了篩選出特征外,同時也進行了降維。使用feature_selection庫的SelectFromModel類結合帶L1懲罰項的邏輯回歸模型,來選擇特征的代碼如下:
from sklearn.feature_selection import SelectFromModel from sklearn.linear_model import LogisticRegression #帶L1懲罰項的邏輯回歸作為基模型的特征選擇 SelectFromModel(LogisticRegression(penalty="l1", C=0.1)).fit_transform(iris.data, iris.target)
L1懲罰項降維的原理在於保留多個對目標值具有同等相關性的特征中的一個,所以沒選到的特征不代表不重要。故,可結合L2懲罰項來優化。具體操作為:若一個特征在L1中的權值為1,選擇在L2中權值差別不大且在L1中權值為0的特征構成同類集合,將這一集合中的特征平分L1中的權值,故需要構建一個新的邏輯回歸模型:
View Code
from sklearn.linear_model import LogisticRegression class LR(LogisticRegression): def __init__(self, threshold=0.01, dual=False, tol=1e-4, C=1.0, fit_intercept=True, intercept_scaling=1, class_weight=None, random_state=None, solver='liblinear', max_iter=100, multi_class='ovr', verbose=0, warm_start=False, n_jobs=1): #權值相近的閾值 self.threshold = threshold LogisticRegression.__init__(self, penalty='l1', dual=dual, tol=tol, C=C, fit_intercept=fit_intercept, intercept_scaling=intercept_scaling, class_weight=class_weight, random_state=random_state, solver=solver, max_iter=max_iter, multi_class=multi_class, verbose=verbose, warm_start=warm_start, n_jobs=n_jobs) #使用同樣的參數創建L2邏輯回歸 self.l2 = LogisticRegression(penalty='l2', dual=dual, tol=tol, C=C, fit_intercept=fit_intercept, intercept_scaling=intercept_scaling, class_weight = class_weight, random_state=random_state, solver=solver, max_iter=max_iter, multi_class=multi_class, verbose=verbose, warm_start=warm_start, n_jobs=n_jobs) def fit(self, X, y, sample_weight=None): #訓練L1邏輯回歸 super(LR, self).fit(X, y, sample_weight=sample_weight) self.coef_old_ = self.coef_.copy() #訓練L2邏輯回歸 self.l2.fit(X, y, sample_weight=sample_weight) cntOfRow, cntOfCol = self.coef_.shape #權值系數矩陣的行數對應目標值的種類數目 for i in range(cntOfRow): for j in range(cntOfCol): coef = self.coef_[i][j] #L1邏輯回歸的權值系數不為0 if coef != 0: idx = [j] #對應在L2邏輯回歸中的權值系數 coef1 = self.l2.coef_[i][j] for k in range(cntOfCol): coef2 = self.l2.coef_[i][k] #在L2邏輯回歸中,權值系數之差小於設定的閾值,且在L1中對應的權值為0 if abs(coef1-coef2) < self.threshold and j != k and self.coef_[i][k] == 0: idx.append(k) #計算這一類特征的權值系數均值 mean = coef / len(idx) self.coef_[i][idx] = mean return self
使用feature_selection庫的SelectFromModel類結合帶L1以及L2懲罰項的邏輯回歸模型,來選擇特征的代碼如下:
from sklearn.feature_selection import SelectFromModel #帶L1和L2懲罰項的邏輯回歸作為基模型的特征選擇 #參數threshold為權值系數之差的閾值 SelectFromModel(LR(threshold=0.5, C=0.1)).fit_transform(iris.data, iris.target)
3.2 基於樹模型的特征選擇法
樹模型中GBDT也可用來作為基模型進行特征選擇,使用feature_selection庫的SelectFromModel類結合GBDT模型,來選擇特征的代碼如下:
from sklearn.feature_selection import SelectFromModel from sklearn.ensemble import GradientBoostingClassifier #GBDT作為基模型的特征選擇 SelectFromModel(GradientBoostingClassifier()).fit_transform(iris.data, iris.target)
4 sklearn數據包相關類功能整理
|
類
|
所屬方式
|
說明
|
|
VarianceThreshold
|
Filter
|
方差選擇法
|
|
SelectKBest
|
Filter
|
可選關聯系數、卡方校驗、最大信息系數作為得分計算的方法
|
|
RFE
|
Wrapper
|
遞歸地訓練基模型,將權值系數較小的特征從特征集合中消除
|
|
SelectFromModel
|
Embedded
|
訓練基模型,選擇權值系數較高的特征
|
參考:
https://blog.csdn.net/Lee20093905/article/details/79397803
https://www.cnblogs.com/jasonfreak/p/5448385.html
