1. 程式人生 > >機器學習歸一化

機器學習歸一化

轉自https://www.cnblogs.com/volcao/p/9089716.html

資料歸一化(Feature Scaling)

一、為什麼要進行資料歸一化

  • 原則:樣本的所有特徵,在特徵空間中,對樣本的距離產生的影響是同級的;
  • 問題:特徵數字化後,由於取值大小不同,造成特徵空間中樣本點的距離會被個別特徵值所主導,而受其它特徵的影響比較小;
  • 例:特徵1 = [1, 3, 2, 6, 5, 7, 9],特徵2 = [1000, 3000, 5000, 2000, 4000, 8000, 3000],計算兩個樣本在特徵空間的距離時,主要被特徵2所決定;
  • 定義:將所有的資料對映到同一個尺度中;
  • 歸一化的過程,是演算法的一部分;

 

二、資料歸一化的方法

 1)最值歸一化(normalization)

  1、思路:把所有資料對映到0~1之間;

  2、公式:

   

   # x為資料集中每一種特徵的值;

   # 將資料集中的每一種特徵都做對映;

  3、特點:多適用於分佈有明顯邊界的情況;如考試成績、人的身高、顏色的分佈等,都有範圍;而不是些沒有範圍約定,或者範圍非常大的資料;

   # 明顯邊界:同一特徵的資料大小相差不大;不會出現大部分資料在0~200之間,有個別數據在100000左右;

  4、缺點:受outlier影響較大;

 

 2)均值方差歸一化(standardization)

  1、思路:把所有資料歸一到均值為0方差為1的分佈中;

  2、公式:

   

   # Xmean:特徵的均值(均值就是平均值);

   # S:特徵值的方差;

   # X:每一個特徵值;

   # Xscale:歸一化後的特徵值;

  3、特點1:使用於資料分佈沒有明顯的邊界;(有可能存在極端的資料值)

   # 歸一化後,資料集中的每一種特徵的均值為0,方差為1;

  4、優點(相對於最值歸一化):即使原資料集中有極端值,歸一化有的資料集,依然滿足均值為0方差為1,不會形成一個有偏的資料;

 

三、訓練資料集的歸一化

  1)最值歸一化:

複製程式碼

import numpy as np

# 對一維向量做歸一化
x = np.random.randint(0, 100, size = 100)
x = np.array(x, dtype=float)
x = (x - np.min(x)) / (np.max(x) - np.min(x))


# 對二維矩陣做歸一化
X = np.random.randint(0, 100, (50, 2))
X = np.array(X, dtype=float)
# 分別對每一列進行最值歸一化,方式與向量做最值歸一化一樣

複製程式碼

 

 2)均值方差歸一化:

複製程式碼

import numpy as np

X2 = np.random.randint(0, 100, (50, 2))
X2 = np.array(X2, dtype=float)
X2[:,0] = (X2[:,0] - np.mean(X2[:,0])) / np.std(X2[:,0])
X2[:,1] = (X2[:,1] - np.mean(X2[:,1])) / np.std(X2[:,1])

複製程式碼

  # np.mean(array):求向量的平均值;

  # np.std(array):求向量的方差;

 

四、測試資料集的歸一化

 1)問題

  • 訓練資料集歸一化,用於訓練模型,測試資料集如何歸一化?

 2)方案

  • 不能直接對測試資料集按公式進行歸一化,而是要使用訓練資料集的均值和方差對測試資料集歸一化;

 3)原因

  • 原因1:真實的環境中,資料會源源不斷輸出進模型,無法求取均值和方差的;
  • 原因2:訓練資料集是模擬真實環境中的資料,不能直接使用自身的均值和方差;
  • 原因3:真實環境中,無法對單個數據進行歸一化;

  # 對資料的歸一化也是演算法的一部分;

 4)方式

  • (X_test - mean_train) / std_train
  1. X_test:測試資料集;
  2. mean_train:訓練資料集的均值;
  3. std_train:訓練資料集的方差;

 

 

五、使用scikit-learn中的Scaler類

 1)呼叫的步驟

  • scikit-learn中將訓練資料集的均值和方差封裝在了類Scalar中;

  1. fit:根據訓練資料集獲取均值和方差,scikit-learn中返回一個Scalar物件;
  2. transform:對訓練資料集、測試資料集進行歸一化;

 

複製程式碼

import numpy as np
from sklearn import datasets

iris = datasets.load_iris()
X = iris.data
y = iris.target

# 1)歸一化前,將原始資料分割
from ALG.train_test_split import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, seed = 666)

# 2)匯入均值方差歸一化模組:StandardScaler
from sklearn.preprocessing import StandardScaler

# 例項化,不需要傳入引數
standardScaler = StandardScaler()

# 3)fit過程:返回StandardScaler物件,物件內包含訓練資料集的均值和方差
# fit過程,傳入訓練資料集;
standardScaler.fit(X_train)
# 輸出:StandardScaler(copy=True, with_mean=True, with_std=True)

# fit後可通過standardScaler檢視均值和方差
# standardScaler.mean_:檢視均值
# standardScaler.scale_:檢視方差

# 4)transform:對訓練資料集和測試資料集進行歸一化,分別傳入對應的資料集
# 歸一化並沒有改變訓練資料集,而是又生成一個新的矩陣,除非將新生成的資料集賦給原資料集,一般不改變原資料
X_train_standard = standardScaler.transform(X_train)
X_test_standard = standardScaler.transform(X_test)

# 接下來就是使用歸一化後的資料集訓練並測試模型

複製程式碼

 

 3)注意

  1. 步驟:資料分割——匯入並例項化歸一化模組——fit(得到均值和方差)——transform(得到歸一化後的資料集);
  2. 例項化StandardScaler()時,不需要傳入引數;
  3. 歸一化並沒有改變資料集,而是又生成一個新的矩陣,一般不要改變原資料;

 

 4)實現scikit-learn的StandardScaler類中的內部邏輯

import numpy as np

class StandardScaler:

    def __init__(self):
        self.mean_ = None
        self.scale_ = None

    def fit(self, X):
        """根據訓練資料集獲取均值和方差"""
        assert X.ndim == 2,"the dimension of X must be 2"
        self.mean_ = np.array([np.mean(X[:,i]) for i in range(0,X.shape[1])])
        self.scale_ = np.array([np.std(X[:,i]) for i in range(0,X.shape[1])])

        return self

    def transform(self, X):
        """將X根據這個StandardScaler進行均值方差歸一化處理"""
        assert X_train.ndim == 2, "the dimension of X_train must be 2"
        assert self.mean_ is not None and self.scale_ is not None,\
            "must fit before transform"
        assert X.shape[1] == len(self.mean_),\
            "the feature number of X must be equal to mean_ and std_"

        reasX = np.empty(shape=X.shape, dtype=float)
        for col in range(X.shape[1]):
            resX[:,col] = (X[:,col] - self.mean_[col]) / self.scale_[col]

        return resX