特征选择过滤法-方差过滤、F检验、互信息法
過濾法
過濾法通常用作預(yù)處理步驟,特征選擇完全獨(dú)立于任何機(jī)器學(xué)習(xí)算法。它是根據(jù)各種統(tǒng)計(jì)檢驗(yàn)分?jǐn)?shù)和相關(guān)性指標(biāo)來選擇特征。
? ? ? ? 全部特征--->最佳特征子集--->算法--->模型評(píng)估
1.方差過濾 ---VarianceThreshold
這是一個(gè)通過特征本身的方差來篩選特征的類。比如一個(gè)特征的方差很小,就表示樣本在這個(gè)特征上基本沒有差異,可能特征中的大多數(shù)值都一樣,甚至整個(gè)特征的取值都相同,那么這個(gè)特征對(duì)于樣本區(qū)分沒有什么作用。所以無論接下來的特征工程要做什么,都要先消除方差為0的特征。VarianceThreshold有重要參數(shù)threshold,表示方差的閾值,表示舍棄所有方差小于threshold的特征,不填默認(rèn)為0,即刪除所有記錄都相同的特征。方差過濾示例代碼如下:
import pandas as pd data=pd.read_csv(r"F:\sklearn預(yù)處理數(shù)據(jù)集\digit recognizor.csv") x=data.iloc[:,1:] y=data.iloc[:,0] x.shape #(42000, 784) 此數(shù)據(jù)集有42000行,784個(gè)特征from sklearn.feature_selection import VarianceThreshold selector=VarianceThreshold() #實(shí)例化,不填參數(shù)默認(rèn)方差為0 x_var0=selector.fit_transform(x) #獲取刪除不合格特征之后的新特征矩陣 #也可以直接寫成x=VarianceThreshold().fit_transform(x) x_var0.shape #(42000, 708)?可以看出,在刪除了方差為0的特征之后,依然剩下708個(gè)特征,明顯還需要做進(jìn)一步的特征選擇,假如這里只想保留一半的特征,那么可以設(shè)定一個(gè)讓特征總數(shù)減半的閾值,只要找到特征方差的中位數(shù)并設(shè)為參數(shù)threshold的值。
import numpy as np x_fsvar=VarianceThreshold(np.median(x.var().values)).fit_transform(x) x_fsvar.shape-------------------------------代碼分割線---------------------------- (42000, 392)PS:當(dāng)特征是二分類時(shí),特征的取值就是伯努利隨機(jī)變量,這些變量的方差可以計(jì)算為:?Var[X]=p(1-p)。其中X是特征矩陣,p是二分類特征中的一類在這個(gè)特征中所占的概率(注:伯努利分布指的是對(duì)于隨機(jī)變量X有, 參數(shù)為p(0<p<1),如果它分別以概率p和1-p取1和0為值)
假設(shè)p=0.8,即二分類特征中某種分類占到80%以上的時(shí)候刪除特征。
x_bvar=VarianceThreshold(0.8*(1-0.8)).fit_transform(x) x_bvar.shape--------------------代碼分割線---------------------------(42000, 685)1.1方差過濾后對(duì)模型的影響?
為了檢驗(yàn)方差過濾后對(duì)模型的影響,這里分別用KNN和隨機(jī)森林兩種方法分別在方差過濾前和方差過濾后運(yùn)行的效果和運(yùn)行時(shí)間的對(duì)比。(KNN是K近鄰算法中的分類算法,其原理是利用每個(gè)樣本到其它樣本點(diǎn)的距離來判斷每個(gè)樣本點(diǎn)的相似度,然后進(jìn)行樣本分類。KNN必出遍歷每個(gè)特征和每個(gè)樣本,因而特征越多,KNN的計(jì)算越緩慢)完整代碼如下:
#KNN 和 隨機(jī)森林在不同方差過濾效果下的對(duì)比 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)#KNN-方差過濾前效果 cross_val_score(KNN(),x,y,cv=5).mean() %%timeit #計(jì)算代碼平均運(yùn)行時(shí)間 cross_val_score(KNN(),x,y,cv=5).mean() #KNN-方差過濾后效果 cross_val_score(KNN(),x_fsvar,y,cv=5).mean() %%timeit #計(jì)算代碼平均運(yùn)行時(shí)間 cross_val_score(KNN(),x_fsvar,y,cv=5).mean()#隨機(jī)森林-方差過濾前效果 cross_val_score(RFC(n_estimators=10,random_state=0),x,y,cv=5).mean() %%timeit #計(jì)算代碼平均運(yùn)行時(shí)間 cross_val_score(RFC(n_estimators=10,random_state=0),x,y,cv=5).mean() #隨機(jī)森林-方差過濾后效果 cross_val_score(RFC(n_estimators=10,random_state=0),x_fsvar,y,cv=5).mean() %%timeit #計(jì)算代碼平均運(yùn)行時(shí)間 cross_val_score(RFC(n_estimators=10,random_state=0),x_fsvar,y,cv=5).mean() -----------------------------------代碼分割線--------------------------------------- KNN-方差過濾前效果:0.965857142857143 KNN-方差過濾前時(shí)間:34.1 s ± 365 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)KNN-方差過濾后效果:0.966 KNN-方差過濾后時(shí)間:27.6 s ± 173 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)隨機(jī)森林-方差過濾前效果:0.9373571428571429 隨機(jī)森林-方差過濾前時(shí)間:11.5 s ± 305 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)隨機(jī)森林-方差過濾后效果:0.9390476190476191 隨機(jī)森林-方差過濾后時(shí)間:11.1 s ± 72 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)根據(jù)以上結(jié)果,可以觀察到隨機(jī)森林的準(zhǔn)確率略遜于KNN,但運(yùn)行時(shí)間比KNN短。方差過濾后,隨機(jī)森林和KNN的準(zhǔn)確率都微弱上升?,隨機(jī)森林運(yùn)行時(shí)間基本無明顯變化,而KNN運(yùn)行時(shí)間明顯減少。
Q:為什么隨機(jī)森林運(yùn)行如此之快?為什么方差過濾對(duì)隨機(jī)森林沒有很大的影響?
A:這是由于兩種算法的原理中涉及到的計(jì)算量不同。最近鄰算法KNN,單棵決策樹,支持向量機(jī)SVM,神經(jīng)網(wǎng)絡(luò),回歸算法,都需要遍歷特征或升維來進(jìn)行運(yùn)算,所以他們本身的運(yùn)算量就很大,需要的時(shí)間就很長,因此方差過濾這樣的特征選擇對(duì)他們來說尤為重要。但對(duì)于不需要遍歷特征的算法,比如隨機(jī)森林,它隨機(jī)選取特征進(jìn)行分枝,本身運(yùn)算就非常快速,因此特征選擇對(duì)它來說效果并不明顯。這其實(shí)很容易理解,無論過濾法如何降低特征的數(shù)量,隨機(jī)森林也只會(huì)選取固定數(shù)量的特征來建模;而最近鄰算法就不同了,特征越少,距離計(jì)算的維度就越少,模型明顯會(huì)隨著特征的減少而變得輕量。因此,
過濾法的主要對(duì)象是:需要遍歷特征或升維的算法
過濾法的主要目的是:在維持算法表現(xiàn)的前提下,幫助算法降低計(jì)算成本
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?--------------菜菜機(jī)器學(xué)習(xí)
Q:過濾法對(duì)隨機(jī)森林無效,卻對(duì)樹模型有效?
A: 從算法原理上來說,傳統(tǒng)決策樹需要遍歷所有特征,計(jì)算不純度后進(jìn)行分枝,而隨機(jī)森林卻是隨機(jī)抽取進(jìn)行計(jì)算和分枝。因此隨機(jī)森林的運(yùn)算更快,過濾法對(duì)隨機(jī)森林無用,對(duì)決策樹卻有用。
在sklearn中,決策樹和隨機(jī)森林都是隨機(jī)選擇特征進(jìn)行分枝,但決策樹在建模過程中隨 機(jī)抽取的特征數(shù)目卻遠(yuǎn)遠(yuǎn)超過隨機(jī)森林當(dāng)中每棵樹隨機(jī)抽取的特征數(shù)目(比如對(duì)于這個(gè)780維的數(shù)據(jù),隨機(jī)森林每棵樹只會(huì)抽取10-20個(gè)特征,而決策樹可能會(huì)抽取200~400個(gè)特征),因此,過濾法對(duì)隨機(jī)森林無用,卻對(duì)決策樹有用。也因此,在sklearn中,隨機(jī)森林中的每棵樹都比單獨(dú)的一棵決策樹簡單得多,高維數(shù)據(jù)下的隨機(jī)森林的計(jì)算比決策樹快很多。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?--------------菜菜機(jī)器學(xué)習(xí)
| 閾值很小? 被過濾掉的特征比較少? | 閾值較大 被過濾掉的特征比較少多 | |
| 模型表現(xiàn) | 不會(huì)有太大影響 | 可能變得更好,代表被濾掉的特征大部分是噪音;也可能變糟糕,代表被濾掉的特征中很多都是有效特征 |
| 運(yùn)行時(shí)間 | 可能降低模型的運(yùn)行時(shí)間基于方差很小的特征有多少 當(dāng)方差很小的特征不多時(shí),對(duì)模型沒有太大影響 | 一定能夠降低模型的運(yùn)行時(shí)間,算法在遍歷特征時(shí)的計(jì)算越復(fù)雜,運(yùn)行時(shí)間下降得越多 |
在我們的對(duì)比中,我們使用的方差閾值是特征方差中的中位數(shù),因此屬于閾值比較大,過濾掉的特征比較多的情況。無論是KNN還是隨機(jī)森林,在過濾掉一般特征之后,模型的精確度都上升了。這說明被我們過濾掉的特征在當(dāng)前模式下大部分都是噪音,那我們就可以保留這個(gè)去掉了一半特征的數(shù)據(jù),來為之后的特征選擇做準(zhǔn)備。當(dāng)然,如果過濾之后模型的效果變差了,我們就可以認(rèn)為,被我們過濾掉的特征中有很多都是有效特征,那就應(yīng)當(dāng)采取另一種方法進(jìn)行特征選擇。
2.相關(guān)性過濾
方差調(diào)訓(xùn)完畢后,接下來就考慮相關(guān)性了,常用的來評(píng)判特征與標(biāo)簽之間的相關(guān)性方法有:卡方檢驗(yàn),F檢驗(yàn),互信息法。
2.1卡方過濾
?????????卡方過濾是專門針對(duì)離散型標(biāo)簽(即分類問題)的相關(guān)性過濾。卡方檢驗(yàn)類feature_selection.chi2計(jì)算每個(gè)非負(fù)特征和標(biāo)簽之間的卡方統(tǒng)計(jì)量,并依照卡方統(tǒng)計(jì)量由高到低為特征排名。再結(jié)合feature_selection.SelectKBest?這個(gè)可以輸入“評(píng)分標(biāo)準(zhǔn)”來選出前K個(gè)分?jǐn)?shù)最高的特征的類,我們可以借此除去最可能獨(dú)立于標(biāo)簽,與我們分類目的無關(guān)的特征。
? ? ? ? 另外,如果卡方檢驗(yàn)檢測到某個(gè)特征中所有的值都相同,會(huì)提示我們適用方差先進(jìn)性方差過濾。并且,剛才我們已經(jīng)驗(yàn)證過,當(dāng)我們適用方差過濾篩掉一般特征之后,模型的表現(xiàn)是提升的,這里我們使用threshold=中位數(shù)時(shí)完成的方差過濾來做卡方檢驗(yàn)。
from sklearn.ensemble import RandomForestClassifier as RFC from sklearn.model_selection import cross_val_score #卡方檢驗(yàn) from sklearn.feature_selection import SelectKBest from sklearn.feature_selection import chi2 #假設(shè)這里需要300個(gè)特征 x_fschi=SelectKBest(chi2,k=300).fit_transform(x_fsvar,y) x_fschi.shape #(42000, 300) #驗(yàn)證模型效果 cross_val_score(RFC(n_estimators=10,random_state=0),x_fschi,y,cv=5).mean()---------------------------------------------------------------------------- 0.9344761904761905此時(shí)模型的效果降低了,說明在設(shè)定k=300的時(shí)候刪除了與模型相關(guān)且有效的特征,我們的k值設(shè)置得太小,需要重新調(diào)整k值,為了能夠選擇一個(gè)最優(yōu)的超參數(shù)k,在這里可畫出學(xué)習(xí)曲線:
%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(390,200,-10),score) plt.show()得到的學(xué)習(xí)曲線如圖:
? ? ? ? ? ? ? ? ? ? ?
通過這條曲線,可以觀察到,隨著k值的不斷增加,模型的表現(xiàn)不斷上升,這說明,k越大越好,數(shù)據(jù)中所有的特征都是與特征相關(guān)的。但是運(yùn)行這條曲線的時(shí)間同樣的也是非常長,接下來介紹一種更好的選擇k的方法:看p值選擇k。
卡方檢驗(yàn)的本質(zhì)是推測兩組數(shù)據(jù)間的差異,期檢驗(yàn)的原假設(shè)是“兩組數(shù)據(jù)是相互獨(dú)立的”。卡方檢驗(yàn)返回卡方值和p值兩個(gè)統(tǒng)計(jì)量,其中卡方值很難界定有效的范圍,而p值,一般使用0.05或0.01作為顯著性特征水平,即p值判斷的邊界
| p值 | <=0.05或0.01 | >0.05或0.01 |
| 數(shù)據(jù)差異 | 差異不是自然形成的 | 這些差異是很自然的樣本誤差 |
| 相關(guān)性 | 兩組數(shù)據(jù)是相關(guān)的 | 兩組數(shù)據(jù)是相互獨(dú)立的 |
| 原假設(shè) | 拒絕原假設(shè),接受備擇假設(shè) | 接受原假設(shè) |
?k=0,說明所有p值都小于0.05,也就是方差過濾已經(jīng)把所有和標(biāo)簽無關(guān)的特征都剔除了,或者中國數(shù)據(jù)集本身就不含與標(biāo)簽無關(guān)的特征。在這種情況下,舍棄任何一個(gè)特征,都會(huì)舍棄對(duì)模型有用的信息,而使模型表現(xiàn)下降。接下來,繼續(xù)試用其它相關(guān)性過濾的方法來驗(yàn)證。
2.2 F檢驗(yàn)
????????F檢驗(yàn),又稱ANOVA,方差齊性檢驗(yàn),是用來捕捉每個(gè)特征與標(biāo)簽之間的線性關(guān)系的過濾方法。F檢驗(yàn)既可以做回歸,也可以做分類,因此包含faeture_selection.f_classif(F檢驗(yàn)分類)和feature_selection.f_regression(F檢驗(yàn)回歸)兩個(gè)類。其中F檢驗(yàn)分類用于標(biāo)簽是離散型變量的數(shù)據(jù),而F檢驗(yàn)回歸用于標(biāo)簽是連續(xù)型變量的數(shù)據(jù)。
? ? ? ? 和卡方檢驗(yàn)一樣,這兩個(gè)類需要和類SelectKBest連用,并且也可以直接通過輸出的統(tǒng)計(jì)量來判斷設(shè)置一個(gè)什么樣的k合適。F檢驗(yàn)在數(shù)據(jù)服從正態(tài)分布時(shí)效果會(huì)非常穩(wěn)定,所以在使用F檢驗(yàn)過濾時(shí)通常會(huì)先將數(shù)據(jù)轉(zhuǎn)化為服從正態(tài)分布的方式。
????????F檢驗(yàn)的本質(zhì)是尋找兩組數(shù)據(jù)之間的線性關(guān)系,其原假設(shè)是“數(shù)據(jù)不存在顯著的線性關(guān)系”。它返回F值和p值兩個(gè)統(tǒng)計(jì)量。和卡方過濾一樣,我們希望選取p值小于0.01或0.05的特征,這些特征與標(biāo)簽是顯著線性相關(guān)的。以F檢驗(yàn)為例,繼續(xù)在數(shù)據(jù)集上進(jìn)行特征選擇:
#F檢驗(yàn) from sklearn.feature_selection import f_classif F,pvalues_f=f_classif(x_fsvar,y) #print("F值",F) #print("p值",pvalues_f) k=F.shape[0]-(pvalues_f>0.05).sum() print(k) -------------------------------------------- k=0得到的結(jié)論和卡方過濾得到的結(jié)果一樣,沒有任何特征的p值大于0.05,所以有特征都與標(biāo)簽相關(guān),因此不需要相關(guān)性過濾。
2.3 互信息法?
????????互信息法是用來捕捉每個(gè)特征與標(biāo)簽之間的任意關(guān)系(包括線性和非線性)的過濾方法。和F檢驗(yàn)相似,它既可以做回歸,也可以做分類,并且包含兩個(gè)類feature_selection.mutual_info_classif(互信息分類) feature_selection.mutual_info_regression(互信息回歸)。這兩個(gè)類的用法和參數(shù)都和F檢驗(yàn)一樣,但F檢驗(yàn)只能找出線性關(guān)系,而互信息法可以找出任意關(guān)系。
? ? ? ? 互信息法不返回F值和p值類似的統(tǒng)計(jì)量,它返回“每個(gè)特征與目標(biāo)之間互信息量的估計(jì)”,這個(gè)估計(jì)量在[0,1]之間取值,0表示兩個(gè)變量相互獨(dú)立,1則表示兩個(gè)變量完全相關(guān),以互信息分類為例的代碼如下:
#互信息法 from sklearn.feature_selection import mutual_info_classif as MIC result=MIC(x_fsvar,y) #得到互信息量的估計(jì) #print(result) (result>0).sum() ------------------------------------------------------------------- 392所有特征的互信息量估計(jì)都大于0,因此所有特征都與標(biāo)簽有關(guān)。
3.過濾法總結(jié)
通常先使用方差過濾,再使用互信息法來捕捉相關(guān)性。
| 類 | 說明 | 超參數(shù)的選擇 |
| VarianceThreshold | 方差過濾,可輸入方差閾值,返回方差大于閾值的新特征矩陣 | (學(xué)習(xí)曲線) |
| SelectKBest | 用來選取K個(gè)統(tǒng)計(jì)量結(jié)果最佳的特征,生成符合統(tǒng)計(jì)量要求的新特征矩陣 | |
| chi2 | 卡方檢驗(yàn),專用于分類算法,捕捉相關(guān)性 | 追求p小于顯著性水平的特征 |
| f_classif | F檢驗(yàn)分類,只能捕捉線性相關(guān)性 要求數(shù)據(jù)服從正態(tài)分布 | 追求p小于顯著性水平的特征 |
| f_regression | F檢驗(yàn)回歸,只能捕捉線性相關(guān)性 要求數(shù)據(jù)服從正態(tài)分布 | 追求p小于顯著性水平的特征 |
| mutual_info_classif | 互信息分類,可以捕捉任何相關(guān)性 不能用于稀疏矩陣 | 追求互信息大于0的特征 |
| mutual_info_regression | 互信息回歸,可以捕捉任何相關(guān)性 不能用于稀疏矩陣 | 追求互信息大于0的特征 |
總結(jié)
以上是生活随笔為你收集整理的特征选择过滤法-方差过滤、F检验、互信息法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 超级电容锂电池混合储能Simulink仿
- 下一篇: shell用法大全