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

常用的數(shù)據(jù)預(yù)處理方式

  1. Standardization, or mean removal and variance scaling
  2. Normalization: scaling individual to have unit norm
  3. Binarization: thresholding numerical features to get boolean values
  4. Encoding categorical feature
  5. Imputation of missing values
  6. Generating polynominal features
  7. Custom transformers
  • 標(biāo)準(zhǔn)化(Standardization)

對(duì)sklearn中的很多機(jī)器學(xué)習(xí)算法,他們都有一個(gè)共同的要求:數(shù)據(jù)集的標(biāo)準(zhǔn)化(Standardization)。如果數(shù)
據(jù)集中某個(gè)特征的取值不服從保準(zhǔn)的正態(tài)分布(Gaussian with zero mean and unit variance),則他們的
性能就會(huì)變得很差。

在實(shí)踐中,我們經(jīng)常忽略分布的形狀(shape of the distribution)而僅僅通過除每個(gè)特征分量的均值
(Mean Removal)將數(shù)據(jù)變換到中心,然后通過除以特征分量的標(biāo)準(zhǔn)差對(duì)數(shù)據(jù)進(jìn)行尺度縮放(variance scaling)。

舉例來說,在學(xué)習(xí)器的目標(biāo)函數(shù)中用到的很多元素(SVM中的RBF核函數(shù),或線性代數(shù)中的L1和L2正則化)都假定了
所有特征分布在0周圍而且每個(gè)分量的方差都差不多大。如果一旦某個(gè)特征分量的方差幅度遠(yuǎn)大于其他特征分量的
方差幅度,那么這個(gè)大方差特征分量將會(huì)主導(dǎo)目標(biāo)函數(shù)的有優(yōu)化過程,使得學(xué)習(xí)器無法正確的從其他特征上學(xué)習(xí)。

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
image

尺度調(diào)整之后的數(shù)據(jù)有0均值和單位方差(==1):

print(X_scaled.mean(axis=0))
print(X_scaled.std(axis=0))
image

Preprocessing模塊進(jìn)一步提供了一個(gè)類StandardScaler,該類實(shí)現(xiàn)了變換器(Transformer)的API用于
計(jì)算訓(xùn)練數(shù)據(jù)集的均值和標(biāo)準(zhǔn)差。然后將此均值與標(biāo)準(zhǔn)差用到對(duì)測(cè)試數(shù)據(jù)集的變換操作中去。所以這個(gè)標(biāo)準(zhǔn)化
的過程應(yīng)該被應(yīng)用到sklearn.pipeline.Pipeline的早期階段。

scaler = preprocessing.StandardScaler().fit(X)
print(scaler)
print('--------')
print(scaler.mean_)
print('--------')
print(scaler.transform(X))
image

在上面的代碼中,scaler實(shí)例已經(jīng)訓(xùn)練完成,就可以再用來對(duì)新的數(shù)據(jù)執(zhí)行在訓(xùn)練集上同樣的變換操作。

image

我們還可以使用參數(shù)來進(jìn)一步的自定義,with_mean=False, with_std=False來不去使用中心化和規(guī)?;?。

把特征變換到指定范圍內(nèi)(Scaling feature to a range)

另外一種標(biāo)準(zhǔn)化是把特征的取值變換到指定的最小值和最大值之間,通常是[0,1]區(qū)間或每個(gè)特征分量的最大絕對(duì)值
被縮放為單位值,這樣的變換可以使用MinMaxScaler或者M(jìn)axAbsScaler。

X_train = np.array([[1., -1., 2.],
                   [2., 0., 0.],
                   [0., 1., -1.]])
min_max_scaler = preprocessing.MinMaxScaler()
X_train_minmax = min_max_scaler.fit_transform(X_train)
X_train_minmax
image

上面X_train上訓(xùn)練好的MinMaxScaler就可以通過transform函數(shù)被用到新的數(shù)據(jù)上,同樣的縮放和平移操作被用到測(cè)試數(shù)據(jù)集

X_test = np.array([[-3., -1.,4. ]])
X_test_minmax = min_max_scaler.transform(X_test)
X_test_minmax
image

還可以通過MinMaxScaler對(duì)象的屬性來獲得在訓(xùn)練集上學(xué)習(xí)到的變換函數(shù)。

image

如果給MinMaxScaler對(duì)象一個(gè)顯式的區(qū)間范圍feature_range=(min,max),則其變換過程如下。

image

MaxAbsScaler的工作方式與MinMaxScaler很相似,但是其變換方式是讓訓(xùn)練數(shù)據(jù)處于區(qū)間[-1,1]。這可以通過把每個(gè)特征分量除以其對(duì)應(yīng)的最大值來做到。這種變換要求數(shù)據(jù)集已經(jīng)被中心化到0或者是稀疏數(shù)據(jù)。

X_train = np.array([[1., -1., 2.],
                   [2., 0., 0. ],
                   [0., 1., -1.]])
max_abs_scaler = preprocessing.MaxAbsScaler()
X_train_maxabs = max_abs_scaler.fit_transform(X_train)
print(X_train_maxabs)
print('-------')
X_test = np.array([[-3., -1., 4.]])
X_test_maxabs = max_abs_scaler.transform(X_test)
print(X_test_maxabs)
print('-------')
print(max_abs_scaler.scale_)
image

縮放稀疏數(shù)據(jù)(Scaling sparse data)

中心化稀疏數(shù)據(jù)(Centering sparse data)將會(huì)破壞數(shù)據(jù)的稀疏型結(jié)構(gòu),因此很少這么做。然而,我們可以對(duì)稀疏的輸入進(jìn)行縮放(Scale sparse inputs),尤其是特征分量的尺度不一樣的時(shí)候。

MaxAbsScaler和maxabs_scale都進(jìn)行了一些特別的設(shè)計(jì)專門用于變換稀疏數(shù)據(jù),是推薦的做法。

scale和StandardScaler也可以接受scipy.sparse矩陣作為輸入,只要參數(shù)with_mean=False被顯式的傳入構(gòu)造器就可以了,否則,會(huì)產(chǎn)生ValueErroe。

RobustScaler不能接受稀疏矩陣,但是你可以在稀疏輸入上使用transform方法。

注意:變換器接受Compressed Sparse Rows和Compressed Sparse Columns格式(scipy.sparse.csr_marxi和scipy.sparse.csc_matrix)。其他任何的稀疏輸入會(huì)被轉(zhuǎn)換成Compressed Sparse Rows,為了避免不必要的內(nèi)存拷貝,推薦使用CSR和CSC。最后,如果你的稀疏數(shù)據(jù)比較小,那么可以使用toarray方法吧稀疏數(shù)據(jù)轉(zhuǎn)換成Numpy array。

Scaling data with outliers

如果數(shù)據(jù)中有很多的outliers(明顯的噪點(diǎn)),均值和方差的估計(jì)就會(huì)有問題,所以使用均值和方法的數(shù)據(jù)集也會(huì)偶遇問題。
在這種情況下,可以使用robust_scale和RobustScaler,他們使用了更加魯棒的方式來估計(jì)數(shù)據(jù)中心和范圍。

  • 規(guī)范化(Normalization)

Normalization: scaling individual to have unit norm

規(guī)范化是指,將單個(gè)的樣本特征向量變換成具有單位長(zhǎng)度(unit norm)的特征向量的過程。當(dāng)你要使用二次形式(quadratic from)如點(diǎn)積或核變換運(yùn)算來度量任意一堆樣本的相似性的時(shí)候,數(shù)據(jù)的規(guī)范化會(huì)非常的有用

假定是基于向量空間模型,經(jīng)常被用于文本分類和內(nèi)容的聚類。

函數(shù)normalize提供了快速簡(jiǎn)單的方法使用L1或L2范數(shù)(距離)執(zhí)行規(guī)范化操作:

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

注意:該函數(shù)按行操作,把每一行變成單位長(zhǎng)度。使用每一個(gè)元素去除以歐式距離。

preprocessing模塊也提供了一個(gè)類Normalizer實(shí)現(xiàn)了規(guī)范化操作,該類是一個(gè)變換器Transformer,具有Transformer API(盡管fit方法在這種時(shí)候是沒有用的: 該類是一個(gè)靜態(tài)類因?yàn)闅w一化操作是將每一個(gè)樣本單獨(dú)進(jìn)行變換,不存在在所有樣本上的統(tǒng)計(jì)學(xué)習(xí)過程。)

規(guī)范化操作類Normalizer作為數(shù)據(jù)預(yù)處理步驟,應(yīng)該用在Pineline管道流的早期階段。

image

以上的transform過程不依賴于上面的X,也就是說fit是多余的,只是為了整個(gè)sklearn的統(tǒng)一。

Sparse input

normalize函數(shù)和Normalizer類都接受dense array-like and sparse matrics from scipy.sparse作為輸入。

對(duì)于稀疏輸入,在進(jìn)入高效的Cython routines處理之前,都會(huì)將其轉(zhuǎn)化成CSR(Compressed Sparse Rows)格式(scipy.sparse.csr_matrix),為了避免不必要的數(shù)據(jù)拷貝,推薦使用CSR格式的稀疏矩陣。

  • 二值化(Binarize)

Binarization: thresholding numerical features to get boolean values

Feature binarization: 將數(shù)值型特征取值閾值化轉(zhuǎn)換為布爾型特征取值,這一過程主要是為概率型的學(xué)習(xí)器(probabilistic estimators)提供數(shù)據(jù)預(yù)處理機(jī)制。

概率型學(xué)習(xí)器(probabilistic estimators)假定輸入數(shù)據(jù)是服從于多變量伯努利分布(multi-variate Bernoulli distribution)的, 概率性學(xué)習(xí)器的典型的例子是sklearn.neural_network.BrenoulliRBM

在文本處理中,也普遍使用二值特征簡(jiǎn)化概率推斷過程,即使歸一化的詞頻特征或TF-IDF特征的表現(xiàn)比而二值特征稍微好一點(diǎn)。

就像Normalizer,Binarizer也應(yīng)該用在sklearn.pipeline.Pipeline的早期階段。fit方法也是什么也不干,有或者沒有是一樣的。

X = [[1., -1., 2.], 
     [2., 0., 0.],
     [0., 1., -1.]]
binarizer = preprocessing.Binarizer().fit(X)
print(binarizer)
print('-----')
print(binarizer.transform(X))
image
binarizer = preprocessing.Binarizer(threshold=1.1)
binarizer.transform(X)
image

就像StandardScaler和Normalizer類一樣,preprocessing模塊也為我們提供了一個(gè)方便的額binarize進(jìn)行數(shù)值特征的二值化。

Sparse input

normalize函數(shù)和Normalizer類都接受dense array-like and sparse matrics from scipy.sparse作為輸入。

對(duì)于稀疏輸入,在進(jìn)入高效的Cython routines處理之前,都會(huì)將其轉(zhuǎn)化成CSR(Compressed Sparse Rows)格式(scipy.sparse.csr_matrix),為了避免不必要的數(shù)據(jù)拷貝,推薦使用CSR格式的稀疏矩陣。

  • 標(biāo)稱型特征編碼(Encoding categorical feature)

有些情況下,某些特征的取值不是連續(xù)的數(shù)值,而是離散的標(biāo)稱變量(categorical)。

比如一個(gè)人的特征描述可能是下面的或幾種:

features ['male', 'female'], ['from Europe', 'from US', 'from Asia'], ['use Firefox', 'use Chorme', 'use Safari', 'Use IE']。

這樣的特征可以被有效的編碼為整型特征值(interger number)。

['male', 'US', 'use IE']  -->>  [0,1,3]
['femel', 'Asia', 'use Chrome']  -->> [1,2,1]

但是這些整數(shù)型的特征向量是無法直接被sklearn的學(xué)習(xí)器使用的,因?yàn)閷W(xué)習(xí)器希望輸入的是連續(xù)變化的量或者可以比較大小的量,但是上述特征里面的數(shù)字大小的比較是沒有意義的。

一種變換標(biāo)稱型特征(categorical features)的方法是使用one-of-K或者叫one-hot encoding,在類OneHotEncoder里面就已經(jīng)實(shí)現(xiàn)了。這個(gè)編碼器將每一個(gè)標(biāo)稱型特征編碼成一個(gè)m維二值特征,其中每一個(gè)樣本特征向量就只有一個(gè)位置是1,其余位置全是0。

enc = preprocessing.OneHotEncoder()
enc.fit([[0,0,3],[1,1,0],[0,2,1],[1,0,2]])
image
enc.transform([[0,1,3]]).toarray()
image

第一列的取值有兩個(gè),使用兩個(gè)數(shù)字編碼;第二列取值有單個(gè),使用三個(gè)數(shù)字編碼;第三列取值有4個(gè),使用四個(gè)數(shù)字編碼。一共使用九個(gè)數(shù)字進(jìn)行編碼。

默認(rèn)情況下,每個(gè)特征分量需要多少個(gè)值是從數(shù)據(jù)集中自動(dòng)推斷出來的。我們還可以通過參數(shù)n_values進(jìn)行顯式的指定。上面的數(shù)據(jù)集中,有兩個(gè)性別,三個(gè)可能的地方以及四個(gè)瀏覽器。然后fit之后在對(duì)每一個(gè)樣本進(jìn)行變換。結(jié)果顯示,前兩個(gè)值編碼了性別,接下來的三個(gè)值編碼了地方,最后的四個(gè)值編碼了瀏覽器。

注意:如果訓(xùn)練數(shù)據(jù)中某個(gè)標(biāo)稱型特征分量的取值沒有完全覆蓋其所有可能的情況,則必須給OneHotEncoder指定每一個(gè)標(biāo)稱型特征分量的取值個(gè)數(shù),設(shè)置參數(shù):n_values。

enc = preprocessing.OneHotEncoder(n_values=[2,3,4])
enc.fit([[1,2,3],[0,2,0]])
image
enc.transform([[1,0,0]]).toarray()
image
  • 缺失值處理(Imputation of missing values)

由于各種各樣的原因,很多真實(shí)世界中的數(shù)據(jù)集包含有缺失值,通常使用blanks,NaNs or other placeholders來代替。這樣的數(shù)據(jù)集是無法直接被sklearn的學(xué)習(xí)器模型處理的。

一個(gè)解決的辦法是將包含缺失值得整行或者整列直接丟棄。然而這樣可能會(huì)丟失很多有價(jià)值的數(shù)據(jù)。

一個(gè)更好的辦法是補(bǔ)全缺失值,也就是從已知的部分?jǐn)?shù)據(jù)推斷出未知的數(shù)據(jù)。

Imputer類提供了補(bǔ)全缺失值得基本策略: 使用一行或者一列的均值,中值,出現(xiàn)次數(shù)最多的值來補(bǔ)全,該類也允許不同缺失值得編碼。

from sklearn.preprocessing import Imputer

imp = Imputer(missing_values='NaN', strategy='mean', axis=0)
imp.fit([[1,2], [np.nan,3], [7,6]])
image
X = [[np.nan,2], [6, np.nan], [7,6]]
imp.transform(X)
image

使用訓(xùn)練得數(shù)據(jù)來進(jìn)行補(bǔ)全。

Imputer類支持稀疏矩陣:

import scipy.sparse as sp
X = sp.csc_matrix([[1,2], [0,3], [7,6]])
imp = Imputer(missing_values=0, strategy='mean', axis=0)
imp.fit(X)

X_test = sp.csc_matrix([[0,2], [6,0], [7,6]])
imp.transform(X_test)
image
  • 多項(xiàng)式特征(Generating polynominal features)

為輸入數(shù)據(jù)添加非線性特征可以增加模型的復(fù)雜度,實(shí)現(xiàn)這一點(diǎn)的常用的簡(jiǎn)單方法是使用多項(xiàng)式特征(polynominal features),他可以引入特征的高階項(xiàng)和互乘積項(xiàng)。

sklearn的PolynominalFeatures類可以用來在出入數(shù)據(jù)的基礎(chǔ)上構(gòu)造多項(xiàng)式特征。

from sklearn.preprocessing import PolynomialFeatures

X = np.arange(6).reshape(3,2)
poly = PolynomialFeatures(2)   # 二階
poly.fit_transform(X)
image
image

有些情況下,我們只想要原始輸入特征分量之間的互乘積項(xiàng),這時(shí)可以設(shè)置參數(shù):interaction_only=True,這時(shí)將不會(huì)出現(xiàn)次方項(xiàng)。

  • 自定義轉(zhuǎn)換器(Custom transformers)

有時(shí)候,你需要把一個(gè)已經(jīng)有的Python函數(shù)變?yōu)橐粋€(gè)變換器transformer來進(jìn)行數(shù)據(jù)的清理和預(yù)處理。

借助于FunctionTransformer類,你可以從任意的Python函數(shù)實(shí)現(xiàn)一個(gè)transformer。比如,構(gòu)造一個(gè)transformer實(shí)現(xiàn)對(duì)數(shù)變換。

from sklearn.preprocessing import FunctionTransformer

transformer = FunctionTransformer(np.log1p)
X = np.array([[0,1], [2,3]])
transformer.transform(X
image
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容