長短期記憶(LSTM)系列_LSTM的資料準備(4)——如何歸一化標準化長短期記憶網路的資料
導讀:
在訓練神經網路(例如長短期記憶復現神經網路)時,可能需要縮放序列預測問題的資料。
當輸入資料序列分佈並不標準,或者變化幅度(標準差)過大時,這會減慢網路的學習和收斂速度,也會阻礙網路的學習效率。
因此您需要了解如何歸一化和標準化序列預測資料,以及如何確定將哪中形式用於輸入和輸出變數。
您可能需要考慮兩種型別的系列縮放:歸一化和標準化。
這些都可以使用scikit-learn庫來實現。
1、什麼時候用歸一化?什麼時候用標準化?
(1)如果對輸出結果範圍有要求,用歸一化。
(2)如果資料較為穩定,不存在極端的最大最小值,用歸一化。
(3)如果資料存在異常值和較多噪音,用標準化,可以間接通過中心化避免異常值和極端值的影響。
某知乎答主的回答提到了他個人經驗:一般來說,我個人建議優先使用標準哈。對於輸出有要求時再嘗試別的方法,如歸一化或者更加複雜的方法。很多方法都可以將輸出範圍調整到[0, 1],如果我們對於資料的分佈有假設的話,更加有效的方法是使用相對應的概率密度函式來轉換。讓我們以高斯分佈為例,我們可以首先計算高斯誤差函式(Gaussian Error Function),此處定為er fc(·),那麼可以用下式進行轉化:
這篇部落格提到他的經驗:1) 在分類、聚類演算法中,需要使用距離來度量相似性的時候、或者使用PCA技術進行降維的時候,第二種方法(Z-score standardization)表現更好。2) 在不涉及距離度量、協方差計算、資料不符合正太分佈的時候,可以使用第一種方法或其他歸一化方法。比如影象處理中,將RGB影象轉換為灰度影象後將其值限定在[0 255]的範圍。
2、 哪些模型必須歸一化/標準化?
(1)SVM
不同的模型對特徵的分佈假設是不一樣的。比如SVM 用高斯核的時候,所有維度共用一個方差,這不就假設特徵分佈是圓的麼,輸入橢圓的就坑了人家,所以簡單的歸一化都還不夠好,來杯白化才有勁。比如用樹的時候就是各個維度各算各的切分點,沒所謂。
(2)KNN
需要度量距離的模型,一般在特徵值差距較大時,都會進行歸一化/標準化。不然會出現“大數吃小數”。
(3)神經網路
1)數值問題
歸一化/標準化可以避免一些不必要的數值問題。輸入變數的數量級未致於會引起數值問題吧,但其實要引起也並不是那麼困難。因為tansig(tanh)的非線性區間大約在[-1.7,1.7]。意味著要使神經元有效,tansig( w1x1 + w2x2 +b) 裡的 w1x1 +w2x2 +b 數量級應該在 1 (1.7所在的數量級)左右。這時輸入較大,就意味著權值必須較小,一個較大,一個較小,兩者相乘,就引起數值問題了。
假如你的輸入是421,你也許認為,這並不是一個太大的數,但因為有效權值大概會在1/421左右,例如0.00243,那麼,在matlab裡輸入 421·0.00243 == 0.421·2.43,會發現不相等,這就是一個數值問題。
2)求解需要
a. 初始化:在初始化時我們希望每個神經元初始化成有效的狀態,tansig函式在[-1.7, 1.7]範圍內有較好的非線性,所以我們希望函式的輸入和神經元的初始化都能在合理的範圍內使得每個神經元在初始時是有效的。(如果權值初始化在[-1,1]且輸入沒有歸一化且過大,會使得神經元飽和)
b. 梯度:以輸入-隱層-輸出這樣的三層BP為例,我們知道對於輸入-隱層權值的梯度有2ew(1-a^2)*x的形式(e是誤差,w是隱層到輸出層的權重,a是隱層神經元的值,x是輸入),若果輸出層的數量級很大,會引起e的數量級很大,同理,w為了將隱層(數量級為1)映身到輸出層,w也會很大,再加上x也很大的話,從梯度公式可以看出,三者相乘,梯度就非常大了。這時會給梯度的更新帶來數值問題。
c. 學習率:由(2)中,知道梯度非常大,學習率就必須非常小,因此,學習率(學習率初始值)的選擇需要參考輸入的範圍,不如直接將資料歸一化,這樣學習率就不必再根據資料範圍作調整。 隱層到輸出層的權值梯度可以寫成 2ea,而輸入層到隱層的權值梯度為 2ew(1-a^2)x ,受 x 和 w 的影響,各個梯度的數量級不相同,因此,它們需要的學習率數量級也就不相同。對w1適合的學習率,可能相對於w2來說會太小,若果使用適合w1的學習率,會導致在w2方向上步進非常慢,會消耗非常多的時間,而使用適合w2的學習率,對w1來說又太大,搜尋不到適合w1的解。如果使用固定學習率,而資料沒歸一化,則後果可想而知。
d.搜尋軌跡:已解釋
(4)PCA
參考:
標準化和歸一化什麼區別? - 知乎:https://www.zhihu.com/question/20467170
R--資料標準化、歸一化、中心化處理:https://zhuanlan.zhihu.com/p/33727799
特徵工程中的[歸一化]有什麼作用? - 知乎:https://www.zhihu.com/question/20455227
神經網路為什麼要歸一化:http://nnetinfo.com/nninfo/showText.jsp?id=37
作者:brucep3
連結:https://www.jianshu.com/p/95a8f035c86c
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。
歸一化系列資料
歸一化是對原始範圍內的資料進行重新縮放,以使所有值都在0和1的範圍內。
標準化要求您知道或能夠準確估計最小和最大可觀察值。您可以從可用資料中估算這些值。如果您的時間序列趨勢向上或向下,估計這些預期值可能會很困難,並且規範化可能不是用於解決問題的最佳方法。
值的歸一化如下:
1 |
y = (x - min) / (max - min) |
其中最小值和最大值與值x被歸一化有關。
例如,對於資料集,我們可以將min和max可觀察值猜測為30和-10。然後我們可以將任何值標準化,如18.8,如下所示:
1 2 3 4 |
y = (x - min) / (max - min) y = (18.8 - (-10)) / (30 - (-10)) y = 28.8 / 40 y = 0.72 |
您可以看到,如果提供的x值超出最小值和最大值的範圍,則結果值將不在0和1的範圍內。您可以在進行預測之前檢查這些觀察值並刪除它們來自資料集或將它們限制為預定義的最大值或最小值。
您可以使用scikit-learn物件MinMaxScaler規範化資料集。
使用MinMaxScaler和其他縮放技術的良好實踐用法如下:
- 使用可用的訓練資料安裝定標器。對於歸一化,這意味著訓練資料將用於估計最小和最大可觀察值。這是通過呼叫fit()函式完成的。
- 將比例應用於訓練資料。這意味著您可以使用標準化資料來訓練模型。這是通過呼叫transform()函式完成的。
- 將比例應用於未來的資料。這意味著您可以在將來準備要預測的新資料。
如果需要,可以反轉變換。這對於將預測轉換回其原始比例以進行報告或繪圖非常有用。這可以通過呼叫inverse_transform()函式來完成。
下面是一個標準化10個量的人為序列的例子。
縮放器物件要求將資料作為行和列的矩陣提供。載入的時間序列資料作為Pandas系列載入。
from pandas import Series
from sklearn.preprocessing import MinMaxScaler
# 手動定義一串序列
data = [10.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 90.0, 100.0]
series = Series(data)
print(series)
# 準備歸一化資料格式
values = series.values
values = values.reshape((len(values), 1))
# 配置資料歸一化方法MinMaxScaler
scaler = MinMaxScaler(feature_range=(0, 1))
scaler = scaler.fit(values)
print('Min: %f, Max: %f' % (scaler.data_min_, scaler.data_max_))
# 輸出歸一化資料
normalized = scaler.transform(values)
print(normalized)
# 歸一化逆轉換
inversed = scaler.inverse_transform(normalized)
print(inversed)
我們還可以看到資料集的最小值和最大值分別為10.0和100.0。執行該示例列印序列,列印從序列估計的最小值和最大值,列印相同的標準化序列,然後使用逆變換將值返回到其原始比例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
0 10.0 1 20.0 2 30.0 3 40.0 4 50.0 5 60.0 6 70.0 7 80.0 8 90.0 9 100.0
Min: 10.000000, Max: 100.000000
[[ 0. ] [ 0.11111111] [ 0.22222222] [ 0.33333333] [ 0.44444444] [ 0.55555556] [ 0.66666667] [ 0.77777778] [ 0.88888889] [ 1. ]]
[[ 10.] [ 20.] [ 30.] [ 40.] [ 50.] [ 60.] [ 70.] [ 80.] [ 90.] [ 100.]] |
標準化系列資料
標準化資料集涉及重新調整值的分佈,以便觀察值的平均值為0,標準差為1。
這可以被認為是減去平均值或使資料居中。
與標準化一樣,當您的資料具有不同比例的輸入值時,標準化可能很有用,甚至在某些機器學習演算法中也是必需的。
標準化假定您的觀察結果符合高斯分佈(鐘形曲線),具有良好的平均值和標準偏差。如果不滿足此期望,您仍然可以標準化時間序列資料,但可能無法獲得可靠的結果。
標準化要求您知道或能夠準確估計可觀察值的均值和標準差。您可以從訓練資料中估算這些值。
值標準化如下:
1 |
y = (x - mean) / standard_deviation |
平均值計算如下:
1 |
mean = sum(x) / count(x) |
而standard_deviation計算如下:
1 |
standard_deviation = sqrt( sum( (x - mean)^2 ) / count(x)) |
我們可以猜測平均值為10,標準偏差約為5.使用這些值,我們可以將第一個值20.7標準化如下:
1 2 3 4 |
y = (x - mean) / standard_deviation y = (20.7 - 10) / 5 y = (10.7) / 5 y = 2.14 |
資料集的均值和標準差估計對新資料的穩健性可能比最小值和最大值更強。
您可以使用scikit-learn物件StandardScaler來標準化資料集。
from pandas import Series
from sklearn.preprocessing import StandardScaler
from math import sqrt
# 手動定義一個待標準化序列
data = [1.0, 5.5, 9.0, 2.6, 8.8, 3.0, 4.1, 7.9, 6.3]
series = Series(data)
print(series)
# 準備標準化資料格式
values = series.values
values = values.reshape((len(values), 1))
# 配置標準化方法StandardScaler
scaler = StandardScaler()
scaler = scaler.fit(values)
print('Mean: %f, StandardDeviation: %f' % (scaler.mean_, sqrt(scaler.var_)))
# 輸出標準化後的資料
standardized = scaler.transform(values)
print(standardized)
# 標準化資料的逆轉換
inversed = scaler.inverse_transform(standardized)
print(inversed)
我們可以看到估計的平均值和標準偏差分別約為5.3和2.7。執行該示例列印序列,列印從序列估計的均值和標準差,列印標準化值,然後以原始比例列印值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
0 1.0 1 5.5 2 9.0 3 2.6 4 8.8 5 3.0 6 4.1 7 7.9 8 6.3
Mean: 5.355556, StandardDeviation: 2.712568
[[-1.60569456] [ 0.05325007] [ 1.34354035] [-1.01584758] [ 1.26980948] [-0.86838584] [-0.46286604] [ 0.93802055] [ 0.34817357]]
[[ 1. ] [ 5.5] [ 9. ] [ 2.6] [ 8.8] [ 3. ] [ 4.1] [ 7.9] [ 6.3]] |
輸入變數是否需要縮放取決於問題和每個變數的具體情況。我們來看一些例子。
分類輸入
您可能有一系列分類輸入,例如字母或狀態。
通常,分類輸入首先是整數編碼,然後是一個熱編碼。也就是說,為每個不同的可能輸入分配唯一的整數值,然後使用1和0的二進位制向量來表示每個整數值。
根據定義,一個熱編碼將確保每個輸入是一個小的實際值,在這種情況下為0.0或1.0。
實值輸入
您可能有一系列數量作為輸入,例如價格或溫度。
如果數量的分佈是正常的,則應該標準化,否則系列應該標準化。如果數值範圍很大(10s 100s等)或小(0.01,0.0001),則適用。
如果數量值很小(接近0-1)且分佈有限(例如標準偏差接近1),那麼也許你可以在沒有系列縮放的情況下逃脫。
其他輸入
問題可能很複雜,如何最好地擴充套件輸入資料可能並不清楚。
如果有疑問,請將輸入序列標準化。如果您擁有這些資源,請使用原始資料,標準化資料和標準化來探索建模,並檢視是否存在有益的差異。
縮放輸出變數
輸出變數是網路預測的變數。
您必須確保輸出變數的比例與網路輸出層上的啟用函式(傳遞函式)的比例相匹配。
二元分類問題
如果您的問題是二進位制分類問題,那麼輸出將是類值0和1.這最好使用輸出層上的sigmoid啟用函式建模。輸出值將是介於0和1之間的實數值,可以捕捉到清晰的值。
多類分類問題
如果您的問題是多類分類問題,那麼輸出將是一個介於0和1之間的二進位制類值的向量,每個類值一個輸出。這最好使用輸出層上的softmax啟用功能建模。同樣,輸出值將是介於0和1之間的實數值,可以捕捉到清晰的值。
迴歸問題
如果您的問題是迴歸問題,那麼輸出將是一個實際值。這最好使用線性啟用功能建模。如果值的分佈正常,則可以標準化輸出變數。否則,可以對輸出變數進行標準化。
其他問題
可以在輸出層上使用許多其他啟用函式,並且您的問題的細節可能會增加混淆。
經驗法則是確保網路輸出與資料規模相匹配。
擴充套件時的實際考慮因素
縮放序列資料時有一些實際考慮因素。
- 估算係數。您可以從訓練資料中估算係數(標準化的最小值和最大值或標準化的平均值和標準偏差)。檢查這些首先估算並使用領域知識或領域專家來幫助改進這些估算,以便將來對所有資料進行有用的更正。
- 儲存係數。您將需要以與用於訓練模型的資料完全相同的方式對未來的新資料進行標準化。儲存用於存檔的係數,並在需要在進行預測時擴充套件新資料時載入它們。
- 資料分析。使用資料分析可以幫助您更好地瞭解資料。例如,一個簡單的直方圖可以幫助您快速瞭解數量分佈,看看標準化是否有意義。
- 擴充套件每個系列。如果您的問題有多個系列,請將每個系列視為一個單獨的變數,然後分別對它們進行縮放。
- 在合適的時間縮放。在正確的時間應用任何縮放變換非常重要。例如,如果您有一系列非靜止的數量,則在首次使資料靜止後進行縮放可能是合適的。在將系列轉換為監督學習問題後對其進行擴充套件是不合適的,因為每個列的處理方式都不同,這是不正確的。
- 如果懷疑則縮放。您可能需要重新調整輸入和輸出變數。如果有疑問,至少要對資料進行標準化。