用scikit-learn做數據預處理

數據預處理是進行機器學習的必要環節,對原始數據進行加工,比如標準化、歸一化、二進制化、特征編碼、插補缺失值、生成多項式特征等。

scikit-learn 是 Python 下的機器學習工具包,集成了預處理、降維、聚類、分類等方法。我們用此工具來介紹數據預處理。

主要應用的是 preprocessing 類。

標準化 Standardization

常用的標準化方法為 z-score 法,目的是將傳入的矩陣變為每列均值為0、方差為1的標準型,因為機器學習中的函數許多是以0為中心的,例如 sigmoid 函數,方差為1可以使數據分布均勻,防止某個特征數據過大影響模型的訓練。

z-score 公式

我們用 sklearn 中的 preprocessing 類中的 scale 方法簡單進行標準化。

>>> from sklearn import preprocessing
>>> import numpy as np
>>> X = np.array([[ 1., -1.,  2.],
...               [ 2.,  0.,  0.],
...               [ 0.,  1., -1.]])
>>> X_scaled = preprocessing.scale(X)

>>> X_scaled                                          
array([[ 0.  ..., -1.22...,  1.33...],
       [ 1.22...,  0.  ..., -0.26...],
       [-1.22...,  1.22..., -1.06...]])

或者可以將計算均值和方差與轉換的步驟分開。

>>> scaler = preprocessing.StandardScaler().fit(X)
>>> scaler
StandardScaler(copy=True, with_mean=True, with_std=True)

>>> scaler.transform(X)                               
array([[ 0.  ..., -1.22...,  1.33...],
       [ 1.22...,  0.  ..., -0.26...],
       [-1.22...,  1.22..., -1.06...]])

fit 是計算過程,transform 是轉換過程。transform 的一個好處是可以繼續使用 fit 的數據,例如 transform 訓練數據之后之后可以直接 transform 測試數據。

有時標準化時要求把數據縮放到某一個范圍中,preprocessing 類也提供了 MinMaxScaler 方法,設置 MinMaxScaler 的參數 feature_range=(min, max) 。
當然最常用的就是(0,1)范圍。

>>> X_train = np.array([[ 1., -1.,  2.],
...                     [ 2.,  0.,  0.],
...                     [ 0.,  1., -1.]])
...
>>> min_max_scaler = preprocessing.MinMaxScaler(feature_range=(0, 1))
>>> X_train_minmax = min_max_scaler.fit_transform(X_train)
>>> X_train_minmax
array([[ 0.5       ,  0.        ,  1.        ],
       [ 1.        ,  0.5       ,  0.33333333],
       [ 0.        ,  1.        ,  0.        ]])
歸一化 Normalization

歸一化是將每個樣本縮放到單位范數(可以粗略地理解為向量的函數)的過程。如果后面要使用如二次型(點積)或者其它核方法計算兩個樣本之間的相似性這個方法會很有用。歸一化的計算方法是 1除以p-范數。歸一化之后的樣本的 p-范數等于1。

向量的p-范數

preprocessing 類下的 normalize 方法可以直接歸一化,并可以選擇 l1 范數與 l2 范數,默認是 l2 范數。

>>> X = [[ 1., -1.,  2.],
...      [ 2.,  0.,  0.],
...      [ 0.,  1., -1.]]
>>> X_normalized = preprocessing.normalize(X, norm='l2')

>>> X_normalized                                      
array([[ 0.40..., -0.40...,  0.81...],
       [ 1.  ...,  0.  ...,  0.  ...],
       [ 0.  ...,  0.70..., -0.70...]])

normalize 也同樣有 fit 方法與 transform 方法。

>>> normalizer = preprocessing.Normalizer().fit(X)  # fit does nothing
>>> normalizer
Normalizer(copy=True, norm='l2')

>>> normalizer.transform(X)                            
array([[ 0.40..., -0.40...,  0.81...],
       [ 1.  ...,  0.  ...,  0.  ...],
       [ 0.  ...,  0.70..., -0.70...]])
.
>>> normalizer.transform([[-1.,  1., 0.]])             
array([[-0.70...,  0.70...,  0.  ...]])
二進制化 Binarization

二進制化的方法是設定一個閾值,樣本值比閾值大的為1,小的為0。

文本處理領域愿意使用二進制化,雖然歸一化和 TF-IDF 加工的特征表現得更好,但使用二進制化來簡化數據更為普遍(可能簡化概率推理)。

>>> X = [[ 1., -1.,  2.],
...      [ 2.,  0.,  0.],
...      [ 0.,  1., -1.]]

>>> binarizer = preprocessing.Binarizer().fit(X)  # fit does nothing
>>> binarizer
Binarizer(copy=True, threshold=0.0)

>>> binarizer.transform(X)
array([[ 1.,  0.,  1.],
       [ 1.,  0.,  0.],
       [ 0.,  1.,  0.]])

閾值調整需要設置 threshold 參數,下面代碼是設置閾值1.1的情況。

>>> binarizer = preprocessing.Binarizer(threshold=1.1)
>>> binarizer.transform(X)
array([[ 0.,  0.,  1.],
       [ 1.,  0.,  0.],
       [ 0.,  0.,  0.]])
類別特征編碼 Encoding categorical features

比如現在有特征 ["male", "female"] ["from Europe", "from US", "from Asia"],
["uses Firefox", "uses Chrome", "uses Safari", "uses Internet Explorer"],
平常我們將特征進行整數編碼.

["male", "from US", "uses Internet Explorer"] 編碼應該是 [0, 1, 3]

["female", "from Asia", "uses Chrome"]的編碼應該是[1,2,1]

但是 scikit-learn 估計器不能直接使用這種整數型的編碼,它的輸入最好是連續型的,估計器也可能把整數編碼特征特征誤解為有序的數據,這會有害于模型訓練。

類別特征編碼用的是 OneHotEncoder 方法,占第幾位的特征值就是1,其余為0。例如 ["male", "female"] 有兩個特征,male 占第1個位置,剩下的0,male 就是 [1,0],female 就是 [0,1]; ["from Europe", "from US", "from Asia"]有3個特征,"from Europe"就是 [1,0,0],"from US" 就是 [0,1,0],"from Asia"就是 [0,0,1],以此類推。

["male", "from US", "uses Internet Explorer"]的整數編碼[0,1,3]的二進制編碼就是
[1,0, 0,1,0, 0,0,0,1]。

代碼實現用的是 preprocessing 類下的 OneHotEncoder 方法。

>>> enc = preprocessing.OneHotEncoder()
>>> enc.fit([[0, 0, 3], [1, 1, 0], [0, 2, 1], [1, 0, 2]])  
OneHotEncoder(categorical_features='all', dtype=<... 'numpy.float64'>,
       handle_unknown='error', n_values='auto', sparse=True)
>>> enc.transform([[0, 1, 3]]).toarray()
array([[ 1.,  0.,  0.,  1.,  0.,  0.,  0.,  0.,  1.]])
插補缺失值 Imputation of missing values

以往對于數據中有丟失值的情況,做法是把該數據所在行和列都刪掉,這樣的后果是容易丟失重要的數據。

imputer 的方法利用平均值、中位數或出現頻率最高的數據對缺失的數據進行填補。代碼如下,NaN 即位丟失的值。

>>> import numpy as np
>>> from sklearn.preprocessing import Imputer
>>> imp = Imputer(missing_values='NaN', strategy='mean', axis=0)
>>> imp.fit([[1, 2], [np.nan, 3], [7, 6]])
Imputer(axis=0, copy=True, missing_values='NaN', strategy='mean', verbose=0)
>>> X = [[np.nan, 2], [6, np.nan], [7, 6]]
>>> print(imp.transform(X))                           
[[ 4.          2.        ]
 [ 6.          3.666...]
 [ 7.          6.        ]]

strategy 告訴了本代碼用 mean 平均值找補,fit 是用它括號里的數據計算平均值,transform 是應用變換。

生成多項式特征 Generating polynomial features

生成多項式的預處理方式是為了給輸入數據增加復雜性。處理后的特征會獲得高階的數據和交叉的數據。

用到的是 preprocessing 下的 PolynomialFeatures 方法。

>>> import numpy as np
>>> from sklearn.preprocessing import PolynomialFeatures
>>> X = np.arange(6).reshape(3, 2)
>>> X                                                 
array([[0, 1],
       [2, 3],
       [4, 5]])
>>> poly = PolynomialFeatures(2)
>>> poly.fit_transform(X)                             
array([[  1.,   0.,   1.,   0.,   0.,   1.],
       [  1.,   2.,   3.,   4.,   6.,   9.],
       [  1.,   4.,   5.,  16.,  20.,  25.]])

PolynomialFeatures(2) 指的是最多生成二次項。
X的特征值由(X1,X2)變成了(1,X1,X2,X12,X1X2,X22)。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容