3.1.2 相關性過濾
方差挑選完畢之后,我們就要考慮下一個問題:相關性了。我們希望選出與標簽相關且有意義的特征,因為這樣的
特征能夠為我們提供大量信息。如果特征與標簽無關,那只會白白浪費我們的計算內存,可能還會給模型帶來噪
音。在sklearn當中,我們有三種常用的方法來評判特征與標簽之間的相關性:卡方,F檢驗,互信息
3.1.2.1 卡方過濾
卡方過濾是專門針對離散型標簽(即分類問題)的相關性過濾。卡方檢驗類feature_selection.chi2計算每個非負
特征和標簽之間的卡方統計量,並依照卡方統計量由高到低為特征排名。再結合feature_selection.SelectKBest
這個可以輸入”評分標准“來選出前K個分數最高的特征的類,我們可以借此除去最可能獨立於標簽,與我們分類目
的無關的特征。
另外,如果卡方檢驗檢測到某個特征中所有的值都相同,會提示我們使用方差先進行方差過濾。並且,剛才我們已
經驗證過,當我們使用方差過濾篩選掉一半的特征后,模型的表現時提升的。因此在這里,我們使用threshold=中
位數時完成的方差過濾的數據來做卡方檢驗(如果方差過濾后模型的表現反而降低了,那我們就不會使用方差過濾
后的數據,而是使用原數據):
from sklearn.ensemble import RandomForestClassifier as RFC from sklearn.model_selection import cross_val_score from sklearn.feature_selection import SelectKBest from sklearn.feature_selection import chi2 #假設在這里我一直我需要300個特征 X_fschi = SelectKBest(chi2, k=300).fit_transform(X_fsvar, y) X_fschi.shape
驗證一下模型的效果如何:
cross_val_score(RFC(n_estimators=10,random_state=0),X_fschi,y,cv=5).mean()
可以看出,模型的效果降低了,這說明我們在設定k=300的時候刪除了與模型相關且有效的特征,我們的K值設置
得太小,要么我們需要調整K值,要么我們必須放棄相關性過濾。當然,如果模型的表現提升,則說明我們的相關
性過濾是有效的,是過濾掉了模型的噪音的,這時候我們就保留相關性過濾的結果。
3.1.2.2 選取超參數K
那如何設置一個最佳的K值呢?在現實數據中,數據量很大,模型很復雜的時候,我們也許不能先去跑一遍模型看
看效果,而是希望最開始就能夠選擇一個最優的超參數k。那第一個方法,就是我們之前提過的學習曲線:
#======【TIME WARNING: 5 mins】======# %matplotlib inline import matplotlib.pyplot as plt
score = [] for i in range(390,200,-10): X_fschi = SelectKBest(chi2, k=i).fit_transform(X_fsvar, y) once = cross_val_score(RFC(n_estimators=10,random_state=0),X_fschi,y,cv=5).mean() score.append(once) plt.plot(range(350,200,-10),score) plt.show()

通過這條曲線,我們可以觀察到,隨着K值的不斷增加,模型的表現不斷上升,這說明,K越大越好,數據中所有的
特征都是與標簽相關的。但是運行這條曲線的時間同樣也是非常地長,接下來我們就來介紹一種更好的選擇k的方
法:看p值選擇k。
卡方檢驗的本質是推測兩組數據之間的差異,其檢驗的原假設是”兩組數據是相互獨立的”。卡方檢驗返回卡方值和
P值兩個統計量,其中卡方值很難界定有效的范圍,而p值,我們一般使用0.01或0.05作為顯著性水平,即p值判斷
的邊界,具體我們可以這樣來看:
P值 =<0.05或0.01 >0.05或0.01
拒絕原假設,接受備擇假設 接受原假設
從特征工程的角度,我們希望選取卡方值很大,p值小於0.05的特征,即和標簽是相關聯的特征。而調用
SelectKBest之前,我們可以直接從chi2實例化后的模型中獲得各個特征所對應的卡方值和P值。
chivalue, pvalues_chi = chi2(X_fsvar,y)
#k取多少?我們想要消除所有p值大於設定值,比如0.05或0.01的特征:
k = chivalue.shape[0] - (pvalues_chi > 0.05).sum()
#X_fschi = SelectKBest(chi2, k=填寫具體的k).fit_transform(X_fsvar, y)
#cross_val_score(RFC(n_estimators=10,random_state=0),X_fschi,y,cv=5).mean()
可以觀察到,所有特征的p值都是0,這說明對於digit recognizor這個數據集來說,方差驗證已經把所有和標簽無
關的特征都剔除了,或者這個數據集本身就不含與標簽無關的特征。在這種情況下,舍棄任何一個特征,都會舍棄
對模型有用的信息,而使模型表現下降,因此在我們對計算速度感到滿意時,我們不需要使用相關性過濾來過濾我
們的數據。如果我們認為運算速度太緩慢,那我們可以酌情刪除一些特征,但前提是,我們必須犧牲模型的表現。
接下來,我們試試看用其他的相關性過濾方法驗證一下我們在這個數據集上的結論
3.1.2.3 F檢驗
F檢驗,又稱ANOVA,方差齊性檢驗,是用來捕捉每個特征與標簽之間的線性關系的過濾方法。它即可以做回歸也
可以做分類,因此包含feature_selection.f_classif(F檢驗分類)和feature_selection.f_regression(F檢驗回
歸)兩個類。其中F檢驗分類用於標簽是離散型變量的數據,而F檢驗回歸用於標簽是連續型變量的數據。
和卡方檢驗一樣,這兩個類需要和類SelectKBest連用,並且我們也可以直接通過輸出的統計量來判斷我們到底要
設置一個什么樣的K。需要注意的是,F檢驗在數據服從正態分布時效果會非常穩定,因此如果使用F檢驗過濾,我
們會先將數據轉換成服從正態分布的方式。
F檢驗的本質是尋找兩組數據之間的線性關系,其原假設是”數據不存在顯著的線性關系“。它返回F值和p值兩個統
計量。和卡方過濾一樣,我們希望選取p值小於0.05或0.01的特征,這些特征與標簽時顯著線性相關的,而p值大於
0.05或0.01的特征則被我們認為是和標簽沒有顯著線性關系的特征,應該被刪除。以F檢驗的分類為例,我們繼續
在數字數據集上來進行特征選擇
from sklearn.feature_selection import f_classif F, pvalues_f = f_classif(X_fsvar,y) k = F.shape[0] - (pvalues_f > 0.05).sum() #X_fsF = SelectKBest(f_classif, k=填寫具體的k).fit_transform(X_fsvar, y) #cross_val_score(RFC(n_estimators=10,random_state=0),X_fsF,y,cv=5).mean()
得到的結論和我們用卡方過濾得到的結論一模一樣:沒有任何特征的p值大於0.01,所有的特征都是和標簽相關
的,因此我們不需要相關性過濾
3.1.2.4 互信息法
互信息法是用來捕捉每個特征與標簽之間的任意關系(包括線性和非線性關系)的過濾方法。和F檢驗相似,它既
可以做回歸也可以做分類,並且包含兩個類feature_selection.mutual_info_classif(互信息分類)和
feature_selection.mutual_info_regression(互信息回歸)。這兩個類的用法和參數都和F檢驗一模一樣,不過
互信息法比F檢驗更加強大,F檢驗只能夠找出線性關系,而互信息法可以找出任意關系。
互信息法不返回p值或F值類似的統計量,它返回“每個特征與目標之間的互信息量的估計”,這個估計量在[0,1]之間
取值,為0則表示兩個變量獨立,為1則表示兩個變量完全相關。以互信息分類為例的代碼如下:
from sklearn.feature_selection import mutual_info_classif as MIC result = MIC(X_fsvar,y) k = result.shape[0] - sum(result <= 0) #X_fsmic = SelectKBest(MIC, k=填寫具體的k).fit_transform(X_fsvar, y) #cross_val_score(RFC(n_estimators=10,random_state=0),X_fsmic,y,cv=5).mean()
所有特征的互信息量估計都大於0,因此所有特征都與標簽相關。
當然了,無論是F檢驗還是互信息法,大家也都可以使用學習曲線,只是使用統計量的方法會更加高效。當統計量
判斷已經沒有特征可以刪除時,無論用學習曲線如何跑,刪除特征都只會降低模型的表現。當然了,如果數據量太
龐大,模型太復雜,我們還是可以犧牲模型表現來提升模型速度,一切都看大家的具體需求
3.1.3 過濾法總結
到這里我們學習了常用的基於過濾法的特征選擇,包括方差過濾,基於卡方,F檢驗和互信息的相關性過濾,講解
了各個過濾的原理和面臨的問題,以及怎樣調這些過濾類的超參數。通常來說,我會建議,先使用方差過濾,然后
使用互信息法來捕捉相關性,不過了解各種各樣的過濾方式也是必要的