天天看點

資料預處理與特征選擇1. 資料預處理2. 特征選擇3. 降維4. 參考資料

資料預處理和特征選擇是資料挖掘與機器學習中關注的重要問題,坊間常說:資料和特征決定了機器學習的上限,而模型和算法隻是逼近這個上限而已。特征工程就是将原始資料轉化為有用的特征,更好的表示預測模型處理的實際問題,提升對于未知資料的預測準确性。下圖給出了特征工程包含的内容:

資料預處理與特征選擇1. 資料預處理2. 特征選擇3. 降維4. 參考資料

本文資料預處理與特征選擇的代碼均采用sklearn所提供的方法,并使用sklearn中的IRIS(鸢尾花)資料集來對特征處理功能進行說明,IRIS資料集由Fisher在1936年整理,包含4個特征:Sepal.Length(花萼長度)、Sepal.Width(花萼寬度)、Petal.Length(花瓣長度)、Petal.Width(花瓣寬度)),特征值都為正浮點數,機關為厘米。目标值為鸢尾花的3個分類:Iris Setosa(山鸢尾)、Iris Versicolour(雜色鸢尾),Iris Virginica(維吉尼亞鸢尾)。導入IRIS資料集的代碼如下:

from sklearn.datasets import load_iris

iris = load_iris() # 導入IRIS資料集
iris.data # 特征矩陣
iris.target # 目标向量
           

1. 資料預處理

1.1 歸一化

我們在對資料進行分析的時候,往往會遇到單個資料的各個次元量綱不同的情況,比如對房子進行價格預測的線性回歸問題中,房子的特征包括面積(平方米)、房間數(個)兩個次元,采用梯度下降進行訓練的過程如下圖所示:

資料預處理與特征選擇1. 資料預處理2. 特征選擇3. 降維4. 參考資料

算法在尋找最優值的時候,由于圖像“細長”,是以要來回找垂直線,兩個特征的取值區間相差越大,圖像就越“細長”,梯度下降就越慢,還可能永遠無法收斂。是以需要使用歸一化的方法将特征的取值區間縮放到某個特定的範圍,例如[0, 1]等,下面介紹兩種方法:

區間縮放(Min-Max scaling)

區間縮放法将原始資料中特征的取值區間轉換到[0 1]範圍,歸一化公式如下:

  • xnorm=x−xminxmax−xmin

該方法實作對原始資料的等比例縮放,其中 x 為原始資料,xnorm為歸一化後的資料, xmax 和 xmin 分别為原始資料的最大值和最小值。使用preproccessing庫的MinMaxScaler類對資料進行區間縮放的代碼如下:

from sklearn.preprocessing import MinMaxScaler

#區間縮放,傳回值為縮放到[0, 1]區間的資料
MinMaxScaler().fit_transform(iris.data)
           

标準化(standardization)

該方法将原始資料歸一化成均值為0、方差1的資料,歸一化公式如下:

  • xnorm=x−μσ

其中, μ 和σ分别為原始資料的均值和方法。該種歸一化方式要求原始資料的分布可以近似為高斯分布,否則歸一化的效果會變得很糟糕。使用preproccessing庫的StandardScaler類對資料進行标準化的代碼如下:

from sklearn.preprocessing import StandardScaler

#标準化,傳回值為标準化後的資料
StandardScaler().fit_transform(iris.data)
           

上述方法是對每個特征(特征矩陣中的列)進行歸一化,除此之外,我們還可以對每個樣本(特征矩陣中的行)進行歸一化,将樣本所對應的特征向量轉化為機關向量,其目的在于樣本向量在點乘運算或其他核函數計算相似性時,擁有統一的标準。使用preproccessing庫的Normalizer類對資料進行歸一化的代碼如下:

from sklearn.preprocessing import Normalizer

#歸一化,傳回值為歸一化後的資料
Normalizer().fit_transform(iris.data)
           

1.2 特征二值化

特征二值化的方法是将特征的取值轉化為0或1。例如,在房價預測問題中對于“是否為學區房”這一特征,取值為1表示該房是學區房,反之則為0。在sklearn中可以設定一個門檻值,大于門檻值的指派為1,小于等于門檻值的指派為0。使用preproccessing庫的Binarizer類對資料進行二值化的代碼如下:

from sklearn.preprocessing import Binarizer

#二值化,門檻值設定為3,傳回值為二值化後的資料
Binarizer(threshold=).fit_transform(iris.data)
           

1.3 one-hot編碼

對于離散特征,例如,性别:{男,女},可以采用one-hot編碼的方式将特征表示為一個m維向量,其中m為特征的取值個數。在one-hot向量中隻有一個次元的值為1,其餘為0。以“性别”這個特征為例,我們可以用向量 “1,0”表示“男”,向量 “0,1”表示“女”。使用one-hot編碼可将離散特征的取值擴充到了歐式空間,便于進行相似度計算。使用preproccessing庫的OneHotEncoder類對資料進行one-hot編碼的代碼如下:

from sklearn.preprocessing import OneHotEncoder

#對IRIS資料集的目标值進行one-hot編碼
OneHotEncoder().fit_transform(iris.target.reshape((-,)))
           

1.4 缺失值計算

在實際應用中,我們得到的資料往往不完整,可以用以下方法進行處理:

  1. 最簡單直接的方法是删除含有缺失值的資料删,這種做法的缺點是可能會導緻資訊丢失
  2. 通過已有資料計算相應特征的平均數、中位數、衆數等來補全缺失值
  3. 建立一個模型來“預測”缺失的資料。(KNN, Matrix completion等方法)
  4. 引入虛拟變量(dummy variable)來表征是否有缺失,是否有補全

用preproccessing庫的Imputer類對資料進行缺失值計算的代碼如下:

from numpy import vstack, array, nan
from sklearn.preprocessing import Imputer

#缺失值計算,傳回值為計算缺失值後的資料
#參數missing_value為缺失值的表示形式,預設為NaN
#對資料集新增一個樣本,4個特征均指派為NaN,表示資料缺失
#參數strategy為缺失值填充方式,預設為mean(均值)
Imputer().fit_transform(vstack((array([nan, nan, nan, nan]), iris.data)))
           

1.5 資料變換

常見的資料變換有基于多項式的、基于指數函數的、基于對數函數的。4個特征,度為2的多項式轉換公式如下:

資料預處理與特征選擇1. 資料預處理2. 特征選擇3. 降維4. 參考資料

使用preproccessing庫的PolynomialFeatures類對資料進行多項式轉換的代碼如下:

from sklearn.preprocessing import PolynomialFeatures

#多項式轉換
#參數degree為度,預設值為2
PolynomialFeatures().fit_transform(iris.data)
           

基于單變元函數的資料變換可以使用一個統一的方式完成,使用preproccessing庫的FunctionTransformer對資料進行對數函數轉換的代碼如下:

from numpy import log1p
from sklearn.preprocessing import FunctionTransformer

#自定義轉換函數為對數函數的資料變換
#第一個參數是單變元函數
FunctionTransformer(log1p).fit_transform(iris.data)
           

1.6 樣本不均衡

樣本不均衡指的是資料集中的正樣本數量與負樣本數量的比例失衡。例如,實際應用中,負樣本的數量通常遠遠大于正樣本。樣本不均衡的危害:造成分類器在多數類精度較高,少數類的分類精度很低,甚至造成分類器失效。解決方案分為以下兩種:

  1. 欠采樣:通過減少多數類樣本來提高少數類的分類性能
    • 随機地去掉一些多數類樣本來減小多數類的規模,該方法的缺點是會丢失多數類的一些重要資訊,不能夠充分利用已有的資訊
    • 通過一定規則有選擇的去掉對分類作用不大的多數樣本(保留與正樣本較為接近的負樣本)
  2. 過抽樣:通過改變訓練資料的分布來消除或減小資料的不平衡
    • 對少數類樣本進行複制,該方法的缺點是可能導緻過拟合,因為沒有給少數類增加任何新的資訊
  3. 算法層面
    • 改進損失函數的權重,加大少數樣本的權值
    • 采用內建學習(bagging, boosting)

2. 特征選擇

資料預處理完成後,接下來需要從給定的特征集合中篩選出對目前學習任務有用的特征,這個過程稱為特征選擇(feature selection)。通常來說,從兩個方面來選擇特征:

  • 特征是否發散:如果一個特征不發散,例如方差接近于0,也就是說樣本在這個特征上基本上沒有差異,這個特征對于樣本的區分并沒有什麼用。
  • 特征與目标的相關性:這點比較顯見,與目标相關性高的特征,應當優選選擇。

常見的特征選擇方法可分為三類:過濾法(Filter)、包裹法(Wrapper)、嵌入法(Embedding)

  1. 過濾法:按照發散性或者相關性對各個特征進行評分,設定門檻值或者待選擇門檻值的個數,選擇特征。
  2. 包裹法:包裹式特征選擇直接把最終要使用的學習器性能作為特征子集的評價标準。
  3. 嵌入法:将特征選擇過程和機器訓練過程融合為一體。兩者在同一優化過程中完成,即在學習器訓練過程中自動進行了特征選擇。

2.1 過濾法(filter)

方差過濾法

方差過濾法需要計算每個特征的方差,然後根據門檻值删除取值小于門檻值的特征。例如,假設某特征的取值為0和1,且訓練集中有90%以上的資料在該特征的取值為1,那麼可認為該特征對于區分不同資料的作用不大。方差過濾法隻能用于篩選離散的特征,如果特征的取值是連續的,就需要将連續值離散化之後才能用。使用feature_selection庫的VarianceThreshold類來選擇特征的代碼如下:

from sklearn.feature_selection import VarianceThreshold

#方差選擇法,傳回值為特征選擇後的資料
#參數threshold為方差的門檻值
VarianceThreshold(threshold=).fit_transform(iris.data)
           

皮爾森相關系數

皮爾森相關系數(Pearson Correlation)是一種最簡單的,能幫助了解特征和目标變量之間關系的方法,該方法衡量的是變量之間的線性相關性,結果的取值區間為[-1,1],-1表示完全的負相關(這個變量下降,那個就會上升),+1表示完全的正相關,0表示沒有線性相關。用feature_selection庫的SelectKBest類結合Pearson 相關系數來選擇特征的代碼如下:

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

#選擇K個最好的特征,傳回選擇特征後的資料
#第一個參數為計算評估特征是否好的函數,該函數輸入特征矩陣和目标向量,輸出二進制組(評分,P值)的數組,數組第i項為第i個特征的評分和P值。在此定義為計算相關系數
#參數k為選擇的特征個數
SelectKBest(lambda X, Y: array(map(lambda x:pearsonr(x, Y), X.T)).T, k=).fit_transform(iris.data, iris.target)
           

互資訊和最大資訊系數

互資訊(Mutual information)用于評價離散特征對離散目标變量的相關性,互資訊計算公式如下:

資料預處理與特征選擇1. 資料預處理2. 特征選擇3. 降維4. 參考資料

互資訊用于特征選擇有以下缺點:

  1. 它不屬于度量方式,也沒有辦法歸一化,在不同資料集上的結果無法做比較;
  2. 對于連續變量的計算不是很友善(X和Y都是集合,x,y都是離散的取值),通常變量需要先離散化,而互資訊的結果對離散化的方式很敏感。

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

from minepy import MINE

m = MINE()
x = np.random.uniform(-, , )
m.compute_score(x, x**)
printm.mic()
           

卡方檢驗

卡方檢驗用于衡量離散特征對離散目标變量的相關性,其計算公式為:

資料預處理與特征選擇1. 資料預處理2. 特征選擇3. 降維4. 參考資料

其中, Ai 為特征A第 i 個取值的觀察頻數, Ei 為特征A第 i 個取值的期望頻數,n為總頻數, pi 為第 i 個取值的期望頻率。用feature_selection庫的SelectKBest類結合卡方檢驗來選擇特征的代碼如下:

from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2

#選擇K個最好的特征,傳回選擇特征後的資料
SelectKBest(chi2, k=).fit_transform(iris.data, iris.target)
           

2.2 包裹法(Wrapper)

遞歸特征消除

遞歸特征消除的主要思想是反複的構模組化型(如SVM或者回歸模型)然後選出最好的(或者最差的)的特征(可以根據系數來選),把選出來的特征放到一邊,然後在剩餘的特征上重複這個過程。feature_selection庫的RFE類來選擇特征的代碼如下:

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

#遞歸特征消除法,傳回特征選擇後的資料
#參數estimator為基模型
#參數n_features_to_select為選擇的特征個數
RFE(estimator=LogisticRegression(), n_features_to_select=).fit_transform(iris.data, iris.target)
           

上面的代碼中,首先,通過全部特征利用logistic回歸訓練評估函數,得出每個特征的權重。然後,将最小權重的特征從特征集合中去除。循環執行以上兩個過程,直到特征數達成需要。

Las Vegas Wrapper(LVW)

  LVW是典型的包裹式特征選擇方法,該算法将最終要使用的學習器的性能作為特征子集的評價标準,然後針對特征空間中的不同子集,計算每個子集的預測效果,效果最好的,即作為最終被挑選出來的特征子集。算法流程如下圖所示:

資料預處理與特征選擇1. 資料預處理2. 特征選擇3. 降維4. 參考資料

其中資料集為 D,特征集為 A,則 LVW 每次從特征集 A 中随機産生一個特征子集 A′,然後使用交叉驗證的方法(僞代碼的第 8 步)估計學習器在特征子集 A′ 上的誤差,若該誤差小于之前獲得的最小誤差,或者與之前的最小誤差相當但 A′ 中包含的特征數更少,則将 A′ 保留下來。  由于 LVW 算法每次評價子集 A′ 時,都需要重新訓練學習器,計算開銷很大,是以設定了參數 T 來控制停止條件。但當特征數很多(即 |A| 很大)并且 T 設定得很大時,可能算法運作很長時間都不能停止。

2.3 嵌入法(Embedding)

L1 正則化

正則化就是把額外的限制或者懲罰項加到已有模型(損失函數)上,以防止過拟合并提高泛化能力。損失函數由原來的 E(X,Y) 變為 E(X,Y)+α||w||L1/L2 ,w是模型的參數, ||⋅|| 一般采用一範數(L1)或者二範數(L2), α 用于控制正則化的強度。L1正則化和L2正則化也稱為Lasso和Ridge。

與L2正則化相比,L1正則化往往會得到一個更為稀疏的w,這意味着w的一些分量會趨于0,而非零分量的特征才會出現在最終的模型裡。是以L1正則化用于進行特征選擇,L2正則化用于防止過拟合。

為了說明這一點,下面舉一個直覺的例子,如下圖所示:假定w有兩個屬性,我們将其作為兩個坐标軸,平方誤差項取值相同的點的連線構成等值線。加入L1/L2正則化項的模型的解為平方誤差等值線與對應範數等值線的交點。從圖中可以看出,采用L1範數時,平方誤差等值線與範數等值線的交點常出現在坐标軸上,即對應分量為0;而采用L2範數時,兩者交點常出現在某象限,即分量均非0。是以采用L1範數更容易得到稀疏解。

資料預處理與特征選擇1. 資料預處理2. 特征選擇3. 降維4. 參考資料

随機森林

随機森林由多個決策樹構成。決策樹中的每一個節點都是基于某個特征的将資料集按照不同的label一分為二。利用随機森林提供的不純度可以進行特征選擇,對于分類問題,通常采用基尼指數或者資訊增益;對于回歸問題,通常采用的是方差或者最小二乘拟合。當訓練随機森林時,可算出每個特征平均減少了多少不純度,并把它平均減少的不純度作為特征選擇的依據。基于随機森林的特征選擇代碼如下:

from sklearn.datasets import load_boston
from sklearn.ensemble import RandomForestRegressor
import numpy as np

#Load boston housing dataset as an example
boston = load_boston()
X = boston["data"]
Y = boston["target"]
names = boston["feature_names"]
rf = RandomForestRegressor()
rf.fit(X, Y)
print"Features sorted by their score:"print sorted(zip(map(lambdax: round(x, ), rf.feature_importances_), names), reverse=True)
           

輸出:

Features sorted by their score: [(, 'LSTAT'), (, 'RM'), (, 'DIS'), (, 'CRIM'), (, 'NOX'), (, 'PTRATIO'), (, 'TAX'), (, 'AGE'), (, 'B'), (, 'INDUS'), (, 'RAD'), (, 'CHAS'), (, 'ZN')]
           

關于随機森林與GBDT的介紹可參考:随機森林與GBDT

3. 降維

當特征數量較多時,會造成計算量大,訓練時間長的問題;甚至當特征數量多于樣本數量時,每個樣本都具有自己的獨特性,樣本點在高維空間中較為分散,是以會造成過拟合。是以降低特征矩陣次元也是必不可少的。常見的降維方法有線性判别分析(LDA)和主成分分析法(PCA)。

3.1 線性判别分析法(LDA)

LDA的思想是:将資料映射到一個低維空間,使得不同類别資料的間隔盡量大(類間間隔大),同一類别中的資料間隔盡量小(類内間隔小),這樣可以最好的将不同類别的資料分隔開。使用lda庫的LDA類選擇特征的代碼如下:

from sklearn.lda import LDA

#線性判别分析法,傳回降維後的資料
#參數n_components為降維後的維數
LDA(n_components=).fit_transform(iris.data, iris.target)
           

3.2 主成分分析法(PCA)

PCA與LDA有着非常近似的意思,LDA的輸入資料是帶标簽的,而PCA的輸入資料是不帶标簽的,是以PCA是一種無監督學習。LDA通常來說是作為一個獨立的算法存在,給定了訓練資料後,将會得到一系列的判别函數(discriminate function),之後對于新的輸入,就可以進行預測了。而PCA更像是一個預處理的方法,它可以将原本的資料降低次元,而使得降低了次元的資料之間的方差最大。使用decomposition庫的PCA類選擇特征的代碼如下:

from sklearn.decomposition import PCA

#主成分分析法,傳回降維後的資料
#參數n_components為主成分數目
PCA(n_components=).fit_transform(iris.data)
           

4. 參考資料

  • 周志華. 機器學習 : = Machine learning[M]. 清華大學出版社, 2016.
  • 使用sklearn做單機特征工程

繼續閱讀