3.1 Filter過濾法
過濾方法通常用作預處理步驟,特征選擇完全獨立於任何機器學習算法。它是根據各種統計檢驗中的分數以及相關
性的各項指標來選擇特征。
3.1.1 方差過濾
3.1.1.1 VarianceThreshold
這是通過特征本身的方差來篩選特征的類。比如一個特征本身的方差很小,就表示樣本在這個特征上基本沒有差
異,可能特征中的大多數值都一樣,甚至整個特征的取值都相同,那這個特征對於樣本區分沒有什么作用。所以無
論接下來的特征工程要做什么,都要優先消除方差為0的特征。VarianceThreshold有重要參數threshold,表示方
差的閾值,表示舍棄所有方差小於threshold的特征,不填默認為0,即刪除所有的記錄都相同的特征。
import pandas as pd data = pd.read_csv("digit recognizor.csv") X = data.iloc[:,1:] y = data.iloc[:,0]
from sklearn.feature_selection import VarianceThreshold selector = VarianceThreshold() #實例化,不填參數默認方差為0 X_var0 = selector.fit_transform(X) #獲取刪除不合格特征之后的新特征矩陣 #也可以直接寫成 X = VairanceThreshold().fit_transform(X) X_var0.shape
import numpy as np X_fsvar = VarianceThreshold(np.median(X.var().values)).fit_transform(X)
當特征是二分類時,特征的取值就是伯努利隨機變量,這些變量的方差可以計算為:
p*(1-p)
#若特征是伯努利隨機變量,假設p=0.8,即二分類特征中某種分類占到80%以上的時候刪除特征
X_bvar = VarianceThreshold(.8 * (1 - .8)).fit_transform(X) X_bvar.shape
3.1.1.2 方差過濾對模型的影響
我們這樣做了以后,對模型效果會有怎樣的影響呢?在這里,我為大家准備了KNN和隨機森林分別在方差過濾前和
方差過濾后運行的效果和運行時間的對比。KNN是K近鄰算法中的分類算法,其原理非常簡單,是利用每個樣本到
其他樣本點的距離來判斷每個樣本點的相似度,然后對樣本進行分類。KNN必須遍歷每個特征和每個樣本,因而特
征越多,KNN的計算也就會越緩慢。由於這一段代碼對比運行時間過長,所以我為大家貼出了代碼和結果。
1. 導入模塊並准備數據
#KNN vs 隨機森林在不同方差過濾效果下的對比 from sklearn.ensemble import RandomForestClassifier as RFC from sklearn.neighbors import KNeighborsClassifier as KNN from sklearn.model_selection import cross_val_score import numpy as np X = data.iloc[:,1:] y = data.iloc[:,0]
X_fsvar = VarianceThreshold(np.median(X.var().values)).fit_transform(X)
我們從模塊neighbors導入KNeighborsClassfier縮寫為KNN,導入隨機森林縮寫為RFC,然后導入交叉驗證模塊和
numpy。其中未過濾的數據是X和y,使用中位數過濾后的數據是X_fsvar,都是我們之前已經運行過的代碼。
2. KNN方差過濾前
#======【TIME WARNING:35mins +】======# cross_val_score(KNN(),X,y,cv=5).mean() #python中的魔法命令,可以直接使用%%timeit來計算運行這個cell中的代碼所需的時間 #為了計算所需的時間,需要將這個cell中的代碼運行很多次(通常是7次)后求平均值,因此運行%%timeit的時間會 #遠遠超過cell中的代碼單獨運行的時間
#======【TIME WARNING:4 hours】======# %%timeit cross_val_score(KNN(),X,y,cv=5).mean()
3. KNN方差過濾后
#======【TIME WARNING:20 mins+】======#
cross_val_score(KNN(),X_fsvar,y,cv=5).mean()
#======【TIME WARNING:2 hours】======# %%timeit cross_val_score(KNN(),X,y,cv=5).mean()
可以看出,對於KNN,
過濾后的效果十分明顯:准確率稍有提升,但平均運行時間減少了10分鍾,特征選擇過后算
法的效率上升了1/3。那隨機森林又如何呢?
4. 隨機森林方差過濾前
cross_val_score(RFC(n_estimators=10,random_state=0),X,y,cv=5).mean()
5. 隨機森林方差過濾后
cross_val_score(RFC(n_estimators=10,random_state=0),X_fsvar,y,cv=5).mean()
首先可以觀察到的是,隨機森林的准確率略遜於KNN,但運行時間卻連KNN的1%都不到,只需要十幾秒鍾。其
次,方差過濾后,隨機森林的准確率也微弱上升,但運行時間卻幾乎是沒什么變化,依然是11秒鍾。
為什么隨機森林運行如此之快?為什么方差過濾對隨機森林沒很大的有影響?這是由於兩種算法的原理中涉及到的
計算量不同。最近鄰算法KNN,單棵決策樹,支持向量機SVM,神經網絡,回歸算法,都需要遍歷特征或升維來進
行運算,所以他們本身的運算量就很大,需要的時間就很長,因此方差過濾這樣的特征選擇對他們來說就尤為重
要。但對於不需要遍歷特征的算法,比如隨機森林,它隨機選取特征進行分枝,本身運算就非常快速,因此特征選
擇對它來說效果平平。這其實很容易理解,無論過濾法如何降低特征的數量,隨機森林也只會選取固定數量的特征
來建模;而最近鄰算法就不同了,特征越少,距離計算的維度就越少,模型明顯會隨着特征的減少變得輕量。因
此,過濾法的主要對象是:需要遍歷特征或升維的算法們,而過濾法的主要目的是:在維持算法表現的前提下,幫
助算法們降低計算成本。
思考:過濾法對隨機森林無效,卻對樹模型有效?
從算法原理上來說,傳統決策樹需要遍歷所有特征,計算不純度后進行分枝,而隨機森林卻是隨機選擇特征進
行計算和分枝,因此隨機森林的運算更快,過濾法對隨機森林無用,對決策樹卻有用
在sklearn中,決策樹和隨機森林都是隨機選擇特征進行分枝(不記得的小伙伴可以去復習第一章:決策樹,
參數random_state),但決策樹在建模過程中隨機抽取的特征數目卻遠遠超過隨機森林當中每棵樹隨機抽取
的特征數目(比如說對於這個780維的數據,隨機森林每棵樹只會抽取10~20個特征,而決策樹可能會抽取
300~400個特征),因此,過濾法對隨機森林無用,卻對決策樹有用
也因此,在sklearn中,隨機森林中的每棵樹都比單獨的一棵決策樹簡單得多,高維數據下的隨機森林的計算
比決策樹快很多。
總結:
閾值很小
被過濾掉得特征比較少
模型表現 不會有太大影響
運行時間 可能降低模型的運行時間 基於方差很小的特征有多少 當方差很小的特征不多時 對模型沒有太大影響
閾值比較大
被過濾掉的特征有很多
模型表現
可能變更好,代表被濾掉的特征大部分是噪音
也可能變糟糕,代表被濾掉的特征中很多都是有效特征
運行時間
定能夠降低模型的運行時間
算法在遍歷特征時的計算越復雜,運行時間下降得越多
在我們的對比當中,我們使用的方差閾值是特征方差的中位數,因此屬於閾值比較大,過濾掉的特征比較多的情
況。我們可以觀察到,無論是KNN還是隨機森林,在過濾掉一半特征之后,模型的精確度都上升了。這說明被我們
過濾掉的特征在當前隨機模式(random_state = 0)下大部分是噪音。那我們就可以保留這個去掉了一半特征的數
據,來為之后的特征選擇做准備。當然,如果過濾之后模型的效果反而變差了,我們就可以認為,被我們過濾掉的
特征中有很多都有有效特征,那我們就放棄過濾,使用其他手段來進行特征選擇
3.1.1.3 選取超參數threshold
我們怎樣知道,方差過濾掉的到底時噪音還是有效特征呢?過濾后模型到底會變好還是會變壞呢?答案是:每個數
據集不一樣,只能自己去嘗試。這里的方差閾值,其實相當於是一個超參數,要選定最優的超參數,我們可以畫學
習曲線,找模型效果最好的點。但現實中,我們往往不會這樣去做,因為這樣會耗費大量的時間。我們只會使用閾
值為0或者閾值很小的方差過濾,來為我們優先消除一些明顯用不到的特征,然后我們會選擇更優的特征選擇方法
繼續削減特征數量