數(shù)據(jù)預處理
在機器學習算法實踐中怎茫,往往需要把不同規(guī)格的數(shù)據(jù)轉(zhuǎn)換到同一規(guī)格辛馆,或者不同分布的數(shù)據(jù)轉(zhuǎn)換到同一分布停忿,這個過程叫做"無量綱化"颜启。
數(shù)據(jù)的無量綱化可以是線性的日杈,也可以是非線性的衡载。線性的無量綱化包括"中心化" (Zero-centered or Mean-substraction)處理和縮放處理 (Scale)奏路。中心化的本質(zhì)是讓所有紀錄減去一個固定值阵幸,即讓數(shù)據(jù)平移到某個位置(通常是0);縮放的本質(zhì)是通過除以一個固定值坡慌,將數(shù)據(jù)固定掛在某個范圍之中黔酥,取對數(shù)也是一種縮放處理。
Note:決策樹即基于決策樹的算法不需要對數(shù)據(jù)進行無量綱化處理洪橘,幾乎可以應對任何形式的數(shù)據(jù)跪者。
標準化 (standardization),也稱為去均值和方差按比例縮放
數(shù)據(jù)集的標準化對于 sklearn 中實現(xiàn)的很多機器學習算法來說都是常見的要求熄求。如果個別特征或多或少看起來不像是標準正態(tài)分布 (具有零均值和單位方差)渣玲,那么它們的表現(xiàn)能力可能會很差。
在實際過程中弟晚,經(jīng)常會忽略特征的分布形狀忘衍,直接經(jīng)過去均值對某個特征進行中心化,再通過除以非常量特征的標準差進行縮放卿城。
函數(shù)scale
為數(shù)組形狀的數(shù)據(jù)集的標準化提供了一個快捷實現(xiàn):
sklearn.preprocessing.scale(X, axis=0, with_mean=True, with_std=True, copy=True)
>>> from sklearn import preprocessing
>>> import numpy as np
>>> X_train = np.array([[ 1., -1., 2.],
... [ 2., 0., 0.],
... [ 0., 1., -1.]])
>>> X_scaled = preprocessing.scale(X_train)
>>> X_scaled
array([[ 0. ..., -1.22..., 1.33...],
[ 1.22..., 0. ..., -0.26...],
[-1.22..., 1.22..., -1.06...]])
>>> X_scaled.mean(axis=0)
array([0., 0., 0.])
>>> X_scaled.std(axis=0)
array([1., 1., 1.])
預處理 (preprocessing) 模塊還提供了一個實用類 StandardScaler
枚钓,它對標準化常用的函數(shù)進行了分裝,常應用于 sklearn.pipeline.Pipeline
的早期步驟:
class sklearn.preprocessing.StandardScaler(copy=True, with_mean=True, with_std=True)
copy=True
:將計算結(jié)果進行返回瑟押;with_mean
=True: 對數(shù)據(jù)進行去中心化搀捷,即將其轉(zhuǎn)為了均值為0;-
with_std
=True: 對數(shù)據(jù)進行縮放勉耀,使其方差為標準差指煎;常用的屬性 (attribute) 和方法 (method):
-
scale_
: 返回該數(shù)組的標準差; -
mean_
: 返回原數(shù)組的平均值便斥; -
var_
: 返回原數(shù)組的方差至壤; -
fit_transform()
: 計算該數(shù)組的平均值和方差,并對其進行轉(zhuǎn)換枢纠; -
fit()
: 計算該數(shù)組的平均值和方差像街; -
transform()
: 根據(jù)平均值和方差 (由調(diào)用fit()
方法時計算得出,不包含該數(shù)組),轉(zhuǎn)換該數(shù)組镰绎; -
inverse_transform()
:可將標準化之后的數(shù)據(jù)反標準化脓斩,返回原始數(shù)據(jù);
-
>>> X_train = np.array([[ 1., -1., 2.],
... [ 2., 0., 0.],
... [ 0., 1., -1.]])
...
>>> scaler = preprocessing.StandardScaler().fit(X_train)
>>> scaler
StandardScaler(copy=True, with_mean=True, with_std=True)
>>> scaler.mean_
array([ 1. ..., 0. ..., 0.33...])
>>> scaler.scale_
array([ 0.81..., 0.81..., 1.24...])
>>> scaler.transform(X_train)
array([[ 0. ..., -1.22..., 1.33...],
[ 1.22..., 0. ..., -0.26...],
[-1.22..., 1.22..., -1.06...]])
StandardScaler()
和 scale()
的計算方法為:
Note:
- 當設置
with_mean = False
時畴栖,不對數(shù)組去中心化随静,這是可以用來處理稀疏矩陣,而且能保持其稀疏性吗讶。 -
fit()
和fit_transform()
接受的數(shù)據(jù)必須是二維數(shù)據(jù)燎猛,如果對某個特征向量單獨進行標準化,需要首先使用.reshape(-1,1)
將其由一維數(shù)組轉(zhuǎn)化為二維數(shù)組照皆。
Normalization 將特征向量縮放至特定范圍內(nèi)
另一種標準化方法是將特征數(shù)組縮放到某一范圍之內(nèi)重绷,通常為(0,1)或 (-1膜毁,1) 之間昭卓,可以使用 MinMaxScaler
和 MaxAbsScaler
實現(xiàn)。
class
sklearn.preprocessing.MinMaxScaler
(feature_range=(0, 1), copy=True)class
sklearn.preprocessing.MaxAbsScaler
(copy=True)
這兩個類的用法和 StandardScaler
類的用法幾乎一樣瘟滨,其對應的函數(shù)分別為 minmax_scale()
和 maxabs_scale()
候醒。
其中:MinMaxScaler
類的計算方式為:
MaxAbsScaler
的計算方法為:
Note:MaxAbsScaler
不但可以處理一般矩陣,還可以處理稀疏矩陣室奏,并且能保持其稀疏性火焰。
StandardScaler 與 MinMaxScaler 該如何選擇
大多數(shù)機器學習算法中劲装,會選擇 StandardScaler
來進行特征縮放胧沫,因為 MinMaxScaler
對異常值非常敏感。在 PCA占业、聚類绒怨、邏輯回歸、支持向量機谦疾、神經(jīng)網(wǎng)絡這些算法中南蹂,StandardScaler
往往是最好的選擇。在不涉及距離度量念恍、梯度六剥、協(xié)方差計算以及數(shù)據(jù)需要被壓縮到特定區(qū)間時,比如數(shù)字圖像處理中量化像素強度時峰伙,往往會使用 MinMaxScaler
將數(shù)據(jù)壓縮到 [0,1] 區(qū)間疗疟。
縮放稀疏矩陣
中心化稀疏矩陣會破壞矩陣的稀疏結(jié)構(gòu),但是對稀疏矩陣進行縮放是有意義的瞳氓,尤其是當幾個特征在不同的量級范圍時策彤。
MaxAbsScaler
以及 maxabsscale
是專門為縮放稀疏矩陣而設計的,并且是縮放稀疏矩陣的推薦方法。同時店诗,scale()
和 StanderdScaler
也可以對稀疏矩陣進行縮放裹刮,必須設置參數(shù) with_mean=False
,否則會破壞其稀疏性庞瘸,當數(shù)據(jù)量很大時捧弃,很容易引起 ValueError
的錯誤。
縮放有離群點 (outflier)的數(shù)據(jù)
對于帶有很多帶有離群點的數(shù)據(jù)擦囊,使用均值和方差進行縮放可能不是很好的選擇塔橡,這時可以使用 robust_scale
函數(shù)或者RobustScaler
,它們對于數(shù)據(jù)的中心和范圍使用更有魯棒性的估計霜第。
sklearn.preprocessing.robust_scale (X, axis=0, with_centering=True, with_scaling=True, quantile_range=(25.0, 75.0), copy=True)
class sklearn.preprocessing.RobustScaler (with_centering=True, with_scaling=True, quantile_range=(25.0, 75.0), copy=True)
RobustScaler
和 robust_scale
也會對數(shù)據(jù)進行去中心化和縮放葛家,但是使用的數(shù)據(jù)不是均值和標準差,而是中間值和第一四分位點和第三四分位點泌类,所以可以很好的降低離群點的影響癞谒。具體計算方法為:
QuantileTransformer 類
preprocessing.``QuantileTransformer
(n_quantiles=1000, output_distribution='uniform', ignore_implicit_zeros=False, subsample=100000, random_state=None, copy=True)
preprocessing.``quantile_transform
(X, axis=0, n_quantiles=1000, output_distribution='uniform', ignore_implicit_zeros=False, subsample=100000, random_state=None, copy='warn')
QuantileTransformer
類和 quantile_transformer()
函數(shù)提供了一個基于分位數(shù)函數(shù)的無參數(shù)轉(zhuǎn)換,能夠?qū)?shù)據(jù)映射到 [0,1] 區(qū)間上的均勻分布刃榨,這種變換能夠平滑異常分布弹砚,比縮放方法受異常值的影響更小,但是它也使特征間及特征內(nèi)的關(guān)聯(lián)和距離失真枢希。
PowerTransformer 類
在很多機器學習模型中桌吃,都會假設數(shù)據(jù)服從高斯分布,都是實際數(shù)據(jù)可能會存在偏度等問題苞轿,不完全符合高斯分布茅诱,這時需要先把數(shù)據(jù)轉(zhuǎn)換為高斯分布。
PowerTransformer
可以將數(shù)據(jù)集從任何分布映射到盡可能接近高斯分布搬卒,以便穩(wěn)定方差和最小化偏斜瑟俭。
preprocessing.``QuantileTransformer
(n_quantiles=1000, output_distribution='uniform', ignore_implicit_zeros=False, subsample=100000, random_state=None, copy=True)
歸一化 (Normalization)
"歸一化"是縮放單個樣本以使其具有單位范數(shù)。如果你計劃使用二次形式 (比如點積或者任何其他核函數(shù)) 來量化任意樣本間的相似度契邀,這個過程將會非常有用摆寄。
這種假設是"向量空間模型"的根本,經(jīng)常在文本分類和內(nèi)容聚類中使用坯门。
Normalizer
類和函數(shù) normalize()
則提供了一個快速簡單的方法在類似于數(shù)組的數(shù)據(jù)結(jié)構(gòu)上執(zhí)行操作微饥,使其具有 l1
或者 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...]])
備注:
-
l1
范式是指該樣本各個特征值的絕對值之和等于 1古戴,即:;
-
l2
范式是指該樣本各個特征值的平方和等于 1欠橘,即:.
- 該類和函數(shù)接受一般矩陣和稀疏矩陣作為輸入。
處理分類型數(shù)據(jù):編碼與啞變量
在 sklearn
當中允瞧,除了專門用來處理文字的算法简软,其他算法在 fit()
的時候要求全部數(shù)組必須為數(shù)值類型蛮拔。
preprocessing.LabelEncoder()
能夠?qū)撕炥D(zhuǎn)化為數(shù)值類型,范圍是 (0痹升,N-1)建炫,N是類型數(shù)。
Note:該類時標簽專用疼蛾,即專門用來轉(zhuǎn)換 y肛跌,因此輸入默認是一維數(shù)組。
preprocessing.OrdinalEncoder()
特征矩陣專用察郁,能夠?qū)⒎诸愄卣鬓D(zhuǎn)換為分類數(shù)值衍慎,輸入默認是二維數(shù)組。
preprocessing.OrdinalEncoder (categories=auto, dtype=np.float64)
>>> enc = preprocessing.OrdinalEncoder()
>>> X = [['male', 'from US', 'uses Safari'], ['female', 'from Europe', 'uses Firefox']]
>>> enc.fit(X)
OrdinalEncoder(categories='auto', dtype=<... 'numpy.float64'>)
>>> enc.transform([['female', 'from US', 'uses Safari']])
array([[0., 1., 1.]])
這樣將類別數(shù)據(jù)轉(zhuǎn)化為整數(shù)特征的變換會帶來另一個問題皮钠,sklearn 中的估計器會將該特征當做是有序稳捆,并且是有一定含義,但實際上是無序的麦轰。另一種轉(zhuǎn)換方式是 one-of-K
, 又稱為 dummy encoding
乔夯。
preprocessing.OneHotEncoder()
對特征進行啞變量編碼;把每一個具有 n_categories 個可能取值的 categorical 特征變換為長度為 n_categories 的二進制特征向量款侵,里面只有一個值為 1末荐,其他值為 0。
preprocessing.``OneHotEncoder
(categories='auto', drop=None, sparse=True, dtype=, handle_unknown='error')
如果訓練數(shù)據(jù)集可能缺少部分分類特征新锈,最好設置 handle_unknown=ignore
, 這樣在轉(zhuǎn)換過程中遇到未知類別時甲脏,就不會報錯,而是將其特征全部設置為 0.
>>> enc = preprocessing.OneHotEncoder()
>>> X = [['male', 'from US', 'uses Safari'], ['female', 'from Europe', 'uses Firefox']]
>>> enc.fit(X)
OneHotEncoder(categorical_features=None, categories=None,
dtype=<... 'numpy.float64'>, handle_unknown='error',
n_values=None, sparse=True)
>>> enc.transform([['female', 'from US', 'uses Safari'],
... ['male', 'from Europe', 'uses Safari']]).toarray()
array([[1., 0., 0., 1., 0., 1.],
[0., 1., 1., 0., 0., 1.]])
離散化:二值化和bins
離散化是將連續(xù)性特征劃分為離散特征的方法妹笆,進行離散化處理可以給線性模型引入非線性块请。
preprocessing.Binarizer()
根據(jù)閾值將數(shù)據(jù) (連續(xù)性數(shù)據(jù)和離散型數(shù)據(jù)都可以) 二值化 (0 或者 1)。大于閾值的值映射為1晾浴,小于或等于閾值的值映射為0.
preprocessing
.Binarizer
(threshold=0.0, copy=True)
>>> binarizer = preprocessing.Binarizer(threshold=1.1)
>>> binarizer.transform(X)
array([[ 0., 0., 1.],
[ 1., 0., 0.],
[ 0., 0., 0.]])
preprocessing.KBinsDiscretizer()
能夠?qū)⑦B續(xù)性變量劃分到 K 個不同的 bins 當中负乡,轉(zhuǎn)化為分類變量,既可以將其轉(zhuǎn)化為 OrdinalEncoder()
這樣的數(shù)字分類變量脊凰,又可以轉(zhuǎn)換為 One Hot
編碼。
preprocessing
.KBinsDiscretizer
(n_bins=5, encode='onehot', strategy='quantile')
>>> X = np.array([[ -3., 5., 15 ],
... [ 0., 6., 14 ],
... [ 6., 3., 11 ]])
>>> est = preprocessing.KBinsDiscretizer(n_bins=[3, 2, 2], encode='ordinal').fit(X)
>>> est.transform(X)
array([[ 0., 1., 1.],
[ 1., 1., 1.],
[ 2., 0., 0.]])
單變量插補
SimpleImpute
類提供了計算缺失值的基本策略茂腥,既可以使用常值填充狸涌,又可以使用缺失值所在行的統(tǒng)計數(shù)據(jù) (平均值、中位數(shù)或眾數(shù))來計算最岗,同時也支持不同的缺失值編碼方式
class
sklearn.impute.SimpleImputer
(missing_values=nan, strategy='mean', fill_value=None, verbose=0, copy=True, add_indicator=False)
missing_values
:缺失值在數(shù)據(jù)中的體現(xiàn)形式帕胆;
strategy
: ‘mean’, ‘median’, ‘most_frequent’, ‘constant’, 決定由平均值,中值或者總數(shù)進行填充般渡。
>>> import numpy as np
>>> from sklearn.impute import SimpleImputer
>>> imp_mean = SimpleImputer(missing_values=np.nan, strategy='mean')
>>> imp_mean.fit([[7, 2, 3], [4, np.nan, 6], [10, 5, 9]])
SimpleImputer()
>>> X = [[np.nan, 2, 3], [4, np.nan, 6], [10, np.nan, 9]]
>>> print(imp_mean.transform(X))
[[ 7. 2. 3. ]
[ 4. 3.5 6. ]
[10. 3.5 9. ]]
當使用 most_frequent
or constant
策略進行填充時懒豹,SimpleImpute
類還支持以 string values
or pandas.Categoricals
表示的分類數(shù)據(jù)芙盘。
>>> import pandas as pd
>>> df = pd.DataFrame([["a", "x"],
... [np.nan, "y"],
... ["a", np.nan],
... ["b", "y"]], dtype="category")
...
>>> imp = SimpleImputer(strategy="most_frequent")
>>> print(imp.fit_transform(df))
[['a' 'x']
['a' 'y']
['a' 'y']
['b' 'y']]