Python sklearn學習之特徵選擇

Python sklearn學習之特徵選擇



一般而言,特徵選擇的過程是指從已有的M個特徵(Feature)中選擇N個特徵使得系統的特定指標最優化,是從原始特徵中選擇出一些最有效特徵以降低數據集維度的過程。其可看爲是一個搜索尋優問題。

原始數據
特徵子集
選中特徵
開始
子集產生
子集評價
停止策略
結果驗證

1. 移除低方差特徵

VarianceThreshold 是特徵選擇的一個簡單基本方法,它會移除所有那些方差不滿足一些閾值的特徵。默認情況下,它將會移除所有的零方差特徵(相同值),即那些在所有的樣本上的取值均不變的特徵。

from sklearn.feature_selection import VarianceThreshold

X = [[0, 2, 0, 3], [0, 1, 4, 3], [0, 1, 1, 3], [0, 2, 3, 3]]
select = VarianceThreshold()
result = select.fit_transform(X)
print(result)
[[2 0]
 [1 4]
 [1 1]
 [2 3]]

VarianceThreshold 在上述代碼中起的作用如下:

將第1列及第4列特徵進行剔除而選擇中間兩列特徵。

  • VarianceThreshold 類定義
def __init__(self, threshold=0.):
  • 參數說明

VarianceThreshold 對象在創建過程中可設置一個參數 threshold 。該參數定義了一個閾值,默認爲0,如果手動設置了,則會刪除訓練集中方差低於該閾值的特徵。

  • 實例

假設我們有一個特徵是布爾值的數據集,我們想要移除那些在整個數據集中特徵值爲0或者爲1的比例超過80%的特徵。布爾特徵是伯努利(Bernoulli)隨機變量,變量的方差爲 Var[X]=p(1p) Var[X] = p(1-p)
於是,整個代碼如下:(第一列中值爲0的概率爲p=5/6>8)

from sklearn.feature_selection import VarianceThreshold

X = [[0, 0, 1], [0, 1, 0], [1, 0, 0], [0, 1, 1], [0, 1, 0], [0, 1, 1]]
select = VarianceThreshold(.8 * (1 - .8))
result = select.fit_transform(X)
print(result)
[[0 1]
 [1 0]
 [0 0]
 [1 1]
 [1 0]
 [1 1]]

2. 單變量特徵選擇

2.1 單變量特徵選擇工具類

單變量的特徵選擇,本質上是對每個變量(特徵)進行一種檢驗,比如卡方檢驗,得到一個測試結果(分數)。根據這個分數來選擇我們需要的特徵。
常見的工具類有以下幾種:

  • SelectKBest(self, score_func=f_classif, k=10): 用score_func指定的檢驗函數對每個特徵進行檢測,保留得分最高的k個(默認爲10)
  • SelectPercentile(self, score_func=f_classif, percentile=10): 用score_func指定的檢驗函數對每個特徵進行檢測,保留前百分之幾的特徵,其中百分數由percentile指定(默認爲%10)
  • SelectFpr(self, score_func=f_classif, alpha=5e-2): 根據FPR測試選擇低於alpha的pvalues,其中FPR測試代表假陽性率測試,它控制錯誤檢測的總量。
  • SelectFdr(score_func=f_classif, alpha=0.05): 選擇估計的錯誤發現率的p值,其中alpha表示要保留的功能的最高未校正p值。
  • SelectFwe(score_func=f_classif, alpha=0.05): 選擇與族系錯誤率對應的p值,其中alpha表示特徵分數的p值
  • GenericUnivariateSelect(score_func=f_classif, mode=’percentile’, param=1e-05): 這是一個可配置的單變量特徵選擇器,用指定的score_func檢驗函數進行檢驗,之後根據mode指定的方式保留需要的特徵,其中mode取值{‘percentile’, ‘k_best’, ‘fpr’, ‘fdr’, ‘fwe’},而param則爲不同mode方式對應的參數

2.2 score_func參數說明

2.2.1 用於迴歸:

  • f_regression : 單變量線性迴歸

I=((X[:,i]mean(X[:,i]))(ymeany))/(std(X[:,i])std(y)) I = ((X[:, i] - mean(X[:, i])) * (y - mean_y)) / (std(X[:, i]) * std(y))

  • mutual_info_regression : 估算連續目標變量的互信息,互信息描述了兩個變量之間的依賴關係,當且僅當兩個隨機變量是獨立的時,其互信息值爲0,當值越大時,依賴性越大。

I(X;Y)=YXp(x,y)log(p(x,y)p(x),p(y))dxdy I(X;Y) = \int_{Y} \int_{X}p(x,y)log({{p(x,y)}\over{p(x),p(y)}})dxdy

其中,p(x,y)是X和Y的聯合概率密度函數,而p(x)與p(y)分別是X和Y的邊緣概率密度函數。

2.2.2用於分類:

  • chi2 : 計算每個非負特徵之間的卡方統計量。

X2=i=1k(finpi2)npi X^2 = \sum^k_{i=1}{({f_i-np_i}^2) \over np_i}

其中,假設總體分佈爲 F(x)F(x),且總體X的分佈率爲 P{X=xi}=pi,i=1,2,3,...P\{X=x_i\}=p_i,i=1,2,3,...

  • f_classif : 計算所提供樣品的ANOVA F值(方差分析),這個函數是上述檢驗工具類的默認函數,它計算的是組間平均方差和組內平均方差的比值。
  • mutual_info_classif : 估計離散目標變量的互信息

I(X;Y)=yYxXlog(p(x,y)p(x),p(y)) I(X;Y) = \sum_{y \in Y} \sum_{x \in X}log({{p(x,y)}\over{p(x),p(y)}})

其中,p(x,y)是X和Y的聯合概率分佈函數,而p(x)與p(y)分別是X和Y的邊緣概率分佈函數。當離散變量變成了連續變量,求和計算則被積分替代。就變成了mutual_info_regression

3. 遞歸式特徵消除

顧名思義,遞歸特徵消除就是先將最不重要的特徵剔除得到子集,再在子集的基礎上,再把最不重要的剔除,得到更小的子集,如此遞歸下去,直到得到滿足需要的特徵子集。而在此過程中,對於特徵的重要程度,則從 coef_ 屬性和 feture_importances_ 屬性獲得。

  • 實例
from sklearn.svm import SVC
from sklearn.datasets import load_digits
from sklearn.feature_selection import RFE
import matplotlib.pyplot as plt

# Load the digits dataset
digits = load_digits()
X = digits.images.reshape((len(digits.images), -1))
y = digits.target
print("變量X的維度:")
print(X.shape)

# Create the RFE object and rank each pixel
svc = SVC(kernel="linear", C=1)
rfe = RFE(estimator=svc, n_features_to_select=1, step=1)
rfe.fit(X, y)
ranking = rfe.ranking_.reshape(digits.images[0].shape)
print("變量ranking的維度:")
print(ranking.shape)

# Plot pixel ranking
plt.matshow(ranking)
plt.colorbar()
plt.title("Ranking of pixels with RFE")
plt.show()
變量X的維度:
(1797, 64)
變量ranking的維度:
(8, 8)

在這裏插入圖片描述

4. SelectFromModel

首先,SelectFromModel 是爲了處理來自於Model的數據而提出來的,如果相關的 coef_ 或者 featureimportances 屬性值低於預先設置的閾值(threshold),這些特徵將會被認爲不重要並且移除掉。除了能夠指定threshold的值外,還可以通過給定字符串參數來使用內置的啓發式方法找到一個合適的閾值。

  • 實例
import matplotlib.pyplot as plt
import numpy as np

from sklearn.datasets import load_boston
from sklearn.feature_selection import SelectFromModel
from sklearn.linear_model import LassoCV

# Load the boston dataset.
boston = load_boston()
X, y = boston['data'], boston['target']

# We use the base estimator LassoCV since the L1 norm promotes sparsity of features.
clf = LassoCV(cv=5)

# Set a minimum threshold of 0.25
sfm = SelectFromModel(clf, threshold=0.25)
sfm.fit(X, y)
n_features = sfm.transform(X).shape[1]

# 修改threshold值
while n_features > 2:
    sfm.threshold += 0.1
    X_transform = sfm.transform(X)
    n_features = X_transform.shape[1]

# 繪製來自於X的兩個特徵變量的散點圖
plt.title(
    "Features selected from Boston using SelectFromModel with "
    "threshold %0.3f." % sfm.threshold)
feature1 = X_transform[:, 0]
feature2 = X_transform[:, 1]
print("變量X的維度:")
print(X.shape)
print("選擇後數據的維度:")
print(X_transform.shape)
plt.plot(feature1, feature2, 'r.')
plt.xlabel("Feature number 1")
plt.ylabel("Feature number 2")
plt.ylim([np.min(feature2), np.max(feature2)])
plt.show()
變量X的維度:
(506, 13)
選擇後數據的維度:
(506, 2)

在這裏插入圖片描述

4.1 基於 L1 的特徵選取

Linear models 使用 L1 正則化的線性模型會得到稀疏解:他們的許多係數爲 0。

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
print("X.shape")
print(X.shape)
lsvc = LinearSVC(C=0.01, penalty="l1", dual=False).fit(X, y)
model = SelectFromModel(lsvc, prefit=True)
X_new = model.transform(X)
print("X_new.shape")
print(X_new.shape)
X.shape
(150, 4)
X_new.shape
(150, 3)

4.2 基於 Tree(樹)的特徵選取

基於樹的特徵選取可以用來計算特徵的重要性,然後可以消除不相關的特徵。

  • 實例
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
print("X.shape")
print(X.shape)
clf = ExtraTreesClassifier()
clf = clf.fit(X, y)
print("clf.feature_importances_")
print(clf.feature_importances_)
model = SelectFromModel(clf, prefit=True)
X_new = model.transform(X)
print("X_new.shape")
print(X_new.shape)
X.shape
(150, 4)
clf.feature_importances_
[0.03024885 0.04546254 0.43126586 0.49302275]
X_new.shape
(150, 2)

5. 特徵選取作爲 pipeline(管道)的一部分

特徵選擇通常在實際的學習之前用來做預處理。在 scikit-learn 中推薦的方式是使用 sklearn.pipeline.Pipeline

clf = Pipeline([
  ('feature_selection', SelectFromModel(LinearSVC(penalty="l1"))),
  ('classification', RandomForestClassifier())
])
clf.fit(X, y)

在這段代碼中,我們利用 sklearn.svm.LinearSVC 和 sklearn.feature_selection.SelectFromModel 來評估特徵的重要性並且選擇出相關的特徵。 然後,在轉化後的輸出中使用一個 sklearn.ensemble.RandomForestClassifier 分類器,比如只使用相關的特徵。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章