1. 特征工程是什么?
數據和特征決定了機器學習的上限,而模型和算法只是逼近了這個上線而已。特征工程的本質是一項工程活動,目的是最大限度地從原始數據中提取特征以供算法和模型使用。通過總結和歸納,人們認為特征工程包括以下方面:
本文使用python sklearn IRIS(鳶尾花)數據集來對特征處理功能進行說明,IRIS數據集包含4個特征(Sepal.Length(花萼長度),Sepal.Width(花萼寬度),Petal.Length(花瓣長度),Petal.Width(花瓣寬度)),特征都為正浮點數,單位為厘米。目標值為鳶尾花的分類(Iris Setosa(山鳶尾) , Iris Versicolour(雜色鳶尾),IrisVirginica (維吉尼亞鳶尾))
from sklearn.datasets import load_iris
#導入IRIS 數據集
iris = load_iris()
#特征矩陣
iris.data
#目標向量
iris.target
2. 數據預處理
通過特征提取,我們能得到未經處理的特征,這是特征可能存在以下問題:
-
不屬于同一量綱:即特征的規格不一樣,不能放在一起比較。無量綱化可以解決這一問題。
- 標準化
# 使用preproccessing庫的 StandardScaler類對數據進行標準化的代碼如下: from sklearn.preprocessing import StandardScaler # 標準化,返回值為標準化后的數據 StandardScaler().fit_transform(iris.data)
- 區間縮放法
區間縮放法的思路有多種,常見的一種為利用兩個最值進行縮放:# 使用preproccessing庫的 MinMaxScaler類對數據進行區間縮放代碼如下: from sklearn.preprocessing import MinMaxScaler # 區間縮放,返回值為縮放到[0,1]區間的數據 MinMaxScaler().fit_transform(iris.data)
- 數據歸一化
歸一化是依照特征矩陣的行處理數據,其目的在于樣本向量在點乘運算或其他核函數計算相似性時,擁有統一的標準,也就是說都轉化為“單位向量”# 使用preprocessing庫的 Normalizer 類對數據進行歸一化的代碼如下: from sklearn.preprocessing import Normalizer # 歸一化,返回值為歸一化后的數據 Normalizer().fit_transform(iris.data)
無量綱化使不同規格的數據轉化到同一規格。常用的無量綱方法有標準化和區間縮放法。區間縮放法利用了界值信息,將特征的取值區間縮放到某個特點的范圍,例如[0,1]
- 標準化
-
信息冗余:對魚某些定量特征,其包含的有效信息為區間劃分,列如學習成績,假若只關心“及格”或“不及格”,那么可以將定量的考分,轉化為“1”和“0”表示及格和未及格,二值化可以解決這一問題。
定量特征二值化的核心在于設定一個閥值,大于閥值的賦值為1,小于等于閥值的賦值為0:#使用preprocessing 庫的 Binarizer類對數據進行二值化的代碼如下: from sklearn.preprocessing import Binarizer # 二值化,閥值設置為3, 返回值為二值化后的數據 Binarizer(threshold = 3).fit_transform(iris.data)
-
定性特征不能直接使用:某些機器學習算法和模型只能接受定量特征的輸入,那么需要獎定性特征轉化為定量特征。最簡單的方式是為每一種定性值,但這種方式過于靈活,增加了調參的工作。通常使用啞編碼的方式將定性特征轉化為定量特征:假設有N種定性值,則將這一個特征擴展為N種特征,當原始特征值為第i種定性值時,第i個擴展特征賦值為1,其他擴展特征賦值為0.啞編碼的方式相比直接指定的方式,不用增加調參的工作,對于線性模型來說,使用啞編碼的特征可達到的非線性的效果。
import pandas as pd from sklearn.preprocessing import OneHotEncoder from sklearn.preprocessing import LabelEncoder # 啞編碼,返回值為啞編碼后的數據 testData = pd.DataFrame({'pet':['cat','dog','dog','fish'],'age':[4,6,3,3], 'salary':[4,5,1,1]}) OneHotEncoder(sparse = False).fit_transform(testData[['age']]) # 對于字符型變量,OneHotEncoder目前無法對其進行編碼
可以采用方法,曲線救國
arry = LabelEncoder().fit_transform(testdata['pet'])
OneHotEncoder(sparse = False).fit_transform(arry.reshape(-1,-1))
```
- 存在缺失值:缺失值需要補充。
- 信息利用率低:不同的機器學習算法和模型對數據中信息的利用是不同的,之前提到在線性模型中,使用對定性特征啞編碼可以達到非線性的效果。類似地,對定量變量多項式化,或者進行其他的轉化,都能達到非線性的效果
常見的數據變換有基于多項式的,基于指數函數的,基于對數函數的# 基于多項式的變幻 from sklearn.preprocessing import PolynomialFeatures # 多項式轉換 # 參數digree 為度, 默認值為2 PolynomialFeatures().fit_transform(iris.data) # 基于單變元函數的數據可以使用統一的方式完成 from numpy import loglp from sklearn.preprocessing import FunctionTransformer # 自定義轉換函數為對數函數的數據變換 # 第一個參數是單變元函數 FunctionTransformer(loglp).fit_transform(iris.data)
我們可以使用sklearn中的preprocessing庫進行數據預處理,可以覆蓋以上問題的解決方案。
3. 特征選擇
當數據預處理完成后,我們需要選擇有意義的特征輸入機械學習的算法和模型中進行訓練。通常來說,從兩個方面考慮來選擇特征:
- 特征是否發散:如果一個特征不發散,例如方差接近于0,也就是說樣本在這個特征上基本上沒有差異,這個特征對于樣本區分并沒有什么用。
- 特征與目標的相關性:這點比較顯而易見,與目標相關性高的特征,應當優選選擇。除方差法外。本文介紹的其他方法均從相關性考慮。
根據特征選擇的形式又可以將特征選擇的方法分為3種:
-
Filter : 過濾法,按照發散性或者相關性對各個特征進行評分,設定閥值或者待選閥值的個數,選擇特征
過濾法與后續機器學習算法的選擇無關。- 方差法(計算各個特征的方差,根據閥值,選擇方差大于閥值的特征)
from sklearn.feature_selection import VarianceThreshold # 方差選擇法,返回值為特征選擇后的數據 # 參數threshold為方差的閥值 VarianceThreshold(threshold = 3).fit_transform(iris.data)
- 相關系數法(先要計算各個特征對目標值的相關系數以及相關系數的P值)
from sklearn.feature_selection import SelectKBest from scipy.stats import pearsonr # 選擇K個最好的特征,返回選擇特征后的數據 # 第一個參數為計算評估特征是否好的函數,該函數輸入特征矩陣和目標向量,輸出二元組(評分,P值)的數組,數組的第i項為第i個特征的評分和P值。在此定義為計算相關系數 SelectKBest(lambda X, Y: array(map(lambda x:pearsonr(x, Y), X.T)).T, k=2).fit_transform(iris.data, iris.target)
- 卡方檢驗
經典的卡方檢驗是檢驗定性自變量對性因變量的相關性。假設自變量有N種取值,因變量有M種取值,考慮自變量等于i且因變量等于j的樣本頻數的觀察值與期望的差距,構建統計量:
from sklearn.feature_selection import SelectKBest from sklearn.feature_selection import chi2 # 選擇K個最好的特征,返回選擇特征后的數據 SelectKBest(chi2, k = 2).fit_transform(iris.data,iris.target)
-
互信息法
經典的互信息也是平價定性自變量對定性因變量的相關性的
from sklearn.feature_selection import SelectKBest from minepy import MINE # 由于MINE的設計不是函數式的,定義mic方法將其為函數式,返回一個二元組, 二元組的第二項設置成固定的P值 0.5 def mic(x,y): m = MINE() m.compute_score(x,y) return (m.mic(), 0.5) # 選擇K個最好的特征,返回特征選擇后的數據 SelectKBest(lambda X, Y : array(map(lambda xmic(x,Y)).T, k = 2).fit_transform(iris.data, iris.target)
-
Wrapper : 包裝法,根據目標函數(通常是預測效果評分),每次選擇若干特征,或者排除若干特征。
- 遞歸特征消除法
遞歸消除特征法使用一個基模型來進行多輪訓練,每輪訓練后,消除若干權值系數的特征,再基于新的特征集進行下一輪訓練。
from sklearn.feature_selection import RFE from sklearn.linear_model import LogisticRegression # 遞歸特征消除法,返回特征選擇后的數據 # 參數 estimator 為基模型 # 參數n_features_to_select為選擇的特征個數 RFE(estimator = LogisticRegression(), n_features_to_select = 2).fit_transform(iris.data, iris.target)
- 遞歸特征消除法
-
Embedded : 集成法,先使用某些機器學習的算法和模型進行訓練,得到各個特征的權值系數,根據系數從大到小選擇特征。類似于 Filter方法,但是是通過訓練來確定特征的
- 基于懲罰項的特征選擇法(沒看懂~)
- 基于樹模型的特征選擇法
from sklearn.feature_selection import SelectFromModel from sklearn.ensemble import GradientBoostingClassifier # GBDT作為基模型的特征選擇 selectFromModel(GradientBoostingClassifier()).fit_transform(iris.data,iris.target)
- 降維
當特征選擇完成以后,可以直接訓練模型了,但是可能由于特征矩陣過大,導致計算量大,訓練時間長的問題,因此降低特征矩陣維度也是必不可少的。常見的降維方法除了以上提到的基于L1懲罰的模型以外,另外還有主成分分析法(PCA)和線性判別分析(LDA),線性判別分析本身也是一個分類模型。PCA和LDA有很多的相似點,其本質是要將原始的樣本映射到維度更低的樣本空間中,但是PCA和LDA的映射目標不一樣:PCA是為了讓映射后的樣本具有最大的發散性;而LDA是為了讓映射后的樣本具有最好的分類性能。所以說PCA是一種無監督的降維方法,而LDA是一種有監督的降維方法。- 主成分分析法(PCA)
from sklearn.decomposition import PCA from sklearn.decomposition import PCA #主成分分析法,返回降維后的數據 #參數n_components為主成分數目 PCA(n_components=2).fit_transform(iris.data)
- 線性判別分析法(LDA)
from sklearn.lda import LDA #線性判別分析法,返回降維后的數據 #參數n_components為降維后的維數 LDA(n_components=2).fit_transform(iris.data, iris.target)