Python sklearn學習之數據預處理——標準化

Python sklearn學習之數據預處理——標準化

1. 數據集常見標準化方式

  • min-max標準化(Min-Max-normalization)

    • 也叫離差標準化(歸一化),本質是對原始數據進行線性變換,使結果落到[0,1]之間
    • 變換本質:

    (XXmin)(XmaxXmin) (X-X_{min})\over(X_{max}-X_{min})

    • 結果:變換後結果落在[0,1]之間,且無量綱
    • 優點:實現特徵極小方差的魯棒性(即穩定性)以及在稀疏矩陣中保留零元素
    • 缺點:當有新數據加入時,可能導致max和min的變化,需要重新定義

此處量綱簡單理解,由於數據的不同單位出現的不同表現力,即單位

  • z-score 標準化(zero-mean-normalization)

    • 標準差標準化
    • 變換本質:

    (XXmean)(Xstd) (X-X_{mean})\over(X_{std})

    • 結果:變換後每個特徵的均值爲0,標準差爲1
    • 適用範圍:數據集最大值和最小值未知,或存在超出取值範圍的離羣數據的情況

2. 數據標準化實現

2.1 z-score 標準化(zero-mean-normalization)

2.1.1 StandardScaler類
  • 類定義
def __init__(self, copy=True, with_mean=True, with_std=True)
  • 參數說明
    • copy :一個可選的boolean類型值參數,默認爲True,
      • True:不修改原數據,而是在原數據的一份拷貝中進行處理,並返回這份拷貝
      • False:用計算處理後的值替換原數據,並進行淺拷貝,即地址引用,但如果被標準化的數據不是np.array或scipy.sparse CSR matrix, 原來的數據還是被copy而不是被替代
    • with_mean :接受boolean型值True和False,默認爲True,表示將數據均值規範到0,但是在處理稀疏矩陣或者 CSC matrices 一定要設置False不然會超內存
    • with_std :接受boolean型值True和False,默認爲True,表示將數據方差規範到1
  • 常見屬性說明
    • scale_: 縮放比例,同時也是標準差
    • mean_: 每個特徵的平均值
    • var_: 每個特徵的方差
    • n_sample_seen_: 樣本數量,可以通過 patial_fit 增加
  • 類主要包含三個方法
    • fit() :計算用於以後縮放的均值和標準差
    • transform() :標準化數據
    • fit_transform() :先計算用於以後縮放的均值和標準差,再標準化
X_scaled = preprocessing.StandardScaler().fit_transform(X_train)
X_scaled = preprocessing.StandardScaler().fit(X_train).transform(X_train)

以上兩句代碼是等價的,其目的都是首先構造一個數據標準化轉換器,之後用需要標準化的數據訓練轉換器以擬合數據,最後實現標準化。

在函數 fit_transform 中,其實調用的是就是fit(X_train).transform(X_train)

if y is None:
	# fit method of arity 1 (unsupervised transformation)
	return self.fit(X, **fit_params).transform(X)
else:	
    # fit method of arity 2 (supervised transformation)
	return self.fit(X, y, **fit_params).transform(X)
  • 其他函數
    • get_params(deep=True): 返回StandardScaler對象的設置參數,即StandardScaler類構造函數中設置的參數
    • **inverse_transform(X,copy=None):**按照縮放規律反向還原當前數據
    • partial_fit(X, y=None): 函數fit() 的實際實現函數,計算平均值和標準差。適合X作爲連續的數據流輸入
  • 實例展示
X_scaled = preprocessing.StandardScaler().fit(X_train).transform(X_train)
X_scaled
array([[ 0.        , -1.22474487,  1.33630621],
       [ 1.22474487,  0.        , -0.26726124],
       [-1.22474487,  1.22474487, -1.06904497]])

X_scaled = preprocessing.StandardScaler().fit_transform(X_train)
X_scaled
array([[ 0.        , -1.22474487,  1.33630621],
       [ 1.22474487,  0.        , -0.26726124],
       [-1.22474487,  1.22474487, -1.06904497]])
  • 原理分析

構造StandardScaler對象的實際意義在於它首先通過執行轉換器的API計算測試集數據的均值和標準差,之後便可用該構造器對測試集數據進行轉換。

scaler = preprocessing.StandardScaler().fit(X_train)  # 用訓練集數據訓練scaler
X_scaled = scaler.transform(X_train)   # 用其轉換訓練集是理所當然的
X_scaled
array([[ 0.        , -1.22474487,  1.33630621],
       [ 1.22474487,  0.        , -0.26726124],
       [-1.22474487,  1.22474487, -1.06904497]])

然而實際上,用訓練好的轉換器去轉換測試集數據也是可以的

# scaler.mean_ = [1.        , 0.        , 0.33333333]
# scaler.scale_ = [0.81649658, 0.81649658, 1.24721913]
X_test = [[-1., 1., 0.]]
X_test_scaled = scaler.transform(X_test)
# [-2.44948974,  1.22474487, -0.26726124]]

上述 X_test_scaledscaler 利用前面測試集的數據得到的均值與標準差完成對測試集數據的標準化,可見它只是簡單的對每個特徵進行計算。

2.1.2 preprocessing.scale 函數
  • 函數定義
def scale(X, axis=0, with_mean=True, with_std=True, copy=True)
  • 參數說明
    • X :需要標準化的數組(矩陣)
    • axis :接受int型值0和1,默認爲0
      • 0:對列進行標準化處理
      • 1:對行進行標準化處理
    • with_mean :接受boolean型值True和False,默認爲True,表示將數據均值規範到0
    • with_std :接受boolean型值True和False,默認爲True,表示將數據方差規範到1
    • copy :一個可選的boolean類型值參數,默認爲True,
      • True:不修改原數據,而是在原數據的一份拷貝中進行處理,並返回這份拷貝
      • False:用計算處理後的值替換原數據,並進行淺拷貝,即地址引用
  • 實例展示
X_train = np.array([[1., -1.,  2.],
                    [2.,  0.,  0.],
                    [0.,  1., -1.]])
x_scale = preprocessing.scale(X_train)
out:
    x_scale
    array([[ 0.        , -1.22474487,  1.33630621],
       [ 1.22474487,  0.        , -0.26726124],
       [-1.22474487,  1.22474487, -1.06904497]])
    # 均值
    x_scaled.mean(axis=0)
	array([ 0.,  0.,  0.])
    # 標準差
    x_scaled.std(axis=0)
	array([ 1.,  1.,  1.])
  • 原理分析

可見數據已經縮放爲標準化,其特徵均值爲0,標準差爲1,該函數的實現方式是對每個特徵,即每一列按如下公式計算:
(XXmean)(Xstd) (X-X_{mean})\over(X_{std})

2.2 min-max標準化(Min-Max-normalization)

2.2.1 MinMaxScaler類
  • 類定義
def __init__(self, feature_range=(0, 1), copy=True)
  • 參數說明

    • feature_range : 特徵範圍,指定標準化後的數據需要落在的範圍,默認設定爲[0,1]

      • 限制:feature_range參數的兩個值分別表示最小值與最大值,其中,最小值一定要小於最大值,不然會拋出 ValueError 錯誤,這個錯誤在執行partial_fit 函數時纔會報錯,partial_fit 函數是 fit 函數的具體實現
      if feature_range[0] >= feature_range[1]:
      	raise ValueError("Minimum of desired feature range must be smaller"
                           " than maximum. Got %s." % str(feature_range))
      
    • copy :一個可選的boolean類型值參數,默認爲True,

      • True:不修改原數據,而是在原數據的一份拷貝中進行處理,並返回這份拷貝
      • False:用計算處理後的值替換原數據,並進行淺拷貝,即地址引用
  • 常見屬性說明

    • data_min_ :每個特徵(列)中的最小值
    • data_max_ :每個特徵(列)中最大值
    • data_range_ :每個特徵(列)中最大值與最小值之差
    • scale_ :期望數據範圍與數據特徵(列)中實際極差之間的比值,含義是每列特徵相對縮放量,計算公式爲 (max-min)/(data_max_ - data_min_)
    • min_ : 期望數據最小值與數據特徵(列)中實際最小值乘相對縮放量之間的差,含義是每列特徵相對最小縮放值,計算公式爲 min-data_min_*scale_
  • 類主要函數

    • fit() :計算用於以後縮放的最大值與最小值
    • transform() :標準化數據
    • fit_transform() :先計算用於以後縮放的最大值與最小值,再標準化
min_max_scaled = preprocessing.MinMaxScaler().fit_transform(X_train)
min_max_scaled = preprocessing.MinMaxScaler().fit(X_train).transform(X_train)

以上兩句代碼是等價的,其目的都是首先構造一個數據標準化轉換器,之後用需要標準化的數據訓練轉換器以擬合數據,最後實現標準化。

  • 其他函數
    • get_params(deep=True): 返回MinMaxScaler對象的設置參數,即MinMaxScaler類構造函數中設置的參數
    • partial_fit(X, y=None): 函數fit() 的實際實現函數,計算用於以後縮放的最大值與最小值。適合X作爲連續的數據流輸入
    • **inverse_transform(X,copy=None):**按照縮放規律反向還原當前數據
  • 基本例子
X_train = np.array([[1., -1.,  2.],
                    [2.,  0.,  0.],
                    [0.,  1., -1.]])
min_max_scaled = preprocessing.MinMaxScaler().fit_transform(X_train)
min_max_scaled
array([[0.5       , 0.        , 1.        ],
       [1.        , 0.5       , 0.33333333],
       [0.        , 1.        , 0.        ]])
  • minmax_scale 函數

實際上,類似於 z-score 標準化,min-max 標準化也有單獨的一個簡單函數可以實現而不是必須構建 MinMaxScaler 類。minmax-scale 函數的參數與 MinMaxScaler 類的參數一致,實現功能也是一致。

實際上,不得不說的一點是,minmax-scale 函數本質上是構造 MinMaxScaler 對象並調用 fit_transform 函數

s = MinMaxScaler(feature_range=feature_range, copy=copy)
    if axis == 0:
        X = s.fit_transform(X)
    else:
        X = s.fit_transform(X.T).T
2.2.2 拓展

MaxAbsScaler 類的工作原理與MinMaxScaler十分相似,它的功能是將數據縮放到[-1,1]之間。但 preprocessing.MinMaxScaler(feature_range=(-1,1)).fit_transform(X_train)preprocessing.MaxAbsScaler().fit_transform(X_train) 所得到的結果並不一致

X_train
array([[ 1., -1.,  2.],
       [ 2.,  0.,  0.],
       [ 0.,  1., -1.]])
preprocessing.MaxAbsScaler().fit_transform(X_train)
array([[ 0.5, -1. ,  1. ],
       [ 1. ,  0. ,  0. ],
       [ 0. ,  1. , -0.5]])
preprocessing.MinMaxScaler(feature_range=(-1,1)).fit_transform(X_train)
array([[ 0.        , -1.        ,  1.        ],
       [ 1.        ,  0.        , -0.33333333],
       [-1.        ,  1.        , -1.        ]])

原因是MinMaxScaler 實際操作是將數據集中每個數據除以該列特徵中的最大值,以此實現最大絕對值縮放操作,並不是線性的。但 MinMaxScaler 卻是需要線性變換,其相對變換比例一致。

3. 其他方式的數據集預處理

3.1 稀疏矩陣數據的縮放

Tips:拓展

在矩陣中,若數值爲0的元素數目遠遠多於非0元素的數目,並且非0元素分佈沒有規律時,則稱該矩陣爲稀疏矩陣;

與之相反,若非0元素數目佔大多數時,則稱該矩陣爲稠密矩陣。

稠密度:非零元素的總數比上矩陣所有元素的總數

對稀疏矩陣數據的縮放,maxabs_scale 函數與 MaxAbsScaler 類均可實現,不過前提是,訓練數據應該是已經零中心化或者是稀疏數據。

Tips:數據中心化

使數據特徵轉換爲均值爲0的數據,稱之爲中心化。本質是將特徵中每個數據減去該特徵的均值

MaxAbsScaler 類以及 maxabs_scale 函數的功能十分簡單,將每個元素除以該列特徵中的最大值,因此它們的可選參數只有一個,不同的是,函數將原數據對象作爲參數,而在轉換器中,元數據是轉換器調用鏈的其中一個環節的參數。

copy :boolean類型,默認爲True,其含義即是否對原數據對象進行修改。

實際上,不得不說的一點是,maxabs_scale 函數本質上是構造 MaxAbsScaler 對象並調用 fit_transform 函數

s = MaxAbsScaler(copy=copy)
    if axis == 0:
        X = s.fit_transform(X)
    else:
        X = s.fit_transform(X.T).T

3.2 存在離羣值數據的縮放

Tips:拓展

離羣值:在數據中有一個或幾個數值與其他數值相比差異較大,定量描述則是,如果一個數值偏離觀測平均值的概率小於等於1/(2n),則該數據應當捨棄(其中n爲觀察例數,概率可以很據數據的分佈進行估計)

對存在離羣值數據的縮放,robust_scale 函數以及 RobustScaler 類均可實現

3.2.1 RobustScaler類
  • 函數定義
def __init__(self, with_centering=True, with_scaling=True,
                 quantile_range=(25.0, 75.0), copy=True):
  • 參數說明

    • with_centering :默認爲True

      • 本質:對數據居中,操作分兩步,首先計算列特徵中位數,之後將每個數據減去對應列中位數
      # 第一步,位於fit()函數
      if self.with_centering:
          self.center_ = np.nanmedian(X, axis=0)
      # 第二步,位於transform()函數
      if self.with_centering:
          X -= self.center_
      
      • 限制:在處理稀疏矩陣或者 CSC matrices 一定要設置False不然會超內存
      if self.with_centering:
          if sparse.issparse(X):
              raise ValueError(
                  "Cannot center sparse matrices: use `with_centering=False`"
                  " instead. See docstring for motivation and alternatives.")
      
    • with_scaling :默認爲True

      • 本質:將數據縮放到四分位數範圍,操作分三步,第一,計算列特徵在quantile_range 指定位置的百分位值;第二步,轉置百分位值矩陣並在列維度計算差值;第三步將差值爲0的數變爲1得到列特徵百分位值;第四步,將每個數據除以對應列中位數
      # 第一步,位於fit()函數
      for feature_idx in range(X.shape[1]):
      	quantiles.append(np.nanpercentile(column_data,self.quantile_range))
      # 第一步,位於fit()函數
      quantiles = np.transpose(quantiles)
      self.scale_ = quantiles[1] - quantiles[0]
      # 第三步,位於fit()函數
      self.scale_ = _handle_zeros_in_scale(self.scale_, copy=False)
      # 第四步,位於transform()函數
      if self.with_scaling:
          X /= self.scale_
      
    • quantile_range:指定百分位值的位置,一個二元數組,默認是[25.0,75.0]

    • copy :略(與前面相同)

  • 屬性說明

    • center_ :訓練集中每個特徵的中值
    • scale_ :訓練集中每個特徵的(縮放)四分位數範圍
  • 基本例子

X = [[1., -2.,  2.],
     [-2.,  1.,  3.],
     [4.,  1., -2.]]
transformer = RobustScaler().fit_transform(X)
transformer
array([[ 0. , -2. ,  0. ],
       [-1. ,  0. ,  0.4],
       [ 1. ,  0. , -1.6]])
  • 移除特徵間的線性關聯

通過使用sklearn.decomposition.PCA 並設定whiten=True 移除特徵間的線性關聯

  • robust_scale 函數

實現的功能與RobustScaler 類一樣的功能,robust_scale 函數本質上是構造 RobustScaler 對象並調用 fit_transform 函數

s = RobustScaler(with_centering=with_centering, with_scaling=with_scaling,
                     quantile_range=quantile_range, copy=copy)
    if axis == 0:
        X = s.fit_transform(X)
    else:
        X = s.fit_transform(X.T).T

3.3 核矩陣的中心化

  • 核函數:在低維輸入空間中通過某個函數就能得到等同於將輸入空間映射到高維特徵空間進行內積計算後的值,這個函數就稱爲核函數
  • 核矩陣:將N個樣本,每兩個樣本進行一次核函數影射得到的N*N維的矩陣,稱爲核矩陣

設K(x,z)是由phi(x)^ T phi(z)定義的核矩陣,其中phi是將x映射到希爾伯特空間的函數。

3.3.1 KernelCenterer類

KernelCenterer 類構造過程中不需要設定任何參數,只在 fit 過程中需要傳入核矩陣,之後進行轉換。實質上,KernelCenterer 中心化數據的過程就是將數據集轉換爲零均值的歸一化過程。但卻不明確地計算phi(x)。可以認爲它是使用sklearn.preprocessing.StandardScaler(with_std=False)phi(x) 居中。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章