lasso特征选择python_转:结合Scikit-learn介绍几种常用的特征选择方法-2
4.2 平均精確率減少 Mean decrease accuracy
另一種常用的特征選擇方法就是直接度量每個特征對模型精確率的影響。主要思路是打亂每個特征的特征值順序,并且度量順序變動對模型的精確率的影響。很明顯,對于不重要的變量來說,打亂順序對模型的精確率影響不會太大,但是對于重要的變量來說,打亂順序就會降低模型的精確率。
這個方法sklearn中沒有直接提供,但是很容易實現,下面繼續在波士頓房價數據集上進行實現。
fromsklearn.cross_validationimportShuffleSplit
fromsklearn.metricsimportr2_score
fromcollectionsimportdefaultdict
X?=?boston["data"]
Y?=?boston["target"]
rf?=?RandomForestRegressor()
scores?=?defaultdict(list)
#crossvalidate?the?scores?on?a?number?of?different?random?splits?of?the?data
fortrain_idx,?test_idxinShuffleSplit(len(X),100,?.3):
X_train,?X_test?=?X[train_idx],?X[test_idx]
Y_train,?Y_test?=?Y[train_idx],?Y[test_idx]
r?=?rf.fit(X_train,?Y_train)
acc?=?r2_score(Y_test,?rf.predict(X_test))
foriinrange(X.shape[1]):
X_t?=?X_test.copy()
np.random.shuffle(X_t[:,?i])
shuff_acc?=?r2_score(Y_test,?rf.predict(X_t))
scores[names[i]].append((acc-shuff_acc)/acc)
print("Features?sorted?by?their?score:")
print(sorted([(round(np.mean(score),4),?feat)for
feat,?score?inscores.items()],?reverse=True))
Features sorted by their score: [(0.7276, ‘LSTAT’), (0.5675, ‘RM’),
(0.0867, ‘DIS’), (0.0407, ‘NOX’), (0.0351, ‘CRIM’), (0.0233,
‘PTRATIO’), (0.0168, ‘TAX’), (0.0122, ‘AGE’), (0.005, ‘B’),
(0.0048, ‘INDUS’), (0.0043, ‘RAD’), (0.0004, ‘ZN’), (0.0001,
‘CHAS’)]
在這個例子當中,LSTAT和RM這兩個特征對模型的性能有著很大的影響,打亂這兩個特征的特征值使得模型的性能下降了73%和57%。注意,盡管這些我們是在所有特征上進行了訓練得到了模型,然后才得到了每個特征的重要性測試,這并不意味著我們扔掉某個或者某些重要特征后模型的性能就一定會下降很多,因為即便某個特征刪掉之后,其關聯特征一樣可以發揮作用,讓模型性能基本上不變。
5 兩種頂層特征選擇算法
之所以叫做頂層,是因為他們都是建立在基于模型的特征選擇方法基礎之上的,例如回歸和SVM,在不同的子集上建立模型,然后匯總最終確定特征得分。
5.1 穩定性選擇 Stability selection
穩定性選擇是一種基于二次抽樣和選擇算法相結合較新的方法,選擇算法可以是回歸、SVM或其他類似的方法。它的主要思想是在不同的數據子集和特征子集上運行特征選擇算法,不斷的重復,最終匯總特征選擇結果,比如可以統計某個特征被認為是重要特征的頻率(被選為重要特征的次數除以它所在的子集被測試的次數)。理想情況下,重要特征的得分會接近100%。稍微弱一點的特征得分會是非0的數,而最無用的特征得分將會接近于0。
sklearn在隨機lasso和隨機邏輯回歸中有對穩定性選擇的實現。
fromsklearn.linear_modelimportRandomizedLasso
fromsklearn.datasetsimportload_boston
boston?=?load_boston()
#using?the?Boston?housing?data.
#Data?gets?scaled?automatically?by?sklearn's?implementation
X?=?boston["data"]
Y?=?boston["target"]
names?=?boston["feature_names"]
rlasso?=?RandomizedLasso(alpha=0.025)
rlasso.fit(X,?Y)
print("Features?sorted?by?their?score:")
print(sorted(zip(map(lambdax:?round(x,4),?rlasso.scores_),
names),?reverse=True))
Features sorted by their score: [(1.0, ‘RM’), (1.0, ‘PTRATIO’),
(1.0, ‘LSTAT’), (0.62, ‘CHAS’), (0.595, ‘B’), (0.39, ‘TAX’),
(0.385, ‘CRIM’), (0.25, ‘DIS’), (0.22, ‘NOX’), (0.125, ‘INDUS’),
(0.045, ‘ZN’), (0.02, ‘RAD’), (0.015, ‘AGE’)]
在上邊這個例子當中,最高的3個特征得分是1.0,這表示他們總會被選作有用的特征(當然,得分會收到正則化參數alpha的影響,但是sklearn的隨機lasso能夠自動選擇最優的alpha)。接下來的幾個特征得分就開始下降,但是下降的不是特別急劇,這跟純lasso的方法和隨機森林的結果不一樣。能夠看出穩定性選擇對于克服過擬合和對數據理解來說都是有幫助的:總的來說,好的特征不會因為有相似的特征、關聯特征而得分為0,這跟Lasso是不同的。對于特征選擇任務,在許多數據集和環境下,穩定性選擇往往是性能最好的方法之一。
5.2 遞歸特征消除 Recursive feature elimination (RFE)
遞歸特征消除的主要思想是反復的構建模型(如SVM或者回歸模型)然后選出最好的(或者最差的)的特征(可以根據系數來選),把選出來的特征放到一遍,然后在剩余的特征上重復這個過程,直到所有特征都遍歷了。這個過程中特征被消除的次序就是特征的排序。因此,這是一種尋找最優特征子集的貪心算法。
RFE的穩定性很大程度上取決于在迭代的時候底層用哪種模型。例如,假如RFE采用的普通的回歸,沒有經過正則化的回歸是不穩定的,那么RFE就是不穩定的;假如采用的是Ridge,而用Ridge正則化的回歸是穩定的,那么RFE就是穩定的。
Sklearn提供了RFE包,可以用于特征消除,還提供了RFECV,可以通過交叉驗證來對的特征進行排序。
fromsklearn.feature_selectionimportRFE
fromsklearn.linear_modelimportLinearRegression
boston?=?load_boston()
X?=?boston["data"]
Y?=?boston["target"]
names?=?boston["feature_names"]
#use?linear?regression?as?the?model
lr?=?LinearRegression()
#rank?all?features,?i.e?continue?the?elimination?until?the?last?one
rfe?=?RFE(lr,?n_features_to_select=1)
rfe.fit(X,Y)
print("Features?sorted?by?their?rank:")
print(sorted(zip(map(lambdax:?round(x,4),?rfe.ranking_),?names)))
Features sorted by their rank: [(1.0, ‘NOX’), (2.0, ‘RM’), (3.0,
‘CHAS’), (4.0, ‘PTRATIO’), (5.0, ‘DIS’), (6.0, ‘LSTAT’), (7.0,
‘RAD’), (8.0, ‘CRIM’), (9.0, ‘INDUS’), (10.0, ‘ZN’), (11.0, ‘TAX’),
(12.0, ‘B’), (13.0, ‘AGE’)]
6 一個完整的例子
下面將本文所有提到的方法進行實驗對比,數據集采用Friedman #1 回歸數據(這篇論文中的數據)。數據是用這個公式產生的:
X1到X5是由單變量分布生成的,e是標準正態變量N(0,1)。另外,原始的數據集中含有5個噪音變量
X5,…,X10,跟響應變量是獨立的。我們增加了4個額外的變量X11,…X14,分別是X1,…,X4的關聯變量,通過f(x)=x+N(0,0.01)生成,這將產生大于0.999的關聯系數。這樣生成的數據能夠體現出不同的特征排序方法應對關聯特征時的表現。
接下來將會在上述數據上運行所有的特征選擇方法,并且將每種方法給出的得分進行歸一化,讓取值都落在0-1之間。對于RFE來說,由于它給出的是順序而不是得分,我們將最好的5個的得分定為1,其他的特征的得分均勻的分布在0-1之間。
fromsklearn.datasetsimportload_boston
fromsklearn.linear_modelimport(LinearRegression,?Ridge,
Lasso,?RandomizedLasso)
fromsklearn.feature_selectionimportRFE,?f_regression
fromsklearn.preprocessingimportMinMaxScaler
fromsklearn.ensembleimportRandomForestRegressor
importnumpy?as?np
fromminepyimportMINE
np.random.seed(0)
size?=?750
X?=?np.random.uniform(0,1,?(size,14))
#"Friedamn?#1”?regression?problem
Y?=?(10*?np.sin(np.pi*X[:,0]*X[:,1])?+20*(X[:,2]?-?.5)**2+
10*X[:,3]?+5*X[:,4]?+?np.random.normal(0,1))
#Add?3?additional?correlated?variables?(correlated?with?X1-X3)
X[:,10:]?=?X[:,:4]?+?np.random.normal(0,?.025,?(size,4))
names?=?["x%s"%?iforiinrange(1,15)]
ranks?=?{}
defrank_to_dict(ranks,?names,?order=1):
minmax?=?MinMaxScaler()
ranks?=?minmax.fit_transform(order*np.array([ranks]).T).T[0]
ranks?=?map(lambdax:?round(x,2),?ranks)
returndict(zip(names,?ranks?))
lr?=?LinearRegression(normalize=True)
lr.fit(X,?Y)
ranks["Linear?reg"]?=?rank_to_dict(np.abs(lr.coef_),?names)
ridge?=?Ridge(alpha=7)
ridge.fit(X,?Y)
ranks["Ridge"]?=?rank_to_dict(np.abs(ridge.coef_),?names)
lasso?=?Lasso(alpha=.05)
lasso.fit(X,?Y)
ranks["Lasso"]?=?rank_to_dict(np.abs(lasso.coef_),?names)
rlasso?=?RandomizedLasso(alpha=0.04)
rlasso.fit(X,?Y)
ranks["Stability"]?=?rank_to_dict(np.abs(rlasso.scores_),?names)
#stop?the?search?when?5?features?are?left?(they?will?get?equal?scores)
rfe?=?RFE(lr,?n_features_to_select=5)
rfe.fit(X,Y)
ranks["RFE"]?=?rank_to_dict(map(float,?rfe.ranking_),?names,?order=-1)
rf?=?RandomForestRegressor()
rf.fit(X,Y)
ranks["RF"]?=?rank_to_dict(rf.feature_importances_,?names)
f,?pval?=?f_regression(X,?Y,?center=True)
ranks["Corr."]?=?rank_to_dict(f,?names)
mine?=?MINE()
mic_scores?=?[]
foriinrange(X.shape[1]):
mine.compute_score(X[:,i],?Y)
m?=?mine.mic()
mic_scores.append(m)
ranks["MIC"]?=?rank_to_dict(mic_scores,?names)
r?=?{}
fornameinnames:
r[name]?=?round(np.mean([ranks[method][name]
formethodinranks.keys()]),2)
methods?=?sorted(ranks.keys())
ranks["Mean"]?=?r
methods.append("Mean")
print("\t%s"%"\t".join(methods))
fornameinnames:
print("%s\t%s"%?(name,"\t".join(map(str,
[ranks[method][name]?formethodinmethods]))))
從以上結果中可以找到一些有趣的發現:
特征之間存在線性關聯關系,每個特征都是獨立評價的,因此X1,…X4的得分和X11,…X14的得分非常接近,而噪音特征X5,…,X10正如預期的那樣和響應變量之間幾乎沒有關系。由于變量X3是二次的,因此X3和響應變量之間看不出有關系(除了MIC之外,其他方法都找不到關系)。這種方法能夠衡量出特征和響應變量之間的線性關系,但若想選出優質特征來提升模型的泛化能力,這種方法就不是特別給力了,因為所有的優質特征都不可避免的會被挑出來兩次。
Lasso能夠挑出一些優質特征,同時讓其他特征的系數趨于0。當如需要減少特征數的時候它很有用,但是對于數據理解來說不是很好用。(例如在結果表中,X11,X12,X13的得分都是0,好像他們跟輸出變量之間沒有很強的聯系,但實際上不是這樣的)
MIC對特征一視同仁,這一點上和關聯系數有點像,另外,它能夠找出X3和響應變量之間的非線性關系。
隨機森林基于不純度的排序結果非常鮮明,在得分最高的幾個特征之后的特征,得分急劇的下降。從表中可以看到,得分第三的特征比第一的小4倍。而其他的特征選擇算法就沒有下降的這么劇烈。
Ridge將回歸系數均勻的分攤到各個關聯變量上,從表中可以看出,X11,…,X14和X1,…,X4的得分非常接近。
穩定性選擇常常是一種既能夠有助于理解數據又能夠挑出優質特征的這種選擇,在結果表中就能很好的看出。像Lasso一樣,它能找到那些性能比較好的特征(X1,X2,X4,X5),同時,與這些特征關聯度很強的變量也得到了較高的得分。
總結
對于理解數據、數據的結構、特點來說,單變量特征選擇是個非常好的選擇。盡管可以用它對特征進行排序來優化模型,但由于它不能發現冗余(例如假如一個特征子集,其中的特征之間具有很強的關聯,那么從中選擇最優的特征時就很難考慮到冗余的問題)。
正則化的線性模型對于特征理解和特征選擇來說是非常強大的工具。L1正則化能夠生成稀疏的模型,對于選擇特征子集來說非常有用;相比起L1正則化,L2正則化的表現更加穩定,由于有用的特征往往對應系數非零,因此L2正則化對于數據的理解來說很合適。由于響應變量和特征之間往往是非線性關系,可以采用basis
expansion的方式將特征轉換到一個更加合適的空間當中,在此基礎上再考慮運用簡單的線性模型。
隨機森林是一種非常流行的特征選擇方法,它易于使用,一般不需要feature
engineering、調參等繁瑣的步驟,并且很多工具包都提供了平均不純度下降方法。它的兩個主要問題,1是重要的特征有可能得分很低(關聯特征問題),2是這種方法對特征變量類別多的特征越有利(偏向問題)。盡管如此,這種方法仍然非常值得在你的應用中試一試。
特征選擇在很多機器學習和數據挖掘場景中都是非常有用的。在使用的時候要弄清楚自己的目標是什么,然后找到哪種方法適用于自己的任務。當選擇最優特征以提升模型性能的時候,可以采用交叉驗證的方法來驗證某種方法是否比其他方法要好。當用特征選擇的方法來理解數據的時候要留心,特征選擇模型的穩定性非常重要,穩定性差的模型很容易就會導致錯誤的結論。對數據進行二次采樣然后在子集上運行特征選擇算法能夠有所幫助,如果在各個子集上的結果是一致的,那就可以說在這個數據集上得出來的結論是可信的,可以用這種特征選擇模型的結果來理解數據。
Tips
什么是卡方檢驗?用方差來衡量某個觀測頻率和理論頻率之間差異性的方法
什么是皮爾森卡方檢驗?這是一種最常用的卡方檢驗方法,它有兩個用途:1是計算某個變量對某種分布的擬合程度,2是根據兩個觀測變量的Contingency
table來計算這兩個變量是否是獨立的。主要有三個步驟:第一步用方差和的方式來計算觀測頻率和理論頻率之間卡方值;第二步算出卡方檢驗的自由度(行數-1乘以列數-1);第三步比較卡方值和對應自由度的卡方分布,判斷顯著性。
什么是p-value?簡單地說,p-value就是為了驗證假設和實際之間一致性的統計學意義的值,即假設檢驗。有些地方叫右尾概率,根據卡方值和自由度可以算出一個固定的p-value,
什么是響應變量(response
value)?簡單地說,模型的輸入叫做explanatroy variables,模型的輸出叫做response
variables,其實就是要驗證該特征對結果造成了什么樣的影響
什么是零假設(null
hypothesis)?在相關性檢驗中,一般會取“兩者之間無關聯”作為零假設,而在獨立性檢驗中,一般會取“兩者之間是獨立”作為零假設。與零假設相對的是備擇假設(對立假設),即希望證明是正確的另一種可能。
That’s it
References
http://blog.datadive.net/selecting-good-features-part-i-univariate-selection/
http://blog.datadive.net/selecting-good-features-part-ii-linear-models-and-regularization/
http://scikit-learn.org/stable/modules/feature_selection.html#univariate-feature-selection
http://www.quora.com/What-are-some-feature-selection-methods
http://www.quora.com/What-are-some-feature-selection-algorithms
http://www.quora.com/What-are-some-feature-selection-methods-for-SVMs
http://www.quora.com/What-is-the-difference-between-principal-component-analysis-PCA-and-feature-selection-in-machine-learning-Is-PCA-a-means-of-feature-selection
總結
以上是生活随笔為你收集整理的lasso特征选择python_转:结合Scikit-learn介绍几种常用的特征选择方法-2的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java对象引用出错_“Java有值传递
- 下一篇: java黄油刀_一篇文章玩转Butter