中文文檔: http://sklearn.apachecn.org/cn/stable/modules/preprocessing.html
英文文檔: http://sklearn.apachecn.org/en/stable/modules/preprocessing.html
官方文檔: http://scikit-learn.org/stable/
GitHub: https://github.com/apachecn/scikit-learn-doc-zh(覺得不錯麻煩給個 Star,我們一直在努力)
貢獻者: https://github.com/apachecn/scikit-learn-doc-zh#貢獻者
關於我們: http://www.apachecn.org/organization/209.html
4.3. 預處理數據
sklearn.preprocessing
包提供了幾個常見的實用功能和變換器類型,用來將原始特徵向量更改爲更適合機器學習模型的形式。
一般來說,機器學習算法受益於數據集的標準化。如果數據集中存在一些離羣值,那麼穩定的縮放或轉換更合適。不同縮放、轉換以及歸一在一個包含邊緣離羣值的數據集中的表現在 Compare the effect of different scalers on data with outliers 中有着重說明。
4.3.1. 標準化,也稱去均值和方差按比例縮放
數據集的 標準化 對scikit-learn中實現的大多數機器學習算法來說是 常見的要求 。如果個別特徵或多或少看起來不是很像標準正態分佈(具有零均值和單位方差),那麼它們的表現力可能會較差。
在實際情況中,我們經常忽略特徵的分佈形狀,直接經過去均值來對某個特徵進行中心化,再通過除以非常量特徵(non-constant features)的標準差進行縮放。
例如,在機器學習算法的目標函數(例如SVM的RBF內核或線性模型的l1和l2正則化),許多學習算法中目標函數的基礎都是假設所有的特徵都是零均值並且具有同一階數上的方差。如果某個特徵的方差比其他特徵大幾個數量級,那麼它就會在學習算法中佔據主導位置,導致學習器並不能像我們說期望的那樣,從其他特徵中學習。
函數 scale
爲數組形狀的數據集的標準化提供了一個快捷實現:
>>> 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.])
預處理
模塊還提供了一個實用類 StandardScaler
,它實現了轉化器的API來計算訓練集上的平均值和標準偏差,以便以後能夠在測試集上重新應用相同的變換。因此,這個類適用於 sklearn.pipeline.Pipeline
的早期步驟:
>>> 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...]])
縮放類對象可以在新的數據上實現和訓練集相同縮放操作:
>>> X_test = [[-1., 1., 0.]]
>>> scaler.transform(X_test)
array([[-2.44..., 1.22..., -0.26...]])
你也可以通過在構造函數 :class:StandardScaler 中傳入參數 with_mean=False` 或者``with_std=False
來取消中心化或縮放操作。
4.3.1.1. 將特徵縮放至特定範圍內
一種標準化是將特徵縮放到給定的最小值和最大值之間,通常在零和一之間,或者也可以將每個特徵的最大絕對值轉換至單位大小。可以分別使用 MinMaxScaler
和 MaxAbsScaler
實現。
使用這種縮放的目的包括實現特徵極小方差的魯棒性以及在稀疏矩陣中保留零元素。
以下是一個將簡單的數據矩陣縮放到``[0, 1]``的例子:
>>> 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
array([[ 0.5 , 0. , 1. ],
[ 1. , 0.5 , 0.33333333],
[ 0. , 1. , 0. ]])
同樣的轉換實例可以被用與在訓練過程中不可見的測試數據:實現和訓練數據一致的縮放和移位操作:
>>> X_test = np.array([[ -3., -1., 4.]])
>>> X_test_minmax = min_max_scaler.transform(X_test)
>>> X_test_minmax
array([[-1.5 , 0. , 1.66666667]])
可以檢查縮放器(scaler)屬性,來觀察在訓練集中學習到的轉換操作的基本性質:
>>> min_max_scaler.scale_
array([ 0.5 , 0.5 , 0.33...])
>>> min_max_scaler.min_
array([ 0. , 0.5 , 0.33...])
如果給 MinMaxScaler
提供一個明確的 feature_range=(min, max)
,完整的公式是:
X_std = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0))
X_scaled = X_std * (max - min) + min
類 MaxAbsScaler
的工作原理非常相似,但是它只通過除以每個特徵的最大值將訓練數據特徵縮放至 [-1, 1]
範圍內,這就意味着,訓練數據應該是已經零中心化或者是稀疏數據。
例子::用先前例子的數據實現最大絕對值縮放操作。
以下是使用上例中數據運用這個縮放器的例子:
>>> 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)
>>> X_train_maxabs # doctest +NORMALIZE_WHITESPACE^
array([[ 0.5, -1. , 1. ],
[ 1. , 0. , 0. ],
[ 0. , 1. , -0.5]])
>>> X_test = np.array([[ -3., -1., 4.]])
>>> X_test_maxabs = max_abs_scaler.transform(X_test)
>>> X_test_maxabs
array([[-1.5, -1. , 2. ]])
>>> max_abs_scaler.scale_
array([ 2., 1., 2.])
在 scale
模塊中進一步提供了方便的功能。當你不想創建對象時,可以使用如 minmax_scale
以及 maxabs_scale
。
4.3.1.2. 縮放稀疏(矩陣)數據
中心化稀疏(矩陣)數據會破壞數據的稀疏結構,因此很少有一個比較明智的實現方式。但是縮放稀疏輸入是有意義的,尤其是當幾個特徵在不同的量級範圍時。
MaxAbsScaler
以及 maxabs_scale
是專爲縮放數據而設計的,並且是縮放數據的推薦方法。但是, scale
和 StandardScaler
也能夠接受 scipy.sparse
作爲輸入,只要參數 with_mean=False
被準確傳入它的構造器。否則會出現 ValueError
的錯誤,因爲默認的中心化會破壞稀疏性,並且經常會因爲分配過多的內存而使執行崩潰。 RobustScaler
不能適應稀疏輸入,但你可以在稀疏輸入使用 transform
方法。
注意,縮放器同時接受壓縮的稀疏行和稀疏列(參見 scipy.sparse.csr_matrix
以及 scipy.sparse.csc_matrix
)。任何其他稀疏輸入將會 轉化爲壓縮稀疏行表示 。爲了避免不必要的內存複製,建議在上游(早期)選擇CSR或CSC表示。
最後,最後,如果已經中心化的數據並不是很大,使用 toarray
方法將輸入的稀疏矩陣顯式轉換爲數組是另一種選擇。
4.3.1.3. 縮放有離羣值的數據
如果你的數據包含許多異常值,使用均值和方差縮放可能並不是一個很好的選擇。這種情況下,你可以使用 robust_scale
以及 RobustScaler
作爲替代品。它們對你的數據的中心和範圍使用更有魯棒性的估計。
參考:
更多關於中心化和縮放數據的重要性討論在此FAQ中提及: Should I normalize/standardize/rescale the data?
Scaling vs Whitening 有時候獨立地中心化和縮放數據是不夠的,因爲下游的機器學習模型能夠對特徵之間的線性依賴做出一些假設(這對模型的學習過程來說是不利的)。
要解決這個問題,你可以使用 sklearn.decomposition.PCA
或 sklearn.decomposition.RandomizedPCA
並指定參數 whiten=True
來更多移除特徵間的線性關聯。
在迴歸中縮放目標變量
scale
以及 StandardScaler
可以直接處理一維數組。在迴歸中,縮放目標/相應變量時非常有用。
4.3.1.4. 核矩陣的中心化
如果你有一個核矩陣 ,它計算由函數 定義的特徵空間的點積,那麼一個 KernelCenterer
類能夠轉化這個核矩陣,通過移除特徵空間的平均值,使它包含由函數 定義的內部產物。
4.3.2. 非線性轉換
類似於縮放, QuantileTransformer
類將每個特徵縮放在同樣的範圍或分佈情況下。但是,通過執行一個秩轉換能夠使異常的分佈平滑化,並且能夠比縮放更少地受到離羣值的影響。但是它的確使特徵間及特徵內的關聯和距離失真了。
QuantileTransformer
類以及 quantile_transform
函數提供了一個基於分位數函數的無參數轉換,將數據映射到了零到一的均勻分佈上:
>>> from sklearn.datasets import load_iris
>>> from sklearn.model_selection import train_test_split
>>> iris = load_iris()
>>> X, y = iris.data, iris.target
>>> X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
>>> quantile_transformer = preprocessing.QuantileTransformer(random_state=0)
>>> X_train_trans = quantile_transformer.fit_transform(X_train)
>>> X_test_trans = quantile_transformer.transform(X_test)
>>> np.percentile(X_train[:, 0], [0, 25, 50, 75, 100])
array([ 4.3, 5.1, 5.8, 6.5, 7.9])
這個特徵是萼片的釐米單位的長度。一旦應用分位數轉換,這些元素就接近於之前定義的百分位數:
>>> np.percentile(X_train_trans[:, 0], [0, 25, 50, 75, 100])
...
array([ 0.00... , 0.24..., 0.49..., 0.73..., 0.99... ])
這可以在具有類似形式的獨立測試集上確認:
>>> np.percentile(X_test[:, 0], [0, 25, 50, 75, 100])
...
array([ 4.4 , 5.125, 5.75 , 6.175, 7.3 ])
>>> np.percentile(X_test_trans[:, 0], [0, 25, 50, 75, 100])
...
array([ 0.01..., 0.25..., 0.46..., 0.60... , 0.94...])
也可以通過設置 output_distribution='normal'
將轉換後的數據映射到正態分佈:
>>> quantile_transformer = preprocessing.QuantileTransformer(
... output_distribution='normal', random_state=0)
>>> X_trans = quantile_transformer.fit_transform(X)
>>> quantile_transformer.quantiles_
array([[ 4.3..., 2..., 1..., 0.1...],
[ 4.31..., 2.02..., 1.01..., 0.1...],
[ 4.32..., 2.05..., 1.02..., 0.1...],
...,
[ 7.84..., 4.34..., 6.84..., 2.5...],
[ 7.87..., 4.37..., 6.87..., 2.5...],
[ 7.9..., 4.4..., 6.9..., 2.5...]])
這樣,輸入的中值稱爲輸出的平均值,並且以0爲中心。正常輸出被剪切,使得輸入的最小和最大值分別對應於1e-7和1-1e-7分位數——在變換下不會變得無限大。
4.3.3. 歸一化
歸一化 是 縮放單個樣本以具有單位範數 的過程。如果你計劃使用二次形式(如點積或任何其他核函數)來量化任何樣本間的相似度,則此過程將非常有用。
這個觀點基於 向量空間模型(Vector Space Model) ,經常在文本分類和內容聚類中使用.
函數 normalize
提供了一個快速簡單的方法在類似數組的數據集上執行操作,使用 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...]])
preprocessing
預處理模塊提供的 Normalizer
工具類使用 Transformer
API
實現了相同的操作(即使在這種情況下, fit
方法是無用的:該類是無狀態的,因爲該操作獨立對待樣本).
因此這個類適用於 sklearn.pipeline.Pipeline
的早期步驟:
>>> 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. ...]])
稀疏(數據)輸入
函數 normalize
以及類 Normalizer
接收 來自scipy.sparse的密集類數組數據和稀疏矩陣 作爲輸入。
對於稀疏輸入,在被提交給高效Cython例程前,數據被 轉化爲壓縮的稀疏行形式 (參見 scipy.sparse.csr_matrix
)。爲了避免不必要的內存複製,推薦在上游選擇CSR表示。
4.3.4. 二值化
4.3.4.1. 特徵二值化
特徵二值化 是 將數值特徵用閾值過濾得到布爾值 的過程。這對於下游的概率型模型是有用的,它們假設輸入數據是多值 伯努利分佈(Bernoulli
distribution) 。例如這個例子 sklearn.neural_network.BernoulliRBM
。
即使歸一化計數(又名術語頻率)和TF-IDF值特徵在實踐中表現稍好一些,文本處理團隊也常常使用二值化特徵值(這可能會簡化概率估計)。
相比於 Normalizer
,實用程序類 Binarizer
也被用於 sklearn.pipeline.Pipeline
的早期步驟中。因爲每個樣本被當做是獨立於其他樣本的,所以 fit
方法是無用的:
>>> 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.]])
也可以爲二值化器賦一個閾值:
>>> binarizer = preprocessing.Binarizer(threshold=1.1)
>>> binarizer.transform(X)
array([[ 0., 0., 1.],
[ 1., 0., 0.],
[ 0., 0., 0.]])
相比於 StandardScaler
和 Normalizer
類的情況,預處理模塊提供了一個相似的函數 binarize
,以便不需要轉換接口時使用。
4.3.5. 分類特徵編碼
在機器學習中,特徵經常不是數值型的而是分類型的。舉個例子,一個人可能有 ["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的估計器中直接使用,因爲這樣的連續輸入,估計器會認爲類別之間是有序的,但實際卻是無序的。(例如:瀏覽器的類別數據則是任意排序的)
一種將分類特徵轉換爲能夠被scikit-learn中模型使用的編碼是one-of-K或one-hot編碼,在 OneHotEncoder
中實現。這個類使用 m
個可能值轉換爲 m
值化特徵,將分類特徵的每個元素轉化爲一個值。
考慮如下例子:
>>> 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.]])
默認情況下,每個特徵使用幾維的數值由數據集自動推斷。當然,你也可以通過使用參數``n_values``來精確指定。 在我們的例子數據集中,有兩個可能得性別類別,三個洲,四個網絡瀏覽器。接着,我們訓練編碼算法,並用來對一個樣本數據進行轉換。 在結果中,前兩個數值是性別編碼,緊接着的三個數值是洲編碼,最後的四個數值是瀏覽器編碼
注意,如果訓練集中有丟失的分類特徵值,必須顯式地設置 n_values
,舉個例子,
>>> enc = preprocessing.OneHotEncoder(n_values=[2, 3, 4])
>>> # 注意到第二、三個特徵是不全的
>>> # features
>>> enc.fit([[1, 2, 3], [0, 2, 0]])
OneHotEncoder(categorical_features='all', dtype=<... 'numpy.float64'>,
handle_unknown='error', n_values=[2, 3, 4], sparse=True)
>>> enc.transform([[1, 0, 0]]).toarray()
array([[ 0., 1., 1., 0., 0., 1., 0., 0., 0.]])
參見 從字典類型加載特徵 ,它對於分類特徵代表一個dict,而不是整數。
4.3.6. 缺失值插補
因爲各種各樣的原因,真實世界中的許多數據集都包含缺失數據,這類數據經常被編碼成空格、NaNs,或者是其他的佔位符。但是這樣的數據集並不能scikit-learn學習算法兼容,因爲大多的學習算法都默認假設數組中的元素都是數值,因而所有的元素都有自己的意義。 使用不完整的數據集的一個基本策略就是捨棄掉整行或整列包含缺失值的數據。但是這樣就付出了捨棄可能有價值數據(即使是不完整的 )的代價。 處理缺失數值的一個更好的策略就是從已有的數據推斷出缺失的數值。
Imputer
類提供了估算缺失值的基本策略,使用缺失值所在的行/列中的平均值、中位數或者衆數來填充。這個類也支持不同的缺失值編碼。
以下代碼段演示瞭如何使用包含缺失值的列(軸0)的平均值來替換編碼爲 np.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. ]]
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)
Imputer(axis=0, copy=True, missing_values=0, strategy='mean', verbose=0)
>>> X_test = sp.csc_matrix([[0, 2], [6, 0], [7, 6]])
>>> print(imp.transform(X_test))
[[ 4. 2. ]
[ 6. 3.666...]
[ 7. 6. ]]
注意,缺失值被編碼爲0,因此隱式地存儲在矩陣中。當缺失值比可觀察到的值多的時候,這種格式是合適的。
Imputer
可以在
Pipeline 中用作構建支持插補的合成模型。參見 Imputing
missing values before building an estimator 。
4.3.7. 生成多項式特徵
在機器學習中,通過增加一些輸入數據的非線性特徵來增加模型的複雜度通常是有效的。一個簡單通用的辦法是使用多項式特徵,這可以獲得特徵的更高維度和互相間關係的項。這在 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.]])
X 的特徵已經從 轉換爲 。
在一些情況下,只需要特徵間的交互項,這可以通過設置 interaction_only=True
來得到:
>>> X = np.arange(9).reshape(3, 3)
>>> X
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])
>>> poly = PolynomialFeatures(degree=3, interaction_only=True)
>>> poly.fit_transform(X)
array([[ 1., 0., 1., 2., 0., 0., 2., 0.],
[ 1., 3., 4., 5., 12., 15., 20., 60.],
[ 1., 6., 7., 8., 42., 48., 56., 336.]])
X的特徵已經從 轉換爲 。
注意,當使用多項的 :ref:`svm_kernels`時
,多項式特徵被隱式地使用在 `核函數(kernel methods) <https://en.wikipedia.org/wiki/Kernel_method>`_ 中(比如, sklearn.svm.SVC
, sklearn.decomposition.KernelPCA
)。
創建並使用多項式特徵的嶺迴歸實例請見 Polynomial interpolation 。
4.3.8. 自定義轉換器
在機器學習中,想要將一個已有的 Python 函數轉化爲一個轉換器來協助數據清理或處理。可以使用 FunctionTransformer
從任意函數中實現一個轉換器。例如,在一個管道中構建一個實現日誌轉換的轉化器,這樣做:
>>> import numpy as np
>>> from sklearn.preprocessing import FunctionTransformer
>>> transformer = FunctionTransformer(np.log1p)
>>> X = np.array([[0, 1], [2, 3]])
>>> transformer.transform(X)
array([[ 0. , 0.69314718],
[ 1.09861229, 1.38629436]])
使用一個 FunctionTransformer
類來做定製化特徵選擇的例子,請見 Using
FunctionTransformer to select columns 。
中文文檔: http://sklearn.apachecn.org/cn/stable/modules/preprocessing.html
英文文檔: http://sklearn.apachecn.org/en/stable/modules/preprocessing.html
官方文檔: http://scikit-learn.org/stable/
GitHub: https://github.com/apachecn/scikit-learn-doc-zh(覺得不錯麻煩給個 Star,我們一直在努力)
貢獻者: https://github.com/apachecn/scikit-learn-doc-zh#貢獻者
關於我們: http://www.apachecn.org/organization/209.html
有興趣的們也可以和我們一起來維護,持續更新中 。。。
機器學習交流羣: 629470233