【機器學習實戰】數據歸一化

 目錄:

一、介紹

二、最值歸一化

1.計算公式

2.Python實戰

三、均值方差歸一化

1.計算公式

2.Python實戰

四、歸一化要點

五、使用scikit-learn進行數據歸一化


一、介紹

爲什麼需要進行數據歸一化?

舉個簡單的例子,樣本1以[1, 200]輸入到模型中去的時候,由於200可能會直接忽略到1的存在。此時樣本間的距離由時間所主導。

此時,如果將天數轉換爲佔比1年的比例,200/365=0.5479, 100/365=0.2740。但也導致樣本間的距離又被腫瘤大小所主導。因此有必要進行數據歸一化處理。不然直接計算樣本間的距離是有一定偏差的

解決方案:

將所有的數據映射到統一尺度。

兩種數據歸一化的方法:

  • 最值歸一化(Normalization):把所有數據映射到0-1之間。適用於分佈有明顯邊界的情況;受outliner影響較大。
  • 均值方差歸一化(standardization):把所有數據歸一化到均值爲0方差爲1的分佈中。適用於數據分佈沒有明顯的邊界;有可能存在極端的數據值。

二、最值歸一化

1.計算公式

該方法實現對原始數據的等比例縮放,其中Xscale爲歸一化後的數據,X爲原始數據,Xmax、Xmin分別爲原始數據集的最大值和最小值。

2.Python實戰

# 導包
import numpy as np
import matplotlib.pyplot as plt

# 隨機生成0-100之間的100個數
x = np.random.randint(0, 100, size=100)
x

輸出結果:

array([10, 92, 55, 25, 67, 84, 64,  2,  5, 56, 32, 37, 69, 40, 24, 86, 65,
       29, 49, 93, 13, 80, 90, 70, 80, 63, 90, 95, 25, 50, 92, 37, 42, 16,
       83, 52, 36, 14, 73,  4, 53, 84, 34, 62, 59, 50, 46, 55, 72, 43, 39,
        1, 58,  6, 84, 64, 72, 70, 41, 30, 51, 62, 79, 14, 89, 20,  7, 37,
       44, 36, 40, 89, 70, 62,  6,  3, 74, 88, 36, 90,  0, 30, 20,  6,  0,
       67, 50,  4, 36, 28, 62, 91, 94, 96, 75, 22, 19, 56, 81, 28])
# 最值歸一化處理,把所有數據映射到0-1之間
(X - np.min(X)) / (np.max(X) - np.min(X))

輸出結果:

array([0.10416667, 0.95833333, 0.57291667, 0.26041667, 0.69791667,
       0.875     , 0.66666667, 0.02083333, 0.05208333, 0.58333333,
       0.33333333, 0.38541667, 0.71875   , 0.41666667, 0.25      ,
       0.89583333, 0.67708333, 0.30208333, 0.51041667, 0.96875   ,
       0.13541667, 0.83333333, 0.9375    , 0.72916667, 0.83333333,
       0.65625   , 0.9375    , 0.98958333, 0.26041667, 0.52083333,
       0.95833333, 0.38541667, 0.4375    , 0.16666667, 0.86458333,
       0.54166667, 0.375     , 0.14583333, 0.76041667, 0.04166667,
       0.55208333, 0.875     , 0.35416667, 0.64583333, 0.61458333,
       0.52083333, 0.47916667, 0.57291667, 0.75      , 0.44791667,
       0.40625   , 0.01041667, 0.60416667, 0.0625    , 0.875     ,
       0.66666667, 0.75      , 0.72916667, 0.42708333, 0.3125    ,
       0.53125   , 0.64583333, 0.82291667, 0.14583333, 0.92708333,
       0.20833333, 0.07291667, 0.38541667, 0.45833333, 0.375     ,
       0.41666667, 0.92708333, 0.72916667, 0.64583333, 0.0625    ,
       0.03125   , 0.77083333, 0.91666667, 0.375     , 0.9375    ,
       0.        , 0.3125    , 0.20833333, 0.0625    , 0.        ,
       0.69791667, 0.52083333, 0.04166667, 0.375     , 0.29166667,
       0.64583333, 0.94791667, 0.97916667, 1.        , 0.78125   ,
       0.22916667, 0.19791667, 0.58333333, 0.84375   , 0.29166667])
# 隨機生成0-100之間的100個數(50×2的矩陣)
X = np.random.randint(0, 100, (50, 2))

# 將整數轉成浮點數
X = np.array(X, dtype=float)

# 最值歸一化
X[:, 0] = (X[:, 0] - np.min(X[:, 0])) / (np.max(X[:, 0]) - np.min(X[:, 0]))
X[:, 1] = (X[:, 1] - np.min(X[:, 1])) / (np.max(X[:, 1]) - np.min(X[:, 1]))

# 繪製散點圖
plt.scatter(X[:, 0], X[:, 1])
plt.show()

print('第一列數據的均值爲', np.mean(X[:, 0]))
print('第一列數據的方差爲', np.std(X[:, 0])
print('第二列數據的均值爲', np.mean(X[:, 1]))
print('第二列數據的方差爲', np.std(X[:, 1]))

輸出結果:

第一列數據的均值爲 0.4480412371134021
第一列數據的方差爲 0.29316230758866496
第二列數據的均值爲 0.48494845360824745
第二列數據的方差爲 0.3163383877358538

三、均值方差歸一化

1.計算公式

其中,Xmean、S分別爲原始數據集的均值和方差。該歸一化方式要求原始數據的分佈可以近似爲高斯分佈,否則歸一化的效果會變得很糟糕。

2.Python實戰

# 導包
import numpy as np
import matplotlib.pyplot as plt

# 隨機生成0-100之間的100個數(50×2的矩陣)
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[:, 0] = (X2[:, 1] - np.mean(X2[:, 1])) / np.std(X2[:, 1])

# 繪製散點圖
plt.scatter(X2[:, 0], X2[:, 1])
plt.show()

print('第一列數據的均值爲', np.mean(X2[:, 0]))
print('第一列數據的方差爲', np.std(X2[:, 0])
print('第二列數據的均值爲', np.mean(X2[:, 1]))
print('第二列數據的方差爲', np.std(X2[:, 1]))

輸出結果:

第一列數據的均值爲 -9.325873406851315e-17
第一列數據的方差爲 1.0
第二列數據的均值爲 5.329070518200751e-17
第二列數據的方差爲 1.0

四、歸一化要點

​ 我們得到數據集訓練模型之前,首先會把數據集進行切分,分成訓練集和測試集,如果需要對數據進行歸一化,我們可以很容易地通過訓練集得到其最大值、最小值、均值和方差。但是測試集呢?如何對測試集進行數據歸一化呢?

正常情況下,測試數據集是模擬真實環境的,既然是真實環境,我們就很可能無法得到所有的測試集。因此當有一個新的數據需要進行預測時,我們需要使用訓練集的最大值、最小值、均值和方差對測試集數據進行歸一化

五、使用scikit-learn進行數據歸一化

本案例採用鳶尾花數據集進行測試。

# 導包
import numpy as np
from sklearn import datasets 

# 加載iris數據集
iris = datasets.load_iris()

X = iris.data
y = iris.target
# 將數據集分成訓練集和測試集
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 666)

# 導入StandardScaler包(進行均值方差歸一化)
from sklearn.preprocessing import StandardScaler

standardScaler = StandardScaler()

# 訓練
standardScaler.fit(X_train)

print(standardScaler.mean_)   # 均值 四個特徵的均值
print(standardScaler.scale_)  # 分佈範圍

輸出結果:

array([5.83416667, 3.08666667, 3.70833333, 1.17      ])
array([0.81019502, 0.44327067, 1.76401924, 0.75317107])
# 歸一化處理
X_train = standardScaler.transform(X_train) 
X_test_standard = standardScaler.transform(X_test)
X_test_standard

輸出結果:

array([[-0.28902506, -0.19551636,  0.44878573,  0.43814747],
       [-0.04217092, -0.64670795,  0.78891808,  1.63309511],
       [-1.0295875 , -1.77468693, -0.23147896, -0.22571233],
       [-0.04217092, -0.87230374,  0.78891808,  0.96923531],
       [-1.52329579,  0.03007944, -1.25187599, -1.28788802],
       [-0.41245214, -1.32349533,  0.16534211,  0.17260355],
       [-0.16559799, -0.64670795,  0.44878573,  0.17260355],
       [ 0.82181859, -0.19551636,  0.8456068 ,  1.10200727],
       [ 0.57496445, -1.77468693,  0.39209701,  0.17260355],
       [-0.41245214, -1.09789954,  0.39209701,  0.03983159],
       [ 1.06867274,  0.03007944,  0.39209701,  0.30537551],
       [-1.64672287, -1.77468693, -1.36525344, -1.15511606],
       [-1.27644165,  0.03007944, -1.19518726, -1.28788802],
       [-0.53587921,  0.70686683, -1.25187599, -1.0223441 ],
       [ 1.68580811,  1.15805842,  1.35580532,  1.76586707],
       [-0.04217092, -0.87230374,  0.22203084, -0.22571233],
       [-1.52329579,  1.15805842, -1.53531961, -1.28788802],
       [ 1.68580811,  0.25567524,  1.29911659,  0.83646335],
       [ 1.31552689,  0.03007944,  0.78891808,  1.50032315],
       [ 0.69839152, -0.87230374,  0.90229552,  0.96923531],
       [ 0.57496445,  0.48127103,  0.56216318,  0.57091943],
       [-1.0295875 ,  0.70686683, -1.25187599, -1.28788802],
       [ 2.30294347, -1.09789954,  1.80931511,  1.50032315],
       [-1.0295875 ,  0.48127103, -1.30856471, -1.28788802],
       [ 0.45153738, -0.42111215,  0.33540828,  0.17260355],
       [ 0.08125616, -0.19551636,  0.27871956,  0.43814747],
       [-1.0295875 ,  0.25567524, -1.42194216, -1.28788802],
       [-0.41245214, -1.77468693,  0.16534211,  0.17260355],
       [ 0.57496445,  0.48127103,  1.29911659,  1.76586707],
       [ 2.30294347, -0.19551636,  1.35580532,  1.50032315]])
# 導包,測試數據歸一化之後KNN的性能
from sklearn.neighbors import KNeighborsClassifier

knn_clf = KNeighborsClassifier(n_neighbors = 3)
knn_clf.fit(X_train, y_train)

# 計算準確度
knn_clf.score(X_test_standard, y_test) 

輸出結果:

1.0

如果訓練集進行了歸一化,測試集不做歸一化?結果又會如何?

knn_clf.score(X_test, y_test)

輸出結果:

0.3333333333333333

菜鳥還在學習ing!

後續,如有學習其他數據歸一化處理方法,繼續補充!

 

 

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