常用的數(shù)據(jù)預(yù)處理方式
- Standardization, or mean removal and variance scaling
- Normalization: scaling individual to have unit norm
- Binarization: thresholding numerical features to get boolean values
- Encoding categorical feature
- Imputation of missing values
- Generating polynominal features
- Custom transformers
-
標(biāo)準(zhǔn)化(Standardization)
對sklearn中的很多機器學(xué)習(xí)算法,他們都有一個共同的要求:數(shù)據(jù)集的標(biāo)準(zhǔn)化(Standardization)督弓。如果數(shù)
據(jù)集中某個特征的取值不服從保準(zhǔn)的正態(tài)分布(Gaussian with zero mean and unit variance)曙寡,則他們的
性能就會變得很差途事。
在實踐中良漱,我們經(jīng)常忽略分布的形狀(shape of the distribution)而僅僅通過除每個特征分量的均值
(Mean Removal)將數(shù)據(jù)變換到中心赔癌,然后通過除以特征分量的標(biāo)準(zhǔn)差對數(shù)據(jù)進(jìn)行尺度縮放(variance scaling)蔫仙。
舉例來說,在學(xué)習(xí)器的目標(biāo)函數(shù)中用到的很多元素(SVM中的RBF核函數(shù)巨坊,或線性代數(shù)中的L1和L2正則化)都假定了
所有特征分布在0周圍而且每個分量的方差都差不多大撬槽。如果一旦某個特征分量的方差幅度遠(yuǎn)大于其他特征分量的
方差幅度,那么這個大方差特征分量將會主導(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
尺度調(diào)整之后的數(shù)據(jù)有0均值和單位方差(==1):
print(X_scaled.mean(axis=0))
print(X_scaled.std(axis=0))
Preprocessing模塊進(jìn)一步提供了一個類StandardScaler,該類實現(xiàn)了變換器(Transformer)的API用于
計算訓(xùn)練數(shù)據(jù)集的均值和標(biāo)準(zhǔn)差鼓寺。然后將此均值與標(biāo)準(zhǔn)差用到對測試數(shù)據(jù)集的變換操作中去勋拟。所以這個標(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))
在上面的代碼中妈候,scaler實例已經(jīng)訓(xùn)練完成敢靡,就可以再用來對新的數(shù)據(jù)執(zhí)行在訓(xùn)練集上同樣的變換操作。
我們還可以使用參數(shù)來進(jìn)一步的自定義苦银,with_mean=False, with_std=False來不去使用中心化和規(guī)男ル剩化。
把特征變換到指定范圍內(nèi)(Scaling feature to a range)
另外一種標(biāo)準(zhǔn)化是把特征的取值變換到指定的最小值和最大值之間幔虏,通常是[0,1]區(qū)間或每個特征分量的最大絕對值
被縮放為單位值幌甘,這樣的變換可以使用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
上面X_train上訓(xùn)練好的MinMaxScaler就可以通過transform函數(shù)被用到新的數(shù)據(jù)上蔑穴,同樣的縮放和平移操作被用到測試數(shù)據(jù)集
X_test = np.array([[-3., -1.,4. ]])
X_test_minmax = min_max_scaler.transform(X_test)
X_test_minmax
還可以通過MinMaxScaler對象的屬性來獲得在訓(xùn)練集上學(xué)習(xí)到的變換函數(shù)这嚣。
如果給MinMaxScaler對象一個顯式的區(qū)間范圍feature_range=(min,max)
,則其變換過程如下瑟蜈。
MaxAbsScaler的工作方式與MinMaxScaler很相似烟逊,但是其變換方式是讓訓(xùn)練數(shù)據(jù)處于區(qū)間[-1,1]。這可以通過把每個特征分量除以其對應(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_)
縮放稀疏數(shù)據(jù)(Scaling sparse data)
中心化稀疏數(shù)據(jù)(Centering sparse data)將會破壞數(shù)據(jù)的稀疏型結(jié)構(gòu),因此很少這么做位迂。然而访雪,我們可以對稀疏的輸入進(jìn)行縮放(Scale sparse inputs),尤其是特征分量的尺度不一樣的時候掂林。
MaxAbsScaler和maxabs_scale都進(jìn)行了一些特別的設(shè)計專門用于變換稀疏數(shù)據(jù)臣缀,是推薦的做法。
scale和StandardScaler也可以接受scipy.sparse矩陣作為輸入党饮,只要參數(shù)with_mean=False
被顯式的傳入構(gòu)造器就可以了肝陪,否則,會產(chǎn)生ValueErroe刑顺。
RobustScaler不能接受稀疏矩陣氯窍,但是你可以在稀疏輸入上使用transform方法饲常。
注意:變換器接受Compressed Sparse Rows和Compressed Sparse Columns格式(scipy.sparse.csr_marxi和scipy.sparse.csc_matrix)。其他任何的稀疏輸入會被轉(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(明顯的噪點)布隔,均值和方差的估計就會有問題离陶,所以使用均值和方法的數(shù)據(jù)集也會偶遇問題。
在這種情況下衅檀,可以使用robust_scale和RobustScaler招刨,他們使用了更加魯棒的方式來估計數(shù)據(jù)中心和范圍。
-
規(guī)范化(Normalization)
Normalization: scaling individual to have unit norm
規(guī)范化是指哀军,將單個的樣本特征向量變換成具有單位長度(unit norm)的特征向量的過程沉眶。當(dāng)你要使用二次形式(quadratic from)如點積或核變換運算來度量任意一堆樣本的相似性的時候,數(shù)據(jù)的規(guī)范化會非常的有用
假定是基于向量空間模型杉适,經(jīng)常被用于文本分類和內(nèi)容的聚類谎倔。
函數(shù)normalize提供了快速簡單的方法使用L1或L2范數(shù)(距離)執(zhí)行規(guī)范化操作:
X = [[1., -1., 2.],
[2., 0., 0.],
[0., 1., -1.]]
X_normalized = preprocessing.normalize(X, norm='l2')
X_normalized
注意:該函數(shù)按行操作,把每一行變成單位長度猿推。使用每一個元素去除以歐式距離片习。
preprocessing模塊也提供了一個類Normalizer實現(xiàn)了規(guī)范化操作,該類是一個變換器Transformer彤守,具有Transformer API(盡管fit方法在這種時候是沒有用的: 該類是一個靜態(tài)類因為歸一化操作是將每一個樣本單獨進(jìn)行變換毯侦,不存在在所有樣本上的統(tǒng)計學(xué)習(xí)過程。)
規(guī)范化操作類Normalizer作為數(shù)據(jù)預(yù)處理步驟具垫,應(yīng)該用在Pineline管道流的早期階段。
以上的transform過程不依賴于上面的X试幽,也就是說fit是多余的筝蚕,只是為了整個sklearn的統(tǒng)一。
Sparse input
normalize函數(shù)和Normalizer類都接受dense array-like and sparse matrics from scipy.sparse作為輸入铺坞。
對于稀疏輸入起宽,在進(jìn)入高效的Cython routines處理之前,都會將其轉(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ù)處理機制腐晾。
概率型學(xué)習(xí)器(probabilistic estimators)假定輸入數(shù)據(jù)是服從于多變量伯努利分布(multi-variate Bernoulli distribution)的叉弦, 概率性學(xué)習(xí)器的典型的例子是sklearn.neural_network.BrenoulliRBM
在文本處理中,也普遍使用二值特征簡化概率推斷過程藻糖,即使歸一化的詞頻特征或TF-IDF特征的表現(xià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))
binarizer = preprocessing.Binarizer(threshold=1.1)
binarizer.transform(X)
就像StandardScaler和Normalizer類一樣洋满,preprocessing模塊也為我們提供了一個方便的額binarize進(jìn)行數(shù)值特征的二值化晶乔。
Sparse input
normalize函數(shù)和Normalizer類都接受dense array-like and sparse matrics from scipy.sparse作為輸入。
對于稀疏輸入牺勾,在進(jìn)入高效的Cython routines處理之前瘪弓,都會將其轉(zhuǎn)化成CSR(Compressed Sparse Rows)格式(scipy.sparse.csr_matrix),為了避免不必要的數(shù)據(jù)拷貝禽最,推薦使用CSR格式的稀疏矩陣腺怯。
-
標(biāo)稱型特征編碼(Encoding categorical feature)
有些情況下,某些特征的取值不是連續(xù)的數(shù)值川无,而是離散的標(biāo)稱變量(categorical)呛占。
比如一個人的特征描述可能是下面的或幾種:
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í)器使用的晾虑,因為學(xué)習(xí)器希望輸入的是連續(xù)變化的量或者可以比較大小的量,但是上述特征里面的數(shù)字大小的比較是沒有意義的仅叫。
一種變換標(biāo)稱型特征(categorical features)的方法是使用one-of-K或者叫one-hot encoding帜篇,在類OneHotEncoder里面就已經(jīng)實現(xiàn)了。這個編碼器將每一個標(biāo)稱型特征編碼成一個m維二值特征诫咱,其中每一個樣本特征向量就只有一個位置是1笙隙,其余位置全是0。
enc = preprocessing.OneHotEncoder()
enc.fit([[0,0,3],[1,1,0],[0,2,1],[1,0,2]])
enc.transform([[0,1,3]]).toarray()
第一列的取值有兩個坎缭,使用兩個數(shù)字編碼竟痰;第二列取值有單個,使用三個數(shù)字編碼掏呼;第三列取值有4個坏快,使用四個數(shù)字編碼。一共使用九個數(shù)字進(jìn)行編碼憎夷。
默認(rèn)情況下莽鸿,每個特征分量需要多少個值是從數(shù)據(jù)集中自動推斷出來的。我們還可以通過參數(shù)n_values進(jìn)行顯式的指定拾给。上面的數(shù)據(jù)集中祥得,有兩個性別兔沃,三個可能的地方以及四個瀏覽器。然后fit之后在對每一個樣本進(jìn)行變換啃沪。結(jié)果顯示粘拾,前兩個值編碼了性別,接下來的三個值編碼了地方创千,最后的四個值編碼了瀏覽器缰雇。
注意:如果訓(xùn)練數(shù)據(jù)中某個標(biāo)稱型特征分量的取值沒有完全覆蓋其所有可能的情況,則必須給OneHotEncoder指定每一個標(biāo)稱型特征分量的取值個數(shù)追驴,設(shè)置參數(shù):n_values械哟。
enc = preprocessing.OneHotEncoder(n_values=[2,3,4])
enc.fit([[1,2,3],[0,2,0]])
enc.transform([[1,0,0]]).toarray()
-
缺失值處理(Imputation of missing values)
由于各種各樣的原因,很多真實世界中的數(shù)據(jù)集包含有缺失值殿雪,通常使用blanks暇咆,NaNs or other placeholders來代替。這樣的數(shù)據(jù)集是無法直接被sklearn的學(xué)習(xí)器模型處理的丙曙。
一個解決的辦法是將包含缺失值得整行或者整列直接丟棄爸业。然而這樣可能會丟失很多有價值的數(shù)據(jù)。
一個更好的辦法是補全缺失值亏镰,也就是從已知的部分?jǐn)?shù)據(jù)推斷出未知的數(shù)據(jù)扯旷。
Imputer類提供了補全缺失值得基本策略: 使用一行或者一列的均值,中值索抓,出現(xiàn)次數(shù)最多的值來補全钧忽,該類也允許不同缺失值得編碼。
from sklearn.preprocessing import Imputer
imp = Imputer(missing_values='NaN', strategy='mean', axis=0)
imp.fit([[1,2], [np.nan,3], [7,6]])
X = [[np.nan,2], [6, np.nan], [7,6]]
imp.transform(X)
使用訓(xùn)練得數(shù)據(jù)來進(jìn)行補全逼肯。
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)
-
多項式特征(Generating polynominal features)
為輸入數(shù)據(jù)添加非線性特征可以增加模型的復(fù)雜度耸黑,實現(xiàn)這一點的常用的簡單方法是使用多項式特征(polynominal features),他可以引入特征的高階項和互乘積項篮幢。
sklearn的PolynominalFeatures類可以用來在出入數(shù)據(jù)的基礎(chǔ)上構(gòu)造多項式特征大刊。
from sklearn.preprocessing import PolynomialFeatures
X = np.arange(6).reshape(3,2)
poly = PolynomialFeatures(2) # 二階
poly.fit_transform(X)
有些情況下,我們只想要原始輸入特征分量之間的互乘積項洲拇,這時可以設(shè)置參數(shù):interaction_only=True
奈揍,這時將不會出現(xiàn)次方項。
-
自定義轉(zhuǎn)換器(Custom transformers)
有時候赋续,你需要把一個已經(jīng)有的Python函數(shù)變?yōu)橐粋€變換器transformer來進(jìn)行數(shù)據(jù)的清理和預(yù)處理。
借助于FunctionTransformer類另患,你可以從任意的Python函數(shù)實現(xiàn)一個transformer纽乱。比如,構(gòu)造一個transformer實現(xiàn)對數(shù)變換昆箕。
from sklearn.preprocessing import FunctionTransformer
transformer = FunctionTransformer(np.log1p)
X = np.array([[0,1], [2,3]])
transformer.transform(X