在前一篇文章中我介紹了一些資料預處理的方法,原始資料在經過預處理之後可以被演算法處理了,但是實際中可能有一些特徵是沒有必要的,比如在中國採集的一些資料,那麼國籍就都是中國,其實也就沒有意義了,反映在統計量上就是方差過小,也就是樣本在這個特徵上變化很小。還有一種情況是特徵和最後的結果相關性很小,也就是這個特徵不起作用,衡量這種相關性我們可以用卡方檢驗,f-檢驗以及互資訊等。其實很多sklearn的演算法本身帶有coef_和feature_importance_屬性,而這個屬性就可以被利用來篩選特徵。前面說過的方法其實都是在已有特徵的基礎上排除特徵的方法,但是在實際中我們很多時候需要自己構造特徵,構造出好的特徵可以大大提公升模型的效能,對於這方面我就不是很了解了,畢竟我也是個新手,沒有太多經驗。
sklearn中variancethreshold可以起到這個作用
from sklearn.feature_selection import variancethreshold
sel = variancethreshold(0.2)
sel.fit_transform(data)
上述**起到移除方差小於0.2的特徵的作用(只起到示意作用)。
單一變數選擇就是通過某種得分來度量相關性,進而選擇特徵,sklearn中有兩個比較常用
. selectkbest :選擇前k個最好的特徵,也就是得分最高的k個
. selectpercentile :選擇前百分之幾的特徵,這個百分比由使用者指定
所以從上面就可以看出必須要有乙個方法來衡量這種相關性,來傳給上面的兩個方法,才能夠做出選擇。衡量方法也就是上面提到的,卡方檢驗,f-檢驗以及互資訊。這幾種方法在sklearn中是有專門的實現的,再進行單一變數特徵選擇的時候將他們作為引數傳遞進去。下面以卡方檢驗為例
>>>
from sklearn.datasets import load_iris
>>>
from sklearn.feature_selection import selectkbest
>>>
from sklearn.feature_selection import chi2
>>> iris = load_iris()
>>> x, y = iris.data, iris.target
>>> x.shape
(150, 4)
>>> x_new = selectkbest(chi2, k=2).fit_transform(x, y)
>>> x_new.shape
(150, 2)
作為引數的打分的函式對於回歸和分類是不同的:
-回歸:f_regression, mutual_info_regression
-分類:chi2, f_classif, mutual_info_classif
值得注意的是互資訊(mutual_info_regression, mutual_info_classif)可以得到特徵和最後的結果之間的非線性的相關性,而卡方檢驗和f-檢驗應該只能夠判斷線性性。互資訊的公式是 i(
x;y)
=∑x∈
x∑y∈
yp(x
,y)p
(x,y
)p(x
)p(y
) i(x
;y)=
∑x∈x
∑y∈y
p(x,
y)p(
x,y)
p(x)
p(y)
遞迴特徵消除(rfe)很好理解,給定乙個模型,要求這個模型要能夠給出coef_或者feature_importance_,然後我們就能夠根據訓練的這些相關性特徵刪除得分最差的特徵,然後再一次訓練,重複這個過程,直到最後滿足我們預設的特徵個數。還可以用rfecv通過交叉驗證找出最佳的特徵個數。下面是乙個示例。
from sklearn.feature_selection import rfe
from sklearn.linear_model import logisticregression
#遞迴特徵消除法,返回特徵選擇後的資料
#引數estimator為基模型
#引數n_features_to_select為選擇的特徵個數
rfe(estimator=logisticregression(), n_features_to_select=2).fit_transform(iris.data, iris.target)
slectformmodel也就是從模型中選擇,感覺上和上面的遞迴特徵消除有點相似,它是乙個「元轉換器」,可以和任何帶有coef_或者feature_importance_的模型一起使用。另外我們會指定乙個引數「閾值」,小於這個閾值的特徵被認為是不重要的,並且會被移除,不像是rfe會反覆地擬合模型每次移除乙個。大致用法如下
clf = lassocv()
# set a minimum threshold of 0.25
sfm = selectfrommodel(clf, threshold=0.25)
sfm.fit(x, y)
n_features = sfm.transform(x).shape[1]
上面用的是lassocv結合selectfrommodel進行特徵選擇。
帶有l1懲罰項的線性模型容易產生稀疏解,那麼我們可以讓selectfrommodel和這種模型相結合,最後選擇相關係數不為0的特徵就行。一般的線性模型有lasso,logisiticregression以及linearsvc
>>>
from sklearn.svm import linearsvc
>>>
from sklearn.datasets import load_iris
>>>
from sklearn.feature_selection import selectfrommodel
>>> iris = load_iris()
>>> x, y = iris.data, iris.target
>>> x.shape
(150, 4)
>>> lsvc = linearsvc(c=0.01, penalty="l1", dual=false).fit(x, y)
>>> model = selectfrommodel(lsvc, prefit=true)
>>> x_new = model.transform(x)
>>> x_new.shape
(150, 3)
對於svc和logisticregression越小的c,越少的特徵被選擇。對於lasso,越大的alpha越少的特徵被選擇。具體是什麼原因,我也不知道。
這個方法的原理也是類似的,因為樹在生成過程中一定也會選擇特徵。回憶一下決策樹,不論是id3,c4.5還是cart開始的時候都是先找乙個最能夠區分資料集的特徵,cart是二叉樹,第一步要找出最優特徵和最優切分點,之後不斷迴圈。這個過程不就是篩選出最優特徵的過程嗎?不過在應用中,**還是和上面類似,和selectfrommodel已啟用。
>>> from sklearn.ensemble import extratreesclassifier
>>> from sklearn.datasets import load_iris
>>> from sklearn.feature_selection import selectfrommodel
>>> iris = load_iris()
>>> x, y = iris.data, iris.target
>>> x.shape
>(150, 4)
>>> clf = extratreesclassifier()
>>> clf = clf.fit(x, y)
>>> clf.feature_importances_
array([ 0.04
..., 0.05
..., 0.4
..., 0.4
...])
>>> model = selectfrommodel(clf, prefit=true)
>>> x_new = model.transform(x)
>>> x_new.shape
(150, 2)
以上是一些特徵篩選的方法,另外還有特徵的構造,但本人經驗不足,在此就略去這方面的論述了。 特徵工程之特徵選擇
特徵選擇其實就是減少屬性個數,為什麼要這麼做呢?直接使用原始資料來訓練模型的話,雖然說在訓練模型上的準確率會非常高,但是在測試樣本上的準確率將會大打折扣,也就是會產生過擬合的現象。所以說需要選擇出最適合的屬性進行訓練。特徵選擇的原因 2 雜訊 部分特徵對 結果又影響 進行特徵選擇的時候有兩種情況 一...
特徵工程之特徵選擇
在做資料分析的時候,特徵的 一般有兩塊,一塊是業務已經整理好各種特徵資料,我們需要去找出適合我們問題需要的特徵 另一塊是我們從業務特徵中自己去尋找高階資料特徵。我們就針對這兩部分來分別討論。2.選擇合適的特徵 我們首先看當業務已經整理好各種特徵資料時,我們如何去找出適合我們問題需要的特徵,此時特徵數...
特徵工程之特徵表達
在特徵工程之特徵選擇中,我們講到了特徵選擇的一些要點。本篇我們繼續討論特徵工程,不過會重點關注於特徵表達部分,即如果對某乙個特徵的具體表現形式做處理。主要包括缺失值處理,特殊的特徵處理比如時間和地理位置處理,離散特徵的連續化和離散化處理,連續特徵的離散化處理幾個方面。特徵有缺失值是非常常見的,大部分...