數(shù)據(jù)維度爆炸?5大常用的特征選擇方法詳解(下)
Edwin Jarvis | 作者
cnblog博客 |?來源
5
兩種頂層特征選擇算法
之所以叫做頂層,是因為他們都是建立在基于模型的特征選擇方法基礎(chǔ)之上的,例如回歸和SVM,在不同的子集上建立模型,然后匯總最終確定特征得分。
?穩(wěn)定性選擇?
穩(wěn)定性選擇是一種基于二次抽樣和選擇算法相結(jié)合較新的方法,選擇算法可以是回歸、SVM或其他類似的方法。它的主要思想是在不同的數(shù)據(jù)子集和特征子集上運行特征選擇算法,不斷的重復(fù),最終匯總特征選擇結(jié)果,比如可以統(tǒng)計某個特征被認為是重要特征的頻率(被選為重要特征的次數(shù)除以它所在的子集被測試的次數(shù))。理想情況下,重要特征的得分會接近100%。稍微弱一點的特征得分會是非0的數(shù),而最無用的特征得分將會接近于0。
sklearn在隨機lasso和隨機邏輯回歸中有對穩(wěn)定性選擇的實現(xiàn)。
from?sklearn.linear_model?import?RandomizedLasso
from?sklearn.datasets?import?load_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(lambda?x: round(x,?4), rlasso.scores_),?
?????????????????names), reverse=True)
在上邊這個例子當(dāng)中,最高的3個特征得分是1.0,這表示他們總會被選作有用的特征(當(dāng)然,得分會收到正則化參數(shù)alpha的影響,但是sklearn的隨機lasso能夠自動選擇最優(yōu)的alpha)。接下來的幾個特征得分就開始下降,但是下降的不是特別急劇,這跟純lasso的方法和隨機森林的結(jié)果不一樣。
能夠看出穩(wěn)定性選擇對于克服過擬合和對數(shù)據(jù)理解來說都是有幫助的:總的來說,好的特征不會因為有相似的特征、關(guān)聯(lián)特征而得分為0,這跟Lasso是不同的。對于特征選擇任務(wù),在許多數(shù)據(jù)集和環(huán)境下,穩(wěn)定性選擇往往是性能最好的方法之一。
?遞歸特征消除?
遞歸特征消除的主要思想是反復(fù)的構(gòu)建模型(如SVM或者回歸模型)然后選出最好的(或者最差的)的特征(可以根據(jù)系數(shù)來選),把選出來的特征放到一遍,然后在剩余的特征上重復(fù)這個過程,直到所有特征都遍歷了。這個過程中特征被消除的次序就是特征的排序。因此,這是一種尋找最優(yōu)特征子集的貪心算法。
RFE的穩(wěn)定性很大程度上取決于在迭代的時候底層用哪種模型。例如,假如RFE采用的普通的回歸,沒有經(jīng)過正則化的回歸是不穩(wěn)定的,那么RFE就是不穩(wěn)定的;假如采用的是Ridge,而用Ridge正則化的回歸是穩(wěn)定的,那么RFE就是穩(wěn)定的。
Sklearn提供了RFE包,可以用于特征消除,還提供了RFECV,可以通過交叉驗證來對的特征進行排序。
from?sklearn.feature_selection?import?RFE
from?sklearn.linear_model?import?LinearRegression
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(lambda?x: round(x,?4), rfe.ranking_), names))6
一個完整的例子
下面將本文所有提到的方法進行實驗對比,數(shù)據(jù)集采用Friedman #1 回歸數(shù)據(jù)(這篇論文中的數(shù)據(jù))。數(shù)據(jù)是用這個公式產(chǎn)生的:

X1到X5是由單變量分布生成的,e是標準正態(tài)變量N(0,1)。另外,原始的數(shù)據(jù)集中含有5個噪音變量 X5,…,X10,跟響應(yīng)變量是獨立的。我們增加了4個額外的變量X11,…X14,分別是X1,…,X4的關(guān)聯(lián)變量,通過f(x)=x+N(0,0.01)生成,這將產(chǎn)生大于0.999的關(guān)聯(lián)系數(shù)。這樣生成的數(shù)據(jù)能夠體現(xiàn)出不同的特征排序方法應(yīng)對關(guān)聯(lián)特征時的表現(xiàn)。
接下來將會在上述數(shù)據(jù)上運行所有的特征選擇方法,并且將每種方法給出的得分進行歸一化,讓取值都落在0-1之間。對于RFE來說,由于它給出的是順序而不是得分,我們將最好的5個的得分定為1,其他的特征的得分均勻的分布在0-1之間。
from?sklearn.datasets?import?load_boston
from?sklearn.linear_model?import?(LinearRegression, Ridge,?
??????????????????????????????????Lasso, RandomizedLasso)
from?sklearn.feature_selection?import?RFE, f_regression
from?sklearn.preprocessing?import?MinMaxScaler
from?sklearn.ensemble?import?RandomForestRegressor
import?numpy?as?np
from?minepy?import?MINE
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"?% i?for?i?in?range(1,15)]
ranks = {}
def?rank_to_dict(ranks, names, order=1):
????minmax = MinMaxScaler()
????ranks = minmax.fit_transform(order*np.array([ranks]).T).T[0]
????ranks = map(lambda?x: round(x,?2), ranks)
????return?dict(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 = []
for?i?in?range(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 = {}
for?name?in?names:
????r[name] = round(np.mean([ranks[method][name]?
?????????????????????????????for?method?in?ranks.keys()]),?2)
methods = sorted(ranks.keys())
ranks["Mean"] = r
methods.append("Mean")
print?"\t%s"?%?"\t".join(methods)
for?name?in?names:
????print?"%s\t%s"?% (name,?"\t".join(map(str,?
?????????????????????????[ranks[method][name]?for?method?in?methods])))
從以上結(jié)果中可以找到一些有趣的發(fā)現(xiàn):
特征之間存在線性關(guān)聯(lián)關(guān)系,每個特征都是獨立評價的,因此X1,…X4的得分和X11,…X14的得分非常接近,而噪音特征X5,…,X10正如預(yù)期的那樣和響應(yīng)變量之間幾乎沒有關(guān)系。由于變量X3是二次的,因此X3和響應(yīng)變量之間看不出有關(guān)系(除了MIC之外,其他方法都找不到關(guān)系)。
這種方法能夠衡量出特征和響應(yīng)變量之間的線性關(guān)系,但若想選出優(yōu)質(zhì)特征來提升模型的泛化能力,這種方法就不是特別給力了,因為所有的優(yōu)質(zhì)特征都不可避免的會被挑出來兩次。
Lasso能夠挑出一些優(yōu)質(zhì)特征,同時讓其他特征的系數(shù)趨于0。當(dāng)如需要減少特征數(shù)的時候它很有用,但是對于數(shù)據(jù)理解來說不是很好用。(例如在結(jié)果表中,X11,X12,X13的得分都是0,好像他們跟輸出變量之間沒有很強的聯(lián)系,但實際上不是這樣的)
MIC對特征一視同仁,這一點上和關(guān)聯(lián)系數(shù)有點像,另外,它能夠找出X3和響應(yīng)變量之間的非線性關(guān)系。
隨機森林基于不純度的排序結(jié)果非常鮮明,在得分最高的幾個特征之后的特征,得分急劇的下降。從表中可以看到,得分第三的特征比第一的小4倍。而其他的特征選擇算法就沒有下降的這么劇烈。
Ridge將回歸系數(shù)均勻的分攤到各個關(guān)聯(lián)變量上,從表中可以看出,X11,…,X14和X1,…,X4的得分非常接近。
穩(wěn)定性選擇常常是一種既能夠有助于理解數(shù)據(jù)又能夠挑出優(yōu)質(zhì)特征的這種選擇,在結(jié)果表中就能很好的看出。像Lasso一樣,它能找到那些性能比較好的特征(X1,X2,X4,X5),同時,與這些特征關(guān)聯(lián)度很強的變量也得到了較高的得分。
7
總 結(jié)
對于理解數(shù)據(jù)、數(shù)據(jù)的結(jié)構(gòu)、特點來說,單變量特征選擇是個非常好的選擇。盡管可以用它對特征進行排序來優(yōu)化模型,但由于它不能發(fā)現(xiàn)冗余(例如假如一個特征子集,其中的特征之間具有很強的關(guān)聯(lián),那么從中選擇最優(yōu)的特征時就很難考慮到冗余的問題)。
正則化的線性模型對于特征理解和特征選擇來說是非常強大的工具。L1正則化能夠生成稀疏的模型,對于選擇特征子集來說非常有用;相比起L1正則化,L2正則化的表現(xiàn)更加穩(wěn)定,由于有用的特征往往對應(yīng)系數(shù)非零,因此L2正則化對于數(shù)據(jù)的理解來說很合適。
由于響應(yīng)變量和特征之間往往是非線性關(guān)系,可以采用basis expansion的方式將特征轉(zhuǎn)換到一個更加合適的空間當(dāng)中,在此基礎(chǔ)上再考慮運用簡單的線性模型。
隨機森林是一種非常流行的特征選擇方法,它易于使用,一般不需要feature engineering、調(diào)參等繁瑣的步驟,并且很多工具包都提供了平均不純度下降方法。它的兩個主要問題:
重要的特征有可能得分很低(關(guān)聯(lián)特征問題)
這種方法對特征變量類別多的特征越有利(偏向問題)。盡管如此,這種方法仍然非常值得在你的應(yīng)用中試一試。
特征選擇在很多機器學(xué)習(xí)和數(shù)據(jù)挖掘場景中都是非常有用的。在使用的時候要弄清楚自己的目標是什么,然后找到哪種方法適用于自己的任務(wù)。當(dāng)選擇最優(yōu)特征以提升模型性能的時候,可以采用交叉驗證的方法來驗證某種方法是否比其他方法要好。
當(dāng)用特征選擇的方法來理解數(shù)據(jù)的時候要留心,特征選擇模型的穩(wěn)定性非常重要,穩(wěn)定性差的模型很容易就會導(dǎo)致錯誤的結(jié)論。對數(shù)據(jù)進行二次采樣然后在子集上運行特征選擇算法能夠有所幫助,如果在各個子集上的結(jié)果是一致的,那就可以說在這個數(shù)據(jù)集上得出來的結(jié)論是可信的,可以用這種特征選擇模型的結(jié)果來理解數(shù)據(jù)。
-?END -
本文為轉(zhuǎn)載分享&推薦閱讀,若侵權(quán)請聯(lián)系后臺刪除
