1. 程式人生 > >常用的特徵選擇演算法介紹

常用的特徵選擇演算法介紹

特徵選擇(排序)對於資料科學家、機器學習從業者來說非常重要。好的特徵選擇能夠提升模型的效能,更能幫助我們理解資料的特點、底層結構,這對進一步改善模型、演算法都有著重要作用。

特徵選擇主要有兩個功能:

  1. 減少特徵數量、降維,使模型泛化能力更強,減少過擬合
  2. 增強對特徵和特徵值之間的理解

拿到資料集,一個特徵選擇方法,往往很難同時完成這兩個目的。通常情況下,我們經常不管三七二十一,選擇一種自己最熟悉或者最方便的特徵選擇方法(往往目的是降維,而忽略了對特徵和資料理解的目的)。

在許多機器學習相關的書裡,很難找到關於特徵選擇的內容,因為特徵選擇要解決的問題往往被視為機器學習的一種副作用,一般不會單獨拿出來討論。

本文將結合 

Scikit-learn提供的例子 介紹幾種常用的特徵選擇方法,它們各自的優缺點和問題。

1 去掉取值變化小的特徵 Removing features with low variance

這應該是最簡單的特徵選擇方法了:假設某特徵的特徵值只有0和1,並且在所有輸入樣本中,95%的例項的該特徵取值都是1,那就可以認為這個特徵作用不大。如果100%都是1,那這個特徵就沒意義了。當特徵值都是離散型變數的時候這種方法才能用,如果是連續型變數,就需要將連續變數離散化之後才能用,而且實際當中,一般不太會有95%以上都取某個值的特徵存在,所以這種方法雖然簡單但是不太好用。可以把它作為特徵選擇的預處理,先去掉那些取值變化小的特徵,然後再從接下來提到的的特徵選擇方法中選擇合適的進行進一步的特徵選擇。

2 單變數特徵選擇 Univariate feature selection

單變數特徵選擇能夠對每一個特徵進行測試,衡量該特徵和響應變數之間的關係,根據得分扔掉不好的特徵。對於迴歸和分類問題可以採用卡方檢驗等方式對特徵進行測試。

這種方法比較簡單,易於執行,易於理解,通常對於理解資料有較好的效果(但對特徵優化、提高泛化能力來說不一定有效);這種方法有許多改進的版本、變種。

2.1 Pearson相關係數 Pearson Correlation

皮爾森相關係數是一種最簡單的,能幫助理解特徵和響應變數之間關係的方法,該方法衡量的是變數之間的線性相關性,結果的取值區間為[-1,1],-1表示完全的負相關(這個變數下降,那個就會上升),+1表示完全的正相關,0表示沒有線性相關。

Pearson Correlation速度快、易於計算,經常在拿到資料(經過清洗和特徵提取之後的)之後第一時間就執行。Scipy的 pearsonr 方法能夠同時計算相關係數和p-value,

import numpy as np
from scipy.stats import pearsonr
np.random.seed(0)
size = 300
x = np.random.normal(0, 1, size)
print "Lower noise", pearsonr(x, x + np.random.normal(0, 1, size))
print "Higher noise", pearsonr(x, x + np.random.normal(0, 10, size))

Lower noise (0.71824836862138386, 7.3240173129992273e-49)Higher noise (0.057964292079338148, 0.31700993885324746)

這個例子中,我們比較了變數在加入噪音之前和之後的差異。當噪音比較小的時候,相關性很強,p-value很低。

Scikit-learn提供的 f_regrssion 方法能夠批量計算特徵的p-value,非常方便,參考sklearn的 pipeline

Pearson相關係數的一個明顯缺陷是,作為特徵排序機制,他只對線性關係敏感。如果關係是非線性的,即便兩個變數具有一一對應的關係,Pearson相關性也可能會接近0。

x = np.random.uniform(-1, 1, 100000)
print pearsonr(x, x**2)[0]

-0.00230804707612

更多類似的例子參考 sample plots 。另外,如果僅僅根據相關係數這個值來判斷的話,有時候會具有很強的誤導性,如 Anscombe’s quartet ,最好把資料可視化出來,以免得出錯誤的結論。

2.2 互資訊和最大資訊係數 Mutual information and maximal information coefficient (MIC)

以上就是經典的互資訊公式了。想把互資訊直接用於特徵選擇其實不是太方便:1、它不屬於度量方式,也沒有辦法歸一化,在不同資料及上的結果無法做比較;2、對於連續變數的計算不是很方便(X和Y都是集合,x,y都是離散的取值),通常變數需要先離散化,而互資訊的結果對離散化的方式很敏感。

最大資訊係數克服了這兩個問題。它首先尋找一種最優的離散化方式,然後把互資訊取值轉換成一種度量方式,取值區間在[0,1]。 minepy 提供了MIC功能。

反過頭來看y=x^2這個例子,MIC算出來的互資訊值為1(最大的取值)。

from minepy import MINE
m = MINE()
x = np.random.uniform(-1, 1, 10000)
m.compute_score(x, x**2)
print m.mic()

1.0

MIC的統計能力遭到了 一些質疑 ,當零假設不成立時,MIC的統計就會受到影響。在有的資料集上不存在這個問題,但有的資料集上就存在這個問題。

2.3 距離相關係數 (Distance correlation)

距離相關係數是為了克服Pearson相關係數的弱點而生的。在x和x^2這個例子中,即便Pearson相關係數是0,我們也不能斷定這兩個變數是獨立的(有可能是非線性相關);但如果距離相關係數是0,那麼我們就可以說這兩個變數是獨立的。

R的 energy 包裡提供了距離相關係數的實現,另外這是 Python gist 的實現。

#R-code
>x=runif(1000,-1,1)
>dcor(x,x**2)
[1] 0.4943864

儘管有MIC和距離相關係數在了,但當變數之間的關係接近線性相關的時候,Pearson相關係數仍然是不可替代的。第一、Pearson相關係數計算速度快,這在處理大規模資料的時候很重要。第二、Pearson相關係數的取值區間是[-1,1],而MIC和距離相關係數都是[0,1]。這個特點使得Pearson相關係數能夠表徵更豐富的關係,符號表示關係的正負,絕對值能夠表示強度。當然,Pearson相關性有效的前提是兩個變數的變化關係是單調的。

2.4 基於學習模型的特徵排序 (Model based ranking)

這種方法的思路是直接使用你要用的機器學習演算法,針對每個單獨的特徵和響應變數建立預測模型。其實Pearson相關係數等價於線性迴歸裡的標準化迴歸係數。假如某個特徵和響應變數之間的關係是非線性的,可以用基於樹的方法(決策樹、隨機森林)、或者擴充套件的線性模型等。基於樹的方法比較易於使用,因為他們對非線性關係的建模比較好,並且不需要太多的除錯。但要注意過擬合問題,因此樹的深度最好不要太大,再就是運用交叉驗證。

在 波士頓房價資料集 上使用sklearn的 隨機森林迴歸 給出一個單變數選擇的例子:

from sklearn.cross_validation import cross_val_score, ShuffleSplit
from sklearn.datasets import load_boston
from sklearn.ensemble import RandomForestRegressor

#Load boston housing dataset as an example
boston = load_boston()
X = boston["data"]
Y = boston["target"]
names = boston["feature_names"]

rf = RandomForestRegressor(n_estimators=20, max_depth=4)
scores = []
for i in range(X.shape[1]):
     score = cross_val_score(rf, X[:, i:i+1], Y, scoring="r2",
                              cv=ShuffleSplit(len(X), 3, .3))
     scores.append((round(np.mean(score), 3), names[i]))
print sorted(scores, reverse=True)

[(0.636, ‘LSTAT’), (0.59, ‘RM’), (0.472, ‘NOX’), (0.369, ‘INDUS’), (0.311, ‘PTRATIO’), (0.24, ‘TAX’), (0.24, ‘CRIM’), (0.185, ‘RAD’), (0.16, ‘ZN’), (0.087, ‘B’), (0.062, ‘DIS’), (0.036, ‘CHAS’), (0.027, ‘AGE’)]

3 線性模型和正則化

單變數特徵選擇方法獨立的衡量每個特徵與響應變數之間的關係,另一種主流的特徵選擇方法是基於機器學習模型的方法。有些機器學習方法本身就具有對特徵進行打分的機制,或者很容易將其運用到特徵選擇任務中,例如迴歸模型,SVM,決策樹,隨機森林等等。說句題外話,這種方法好像在一些地方叫做wrapper型別,大概意思是說,特徵排序模型和機器學習模型是耦盒在一起的,對應的非wrapper型別的特徵選擇方法叫做filter型別。

下面將介紹如何用迴歸模型的係數來選擇特徵。越是重要的特徵在模型中對應的係數就會越大,而跟輸出變數越是無關的特徵對應的係數就會越接近於0。在噪音不多的資料上,或者是資料量遠遠大於特徵數的資料上,如果特徵之間相對來說是比較獨立的,那麼即便是運用最簡單的線性迴歸模型也一樣能取得非常好的效果。

from sklearn.linear_model import LinearRegression
import numpy as np
np.random.seed(0)
size = 5000
#Adatasetwith3features
X = np.random.normal(0, 1, (size, 3))
#Y=X0+2*X1+noise
Y = X[:,0] + 2*X[:,1] + np.random.normal(0, 2, size)
lr = LinearRegression()
lr.fit(X, Y)
#Ahelpermethodforpretty-printinglinearmodels
defpretty_print_linear(coefs,names=None,sort=False):
	if names == None:
		names = ["X%s" % x for x in range(len(coefs))]
	lst = zip(coefs, names)
	if sort:
		lst = sorted(lst,  key = lambda x:-np.abs(x[0]))
	return " + ".join("%s * %s" % (round(coef, 3), name)
								   for coef, name in lst)
print "Linear model:", pretty_print_linear(lr.coef_)

Linear model: 0.984 * X0 + 1.995 * X1 + -0.041 * X2

在這個例子當中,儘管資料中存在一些噪音,但這種特徵選擇模型仍然能夠很好的體現出資料的底層結構。當然這也是因為例子中的這個問題非常適合用線性模型來解:特徵和響應變數之間全都是線性關係,並且特徵之間均是獨立的。

在很多實際的資料當中,往往存在多個互相關聯的特徵,這時候模型就會變得不穩定,資料中細微的變化就可能導致模型的巨大變化(模型的變化本質上是係數,或者叫引數,可以理解成W),這會讓模型的預測變得困難,這種現象也稱為多重共線性。例如,假設我們有個資料集,它的真實模型應該是Y=X1+X2,當我們觀察的時候,發現Y’=X1+X2+e,e是噪音。如果X1和X2之間存線上性關係,例如X1約等於X2,這個時候由於噪音e的存在,我們學到的模型可能就不是Y=X1+X2了,有可能是Y=2X1,或者Y=-X1+3X2。

下邊這個例子當中,在同一個資料上加入了一些噪音,用隨機森林演算法進行特徵選擇。

from sklearn.linear_model import LinearRegression

size = 100
np.random.seed(seed=5)

X_seed = np.random.normal(0, 1, size)
X1 = X_seed + np.random.normal(0, .1, size)
X2 = X_seed + np.random.normal(0, .1, size)
X3 = X_seed + np.random.normal(0, .1, size)

Y = X1 + X2 + X3 + np.random.normal(0,1, size)
X =