結合sklearn進行特徵工程

1 前言

該篇博客主要涉及到sklearn.feature_selection 以及其他相關模型,主要介紹瞭如何利用sklearn進行特徵工程,特徵工程在機器學習中佔有工程師的大部分精力,目前也有很多成熟的方法和理論,但是結合實際業務背景選擇特徵仍然是提升模型性能的關鍵點。sklearn.feature_selection是一個強大的特徵處理工具包,磨刀不誤砍柴工,熟練使用工具是重中之重!以下是特徵工程的概要圖。

特徵工程

2 數據預處理

  1. 不屬於同一量綱:即特徵的規格不一樣,不能夠放在一起比較。無量綱化可以解決這一問題。
  2. 缺失值處理:包括缺失值刪除及補充。

導入數據集,sklearn具有自動生成數據集工具包例如sklearn.dataset.make_classification,也有標準數據集比如sklearn.dataset.load_boston,sklearn.dataset.load_iris,下面是鳶尾花IRIS數據的下載程序

from sklearn.datasets import load_iris

#導入IRIS數據集
iris = load_iris()
#特徵矩陣
dataset = iris.data

#目標向量
labels = iris.target

print "特徵矩陣\n",dataset[:5,:]
print '標籤\n',set(labels)
特徵矩陣
[[ 5.1  3.5  1.4  0.2]
 [ 4.9  3.   1.4  0.2]
 [ 4.7  3.2  1.3  0.2]
 [ 4.6  3.1  1.5  0.2]
 [ 5.   3.6  1.4  0.2]]
標籤
set([0, 1, 2])

2.1 數據無量綱化

無量綱化使不同規格的數據轉換到同一規格。常見的無量綱化方法有標準化和區間縮放法。標準化的前提是特徵值服從正態分佈,標準化後,其轉換成標準正態分佈。區間縮放法利用了邊界值信息,將特徵的取值區間縮放到某個特定的範圍,例如[0, 1]等。

2.1.1 標準化

標準化需要計算每個特徵的均值和標準差,公式表達爲:
x=xX¯S

使用preproccessing庫的StandardScaler類對數據進行標準化的代碼如下:
標準化之後的數據範圍在[-1,1]之間

至於爲什麼用.fit_transform(),可參考http://www.cnblogs.com/jasonfreak/p/5448462.html

from sklearn.preprocessing import StandardScaler

#標準化,返回值爲標準化後的數據,矩陣形式,下面只顯示了前10行數據
StandardScaler().fit_transform(dataset)[:10,:]
array([[-0.90068117,  1.03205722, -1.3412724 , -1.31297673],
       [-1.14301691, -0.1249576 , -1.3412724 , -1.31297673],
       [-1.38535265,  0.33784833, -1.39813811, -1.31297673],
       [-1.50652052,  0.10644536, -1.2844067 , -1.31297673],
       [-1.02184904,  1.26346019, -1.3412724 , -1.31297673],
       [-0.53717756,  1.95766909, -1.17067529, -1.05003079],
       [-1.50652052,  0.80065426, -1.3412724 , -1.18150376],
       [-1.02184904,  0.80065426, -1.2844067 , -1.31297673],
       [-1.74885626, -0.35636057, -1.3412724 , -1.31297673],
       [-1.14301691,  0.10644536, -1.2844067 , -1.4444497 ]])

2.1.2 歸一化處理

標準化與歸一化的區別
簡單來說,
標準化是依照特徵矩陣(每一列是用同一個特徵的不同取值)的列處理數據,其通過求z-score的方法,將樣本的每個特徵的值轉換到同一量綱下。
歸一化是依照特徵矩陣(每一行是不同特徵的取值)的行處理數據,其目的在於樣本向量在點乘運算或其他核函數計算相似性時,擁有統一的標準,也就是說都轉化爲“單位向量”。

規則爲L2 範數的歸一化公式如下:
x=xj=1mx2j

使用preproccessing庫的Normalizer類對數據進行歸一化的代碼如下:

from sklearn.preprocessing import Normalizer

#歸一化,返回值爲歸一化後的數據的符號與原數據符號相同
Normalizer().fit_transform(dataset)[:10,:]
array([[ 0.80377277,  0.55160877,  0.22064351,  0.0315205 ],
       [ 0.82813287,  0.50702013,  0.23660939,  0.03380134],
       [ 0.80533308,  0.54831188,  0.2227517 ,  0.03426949],
       [ 0.80003025,  0.53915082,  0.26087943,  0.03478392],
       [ 0.790965  ,  0.5694948 ,  0.2214702 ,  0.0316386 ],
       [ 0.78417499,  0.5663486 ,  0.2468699 ,  0.05808704],
       [ 0.78010936,  0.57660257,  0.23742459,  0.0508767 ],
       [ 0.80218492,  0.54548574,  0.24065548,  0.0320874 ],
       [ 0.80642366,  0.5315065 ,  0.25658935,  0.03665562],
       [ 0.81803119,  0.51752994,  0.25041771,  0.01669451]])

2.1.3 區間縮放法

區間縮放法的思路有多種,常見的一種爲利用兩個最值進行縮放,公式表達爲:
x=xMinMaxMin

使用preproccessing庫的MinMaxScaler類對數據進行區間縮放的代碼如下:區間縮放之後數據範圍在[0,1]之間

from sklearn.preprocessing import MinMaxScaler

#區間縮放,返回值爲縮放到[0, 1]區間的數據
MinMaxScaler().fit_transform(dataset)[:10,:]
array([[ 0.22222222,  0.625     ,  0.06779661,  0.04166667],
       [ 0.16666667,  0.41666667,  0.06779661,  0.04166667],
       [ 0.11111111,  0.5       ,  0.05084746,  0.04166667],
       [ 0.08333333,  0.45833333,  0.08474576,  0.04166667],
       [ 0.19444444,  0.66666667,  0.06779661,  0.04166667],
       [ 0.30555556,  0.79166667,  0.11864407,  0.125     ],
       [ 0.08333333,  0.58333333,  0.06779661,  0.08333333],
       [ 0.19444444,  0.58333333,  0.08474576,  0.04166667],
       [ 0.02777778,  0.375     ,  0.06779661,  0.04166667],
       [ 0.16666667,  0.45833333,  0.08474576,  0.        ]])

2.2 缺失值處理

  1. 直接除去含有缺失值的樣本點
  2. 缺失值填補(其中sklearn、numpy、pandas等python工具包都有相應處理方法),在本次博客中,只介紹sklearn工具包中的處理方法(imputer類),numpy和pandas會在其他博客中給出。

由於IRIS數據包中並沒有缺失值,這裏會給出人工數據集的測試用例,處理缺失值的一般步驟如下所示:
1. 使用字符串’nan’來代替數據集中的缺失值;
2. 將該數據集轉換爲浮點型便可以得到包含np.nan的數據集;
3. 使用sklearn.preprocessing.Imputer類來處理使用np.nan對缺失值處理過的數據集。

import numpy as np
from sklearn.preprocessing import Imputer

#含有空格的數據
tem='1,2,3, ,3,4,5,6,7,8, ,9'
print tem

#替換空格字符
tem = tem.replace(' ','nan').split(',')
print tem
#將數據轉換成浮點型矩陣形式
x = np.array(tem,dtype = float).reshape((4,3))
print x
1,2,3, ,3,4,5,6,7,8, ,9
['1', '2', '3', 'nan', '3', '4', '5', '6', '7', '8', 'nan', '9']
[[  1.   2.   3.]
 [ nan   3.   4.]
 [  5.   6.   7.]
 [  8.  nan   9.]]
Imputer().fit_transform(x)
array([[ 1.        ,  2.        ,  3.        ],
       [ 4.66666667,  3.        ,  4.        ],
       [ 5.        ,  6.        ,  7.        ],
       [ 8.        ,  3.66666667,  9.        ]])

Imputer()的參數有:
1. missing_values:默認是((default=”NaN”))
2. strategy :string字符格式, optional (default=”mean”),一般有mean(均值),median(中位數),most_frequent(衆數)
3. axis:軸向,默認是(列向,axis =0),行是(axis=1)
可通過help指令顯示對Imputer的解釋

help(Imputer())

3 特徵構建

特徵構建包括以下內容:
1. 基於統計方法構造統計量
2. 對某些連續定量特徵進行離散化,以便去除冗餘信息
3. 對定性特徵進行啞編碼,將其轉換成定量特徵
4. 特徵交叉

3.1 基於統計方法的構造統計量

該方法更多的是針對時間序列數據,例如,一段時間的廣告點擊量的單位時間均值,一段時間,某個用戶對某個商品的瀏覽總數等。

3.2 對某些連續定量特徵離散化,以便去除冗餘信息

3.2.1 對連續定量數據二值化

定量特徵二值化的核心在於設定一個閾值,大於閾值的賦值爲1,小於等於閾值的賦值爲0,公式表達如下:

x={1,x>threshold0,xthreshold

使用preproccessing庫的Binarizer類對數據進行二值化的代碼如下:

from sklearn.preprocessing import Binarizer

#二值化,閾值設置爲3,返回值爲二值化後的數據
Binarizer(threshold = 3).fit_transform(dataset)[:10,:]
array([[ 1.,  1.,  0.,  0.],
       [ 1.,  0.,  0.,  0.],
       [ 1.,  1.,  0.,  0.],
       [ 1.,  1.,  0.,  0.],
       [ 1.,  1.,  0.,  0.],
       [ 1.,  1.,  0.,  0.],
       [ 1.,  1.,  0.,  0.],
       [ 1.,  1.,  0.,  0.],
       [ 1.,  0.,  0.,  0.],
       [ 1.,  1.,  0.,  0.]])

3.3 定性特徵啞編碼

特徵更多的時候是分類特徵,而不是連續的數值特徵。

比如一個人的特徵可以是[“male”, “female”], [“from Europe”, “from US”, “from Asia”], [“uses Firefox”, “uses Chrome”, “uses Safari”, “uses Internet Explorer”]。 這樣的特徵可以高效的編碼成整數,

例如 [“male”, “from US”, “uses Internet Explorer”]可以表示成[0, 1, 3],

[“female”, “from Asia”, “uses Chrome”]就是[1, 2, 1]。

這個的整數特徵表示並不能在scikit-learn的估計器中直接使用,因爲這樣的連續輸入,估計器會認爲類別之間是有序的,但實際卻是無序的。(例如:瀏覽器的類別數據則是任意排序的)。

一個將分類特徵轉換成scikit-learn估計器可用特徵的可選方法是使用one-of-K或者one-hot編碼,該方法是:class:OneHotEncoder的一個實現。該方法將每個類別特徵的 “m” 可能值轉換成”m”個二進制特徵值,當然只有一個是激活值。

from sklearn.preprocessing import OneHotEncoder
array = np.array([[0.1,0,3],[1,1,0],[0.7,2,1],[1,0,2]])
print array
print OneHotEncoder().fit_transform(array).toarray()
[[ 0.1  0.   3. ]
 [ 1.   1.   0. ]
 [ 0.7  2.   1. ]
 [ 1.   0.   2. ]]
[[ 1.  0.  1.  0.  0.  0.  0.  0.  1.]
 [ 0.  1.  0.  1.  0.  1.  0.  0.  0.]
 [ 1.  0.  0.  0.  1.  0.  1.  0.  0.]
 [ 0.  1.  1.  0.  0.  0.  0.  1.  0.]]
help(OneHotEncoder)

注意
1. 該編碼方法輸入矩陣的數據應爲浮點型會整型,當爲浮點型時,會自動轉爲整型,直接保留整數位數據
2. 在矩陣array中,共有4行3列,假設每一列對應一個特徵,則第一列有兩個可能取值(屬性):0,1;第二列有三個可能取值:0,1,2;第三列可能取值:0,1,2,3;這樣一來,第一列(第一個特徵)可以用2位的二進制碼來表示,第二列可以用3位二進制碼來表示,第四列用4位二進制碼來表示;因此會產生2+3+4=9列,從結果中可以看出第一列第一位0.1=1,0(二進制),第二列第一位0=1,0,0,第三列第一位3=0,0,0,1
3. 從結果中還可以看出,編碼之前會對每一列的屬性值進行排序,屬性值對應的編碼值,第一位爲最小屬性值,最後一位爲最高屬性值。

3.4 特徵交叉

交叉從理論上而言是爲了引入特徵之間的交互,也即爲了引入非線性性。舉個簡單的例子,在特徵爲性別的屬性值爲對不同種類廣告的CTR(廣告點擊率),當然還有其他方式,包括CTR與年齡,CTR與地域,下面介紹一種多項式特徵構建方法

很多情況下,多項式特徵是通過考慮輸入數據中的非線性特徵來增加模型的複雜性,它能捕捉到特徵中高階和相互作用的項。 :class:PolynomialFeatures類中可以實現該功能,其代碼實現如下所示:

from sklearn.preprocessing import PolynomialFeatures
x =  np.arange(6).reshape(3,2)
print x
[[0 1]
 [2 3]
 [4 5]]
poly = PolynomialFeatures()#默認輸入兩個參數
help(poly)
poly.fit_transform(x)
array([[  1.,   0.,   1.,   0.,   0.,   1.],
       [  1.,   2.,   3.,   4.,   6.,   9.],
       [  1.,   4.,   5.,  16.,  20.,  25.]])

上述執行過程是在input_feature = (x1,x2),output_feature = (1,x1,x2,x21,x22,x1x2) ,參數degree =2,interaction_only = False

x = np.arange(9).reshape(3, 3)
poly = PolynomialFeatures(degree = 3,interaction_only = True)
poly.fit_transform(x)
array([[   1.,    0.,    1.,    2.,    0.,    0.,    2.,    0.],
       [   1.,    3.,    4.,    5.,   12.,   15.,   20.,   60.],
       [   1.,    6.,    7.,    8.,   42.,   48.,   56.,  336.]])

上述執行過程是在input_feature = (x1,x2,x3),output_feature = (1,x1,x2,x3,x1x2,x1x3,x2x3,x1x2x3) ,參數degree = 3,interaction_only = True

注意多項式特徵被隱含地使用在覈方法

4 特徵選擇

特徵選擇主要有三種方法:
1. Fliter 過濾法按照發散性或者相關性對各個特徵進行評分,設定閾值或者待選擇閾值的個數,選擇特徵。
2. Wrapper:包裝法,根據目標函數(通常是預測效果評分),每次選擇若干特徵,或者排除若干特徵。
3. Embedded:嵌入法,先使用某些機器學習的算法和模型進行訓練,得到各個特徵的權值係數,根據係數從大到小選擇特徵。類似於Filter方法,但是是通過訓練來確定特徵的優劣。

4.1 Fliter 過濾法

4.1.1 方差選擇法

使用方差選擇法,先要計算各個特徵的方差,然後根據閾值,選擇方差大於閾值的特徵。使用feature_selection庫的VarianceThreshold類來選擇特徵,是特徵選擇中的一項基本方法。它會移除所有方差不滿足閾值的特徵。默認設置下,它將移除所有方差爲0的特徵,即那些在所有樣本中數值完全相同的特徵(類似常數特徵)。

from sklearn.feature_selection import VarianceThreshold

print np.cov(dataset.T)
print dataset[:5,:]
#參數threshold爲方差的閾值,該方法會移除方差小於3的特徵,人爲選擇閾值具有主觀性
VarianceThreshold(threshold=3).fit_transform(dataset)[:5,:]
[[ 0.68569351 -0.03926846  1.27368233  0.5169038 ]
 [-0.03926846  0.18800403 -0.32171275 -0.11798121]
 [ 1.27368233 -0.32171275  3.11317942  1.29638747]
 [ 0.5169038  -0.11798121  1.29638747  0.58241432]]
[[ 5.1  3.5  1.4  0.2]
 [ 4.9  3.   1.4  0.2]
 [ 4.7  3.2  1.3  0.2]
 [ 4.6  3.1  1.5  0.2]
 [ 5.   3.6  1.4  0.2]]





array([[ 1.4],
       [ 1.4],
       [ 1.3],
       [ 1.5],
       [ 1.4]])

可以看到,特徵方差爲對角線上元素,只有一個特徵方差大於3,最後的結果中也至於一列被選出來。

4.1.2 相關係數方法

使用相關係數法,先要計算各個特徵對目標值的相關係數以及相關係數的P值。用feature_selection庫的SelectKBest類結合相關係數來選擇特徵的代碼如下:

from sklearn.feature_selection import SelectKBest
from scipy.stats import pearsonr


#選擇K個最好的特徵,返回選擇特徵後的數據
#第一個參數爲計算評估特徵是否好的函數,該函數輸入特徵矩陣和目標向量,輸出二元組(評分,P值)的數組,
#數組第i項爲第i個特徵的評分和P值。在此定義爲計算相關係數
#參數k爲選擇的特徵個數

print np.array(map(lambda x:pearsonr(x,iris.target),dataset.T))

#print dataset.T

SelectKBest(lambda X,Y:np.array(map(lambda x:pearsonr(x,Y),X.T))[:,0],k=2)\
.fit_transform(dataset,iris.target)[:10,:]
[[  7.82561232e-01   2.89047835e-32]
 [ -4.19446200e-01   9.15998497e-08]
 [  9.49042545e-01   4.15547758e-76]
 [  9.56463824e-01   4.77500237e-81]]





array([[ 1.4,  0.2],
       [ 1.4,  0.2],
       [ 1.3,  0.2],
       [ 1.5,  0.2],
       [ 1.4,  0.2],
       [ 1.7,  0.4],
       [ 1.4,  0.3],
       [ 1.5,  0.2],
       [ 1.4,  0.2],
       [ 1.5,  0.1]])
help(pearsonr)
Help on function pearsonr in module scipy.stats.stats:

pearsonr(x, y)
    Calculates a Pearson correlation coefficient and the p-value for testing
    non-correlation.

    The Pearson correlation coefficient measures the linear relationship
    between two datasets. Strictly speaking, Pearson's correlation requires
    that each dataset be normally distributed, and not necessarily zero-mean.
    Like other correlation coefficients, this one varies between -1 and +1
    with 0 implying no correlation. Correlations of -1 or +1 imply an exact
    linear relationship. Positive correlations imply that as x increases, so
    does y. Negative correlations imply that as x increases, y decreases.

    The p-value roughly indicates the probability of an uncorrelated system
    producing datasets that have a Pearson correlation at least as extreme
    as the one computed from these datasets. The p-values are not entirely
    reliable but are probably reasonable for datasets larger than 500 or so.

    Parameters
    ----------
    x : (N,) array_like
        Input
    y : (N,) array_like
        Input

    Returns
    -------
    r : float
        Pearson's correlation coefficient
    p-value : float
        2-tailed p-value

    References
    ----------
    http://www.statsoft.com/textbook/glosp.html#Pearson%20Correlation

4.1.3 卡方檢驗

經典的卡方檢驗是檢驗定性自變量對定性因變量的相關性。由於它最初是由英國統計學家Karl Pearson在1900年首次提出的,因此也稱之爲Pearson χ2,其計算公式爲.假設自變量有N種取值,因變量有M種取值,考慮自變量等於i且因變量等於j的樣本頻數的觀察值與期望的差距,構建統計量:
χ2=i=1k(Ainpi)2npi(i=1,2,...,k)

其中,Ai爲i水平的觀察頻數,Ei爲i水平的期望頻數,n爲總頻數,pi爲i水平的期望頻率。i水平的期望頻數Ei等於總頻數n×i水平的期望概率pi,k爲單元格數。當n比較大時,χ2統計量近似服從k-1(計算Ei時用到的參數個數)個自由度的卡方分佈。
這個統計量的含義簡而言之就是自變量對因變量的相關性。用feature_selection庫的SelectKBest類結合卡方檢驗來選擇特徵的代碼如下:

from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
print dataset[:5,:]
SelectKBest(chi2,k=2).fit_transform(dataset,labels)[:5,:]
[[ 5.1  3.5  1.4  0.2]
 [ 4.9  3.   1.4  0.2]
 [ 4.7  3.2  1.3  0.2]
 [ 4.6  3.1  1.5  0.2]
 [ 5.   3.6  1.4  0.2]]





array([[ 1.4,  0.2],
       [ 1.4,  0.2],
       [ 1.3,  0.2],
       [ 1.5,  0.2],
       [ 1.4,  0.2]])
help(chi2)
Help on function chi2 in module sklearn.feature_selection.univariate_selection:

chi2(X, y)
    Compute chi-squared stats between each non-negative feature and class.

    This score can be used to select the n_features features with the
    highest values for the test chi-squared statistic from X, which must
    contain only non-negative features such as booleans or frequencies
    (e.g., term counts in document classification), relative to the classes.

    Recall that the chi-square test measures dependence between stochastic
    variables, so using this function "weeds out" the features that are the
    most likely to be independent of class and therefore irrelevant for
    classification.

    Read more in the :ref:`User Guide <univariate_feature_selection>`.

    Parameters
    ----------
    X : {array-like, sparse matrix}, shape = (n_samples, n_features_in)
        Sample vectors.

    y : array-like, shape = (n_samples,)
        Target vector (class labels).

    Returns
    -------
    chi2 : array, shape = (n_features,)
        chi2 statistics of each feature.
    pval : array, shape = (n_features,)
        p-values of each feature.

    Notes
    -----
    Complexity of this algorithm is O(n_classes * n_features).

    See also
    --------
    f_classif: ANOVA F-value between label/feature for classification tasks.
    f_regression: F-value between label/feature for regression tasks.

4.1.4 互信息法

經典的互信息也是評價定性自變量對定性因變量的相關性的,互信息計算公式如下:
I(X;Y)=xXyYp(x,y)logp(x,y)p(x)p(y)

爲了處理定量數據,最大信息係數法被提出,使用feature_selection庫的SelectKBest類結合最大信息係數法來選擇特徵的代碼如下:

from sklearn.feature_selection import SelectKBest
from minepy import MINE

#和求相關係數方法類似
#由於MINE的設計不是函數式的,定義mic方法將其爲函數式的,
#返回一個二元組,二元組的第2項設置成固定的P值0.5
def mic(x,y):
    m = MINE()
    m.compute_score(x,y)
    return [m.mic(),0.5]
# 顯示各個特徵與目標變量的熵值
feature_mic = []
for i in range(len(dataset.T)):
    feature_mic.append(mic(dataset[:,i],labels))
print np.array(feature_mic)
print dataset[:5,:]
#選擇K個最好的特徵,返回特徵選擇後的數據
SelectKBest(lambda X,Y:np.array(map(lambda x:mic(x,Y),X.T))[:,0],k=2)\
.fit_transform(dataset,labels)[:5,:]
[[ 0.6421959   0.5       ]
 [ 0.40150415  0.5       ]
 [ 0.91829583  0.5       ]
 [ 0.91829583  0.5       ]]
[[ 5.1  3.5  1.4  0.2]
 [ 4.9  3.   1.4  0.2]
 [ 4.7  3.2  1.3  0.2]
 [ 4.6  3.1  1.5  0.2]
 [ 5.   3.6  1.4  0.2]]





array([[ 1.4,  0.2],
       [ 1.4,  0.2],
       [ 1.3,  0.2],
       [ 1.5,  0.2],
       [ 1.4,  0.2]])

4.1.5 總結

以上filter過濾法,可以解釋成單變量特徵選擇方法,所求的方差,相關係數,卡方,互信息都是針對某個變量或者是某個變量與目標變量的關係。這樣,變量之間的相關性會被忽視,另外,最好特徵個數的選取,以及方差閾值選擇具有主觀性,不過可通過超參數調優來獲取最佳性能。

4.2 Wrapper 方法

4.2.1 遞歸特徵消除法

對於一個爲數據特徵指定權重的預測模型(例如,線性模型對應參數coefficients),遞歸特徵消除 (RFE)通過遞歸減少考察的特徵集規模來選擇特徵。首先,預測模型在原始特徵上訓練,每項特徵指定一個權重。之後,那些擁有最小絕對值權重的特徵被踢出特徵集。如此往復遞歸,直至剩餘的特徵數量達到所需的特徵數量。
RFECV 通過交叉驗證的方式執行RFE,以此來選擇最佳數量的特徵。

RFE 實現代碼如下所示

from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression

#遞歸特徵消除法,返回特徵選擇後的數據
#參數estimator爲基模型
#參數n_features_to_select爲選擇的特徵個數
print dataset[:5,:]
RFE(estimator = LogisticRegression(),n_features_to_select = 2)\
.fit_transform(dataset,labels)[:5,:]
[[ 5.1  3.5  1.4  0.2]
 [ 4.9  3.   1.4  0.2]
 [ 4.7  3.2  1.3  0.2]
 [ 4.6  3.1  1.5  0.2]
 [ 5.   3.6  1.4  0.2]]





array([[ 3.5,  0.2],
       [ 3. ,  0.2],
       [ 3.2,  0.2],
       [ 3.1,  0.2],
       [ 3.6,  0.2]])

RFECV代碼實現如下所示:

from sklearn.feature_selection import RFECV
from sklearn.linear_model import LogisticRegression
from sklearn.cross_validation import StratifiedKFold

RFECV(LogisticRegression(),cv= StratifiedKFold(labels,2))\
.fit_transform(dataset,labels)[:5,:]
array([[ 3.5,  1.4,  0.2],
       [ 3. ,  1.4,  0.2],
       [ 3.2,  1.3,  0.2],
       [ 3.1,  1.5,  0.2],
       [ 3.6,  1.4,  0.2]])

4.3 Embedded

4.3.1 基於懲罰項的特徵選擇法

該方法主要通過類SelectFromModel實現,該類作爲一個基轉換器,可以用於擬合後任何擁有coef_或feature_importances_屬性的預測模型。
在參數L1懲罰項降維的原理在於保留多個對目標值具有同等相關性的特徵中的一個,所以沒選到的特徵不代表不重要。故,可結合L2懲罰項來優化。具體操作爲:若一個特徵在L1中的權值爲1,選擇在L2中權值差別不大且在L1中權值爲0的特徵構成同類集合,將這一集合中的特徵平分L1中的權值,故需要構建一個新的邏輯迴歸模型:

from sklearn.feature_selection import SelectFromModel
from sklearn.linear_model import LogisticRegression

print "前五個樣本的特徵矩陣\n",dataset[:5,:]
#帶L1懲罰項的邏輯迴歸作爲基模型的特徵選擇
print "所選特徵矩陣\n",SelectFromModel(LogisticRegression(penalty='l1',C =0.1)).fit_transform(dataset,labels)[:5,:]
前五個樣本的特徵矩陣
[[ 5.1  3.5  1.4  0.2]
 [ 4.9  3.   1.4  0.2]
 [ 4.7  3.2  1.3  0.2]
 [ 4.6  3.1  1.5  0.2]
 [ 5.   3.6  1.4  0.2]]
所選特徵矩陣
[[ 5.1  3.5  1.4]
 [ 4.9  3.   1.4]
 [ 4.7  3.2  1.3]
 [ 4.6  3.1  1.5]
 [ 5.   3.6  1.4]]

結合L1,L2的邏輯迴歸

不同算法使用基於L1的特徵選擇進行文檔分類的對比

4.3.2 基於樹模型的特徵選擇法

sklearn中基於樹模型的預測模型包括sklearn.treesklearn.ensembel,在這裏使用feature_selection庫的SelectFromModel類結合GBDT模型,來選擇特徵的代碼如下:

from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import GradientBoostingClassifier

#GBDT作爲基模型的特徵選擇
SelectFromModel(GradientBoostingClassifier()).fit_transform(dataset,labels)[:5,:]
array([[ 1.4,  0.2],
       [ 1.4,  0.2],
       [ 1.3,  0.2],
       [ 1.5,  0.2],
       [ 1.4,  0.2]])

5 特徵提取

這裏特徵提取,可以考慮如下應用背景,圖像像素矩陣的特徵提取、多維特徵矩陣中存在相關特徵子集等。此外,當特徵選擇完成後,可以直接訓練模型了,但是可能由於特徵矩陣過大,導致計算量大,訓練時間長的問題,因此降低特徵矩陣維度也是必不可少的。常見的降維方法除了以上提到的基於L1懲罰項的模型以外,另外還有主成分分析法(PCA)和線性判別分析(LDA),線性判別分析本身也是一個分類模型。PCA和LDA有很多的相似點,其本質是要將原始的樣本映射到維度更低的樣本空間中,但是PCA和LDA的映射目標不一樣:PCA是爲了讓映射後的樣本具有最大的發散性;而LDA是爲了讓映射後的樣本有最好的分類性能。所以說PCA是一種無監督的降維方法,而LDA是一種有監督的降維方法。

5.1 主成分分析法(PCA)

使用decomposition庫的PCA類選擇特徵的代碼如下:

from sklearn.decomposition import PCA

#主成分分析法,返回降維後的數據
#參數n_components爲主成分數目
print "變換後的特徵矩陣選取前兩個主元\n",PCA(n_components=2).fit_transform(dataset)[:5,:]
變換後的特徵矩陣選取前兩個主元
[[-2.68420713  0.32660731]
 [-2.71539062 -0.16955685]
 [-2.88981954 -0.13734561]
 [-2.7464372  -0.31112432]
 [-2.72859298  0.33392456]]

PCA是對原始特徵矩陣的一種投影變換,所得到的是在新空間的得分主元,該主元是將原始特徵矩陣中具有較大方差變化信息提取到主元中,並用主要作爲模型的輸入變量。

5.2 線性判別分析(LDA)

sklearn有專門的庫來解決該問題,代碼如下:

from sklearn.lda import LDA

#線性判別分析法,返回降維後的數據
#參數n_components爲降維後的維數
LDA(n_components =2).fit_transform(dataset,labels)[:5,:]
array([[-8.0849532 ,  0.32845422],
       [-7.1471629 , -0.75547326],
       [-7.51137789, -0.23807832],
       [-6.83767561, -0.64288476],
       [-8.15781367,  0.54063935]])

6 參考文獻

使用sklearn做單機特徵工程
sklearn官方文檔特徵選擇(Feature selection)
機器學習之特徵工程

發佈了55 篇原創文章 · 獲贊 158 · 訪問量 75萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章