AI學(xué)習(xí)筆記:特征工程

特征工程作為模型建立之前數(shù)據(jù)預(yù)處理工作,可以說(shuō)對(duì)于模型訓(xùn)練結(jié)果起著至關(guān)重要的作用。 就像前輩們說(shuō)的那樣:** 數(shù)據(jù)和特征決定了機(jī)器學(xué)習(xí)的上線, 而模型和算法只是逼近這個(gè)上線而已**。 個(gè)人覺(jué)得這一部分工作充滿了技巧,并且非常有技術(shù)含量。

1. 什么是特征工程

特征工程就是對(duì)于原始數(shù)據(jù)進(jìn)行數(shù)據(jù)預(yù)處理, 盡可能把可以把后續(xù)模型建立需要的特征提取出來(lái)。并把原始數(shù)據(jù)規(guī)整化,為后續(xù)建模做準(zhǔn)備。

特征工程主要分為三大部分:

  1. 數(shù)據(jù)預(yù)處理:對(duì)應(yīng)sklearn: sklearn-Processing data

  2. 特征選擇:對(duì)應(yīng) sklearn: sklearn-Feature selection

  3. 降維:對(duì)應(yīng)sklearn: sklearn-Dimensionality reduction

文中使用iris數(shù)據(jù)集進(jìn)行演示。先導(dǎo)入測(cè)試數(shù)據(jù)。這里的features包含四列特征數(shù)據(jù), target則是目標(biāo)數(shù)據(jù),是對(duì)數(shù)據(jù)的分類標(biāo)簽。

from sklearn.datasets import load_iris
iris = load_iris()
features = iris.data()
target = iris.target()

2. 數(shù)據(jù)預(yù)處理

對(duì)于拿到的原始數(shù)據(jù), 會(huì)有這樣那樣的問(wèn)題, 需要進(jìn)行原始處理。 一般來(lái)說(shuō)需要處理的問(wèn)題如下:

  1. 量綱不統(tǒng)一: 特征數(shù)據(jù)的計(jì)量單位和數(shù)據(jù)數(shù)值分布范圍不統(tǒng)一, 這樣的數(shù)據(jù)在訓(xùn)練中會(huì)使得數(shù)值較大的特征對(duì)于訓(xùn)練權(quán)重較大, 數(shù)值較小的特征就會(huì)被忽略不計(jì), 即便有可能在業(yè)務(wù)上非常重要。
  2. 信息冗余: 對(duì)于某些特征, 我們只需關(guān)心定性的信息, 比如胖瘦, 比如高矮, 并不需要具體體重和高度的數(shù)值, 可以通過(guò)認(rèn)為規(guī)定閾值對(duì)于這類數(shù)據(jù)進(jìn)行二值化。
  3. 類別特征值需要進(jìn)行啞編碼。 類別特征, 比如顏色特征如: 紅,黃, 藍(lán), 綠。 這類特征數(shù)值化,可以拓展為四個(gè)特征, 分辨用0,1 編碼。 紅色則為, 1,0,0,0 黃色則為0 1 0 0。
  4. 缺失值, 缺失值可以通過(guò)某些方法進(jìn)行填充。
  5. 對(duì)于現(xiàn)有特征進(jìn)行數(shù)據(jù)變化達(dá)成非線性效果。

2.1 無(wú)量綱化

把不同數(shù)值規(guī)格的數(shù)據(jù)轉(zhuǎn)換為同一個(gè)規(guī)格, 比如0附近。

2.1.1 標(biāo)準(zhǔn)化( z-score standardization ) ( 用于列向量)

對(duì)于服從正態(tài)分布或假定服從正態(tài)分布的特征轉(zhuǎn)換為標(biāo)準(zhǔn)正態(tài)分布, 公式如下:



sklean只用preprocess庫(kù)的StandardScaler類可以輕松實(shí)現(xiàn):

from sklearn.preprocessing import StandardScaler
standard_feature = StandardScaler().fit_transform(features)

2.1.2 區(qū)間縮放

使用最大值和最小值進(jìn)行區(qū)間縮放, 可以把數(shù)據(jù)縮放到[0,1]區(qū)間:


from sklearn.preprocessing import MinMaxScaler
MaxMin_feature = MinMaxScaler().fit_transform(features)

2.1.3 歸一化 (對(duì)行向量處理)

歸一化可以使不同維度的數(shù)據(jù)在點(diǎn)乘和核函數(shù)計(jì)算相似性時(shí)擁有統(tǒng)一的標(biāo)準(zhǔn), 數(shù)學(xué)上就是把每整個(gè)向量轉(zhuǎn)化為“單位向量”。公式如下:



公式可以簡(jiǎn)單理解為, 向量的每一個(gè)維度除以向量的模。 模長(zhǎng)的計(jì)算方式sklearn支持兩種,分別為L(zhǎng)1, L2, 兩個(gè)公式分別如下:


from sklearn.preprocessing import Normalizer
normal_feature = Normalizer().fit_transform(features)

2.1.3 不同無(wú)量綱化方法的使用場(chǎng)景

  1. z-score standardization:
    使用用于用距離來(lái)度量相似性的算法, 如各種聚類算法。 或者PCA,LDA需要用到協(xié)方差進(jìn)行降維,同時(shí)數(shù)據(jù)近似服從正態(tài)分布時(shí),
  2. 其他歸一方法:
    不涉及距量度, 協(xié)方差計(jì)算, 數(shù)據(jù)不符合正態(tài)分布, 可以使用區(qū)間縮放或者其他歸一方法。 比如圖像處理的RGB圖轉(zhuǎn)換為灰度圖時(shí), 數(shù)值分布在[0, 255]范圍,不符合正態(tài)分布。

2.2 對(duì)于定量特征二值化(用于列向量)

定性: 高和不高
定量: 180cm, 160cm
如果定量數(shù)據(jù)本質(zhì)上只關(guān)心定性信息時(shí), 可以通過(guò)設(shè)置閾值對(duì)定量信息二值化。 在這個(gè)過(guò)程中會(huì)損失掉我們不關(guān)心的定量信息只留下我們關(guān)心的定性信息。公式如下:



使用sklearn種preprocess包的Binarizer庫(kù)可以輕松上實(shí)現(xiàn):

## 閾值姑且設(shè)置為3
from sklearn.preprocessing import Binarizer
bin_feature = Binarizer(threshold=3).fit_transform(features)

2.3 對(duì)于定性特征進(jìn)行啞編碼。

對(duì)于定性文字標(biāo)記的特征, 并且特征之間沒(méi)有大小關(guān)系,在建模之前需要對(duì)其進(jìn)行啞編碼。 由于每一個(gè)定性標(biāo)簽之間并沒(méi)有大小關(guān)系,所以不能直接轉(zhuǎn)化為數(shù)字。 需要把每一個(gè)標(biāo)簽拆分成單獨(dú)的特征,進(jìn)行0,1 編碼。
如下例子:
一條特征,四個(gè)樣本, 分別為['A', 'B', 'C', 'A'], 通過(guò)啞編碼后可以展開(kāi)為4x3的矩陣。 每一個(gè)類別展開(kāi)為單獨(dú)的特征,代碼如下。 可通過(guò)sklearn里面preprocess庫(kù),OneHotEncoder配合LabelEncoder實(shí)現(xiàn)。

from sklearn.preprocessing import OneHotEncoder
from sklearn.preprocessing import LabelEncoder
import numpy as np
features = np.array(list('ABCA'))
le = LabelEncoder()
features_label = le.fit_transform(features)

enc = OneHotEncoder()
one_hot = enc.fit_transform(features_label.reshape(4, 1)).toarray()
print(one_hot)
## 輸出
[[ 1.  0.  0.]
 [ 0.  1.  0.]
 [ 0.  0.  1.]
 [ 1.  0.  0.]]

2.4 缺失值處理(用于列向量)

數(shù)據(jù)預(yù)處理時(shí)候?qū)τ谌笔е凳潜容^常見(jiàn)的。 最簡(jiǎn)單粗暴的方法莫過(guò)于直接把帶有缺失值的樣本去掉。 但是某些情況下, 幾乎每條數(shù)據(jù)都帶有缺失值, 這樣的話就需要對(duì)缺失值進(jìn)行填充。
sklearn.preprocess.Inputer類中提供了簡(jiǎn)單的缺失值填充方法。

from numpy import vstack, array, nan
from sklearn.preprocessing import Imputer
features = Imputer(strategy='mean').fit_transform(vstack((array([nan, nan, nan, nan]), iris.data)))

Inputer() 里面有一個(gè)重要參數(shù)為strategy, 有三個(gè)可選參數(shù), mean, median, most_frequent. 分別為均值, 中位數(shù), 頻率最高的值。

除此之外, 還可以把缺失值當(dāng)成是標(biāo)簽, 通過(guò)建立模型來(lái)預(yù)測(cè)缺失值。

2.5 數(shù)據(jù)變換

2.5.1 多項(xiàng)式變換(對(duì)行向量處理)

當(dāng)特征比較少的時(shí)候, 可以對(duì)很少的特征進(jìn)行多項(xiàng)式變化,產(chǎn)生更多的特征。 多項(xiàng)式變換,簡(jiǎn)單來(lái)說(shuō)就是把現(xiàn)有的特征排列組合相乘。 如果是degree為2的變換則是, 把現(xiàn)有的特征中, 抽取兩個(gè)相乘,并且獲得所有組合的結(jié)果。 公式如下。



如果是四個(gè)特征, 多項(xiàng)式變幻時(shí)會(huì)補(bǔ)充一個(gè)特征1, 然后計(jì)算出5個(gè)特征的兩兩不重復(fù)的組合, 包括自己和自己的組合。
sklearn.preprocessing庫(kù)的PolynomialFeatures的類可以輕松實(shí)現(xiàn):

poly_feature = PolynomialFeatures(degree=2).fit_transform(features)

2.5.2 自定義變換

使用自定義函數(shù)對(duì)于原始數(shù)據(jù)進(jìn)行變換。 preprocessing種的FunctionTransformer可以實(shí)現(xiàn):

from numpy import log1p
from sklearn.preprocessing import FunctionTransformer
log1p_feature = FunctionTransformer(log1p).fit_transform(features)

FunctionTransformer 里面的需要填入一個(gè)函數(shù),用來(lái)做特征變換。

2.5.3 數(shù)據(jù)預(yù)處理sklearn.preprocessing 的方法總結(jié)。

功能 說(shuō)明
StandardScaler 無(wú)量綱化 標(biāo)準(zhǔn)化,基于特征矩陣的列,將特征值轉(zhuǎn)換至服從標(biāo)準(zhǔn)正態(tài)分布
MinMaxScaler 無(wú)量綱化 區(qū)間縮放,基于最大最小值,將特征值轉(zhuǎn)換到[0, 1]區(qū)間上
Normalizer 歸一化 基于特征矩陣的行,將樣本向量轉(zhuǎn)換為“單位向量”
Binarizer 二值化 基于給定閾值,將定量特征按閾值劃分
OneHotEncoder 啞編碼 將定性數(shù)據(jù)編碼為定量數(shù)據(jù)
Imputer 缺失值計(jì)算 計(jì)算缺失值,缺失值可填充為均值等
PolynomialFeatures 多項(xiàng)式數(shù)據(jù)轉(zhuǎn)換 多項(xiàng)式數(shù)據(jù)轉(zhuǎn)換
FunctionTransformer 自定義單元數(shù)據(jù)轉(zhuǎn)換 使用單變?cè)暮瘮?shù)來(lái)轉(zhuǎn)換數(shù)據(jù)

3. 特征選擇

數(shù)據(jù)預(yù)處理完成以后,特征比較多時(shí),就需要對(duì)特征進(jìn)行選擇。 使有意義的特征輸入模型進(jìn)行訓(xùn)練。 特征選擇通常來(lái)說(shuō)從兩個(gè)方面入手:

  • 特征是否發(fā)散:特征如果不發(fā)散, 方差很小接近于0, 就意味著這個(gè)特征在所有樣本中的分布是沒(méi)有差異的, 說(shuō)明這個(gè)特征對(duì)于樣品區(qū)分沒(méi)有貢獻(xiàn)。
  • 特征與目標(biāo)相關(guān)項(xiàng): 對(duì)于分類問(wèn)題, 特征與分類目標(biāo)相關(guān)性越大說(shuō)明特征對(duì)于分類問(wèn)題作用也就越大。

特征選擇的方法:

  • Filter: 過(guò)濾法, 通過(guò)給定的方差閾值對(duì)特征進(jìn)行分類, 只保留方差過(guò)閾值的特征。
  • Wrapper: 包裝發(fā), 根基后續(xù)模型的學(xué)習(xí)效果, 目標(biāo)函數(shù), 每次選取若干或者排除若干特征。 來(lái)尋找最優(yōu)特征。
  • Embedded: 嵌入法, Filter與Wrapper 的結(jié)合。 先使用某些機(jī)器學(xué)習(xí)算法和模型訓(xùn)練,得到各個(gè)特征的權(quán)值洗漱,根據(jù)系數(shù)大小選擇特征。例如使用RandomForest.

在sklearn中可以使用feature_selection庫(kù)來(lái)進(jìn)行特征選擇。

3.1 Filter法

3.1.1 方差選擇法

方差選擇法需要計(jì)算各特征的方差,然后根據(jù)給定的方差閾值選擇特征。

from sklearn.feature_selection import VarianceThreshold
selected_feature = VarianceThreshold(threshold=3).fit_transform(features)

這里的threshold根據(jù)不同的feature應(yīng)該有所不同, 所以需要對(duì)于樣本有一定的了解。

3.1.2 卡方檢驗(yàn)法

對(duì)于每一個(gè)特征與目標(biāo)分類標(biāo)簽進(jìn)行卡方檢驗(yàn),根據(jù)得出的chi2統(tǒng)計(jì)和p-value對(duì)特征進(jìn)行選擇。

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

selected_feature = SelectKBest(chi2, k=2).fit_transform(features, target)

3.2 Wrapper

3.2.1 遞歸特征消除法

遞歸特征消元法需要給定一個(gè)預(yù)測(cè)模型(基模型),然后使用最初的特征進(jìn)行模型訓(xùn)練得到每一個(gè)特征的權(quán)值, 然后丟棄權(quán)值最小的的特征,重新訓(xùn)練模型。 如此往復(fù)直到得到所需要的數(shù)量時(shí)停止。
sklearn.feature_selection中的RFE類實(shí)現(xiàn)。
代碼例子中,選取邏輯回歸模型作為基模型。

from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression
selected_feature = RFE(estimator=LogisticRegression(), n_features_to_select=2).fit_transform(features, target)

3.3 Embedded

3.3.1 基于懲罰項(xiàng)的特征選擇法

使用帶懲罰項(xiàng)的基模型, 除了篩選特征,同時(shí)進(jìn)行降維。 使用feature_selection庫(kù)的SelectFromModel類結(jié)合L1懲罰項(xiàng)的邏輯回歸模型實(shí)現(xiàn):

from sklearn.feature_selection import SelectFromModel
from sklearn.linear_model import LogisticRegression
selected_feature = SelectFromModel(estimator=LogisticRegression(penalty="l1", C=0.1)).fit_transform(features, target)

3.3.2 基于樹(shù)模型的特征選擇

通過(guò)樹(shù)模型的GBDT作為基模型進(jìn)行特征選擇, 使用SelectFromModel結(jié)合GBDT模型實(shí)現(xiàn):

from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import GradientBoostingClassifier
selected_feature = SelectFromModel(estimator=GradientBoostingClassifier()).fit_transform(features, target)

3.4 總結(jié)

所屬方式 說(shuō)明
VarianceThreshold Filter 方差選擇法
SelectKBest Filter 可選關(guān)聯(lián)系數(shù)、卡方校驗(yàn)、最大信息系數(shù)作為得分計(jì)算的方法
RFE Wrapper 遞歸地訓(xùn)練基模型,將權(quán)值系數(shù)較小的特征從特征集合中消除
SelectFromModel Embedded 訓(xùn)練基模型,選擇權(quán)值系數(shù)較高的特征

4 降維

當(dāng)特征選擇完成后,可以直接訓(xùn)練模型了,但是可能由于特征矩陣過(guò)大,導(dǎo)致計(jì)算量大,訓(xùn)練時(shí)間長(zhǎng)的問(wèn)題,因此降低特征矩陣維度也是必不可少的。常見(jiàn)的降維方法除了以上提到的基于L1懲罰項(xiàng)的模型以外。
另外還有主成分分析法(PCA)和線性判別分析(LDA),線性判別分析本身也是一個(gè)分類模型。PCA和LDA有很多的相似點(diǎn),其本質(zhì)是要將原始的樣本映射到維度更低的樣本空間中,但是PCA和LDA的映射目標(biāo)不一樣:

  • PCA是為了讓映射后的樣本具有最大的發(fā)散性
  • 而LDA是為了讓映射后的樣本有最好的分類性能。

所以說(shuō)PCA是一種無(wú)監(jiān)督的降維方法,而LDA是一種有監(jiān)督的降維方法。

4.1 主成分分析法(PCA)

使用decomposition庫(kù)的PCA類選擇特征的代碼如下:

from sklearn.decomposition import PCA
selected_feeature = PCA(n_components=2).fit_transform(features)
print(selected_feeature)

4.2 線性判別分析法(LDA)

使用LDA進(jìn)行降維的代碼如下:

from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
selected_feeature = LDA(n_components=n).fit_transform(features, target)
print(selected_feeature)

總結(jié)

特征工程包含下面幾個(gè)部分:

  1. 數(shù)據(jù)預(yù)處理:標(biāo)準(zhǔn)化, 區(qū)間縮放, 二值化, 啞編碼, 缺失值處理, 多項(xiàng)式變換, 函數(shù)變換
  2. 特征選擇: 方差選擇, 卡方檢驗(yàn), 遞歸消除, 基于模型消除
  3. 數(shù)據(jù)降維: PCA, LDA
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容