1 使用sklearn進行資料挖掘
資料挖掘通常包括資料采集,資料分析,特征工程,訓練模型,模型評估等步驟。使用sklearn工具可以友善地進行特征工程和模型訓練工作,在《使用sklearn做單機特征工程》中,我們最後留下了一些疑問:特征處理類都有三個方法fit、transform和fit_transform,fit方法居然和模型訓練方法fit同名(不光同名,參數清單都一樣),這難道都是巧合?
顯然,這不是巧合,這正是sklearn的設計風格。我們能夠更加優雅地使用sklearn進行特征工程和模型訓練工作。此時,不妨從一個基本的資料挖掘場景入手:
我們使用sklearn進行虛線框内的工作(sklearn也可以進行文本特征提取)。通過分析sklearn源碼,我們可以看到除訓練,預測和評估以外,處理其他工作的類都實作了3個方法:fit、transform和fit_transform。從命名中可以看到,fit_transform方法是先調用fit然後調用transform,我們隻需要關注fit方法和transform方法即可。
transform方法主要用來對特征進行轉換。從可利用資訊的角度來說,轉換分為無資訊轉換和有資訊轉換。無資訊轉換是指不利用任何其他資訊進行轉換,比如指數、對數函數轉換等。有資訊轉換從是否利用目标值向量又可分為無監督轉換和有監督轉換。無監督轉換指隻利用特征的統計資訊的轉換,統計資訊包括均值、标準差、邊界等等,比如标準化、pca法降維等。有監督轉換指既利用了特征資訊又利用了目标值資訊的轉換,比如通過模型選擇特征、lda法降維等。通過總結常用的轉換類,我們得到下表:
<col>
包
類
參數清單
類别
fit方法有用
說明
sklearn.preprocessing
standardscaler
特征
無監督
y
标準化
minmaxscaler
區間縮放
normalizer
無資訊
n
歸一化
binarizer
定量特征二值化
onehotencoder
定性特征編碼
imputer
缺失值計算
polynomialfeatures
多項式變換(fit方法僅僅生成了多項式的表達式)
functiontransformer
自定義函數變換(自定義函數在transform方法中調用)
sklearn.feature_selection
variancethreshold
方差選擇法
selectkbest
特征/特征+目标值
無監督/有監督
自定義特征評分選擇法
selectkbest+chi2
特征+目标值
有監督
卡方檢驗選擇法
rfe
遞歸特征消除法
selectfrommodel
自定義模型訓練選擇法
sklearn.decomposition
pca
pca降維
sklearn.lda
lda
lda降維
不難看到,隻有有資訊的轉換類的fit方法才實際有用,顯然fit方法的主要工作是擷取特征資訊和目标值資訊,在這點上,fit方法和模型訓練時的fit方法就能夠聯系在一起了:都是通過分析特征和目标值,提取有價值的資訊,對于轉換類來說是某些統計量,對于模型來說可能是特征的權值系數等。另外,隻有有監督的轉換類的fit和transform方法才需要特征和目标值兩個參數。fit方法無用不代表其沒實作,而是除合法性校驗以外,其并沒有對特征和目标值進行任何處理,normalizer的fit方法實作如下:
1 def fit(self, x, y=none):
2 """do nothing and return the estimator unchanged
3 this method is just there to implement the usual api and hence
4 work in pipelines.
5 """
6 x = check_array(x, accept_sparse='csr')
7 return self
基于這些特征處理工作都有共同的方法,那麼試想可不可以将他們組合在一起?在本文假設的場景中,我們可以看到這些工作的組合形式有兩種:流水線式和并行式。基于流水線組合的工作需要依次進行,前一個工作的輸出是後一個工作的輸入;基于并行式的工作可以同時進行,其使用同樣的輸入,所有工作完成後将各自的輸出合并之後輸出。sklearn提供了包pipeline來完成流水線式和并行式的工作。
在此,我們仍然使用iris資料集來進行說明。為了适應提出的場景,對原資料集需要稍微加工:
1 from numpy import hstack, vstack, array, median, nan
2 from numpy.random import choice
3 from sklearn.datasets import load_iris
4
5 #特征矩陣加工
6 #使用vstack增加一行含缺失值的樣本(nan, nan, nan, nan)
7 #使用hstack增加一清單示花的顔色(0-白、1-黃、2-紅),花的顔色是随機的,意味着顔色并不影響花的分類
8 iris.data = hstack((choice([0, 1, 2], size=iris.data.shape[0]+1).reshape(-1,1), vstack((iris.data, array([nan, nan, nan, nan]).reshape(1,-1)))))
9 #目标值向量加工
10 #增加一個目标值,對應含缺失值的樣本,值為衆數
11 iris.target = hstack((iris.target, array([median(iris.target)])))
并行處理,流水線處理,自動化調參,持久化是使用sklearn優雅地進行資料挖掘的核心。并行處理和流水線處理将多個特征處理工作,甚至包括模型訓練工作組合成一個工作(從代碼的角度來說,即将多個對象組合成了一個對象)。在組合的前提下,自動化調參技術幫我們省去了人工調參的反鎖。訓練好的模型是貯存在記憶體中的資料,持久化能夠将這些資料儲存在檔案系統中,之後使用時無需再進行訓練,直接從檔案系統中加載即可。
2 并行處理
并行處理使得多個特征處理工作能夠并行地進行。根據對特征矩陣的讀取方式不同,可分為整體并行處理和部分并行處理。整體并行處理,即并行處理的每個工作的輸入都是特征矩陣的整體;部分并行處理,即可定義每個工作需要輸入的特征矩陣的列。
pipeline包提供了featureunion類來進行整體并行處理:
1 from numpy import log1p
2 from sklearn.preprocessing import functiontransformer
3 from sklearn.preprocessing import binarizer
4 from sklearn.pipeline import featureunion
5
6 #建立将整體特征矩陣進行對數函數轉換的對象
7 step2_1 = ('tolog', functiontransformer(log1p))
8 #建立将整體特征矩陣進行二值化類的對象
9 step2_2 = ('tobinary', binarizer())
10 #建立整體并行處理對象
11 #該對象也有fit和transform方法,fit和transform方法均是并行地調用需要并行處理的對象的fit和transform方法
12 #參數transformer_list為需要并行處理的對象清單,該清單為二進制組清單,第一進制為對象的名稱,第二進制為對象
13 step2 = ('featureunion', featureunion(transformer_list=[step2_1, step2_2, step2_3]))
整體并行處理有其缺陷,在一些場景下,我們隻需要對特征矩陣的某些列進行轉換,而不是所有列。pipeline并沒有提供相應的類(僅onehotencoder類實作了該功能),需要我們在featureunion的基礎上進行優化:
在本文提出的場景中,我們對特征矩陣的第1列(花的顔色)進行定性特征編碼,對第2、3、4列進行對數函數轉換,對第5列進行定量特征二值化處理。使用featureunionext類進行部分并行處理的代碼如下:
3 流水線處理
pipeline包提供了pipeline類來進行流水線處理。流水線上除最後一個工作以外,其他都要執行fit_transform方法,且上一個工作輸出作為下一個工作的輸入。最後一個工作必須實作fit方法,輸入為上一個工作的輸出;但是不限定一定有transform方法,因為流水線的最後一個工作可能是訓練!
根據本文提出的場景,結合并行處理,建構完整的流水線的代碼如下:
4 自動化調參
網格搜尋為自動化調參的常見技術之一,grid_search包提供了自動化調參的工具,包括gridsearchcv類。對組合好的對象進行訓練以及調參的代碼如下:
5 持久化
externals.joblib包提供了dump和load方法來持久化和加載記憶體資料:
1 #持久化資料
2 #第一個參數為記憶體中的對象
3 #第二個參數為儲存在檔案系統中的名稱
4 #第三個參數為壓縮級别,0為不壓縮,3為合适的壓縮級别
5 dump(grid_search, 'grid_search.dmp', compress=3)
6 #從檔案系統中加載資料到記憶體中
7 grid_search = load('grid_search.dmp')
6 回顧
類或方法
sklearn.pipeline
pipeline
流水線處理
featureunion
并行處理
sklearn.grid_search
gridsearchcv
網格搜尋調參
externals.joblib
dump
資料持久化
load
從檔案系統中加載資料至記憶體
注意:組合和持久化都會涉及pickle技術,在sklearn的技術文檔中有說明,将lambda定義的函數作為functiontransformer的自定義轉換函數将不能pickle化。
7 總結
在這個部落格中先不提任何算法和模型,先從資料挖掘工作的第一步開始,使用基于python的各個工具把大部分步驟都走了一遍,希望這樣的梳理能夠少讓初學者走彎路吧。