1. 程式人生 > >數據預處理之標準化

數據預處理之標準化

select 有意 rand 附近 繼續 行數 sts 分享圖片 border

數據的標準化(Standardization)和歸一化(Normalization)有什麽區別?

關於數據的標準化和歸一化區別的說法有點亂。總的來說有這麽幾種分法

1:不做區分,都意味著標準化。

2:大部分說法是這樣的:歸一化是這麽一個過程$x’ = \frac{x-x_{min}}{x_{max}-x_{min}}$

而標準化是這麽一個過程: $x’ = \frac{x-\mu}{\delta} \ \mu為數據的均值 \ \delta為方差$

3:sklearn當中preprocessing中方法是這樣進行劃分的:這裏的標準化包含了$\frac{x-x_{min}}{x_{max}-x_{min}}$和$\frac{x-\mu}{\delta}$ 。歸一化則代表把一個樣本(而不是特征)的數據進行範數歸一化。

我們本篇文章采用第三種分發,而把本文當中所有對數據進行的操作都叫做縮放(scale)。

為什麽要進行數據的縮放

消除數據的量綱,這個過程叫做無量綱化。

無量綱化:我們的數據一般都是有單位的,比如身高的單位有m,cm,這個無量綱化並不是說把m變成cm,而是說,無論是m還是cm,最後都會變成1,也就是沒有了單位。比如 當前身高的單位為cm,經過這個式子的處理:$x’ = \frac{x-x_{最小身高}}{x_{最大身高}-x_{最小身高}}$ 變成了一個沒有單位的數字。

當兩個特征的量級差別很大的時候,這樣的操作是有意義的,假如你有身高和體重兩個個特征。身高的單位是m,它的取值經常是這樣的值:1.65,1,70,1.67等,而體重的單都位是kg,它經常取這樣的值:53,68,73等,我們可以看到體重的值要遠遠大於身高的值,它們已經不是一個量級了。進行數據的縮放可以避免我們的結果由取值較大的特征決定。

加快模型的收斂速度

技術分享圖片

在上圖當中,右上角表示在沒有進行縮放以前模型的收斂情況,左邊表示在進行縮放以後模型收斂的情況。在SVM、線性回歸還有PCA當中經常用到。

標準化 Standardization

數據的標準化Standardization,也叫作(去中心化+方差縮放),通過把一組數據的均值變為0,方差變為1實現數據的縮放。數據的標準化是我們對數據的進行縮放的時候最容易想到的操作,也是最常用到的操作。它也叫z-score方法。

自己寫一個公式來進行標準化:

def my_scale(data):
    mean = sum(data) / len(data)  #先求均值
    variance 
= ( sum([ (I-mean) ** 2 for I in data]) ) / len(data) #再求方差 normal = [(I - mean) / (variance ) ** 0.5 for I in data] #按照公式標準化 return normal

使用scale方法進行標準化

from sklearn import preprocessing
import jumpy as np
X_train = np.array([[ 1., -1.,  2.],
                    [ 2.,  0.,  0.],
                    [ 0.,  1., -1.]])

X_scaled = preprocessing.scale(X_train)
print(X_scaled)

輸出的結果為:

[[ 0.         -1.22474487  1.33630621]
 [ 1.22474487  0.         -0.26726124]
 [-1.22474487  1.22474487 -1.06904497]]

使用StandardScaler方法進行標準化

StandarScaler方法能夠允許我們進行fit,從而保存我們的模型,然後進行transform轉換

from sklearn import preprocessing

scaler = preprocessing.StandardScaler().fit(X_train)
print(scaler.transform(X_train))

輸出同樣的結果。

將結果縮放到一個區間內

MaxMinScaler方法

MaxMinScaler是將數值縮放到[0,1]區間內,使用的公式是$\frac{x-x_{min}}{x_{max}-x_{min}}$

使用這個縮放的情況包括:增強極小方差的值還有保留稀疏樣本中的零值。也叫作最大最小標準化,[0,1]標準化。

import numpy as np
from sklearn import preprocessing

X_train = np.array([[ 1., -1.,  2.],
                    [ 2.,  0.,  0.],
                    [ 0.,  1., -1.]])

min_max_sacler = preprocessing.MinMaxScaler()
min_max_sacler.fit(X_train)

print(min_max_sacler.transform(X_train))

輸出的結果為:

[[0.5        0.         1.        ]
 [1.         0.5        0.33333333]
 [0.         1.         0.        ]]

MaxAbsScaler方法

MaxAbsScaler將值縮放到[-1,1]區間內,$\frac{x}{max\{|x|\}}$ 也就是將x除以那個最大的絕對值。這種情況適合在均值在0附近的值,或者稀疏矩陣。

import numpy as np
from sklearn import preprocessing

X_train = np.array([[ -4., -2.,  2.],
                    [ -5.,  0.,  0.],
                    [ 0.,  1., 6.],
                    [10,   2,  3]])

max_abs_sacler = preprocessing.MaxAbsScaler()
max_abs_sacler.fit(X_train)

print(max_abs_sacler.transform(X_train))

輸出結果如下:(第一列除以10,第二列除以4,第三列除以6)

[[-0.4        -1.          0.33333333]
 [-0.5         0.          0.        ]
 [ 0.          0.25        1.        ]
 [ 1.          0.5         0.5       ]]

特殊數據縮放:

縮放稀疏數據: 使用MaxAbsScaler可以進行稀疏數據的縮放,

縮放異常點較多的數據: 使用robust_scale 或者RobustScaler

非線性轉換 -- 分位數轉換:

這裏主要介紹QuantileTrasformer,和前面提到的縮放一樣,分位數轉換的目的也是把特征數據轉換到一定的範圍內,或者讓他們符合一定的分布。分位數轉換利用的是數據的分位數信息進行變換。它能夠平滑那些異常分布,對於存在異常點的數據也很適合。但是它會破話原來數據的相關性和距離信息。

preprocessing的QantitleTransformer可以進行分位數轉換

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn import preprocessing
import numpy as np
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.fit_transform(X_test)
#查看分位數信息,經過轉換以後,分位數的信息基本不變
print(np.percentile(X_train[:, 0], [0, 25, 50, 75, 100]))
print(np.percentile(X_train_trans[:, 0], [0, 25, 50, 75, 100]))

輸出結果如下:

[4.3 5.1 5.8 6.5 7.9]
[9.99999998e-08 2.38738739e-01 5.09009009e-01 7.43243243e-01
 9.99999900e-01]

至於具體的運算規則:猜測可能涉及到分位數回歸的知識,這裏就沒有繼續探索。

歸一化 Normalization

需要說明是,這裏的歸一化不是對一列的特征進行操作,而是對一行的樣本(記錄)進行操作。歸一化適用於這樣的場景:需要使用點積,或者有的模型需要對樣本的相似性進行度量。

preprocessing中的normalize方法提供了這樣的操作,這個方法有個參數叫做norm,取值可以為 ‘l1’,’l2’,’max’,取不同的值,使用不同的方式進行歸一化。當取值為’l1‘的時候,運用l1範數進行歸一化,計算的方法是 $x’ = \frac{x}{\sum_{i=1}^{n}|x_i|}$ 運用l2範數進行歸一化的時候,計算方法是這樣的:$x’ = \frac{x}{\sqrt{\sum_{i=1}^{n}x_i^2}}$我們來用代碼來看一下:

from sklearn import preprocessing


X = [[ 1., -1.,  2.],
     [ 2.,  0.,  0.],
     [ 0.,  1., -1.],
     [ 3.,  4., 5.]]

X1_normalized = preprocessing.normalize(X, norm=l1)
X2_normalized = preprocessing.normalize(X, norm=l2)

print(X1_normalized)
print(X2_normalized)

輸出結果如下:

[[ 0.25       -0.25        0.5       ]
 [ 1.          0.          0.        ]
 [ 0.          0.5        -0.5       ]
 [ 0.25        0.33333333  0.41666667]]
[[ 0.40824829 -0.40824829  0.81649658]
 [ 1.          0.          0.        ]
 [ 0.          0.70710678 -0.70710678]
 [ 0.42426407  0.56568542  0.70710678]]

另外preproceing 的Normalizer也提供了標準化的方法,可以進行fit和transform操作。

數據預處理之標準化