大數據分析特徵工程如何做?

大數據分析特徵工程如何做?

對於特徵工程是數據分析中最費時費力的一部分的說法,應該是沒人有異議的,特徵工程很重要,可卻沒有明晰的體系,在西瓜書裡也只有一個章節講了特徵選擇,沒有像算法模型一樣有統一的體系,甚至連基本的概念術語都沒有統一,標準化與歸一化分不清理還亂,啞變量也叫虛擬變量,這些都讓特徵工程很難得學習,本文把特徵工程相關學習做下記錄。

特徵工程籠統的分為三個塊,三部分很難說得上前後順序或者遞進關係。

  • 特徵表示
  • 特徵預處理
  • 特徵選擇

大數據分析特徵工程如何做?

第一部分特徵表示

特徵表示,是對特徵具體表現形式做處理,包括缺失值處理,連續特徵的離散化,離散特徵的連續化(亦即,特徵編碼)

1.缺失值處理

對特徵缺失值的處理,主要處理方式是填充,數值特徵一般用均值填充,分類特徵一般是頻繁值來填充。sklearn中使用Imputer而來處理。

<code> #導入SimpleImputer
 from sklearn.impute import SimpleImputer
 import numpy as np
 ​
 #平均值填充
 imp_mean = SimpleImputer(missing_values=np.nan, strategy='mean')
 imp_mean.fit_transform([[1,2,np.nan],
                         [3,np.nan,4],
                         [np.nan,5,6]])  
 ​
 #中位數填充
 imp_median = SimpleImputer(missing_values='na', strategy='median')
 imp_median.fit_transform([['na',1,2,3],
                           [4,5,6,7],
                           [8,9,10,'na'],
                           [11,12,13,14]])
 ​
 #最頻繁值填充,對數值特徵就是眾數
 imp_most = SimpleImputer(missing_values='未知', stragtegy='most_frequent')
 imp_most.fit_transform([['廣州','男',30],
                         ['未知','女',23],
                         ['上海','男',34],
                         ['上海','男',24],
                         ['北京','未知',33]])/<code>


2.離散特徵處理

由於不少的模型是無法直接處理離散特徵,例如性別(男,女)、城市(北京,上海),這些離散特徵在K近鄰、邏輯迴歸等模型都是不能直接使用的,這是需要將離散特徵進行編碼,數值化表示處理。

sklearn中主要的是編碼方式有LabelEncoder,OneHotEncoder,ordinalEncoder,三者的核心其實是相同的,但實現細節不同。

LabelEncoder是最容易理解的,例如季節特徵有春夏秋冬四個特徵值,就編碼為0,1,2,3

<code> from sklearn.preprocessing import LabelEncoder
 labeler = LabelEncoder()
 labeler.fit_transform(['春','夏', '秋', '冬'])
 ​/<code>

*LabelEncoder通常用來轉換目標變量

OrdinalEncoder 的處理方式和LabelEncoder相同,不同的地方是OrdinalEncoder提供參數調整編碼映射,主要是用來處理X變量特徵的。

<code> from sklearn.preprocessing import OrdinalEncoder
 enc = OrdinalEncoder()
 X = [['男', '青年'],['女','中年'],['男','少年']]
 enc.fit_transform(X)/<code>

OneHotEncoder 的編碼方式是將特徵的每個唯一值轉化一個二值化的虛擬特徵。性別特徵轉化為性別-男、性別-女兩個。

<code> from sklearn.preprocessing import OneHotEncoder
 enc = OneHotEncoder()
 X = [['男', 'A'], ['女','C'], ['男','B']]
 enc.fit_transform(X)
 ​/<code>


自然語言處理是離散特徵處理中的一種特殊情況,是按特徵值頻次來做的編碼,有時是直接根據出現頻次的詞頻,或者是出現頻次權重。

3.連續特徵表示處理

連續特徵有時需要做離散化的處理,目前個人還沒找到這樣處理的理論邏輯,可能適合理由是高維稀疏解,部分算法需要例如決策樹。另外連續特徵做離散化處理也多是根據經驗,例如連續的時間特徵抽離出天中小時數,周幾等。

連續特徵的處理主要的思路是基於閾值分桶,收入分成中低高,閾值的確定就變成了特徵處理質量的關鍵,一般是基於經驗或專家意見,如收入分桶就按照收入分類標準;除了這類經驗性的閾值確定外,還可以使用機器學習算法來確定

<code> from sklearn.datasets import make_classification
 from sklearn.model_selection import train_test_split
 from sklearn.ensemble import GradientBoostingClassifier
 from sklearn.preprocessing import OneHotEncoder
 ​
 X, y = make_classification(n_samples=10)
 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.5)
 gbc = GradientBoostingClassifier(n_estimators=2)
 one_hot = OneHotEncoder()
 gbc.fit(X_train, y_train)
 X_train_new = one_hot.fit_transform(gbc.apply(X_train)[:,:,0])
 ​/<code>


大數據分析特徵工程如何做?


第二部分特徵預處理

特徵表示是將單個的特徵類型進行轉化,連續與離散的轉化,經過特徵表示處理之後的特徵是可以用來進行模型訓練了,但是各個特徵的取值範圍都不相同,年齡特徵的範圍可能是0-100,而收入特徵的範圍是0-100000,這對於一些模型性能影響很大(訓練速度,擬合性能),所以需要做特徵的預處理來統一特徵量綱

特徵“正常化”(Normalization)

這部分有個很大問題就是Normalize、standard和標準化、歸一化以及正則化難解難分了

Normalize按詞根是正常化的意思,Standard是標準化的意思,本來這兩詞在sklearn中對應方法是沒問題的

但奈何漢語太博大了,特徵縮放(Feature scaling)操作都是為了統一量綱,所以將所有的特徵縮放(MinMaxScaler,MaxAbsScaler,StandardScaler)操作叫做標準化在漢語語境也可以說通(按統一標準轉化);歸一化也是一樣既代指Normalization,也代指Normalizer。

這個問題希望業界早點統一吧

特徵正常化包括對於特徵操作的MaxAbsScaler,MinMaxScaler,StandardScaler和對樣本方向操作的Normalizer

<code> from sklearn.preprocessing import MaxAbsScaler, MinMaxScaler, StandardScaler
 mas = MaxAbsScaler()
 mas.fit_transfrom(X)
 ​
 scaler = MinMaxScaler()
 scaler.fit_transform(X)
 ​
 Std_scaler = StandardScaler()
 std_scaler.fit_transform(X)/<code>


Normalizer與前三者的一個不同之處在於,Normalizer是針對樣本方向的處理,也是做前三者都是在列方向的處理,Normalizer是在行方向的處理。

Normalizer是用L1或L2範數縮放單個樣本,這種處理方式主要是在向量空間模型使用,如文本分類內容聚類。



大數據分析特徵工程如何做?


第三部分特徵選擇

在將特徵進行編碼分段及標準化之後,我們可以得到一份規整的數據集,面對大量的特徵,我們做出選擇,篩除一些特徵

特徵選擇主要有三類方法,過濾法特徵選擇、包裝法特徵選擇、嵌入法特徵選擇

1.過濾法特徵選擇

過濾法是按照特徵的發散性或者相關性指標對各個特徵進行評分,設定閾值選擇合適特徵,具體來說,常用的幾種方式是,方差、相關係數、假設檢驗、互信息

基於方差 的過濾選擇,是通過計算各特徵的方差,設定方差閾值進行選擇,sklearn中的實現方法是VarianceThreshold

<code> 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]]
 sel = VarianceThreshold(threshold=(.8*(1-.8)))
 sel.fit_transform(X)
 ​
 #方差過濾的手動實現
 def varianceSelect(X,threshold):
   import numpy as np
   
   var = np.var(X, axis=0)
   return X[:,var>threshold]/<code>

基於假設檢驗過濾,是以“特徵與響應變量沒有關係”作為零假設進行檢驗,既然是假設檢驗就涉及F分佈、T分佈、卡方分佈,都對應的是sklearn中的f_classif、f_regression、chi2

<code> from sklearn.datasets import load_iris
 from sklearn.feature_selection import SelectKBest
 from sklearn.feature_selection import chi2
 X, y = load_iris(return_X_y=True)
 X.shape
 out:(150, 4)
 X_new = SelectKBest(chi2, k=2).fit_transform(X, y)
 X_new.shape
 (150, 2)/<code>

基於互信息的過濾,是從信息熵的角度分析各個特徵和輸出值之間的關係評分,互信息值越大,說明該特徵和輸出值之間的相關性越大,越需要保留。對應sklearn中mutual_info_regression、mutual_info_classif

基於假設檢驗和互信息的,都可以通過SelectKBest來使用

2.包裝法特徵選擇

包裝法更像是一種解決策略,它沒有過濾法那麼直接。包裝法將學習模型的性能作為特徵選擇的評價標準,也就通過多次訓練模型找出最佳特徵,因此這種方法的計算開銷更大。

常用的包裝法是遞歸消除特徵法(RFE),遞歸消除特徵法使用一個機器學習模型來進行多輪訓練,每輪訓練後,消除若干權值係數的對應的特徵,再基於新的特徵集進行下一輪訓練。在sklearn中,可以使用RFE函數來選擇特徵。


3.嵌入法特徵選擇

嵌入法是將特徵選擇過程與學習模型訓練過程融合一體,在訓練過程中自動進行特徵選擇。在sklearn中是使用SelectFromModel。

嵌入法的常用方式是使用L1、L2正則化做特徵選擇,一個例子是Ridge迴歸中,正則化懲罰項越大,那麼模型的係數就會越小。當正則化懲罰項大到一定的程度的時候,部分特徵係數會變成0,當正則化懲罰項繼續增大到一定程度時,所有的特徵係數都會趨於0


分享到:


相關文章: