引言
特徵縮放是機器學習預處理數據中最重要的步驟之一,它有時能決定學習模型的好壞。
特徵縮放的作用如下:
- 加快梯度下降
- 提升模型精度(消除不同量綱)
- 防止梯度爆炸(消除過大值的影響)
爲什麼要特徵縮放
在機器學習算法處理數據時通常是忽略數據的單位信息的,或者說不知道這些數據代表什麼。比如50kg和50公里代表着兩個不同的度量,人類是很容易區分它們的。但是對於機器來說,這兩個數據是一樣的。
import pandas as pd
import numpy as np
data = np.array([[1,172,30000],[2,160,60000],[3,175,50000],[4,180,5000]])
df = pd.DataFrame(data,columns=['staff','height','salary'])
df
我們來看下上面的表格,上面是員工身高與薪水的表格。我們人類看到數字172(cm)知道就是身高,看到5000知道肯定是薪水。但是機器就不知道。
假設用神經網絡來學習這份數據,那麼就會導致取值範圍更大的薪水會主導模型的訓練,也就是模型會偏向於薪水,但通常我們不希望我們的算法一開始就偏向於某個特徵。
假設我們嘗試計算兩個員工的歐氏距離,在特徵縮放之前的結果是:
員工1和員工2的距離:
員工2和員工3的距離:
從上面的結果可以看到它們的距離基本上就是薪水的差值。
而在經過最大最小值歸一化後(下文會講到)的結果是:
員工1和員工2的距離:
員工2和員工3的距離:
顯然經過特徵縮放後的結果更具有可比性。
這個問題不僅會出現在神經網絡裏面,還會出現在任何基於距離計算的算法中。特徵縮放就可以解決這個問題。
特徵縮放有哪些方法
有很多種特徵縮放的方法,我們一一來分析。
均值歸一化(Mean Normalization)
將數值範圍縮放到區間裏,數據的均值變爲
以上面的例子說明,假設我們要均值歸一化員工1的薪水。那麼
下面是對薪水和身高進行均值歸一化的結果:
data_mean = data[:,1:]
data_mean = (data_mean - data_mean.mean(axis=0)) / (data_mean.max(axis=0) - data_mean.min(axis=0))
pd.DataFrame(np.c_[np.arange(1,5),data_mean],columns=['staff','height','salary'])
最大最小值歸一化(Min-Max Normalization)
最大最小值歸一化簡稱爲歸一化,將數值範圍縮放到區間裏
以上面的例子說明,假設我們要最大最小值歸一化員工1的薪水。那麼
下面是對薪水和身高進行均最大最小值歸一化的結果:
data_min_max = data[:,1:]
data_min_max = (data_min_max - data_min_max.min(axis=0)) / (data_min_max.max(axis=0) - data_min_max.min(axis=0))
pd.DataFrame(np.c_[np.arange(1,5),data_min_max],columns=['staff','height','salary'])
標準化/z值歸一化(Standardization/Z-Score Normalization)
標準化又叫z值歸一化,將數值縮放到0附近,且數據的分佈變爲均值爲0,標準差爲1的標準正態分佈。
是的標準差,計算公式爲:
以上面的例子說明,假設我們要標準化員工1的薪水。那麼
下面是對薪水和身高進行標準化的結果:
data_std = data[:,1:]
data_std = (data_std - data_std.mean(axis=0)) / (data_std.std(axis=0))
pd.DataFrame(np.c_[np.arange(1,5),data_std],columns=['staff','height','salary'])
常見問題&注意事項
哪些算法需要特徵縮放
特徵縮放對基於距離的算法特別重要。因此像KNN、線性迴歸、邏輯迴歸、SVM等都需要特徵縮放。
不基於距離的算法像樸素貝葉斯以及基於樹結構的算法(決策樹、隨機森林)等不需要特徵縮放。
另外,0/1取值的特徵不需要歸一化。
歸一化還是標準化
- 如果你知道數據分佈不是正態分佈,那麼使用歸一化。像用在KNN和NN這種不假設數據分佈的算法就很合適。 最大最小值歸一化容易受異常值影響,常用於歸一化圖像的灰度值。
- 當數據是正態分佈時進行標準化是很有幫助的,不像歸一化,標準化的數據沒有限定範圍,對異常值不敏感。
- 然後,具體的選擇還是依賴於你的數據或算法,通常最好歸一化和標準化都嘗試一下,看哪種方法好。
注意事項
需要先把數據拆分成訓練集與驗證集,在訓練集上計算出需要的數值(如均值和標準值),對訓練集數據做標準化/歸一化處理(不要在整個數據集上做標準化/歸一化處理,因爲這樣會將驗證集的信息帶入到訓練集中,這是一個非常容易犯的錯誤),然後再用之前計算出的數據(如均值和標準值)對驗證集數據做相同的標準化/歸一化處理。
參考
- https://www.cnblogs.com/HuZihu/p/9761161.html
- https://www.analyticsvidhya.com/blog/2020/04/feature-scaling-machine-learning-normalization-standardization
- https://machinelearningknowledge.ai/feature-scaling-machine-learning/