1. 程式人生 > >【機器學習】Selecting good features – Part IV: stability selection, RFE and everything side by side

【機器學習】Selecting good features – Part IV: stability selection, RFE and everything side by side

Selecting good features – Part IV: stability selection, RFE and everything side by side


在我以前的文章中,我研究了單變數方法、線性模型和正則化以及隨機森林的特徵選擇。

在本文中,我將研究另外兩種方法:穩定性選擇遞迴特徵消除(RFE),這兩種方法都可以考慮包裝方法。它們都建立在其它(基於模型的)選擇方法的基礎上,如迴歸或SVM,在不同的資料子集上建立模型,並從集合中提取排名。

作為總結,我將執行前面討論的所有方法,以突出它們彼此的優缺點和陷阱。

穩定性選擇

穩定性選擇是一種相對新穎的特徵選擇方法,它基於子取樣並結合選擇演算法(可以是迴歸、支援向量機或其他類似的方法)

。高層次的思想是在不同的資料子集和不同的特徵子集上應用特徵選擇演算法。在重複多次處理之後,選擇結果可以被聚合,例如,通過檢查一個特徵在被檢查的特徵子集中被選擇為重要特徵的次數。我們可以期望強大的特性具有接近100%的分數,因為它們總是儘可能地被選擇。較弱、但仍然相關的特徵也將具有非零分數,因為當在當前選擇的子集中不存在更強的特徵時將選擇它們,而無關的特徵將具有分數(接近)零,因為它們永遠不會在所選擇的特徵中。

Skleak實現了隨機套索和隨機物流回歸類中的穩定性選擇。

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))

Features sorted by their score:
[(1.0, 'RM'), (1.0, 'PTRATIO'), (1.0, 'LSTAT'), (0.66500000000000004, 'B'), (0.60499999999999998, 'CHAS'), (0.41499999999999998, 'CRIM'), (0.39000000000000001, 'TAX'), (0.23999999999999999, 'DIS'), (0.20999999999999999, 'NOX'), (0.095000000000000001, 'INDUS'), (0.040000000000000001, 'ZN'), (0.029999999999999999, 'RAD'), (0.014999999999999999, 'AGE')]

正如從示例中看到的,前三個特性的得分相等,為1.0,這意味著它們總是被選擇為有用的特性(當然,當改變正則化引數時,這可能會改變,但是sklearning的隨機lasso實現可以自動選擇一個好的α引數)。分數從那裡平穩地下降,但一般來說,下降並不像通常情況下的純套索或隨機森林。這意味著穩定性選擇對於減少過擬合的純特徵選擇是有用的,但是對於資料解釋也是有用的:一般來說,好的特徵不會因為資料集中有相似的、相關的特徵而獲得0作為係數(套索的情況就是這樣)。對於特性選擇,我發現對於許多不同的資料集和設定來說,它是效能最好的方法之一。

遞迴特徵消除

遞迴特徵消除是基於重複構建模型(例如SVM或迴歸模型)並選擇效能最佳或最差的特徵(例如基於係數),將特徵置之不理,然後用其餘特徵重複該過程的思想。應用此過程直到資料集中的所有特性都用盡為止。然後根據特徵被消除的時間對它們進行排序。因此,尋找效能最好的特徵子集是一個貪婪的優化

RFE的穩定性在很大程度上取決於在每次迭代中用於特徵排序的模型型別。正如非正則迴歸不穩定一樣,RFE在利用它時也是不穩定的,而嶺迴歸可以提供更穩定的結果。

Sklearning提供用於遞迴特徵消除的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)))

Features sorted by their rank:
[(1, 'NOX'), (2, 'RM'), (3, 'CHAS'), (4, 'PTRATIO'), (5, 'DIS'), (6, 'LSTAT'), (7, 'RAD'), (8, 'CRIM'), (9, 'INDUS'), (10, 'ZN'), (11, 'TAX'), (12, 'B'), (13, 'AGE')]

示例:並排執行方法

現在,我將從本文和前面的三個示例中獲取所有示例,並在示例資料集上執行這些方法以並排進行比較。資料集將是所謂的Friedman #1迴歸資料集(來自Friedman’s Multivariate Adaptive Regression Splines paper)。資料是根據公式y=10sin(\pi x_1x_2)+20(x_3-0.5)^2+10X_4+5X_5+\varepsilon生成的,其中x_1x_5是均勻分佈的,\varepsilon是標準正態偏差N(0,1)。此外,原始資料集具有五個獨立於響應變數的噪聲變數x_6,...,x_{10}。我們將進一步增加變數的數目,並新增四個變數x_{11},...,x_{14},每個變數分別與f(x)=x+N(0,0.01)生成的x_1,...,x_4有很強的相關性。這在變數之間產生大於0.999的相關係數。這將說明不同的特徵排序方法如何處理資料中的相關性。

我們將在資料集上應用執行上面列出的每個方法,並對得分進行規範化,以使得分介於0(對於排名最低的特性)和1(對於排名最高的特性)之間。對於遞迴特徵消除,前五個特徵將全部得到分數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]))))

下面是結果表(通過單擊列標題進行排序)(截圖示意),其中每個方法的結果+平均值

這個例子應該強調不同方法的一些有趣的特性。

利用線性相關(..Corr.),每個特徵被獨立評估,因此特徵x1...x4的得分非常類似於x11...x14,而噪聲特徵x5...x10被正確地識別為與響應變數幾乎沒有關係。它不能識別x3與響應變數之間的任何關係,因為這種關係是二次的(實際上,除了MIC,這幾乎適用於所有其他方法)。同樣清楚的是,雖然該方法能夠測量每個特徵和響應變數之間的線性關係,但是選擇效能最好的特徵來改進模型的泛化並不是最佳的,因為所有效能最好的特徵基本上都會被選擇兩次

Lasso挑選出效能最好的特性,同時強制其他特性接近於零。當需要減少特徵的數量時,這顯然是有用的,但不一定是資料解釋所必需的(因為這可能導致人們相信特徵x11...x13與輸出變數沒有強的關係)。

MIC與相關係數在處理所有特徵時“相等”相似,而且能夠發現x3與響應之間的非線性關係。

基於雜質的隨機森林的排名通常具有攻擊性,因為在前幾名之後得分急劇下降。這可以從第三等級的特徵已經比頂級特徵小4倍的示例中看出(而對於其他排序方法,下拉顯然沒有那麼積極)。

嶺迴歸迫使迴歸係數在相關變數之間類似地展開。這在x11...x14在得分方面接近x1...x4的示例中清晰可見。

穩定性選擇通常能夠在資料解釋和頂部特徵選擇之間作出有用的折衷,用於模型改進。這個例子很好地說明了這一點。就像拉索一樣,它能夠識別出最上面的特徵(x1,x2,x4,x5)。同時,相關陰影變數也得到較高的分數,說明它們與反應的關係。

結論

特徵排序在許多機器學習和資料探勘場景中可能非常有用。但關鍵是要清楚地記住最終目標,並理解哪種方法最適合實現它。在選擇用於模型效能改進的頂部特徵時,很容易通過簡單地進行交叉驗證來驗證特定方法是否對替代方案工作良好。當使用特徵排序進行資料解釋時,這並不是簡單的,因為排序方法的穩定性是至關重要的,並且不具有這種性質的方法(如套索)很容易導致錯誤的結論。有什麼可以幫助對資料進行子取樣,並在子集上執行選擇演算法。如果結果在子集之間是一致的,則相對安全地信任方法在這個特定資料上的穩定性,並且因此直接根據排序來解釋資料。

原文連結:http://blog.datadive.net/selecting-good-features-part-iv-stability-selection-rfe-and-everything-side-by-side/