拓端tecdat:PYTHON用LSTM長短期記憶神經網路的引數優化方法預測時間序列洗髮水銷售資料
原文連結:http://tecdat.cn/?p=24431
原文出處:拓端資料部落公眾號
配置神經網路很困難,因為沒有關於如何去做的好的理論。
您必須系統地從動態和客觀結果的角度探索不同的引數配置,以嘗試瞭解給定預測建模問題的情況。
在本教程中,您將瞭解如何探索如何針對時間序列預測問題配置 LSTM 網路引數。
完成本教程後,您將瞭解:
- 如何調整和解釋訓練時期數的結果。
- 如何調整和解釋訓練批次大小的結果。
- 如何調整和解釋神經元數量的結果。
如何使用Keras調整 LSTM 超引數以進行時間序列預測
教程概述
本教程分為 6 個部分;他們是:
- 洗髮水銷售資料集
- 實驗測試
- 調整時期數
- 調整批次大小
- 調整神經元的數量
- 結果總結
環境
本教程假設您已安裝PythonSciPy 環境。您可以在此示例中使用 Python 2 或 3。
本教程假設您已經安裝了Kerasv2.0 或更高版本以及 TensorFlow 。
本教程還假設您已安裝 scikit-learn、Pandas、NumPy 和 Matplotlib。
洗髮水銷售資料集
該資料集描述了 3 年期間每月洗髮水的銷售量。
單位是銷售計數,有 36 個觀察值。
下面的示例載入並建立已載入資料集的圖。
- #載入並繪製資料集
- # 載入資料集
- def paser(x):
- return dattme.strptme('190'+x, '%Y-%m')
- seres = read_csv('sale.csv', header=0, pare_dats=[0])
- # 總結前幾行
- print(seres.head())
- # 繪製線圖
- seres.plot()
執行示例將資料集載入為 Pandas 序列並輸出前 5 行。
然後建立該序列的線圖,顯示出明顯的增加趨勢。
洗髮水銷售資料集的線圖
接下來,我們將看看實驗中使用的 LSTM 配置和測試工具。
實驗測試
本節介紹本教程中使用的測試工具。
資料拆分
我們將把洗髮水銷售資料集分成兩部分:訓練集和測試集。
前兩年的資料將用於訓練資料集,剩餘的一年資料將用於測試集。
將使用訓練資料集開發模型並對測試資料集進行預測。
測試資料集上的永續性預測實現了每月洗髮水銷量 136.761 的誤差。這在測試集上提供了可接受的較低效能界限。
模型評估
使用滾動預測場景。
測試資料集的每個時間步將一次走一個。模型將用於對時間步長進行預測,然後將採用測試集中的實際預期值,並將其提供給模型用於下一個時間步長的預測。
這模擬了一個真實世界的場景,其中每個月都會有新的洗髮水銷售觀察結果,並用於下個月的預測。
這將通過訓練和測試資料集的結構進行模擬。我們將以一次性方法進行所有預測。
將收集對測試資料集的所有預測,並計算誤差以總結模型的技能。將使用均方根誤差 (RMSE),因為它會懲罰大誤差併產生與預測資料(即每月洗髮水銷售量)相同單位的分數。
資料準備
在我們將 LSTM 模型擬合到資料集之前,我們必須轉換資料。
在擬合模型和進行預測之前,對資料集執行以下三個資料轉換。
- 轉換時間序列資料,使其平穩。具體來說,滯後=1 差分以消除資料中的增加趨勢。
- 將時間序列轉換為監督學習問題。具體來說,將資料組織成輸入和輸出模式,其中前一個時間步的觀察被用作預測當前時間步的觀察的輸入
- 將觀測值轉換為特定的量綱。具體來說,將資料重新縮放到 -1 和 1 之間的值以滿足 LSTM 模型的預設雙曲正切啟用函式。
在計算和誤差之前,這些變換在預測中被返回到原始比例。
實驗執行
每個實驗方案將被執行10次。
這樣做的原因是,LSTM網路的隨機初始條件在每次訓練一個給定的配置時,會導致非常不同的結果。
一個診斷方法將被用來研究模型配置。這就是將建立模型技能隨時間變化的線圖(訓練迭代稱為epochs),並對其進行研究,以深入瞭解一個給定的配置是如何執行的,以及如何調整它以獲得更好的效能。
在每個歷時結束時,模型將在訓練和測試資料集上進行評估,並儲存RMSE分數。
每個場景結束時的訓練和測試RMSE分數將被打印出來,以顯示進度。
訓練和測試的RMSE分數系列在執行結束後被繪製成線圖。訓練得分用藍色表示,測試得分用橙色表示。
讓我們深入瞭解一下結果。
調整時期
我們將檢視調整的第一個 LSTM 引數是訓練時期的數量。
該模型將使用一個批次4 和單個神經元。我們將探索針對不同訓練時期數訓練此配置的效果。
500 時期epoch 的診斷
程式碼註釋得相當好,應該很容易理解。
- #能夠在伺服器上儲存影象
- matplotlib.use('Agg')
- # 用於載入資料集的日期時間解析函式
- def paser(x):
- return dateime.strptme('190'+x, '%Y-%m')
- # 將一個序列設定為一個監督學習問題
- colmns.appnd(df)
- df = concat(colns, axis=1)
- # 建立一個差分序列
- diffene(dtaset, ieral=1):
- # 將訓練和測試資料擴充套件到[-1, 1]。
- scae(train, test):
- scler = salr.fit(train)
- # 轉換訓練集
- train = trin.rhape(tain.hpe[0], tran.shpe[1])
- # 變換測試
- tst_caed = scler.trnfom(test)
- # 預測值的逆向縮放
- inve_scle(saer, X, yhat):
- # 在資料集上評估模型,以轉換後的單位返回RMSE
- evaluate(mdel, rw_data, scald_dataet, caler)
- # 分開
- X, y = scald_daaset[:,0:-1], saleddaaset[:,-1)
- # 重塑
- reshaed = X.reshpe(len(X), 1, 1)
- # 預測資料集
- predict(rshped, bth_ize=tchsize)
- # 在預測中反轉資料變換
- for i in rage(len(outut)):
- yat = output[i,0]
- # 反轉比例
- yhat = inrtscle(saer, X[i], yhat)
- # 反轉差分
- yhat = yhat + raaa[i]。
- # 儲存預測
- pdiis.ppd(yhat)
- # 報告效能
- rmse = srt(mensuederror pricions) )
- # 對訓練資料進行LSTM網路擬合
- fitlstm(tran, tet, raw, caler bath_sie, n_eoch, erns):
- # 準備模型
- model = Sequential()
- moel.ad(LSTM(neons, bh_phpe, stateful)
- # 擬合模型
- for i in range(nb_epoch):
- fit(X, y, epocs=1, bathsze, verose=0, shufle=False)
- # 在訓練資料上評估模型
- mse.apend(evalaion(mdel, rawtain, trai, scler, 0, bcize))
- # 在測試資料上評估模型
- rmse.append(evalh_size))
- # 執行診斷性實驗
- run():
- # 載入資料集
- read_csv('sale.csv'
- # 將資料轉化為平穩的
- diffe(raues, 1)
- # 將資料轉化為有監督的學習
- supd = timespevied(diues, 1)
- suplues = supd.vales
- # 將資料分成訓練集和測試集
- train, test = supues[0:-12], suplues[-12:] 。
- # 改變資料的尺度
- scar, traaled, tescaled = scale(tain, tst)
- # 擬合和評估模型
- traed = trainld[2:, :]
- # 配置
- reas = 10
- nbch = 4
- nphs = 500
- nnens = 1
- # 執行診斷性測試
- for i in range(ret):
- fit(train, tes, rawues, scler, nbth, necs, neons)
注意:考慮到演算法或評估程式的隨機性,或數值精度的差異。考慮多次執行該示例並比較平均結果。
執行實驗會在 10 次實驗執行結束時輸出訓練和測試集的 RMSE。
還建立了每個訓練時期之後訓練集和測試集上的一系列 RMSE 分數的線圖。
500 個時期的診斷結果
結果清楚地表明,幾乎所有實驗執行的 RMSE 在訓練時期都有下降趨勢。
它表明模型正在學習問題並且具有一定的預測能力。事實上,所有最終測試分數都低於在這個問題上實現 136.761 的 RMSE 的簡單永續性模型(樸素預測)的誤差。
結果表明,更多的訓練時期將產生更熟練的模型。
讓我們嘗試將 epoch 數從 500 加倍到 1000。
1000個時期的診斷
在本節中,我們使用相同的實驗設定並擬合模型超過 1000 個訓練時期。
具體來說,在run()函式中將n_epochs引數設定為1000。
nepohs=1000
注意:考慮到演算法或評估程式的隨機性,或數值精度的差異。考慮多次執行該示例並比較平均結果。
執行該示例會輸出最後一個 epoch 中訓練集和測試集的 RMSE。
還建立了每個時期的測試和訓練 RMSE 分數的線圖。
1000 個時期的診斷結果
我們可以看到,模型誤差的下降趨勢確實在繼續,而且似乎在放緩。
訓練和測試用例的線條變得更加水平,但仍普遍呈現下降趨勢,儘管變化率較低。一些測試錯誤的例子顯示了大約 600 個時期可能出現的拐點,並且可能顯示出上升趨勢。
我們對測試集上持續改進的平均效能感興趣,而且這種情況可能會持續下去。
讓我們嘗試將 epoch 數從 1000 增加一倍到 2000。
2000 時期Epoch 的診斷
在本節中,我們使用相同的實驗設定並擬合模型超過 2000 個訓練時期。
具體來說,在run()函式中將npoch引數設定為 2000 。
nepoch=2000
注意:考慮到演算法或評估程式的隨機性,或數值精度的差異。考慮多次執行該示例並比較平均結果。
執行該示例會輸出最後一個 epoch 中訓練集和測試集的 RMSE。
還建立了每個時期的測試和訓練 RMSE 分數的線圖。
2000 時期epoch 的診斷結果
正如人們可能已經猜到的那樣,在訓練和測試資料集上的額外 1000 個 epoch 中,誤差的下降趨勢仍在繼續。
值得注意的是,大約一半的案例在執行結束之前一直在減少誤差,而其餘的則顯示出增加趨勢的跡象。
增長的趨勢是過度擬合的標誌。這是當模型過度擬合訓練資料集時,其代價是測試資料集上的效能下降。它的例子是在訓練資料集上的持續改進,以及在測試資料集上的拐點和最差技能之後的改進。在測試資料集上,只有不到一半的執行顯示了這種型別的模式的開始。
儘管如此,測試資料集上的最終歷時結果還是非常好。我們可以通過更長的訓練看到進一步的收益。
讓我們嘗試將歷時數翻倍,從2000到4000。
4000個時期的診斷
在本節中,我們使用相同的實驗設定並擬合模型超過 4000 個訓練時期。
具體來說,在run()函式中將n_epochs引數設定為 4000 。
nepocs=4000
注意:考慮到演算法或評估程式的隨機性,或數值精度的差異。考慮多次執行該示例並比較平均結果。
執行該示例會輸出最後一個 epoch 中訓練集和測試集的 RMSE。
還建立了每個時期的測試和訓練 RMSE 分數的線圖。
4000 epoch 的診斷結果
即使超過 4000 個 epoch,也有提高效能的總體趨勢。存在一種嚴重過擬合的情況,即測試誤差急劇上升。
同樣,大多數執行以“良好”(比永續性更好)的最終測試錯誤結束。
結果總結
上面的診斷執行有助於探索模型的動態行為,但缺乏客觀和可比較的平均效能。
我們可以通過重複相同的實驗並計算和比較每個配置的彙總統計來解決這個問題。在這種情況下,完成了 30 次執行,時間值為 500、1000、2000、4000 和 6000。
這個想法是使用大量執行的彙總統計來比較配置,並確切地檢視哪些配置的平均效能可能更好。
下面列出了完整的程式碼示例。
- # 執行一個重複實驗
- epernt(rpeas, sris, ochs):
- # 將資料轉化為平穩的
- dif_vues = diferne(ravaues, 1)
- # 將資料轉換為有監督的學習
- to_spersed(dif_vles, 1)
- # 將資料分成訓練集和測試集
- train, test = spervsed[0:-2], suervues[-12:] 。
- # 改變資料的尺度
- scale(train, test)
- # 執行實驗
- for r in range(reeats):
- # 擬合模型
- size = 4
- trtried = traled[2:, :]
- ltmol = lstm(tamd, bachsie, eohs, 1)
- # 預測整個訓練資料集,以建立預測的狀態
- trainmd[:, 0].resape(lentran_tmmed), 1, 1)
- predict(tain_rsaped, ah_size=ath_ize)
- # 預測測試資料集
- te_sapd = tstscaled[:,0:-1)
- predict(testped, btze=btc_sze)
- for i in range(len(outut)):
- yhat = output[i,0]
- X = te_saled[i, 0:-1] 。
- # 反轉比例
- yhat = invere(aler, X, yhat)
- # 反轉差分
- yht = invsefece(raw_aues, yat, len+1-i)
- # 報告效能
- sqrt(men_sqred_eror(a_vals[-12:], pedins) )
- # 改變訓練歷時
- echs = [500, 1000, 2000, 4000, 6000] 。
- for e in eochs:
- exiet(rpats, sries, e)
- # 總結結果
- boxlot()
執行程式碼首先輸出 5 個配置中每一個的彙總統計資訊。值得注意的是,這包括來自每個結果群體的 RMSE 分數的平均值和標準差。
平均值給出了配置的平均預期效能的概念,而標準差給出了方差的概念。最小和最大 RMSE 分數還給出了可能期望的最佳和最壞情況示例的範圍。
僅檢視平均 RMSE 分數,結果表明配置為 1000 的 epoch 可能更好。結果還表明,可能需要對 1000 至 2000 之間的值進行進一步分析。
分佈也顯示在箱線圖上。這有助於瞭解分佈如何直接比較。
紅線顯示中位數,方框顯示第 25 個和第 75 個百分位數,或中位數 50% 的資料。這種比較還表明,將 epochs 設定為 1000 的選擇優於測試的替代方案。它還表明,可以在 2000 或 4000 次迭代時獲得最佳效能,但代價是平均效能更差。
總結 Epoch 結果的箱線圖
接下來,我們將看看批次大小的影響。
調整批次大小
批次大小控制更新網路權重的頻率。
重要的是,在 Keras 中,批量大小必須是測試和訓練資料集大小的一個因素。
在上一節探討訓練 epoch 數的部分中,批大小固定為 4,它分為測試資料集(大小為 12)和測試資料集(大小為 20)。
在本節中,我們將探討改變批大小的影響。我們將訓練 epoch 的數量保持在 1000。
診斷 1000 個時期和批次大小為 4
作為提醒,上一節在第二次實驗中評估了批量大小為4,歷時數為1000的實驗。
1000 個時期的診斷結果
診斷 1000 個時期和批次大小為 2
在本節中,我們著眼於將批大小從 4 減半至 2。
這個改動是對run()函式中的n_batch引數進行的;例如:
n_batch=2
執行該示例顯示了與批大小為 4 相同的總體效能趨勢,可能在最後一個時期具有更高的 RMSE。
執行可能會顯示出更早穩定 RMES 的行為,而不是似乎繼續下降趨勢。
下面列出了每次執行最終的 RSME 分數。
還建立了每個時期的測試和訓練 RMSE 分數的線圖。
1000 個時期和批次大小為 2 的診斷結果
讓我們再次嘗試使用批量大小。
診斷 1000 個時期和批次大小為 1
這是在每個訓練模式之後更新網路。可以與批量學習形成對比,其中權重僅在每個 epoch 結束時更新。
我們可以在run()函式中更改n_batch引數;例如:
n_batch=1
同樣,執行該示例會輸出每次執行的最後一期的 RMSE 分數。
還建立了一個每個歷時的測試和訓練RMSE分數的線圖。
該圖表明,隨著時間的推移,測試RMSE有更多的變化,也許訓練RMSE比大批量的測試RMSE穩定得更快。測試RMSE的變異性增加是意料之中的,因為每次更新對網路所做的改變都會帶來很少的反饋。
該圖還表明,如果配置被賦予更多的訓練歷時,也許RMSE的下降趨勢會繼續下去。
1000 個時期和批次大小為 1 的診斷結果
結果總結
與訓練時期一樣,我們可以客觀地比較網路在給定不同批次大小的情況下的效能。
每個配置執行 30 次,並根據最終結果計算彙總統計資訊。
- # 執行一個重複的實驗
- # 將資料轉換為平穩的
- raw_vues = sres.values
- df_vaues = difence(rvalues, 1)
- # 將資料轉換為監督學習
- suesr_lus = surior.values
- # 將資料分成訓練集和測試集
- # 變換資料的尺度
- tra_cled,testscld = scale(tain, tet)
- # 執行實驗
- # 擬合模型
- tran_timed = tan_saled[2:, :]
- lstmmdl = lstm(tainrmd, ach_e, 1000, 1)
- # 預測整個訓練資料集以建立預測狀態
- preit(trairehae,bach_ie=bat_size)
- # 預測測試資料集
- preict(tst_rehapeatc_ze=bathsize)
- X = tes_cd[i, 0:-1]
- # 反轉縮放
- yht = ivetcale(aler, X, yhat)
- # 反轉差分
- yat = invese_dfence(awvalus, yat, le(tetsald)+1-i)
- # 報告表現
- rmse = sqrt(mean_urerror)
- # 載入資料集
- # 實驗
- # 改變訓練批次
- 批次 = [1, 2, 4]
- boxplot()
僅從平均效能來看,結果表明批量大小為 1 時 RMSE 較低。 正如上一節所述,這可能會隨著更多的訓練時期而得到進一步改善。
還建立了資料的箱線圖,以幫助以圖形方式比較分佈。該圖將中值效能顯示為一條紅線,其中批次大小為 4 顯示最大的差異和最低的中值 RMSE。
調整神經網路是平均效能和該效能的可變性的權衡,理想結果具有低平均誤差和低可變性,這意味著它通常是好的和可重複的。
總結批次大小結果的箱線圖
調整神經元的數量
在本節中,我們將研究改變網路中神經元數量的影響。
神經元的數量影響網路的學習能力。一般來說,更多的神經元能夠以更長的訓練時間為代價從問題中學習更多的結構。更多的學習能力也會產生潛在的過度擬合訓練資料的問題。
我們將使用 4 和 1000 個訓練時期的批量大小。
1000 個時期和 1 個神經元的診斷
我們將從 1 個神經元開始。
提醒一下,這是從 epochs 實驗中測試的第二個配置。
1000 個時期的診斷結果
1000 個時期和 2 個神經元的診斷
我們可以將神經元的數量從 1 增加到 2。這有望提高網路的學習能力。
我們可以通過更改run()函式中的n_neurons變數來做到這一點。
n_neurons=2
執行此配置會輸出每次執行的最後一個時期的 RMSE 分數。
結果表明,總體表現不錯,但不是很好。
還建立了每個時期的測試和訓練 RMSE 分數的線圖。
這更能說明問題。它顯示了測試RMSE的快速下降,大約在500-750個時期中,一個拐點顯示了測試RMSE的上升,幾乎所有的執行都是如此。同時,訓練資料集顯示持續下降到最後一期。
這些都是訓練資料集過擬合的跡象。
1000 個時期和 2 個神經元的診斷結果
讓我們看看這種趨勢是否會隨著更多的神經元而繼續。
1000 個時期和 3 個神經元的診斷
本節著眼於將神經元數量增加到 3 的相同配置。
n_neurons=3
執行此配置會輸出每次執行的最後一個時期的 RMSE 分數。
結果與上一節類似;我們看不到 2 或 3 個神經元的最終 epoch 測試分數之間的一般差異。3 個神經元的最終訓練分數似乎確實較低,這可能表明過度擬合加速。
訓練資料集中的拐點似乎比 2 個神經元實驗發生得更早,可能在 300-400 期。
這些神經元數量的增加可能受益於減緩學習速度的額外變化。例如使用正則化方法,如 dropout,減少批量大小,減少訓練時期的數量。
還建立了每個時期的測試和訓練 RMSE 分數的線圖。
1000 個時期和 3 個神經元的診斷結果
結果總結
同樣,我們可以客觀地比較增加神經元數量同時保持所有其他網路配置的影響。
在本節中,我們將每個實驗重複 30 次,並將平均測試 RMSE 效能與 1 到 5 的神經元數量進行比較。
- # 執行一個重複的實驗
- # 將資料轉換為平穩的
- ra_lus = sees.values
- difvles = difece(rwvlus, 1)
- # 將資料轉換為監督學習
- sups_ales = supvor.values
- # 將資料分成訓練集和測試集
- # 變換資料的尺度
- trainsld,tet_scld = scale(tain, est)
- # 執行實驗
- err_scres = list()
- # 擬合模型
- trntied = tr_aed[2:, :]
- lsmel = lstm(tritid, bahze, 1000, eons)
- # 預測整個訓練資料集以建立預測狀態
- trrehap = ti_rimed[:, 0].rehae(len(train_trimmed), 1, 1)
- prdict(trahpe,bahe=achze)
- # 預測測試資料集
- tet_sape = tetsaled[:,0:-1]
- tetrehae = tesespe.reshape(len(tst_ehape), 1, 1)
- prect(tes_rhpe,bath_ize=btchsze)
- X = ts_cld[i, 0:-1]
- # 反轉縮放
- yhat = ivertle(scaer, X, yhat)
- # 反轉差分
- yht = inversefrce(rw_values, hat, len(tet_saed)+1-i)
- # 報告表現
- rmse = sqrt(men_sureero(aw_vue[-12:], preiions))
- # 載入資料集
- # 實驗
- # 改變神經元
- 神經元 = [1, 2, 3, 4, 5]
- boxplot()
執行實驗會輸出每個配置的摘要統計資訊。
僅從平均效能來看,結果表明具有 1 個神經元的網路配置在 1000 個 epoch 中具有最佳效能,批量大小為 4。
盒須圖顯示了中值測試集效能的明顯趨勢,其中神經元的增加導致測試 RMSE 的相應增加。
總結神經元結果的盒須圖
所有結果的總結
在本教程中,我們在洗髮水銷售資料集上完成了相當多的 LSTM 實驗。
一般來說,似乎有狀態的 LSTM 配置了 1 個神經元,批量大小為 4,並且訓練了 1000 個 epochs 可能是一個很好的配置。
結果還表明,也許這種批量大小為 1 並且適合更多 epoch 的配置可能值得進一步探索。
調整神經網路是一項艱鉅的實證工作,事實證明 LSTM 也不例外。
本教程展示了配置行為隨時間的診斷研究以及測試 RMSE 的客觀研究的好處。
擴充套件
本節列出了對本教程中執行的實驗進行擴充套件的一些想法。
如果您探索其中任何一個,請在評論中報告您的結果;我很想看看你想出了什麼。
- dropout。使用正則化方法(例如迴圈 LSTM 連線上的 dropout)減慢學習速度。
- 層。通過在每層新增更多層和不同數量的神經元來探索額外的分層學習能力。
- 正則化。探索如何使用權重正則化(例如 L1 和 L2)來減緩網路在某些配置上的學習和過度擬合。
- 優化演算法。例如經典梯度下降,以檢視加速或減慢學習的特定配置是否會帶來好處。
- 損失函式。
- 特點和時間步長。探索使用滯後觀察作為輸入特徵和特徵的輸入時間步長,看看它們作為輸入的存在是否可以提高模型的學習和/或預測能力。
- 更大的批量。探索大於 4 的批量大小,可能需要進一步處理訓練和測試資料集的大小。
概括
在本教程中,您瞭解瞭如何系統地研究 LSTM 網路的配置以進行時間序列預測。
具體來說,你學到了:
- 如何設計用於評估模型配置的系統測試工具。
- 如何隨著時間的推移使用模型診斷以及客觀預測誤差來解釋模型行為。
- 如何探索和解釋訓練時期數、批量大小和神經元數量的影響。
您對調整 LSTM 或本教程有任何疑問嗎?
在下面的評論中提出您的問題,我們會盡力回答。
最受歡迎的見解
1.用於NLP的Python:使用Keras的多標籤文字LSTM神經網路分類
2.Python中利用長短期記憶模型LSTM進行時間序列預測分析 – 預測電力消耗資料
4.Python中用PyTorch機器學習分類預測銀行客戶流失模型
6.在r語言中使用GAM(廣義相加模型)進行電力負荷時間序列分析
7.R語言中ARMA,ARIMA(Box-Jenkins),SARIMA和ARIMAX模型用於預測時間序列數
▍關注我們 【大資料部落】第三方資料服務提供商,提供全面的統計分析與資料探勘諮詢服務,為客戶定製個性化的資料解決方案與行業報告等。 ▍諮詢連結:http://y0.cn/teradat ▍聯絡郵箱:[email protected]