間序列預(yù)測(cè)期末源碼拆解:從數(shù)據(jù)處理到答辯調(diào)參)
簡(jiǎn)介面向高校期末大作業(yè)與課程設(shè)計(jì)場(chǎng)景的時(shí)間序列預(yù)測(cè)項(xiàng)目源碼基于LSTM模型實(shí)現(xiàn)同時(shí)提供RNN和Transformer對(duì)比模型。代碼結(jié)構(gòu)清晰曾獲高分驗(yàn)證適合深度學(xué)習(xí)初學(xué)者快速理解不同循環(huán)神經(jīng)網(wǎng)絡(luò)在序列建模中的差異。壓縮包共31個(gè)文件包含Python腳本、CSV時(shí)序數(shù)據(jù)集、說(shuō)明文檔、運(yùn)行截圖與項(xiàng)目配置整體大小28.48MB。其中CSV數(shù)據(jù)涵蓋ETTh1、ETTm1、pollution等常見(jiàn)負(fù)荷與空氣質(zhì)量序列模型代碼覆蓋數(shù)據(jù)預(yù)處理、訓(xùn)練、評(píng)估和預(yù)測(cè)全流程README附有環(huán)境配置與運(yùn)行說(shuō)明圖片直觀展示訓(xùn)練曲線和預(yù)測(cè)效果解壓后即可按說(shuō)明部署運(yùn)行。目前已有1026人學(xué)習(xí)下載無(wú)論用于課程設(shè)計(jì)、期末答辯還是代碼復(fù)用都能提供完整可跑的參考實(shí)現(xiàn)。1. 時(shí)間序列預(yù)測(cè)LSTM 模型是玄學(xué)還是送分題一份高分期末源碼的完整拆解時(shí)間序列預(yù)測(cè)LSTM 模型這門課在很多人眼里是玄學(xué)同樣的數(shù)據(jù)有人調(diào)三天還在原地打轉(zhuǎn)有人一把過(guò)還拿了高分。差別往往不在模型多高級(jí)而在數(shù)據(jù)和流程的細(xì)節(jié)對(duì)不對(duì)。這份源碼是已經(jīng)拿高分通過(guò)的期末大作業(yè)一個(gè)可直接打開(kāi)的 PyCharm 工程內(nèi)置 ETTh1、ETTm1、pollution 三套公開(kāi)數(shù)據(jù)集RNN、RNN_gpu、Transformer 三個(gè)模型文件齊整README 連運(yùn)行截圖都配好了解壓裝好依賴就能復(fù)現(xiàn)。它解決的不是讀論文而是交作業(yè)期末要做時(shí)間序列課設(shè)的學(xué)生或者想快速跑通 LSTM 完整流程的入門開(kāi)發(fā)者都能直接抓起來(lái)用。下面按數(shù)據(jù)、模型、跑通、踩坑的順序把這套工程的關(guān)鍵細(xì)節(jié)一次講透。2. 數(shù)據(jù)先行ETTh1、ETTm1、pollution 三套數(shù)據(jù)集怎么選、怎么做滑窗2.1 三套數(shù)據(jù)的出身、字段與適用選題ETTh1.csv 和 ETTm1.csv 來(lái)自同一個(gè)公開(kāi)的電力變壓器溫度數(shù)據(jù)集前者每小時(shí)一條h 后綴表示 hourly后者每 15 分鐘一條m 后綴表示 minutely。特征以電力負(fù)荷、油溫、風(fēng)速這類物理量為主適合基于 LSTM 的變壓器油溫預(yù)測(cè)或電力負(fù)荷短期預(yù)測(cè)這類選題。pollution.csv 是北京 PM2.5 多變量數(shù)據(jù)集字段包括 pm2.5、DEWP露點(diǎn)、TEMP溫度、PRES氣壓、cbwd風(fēng)向、Iws風(fēng)速、Is積雪時(shí)間、Ir降雨量做空氣質(zhì)量預(yù)測(cè)最合適。數(shù)據(jù)集采樣粒度典型選題變量特征ETTh1.csv1 小時(shí)電力負(fù)荷 / 油溫預(yù)測(cè)多變量周期以天、周為尺度ETTm1.csv15 分鐘分鐘級(jí)短期預(yù)測(cè)多變量周期特征更密集pollution.csv1 小時(shí)含完整日期時(shí)間PM2.5 濃度預(yù)測(cè)8 個(gè)特征含分類風(fēng)向選數(shù)據(jù)只有一個(gè)原則需要弄清作業(yè)要求單變量預(yù)測(cè)就把目標(biāo)列單獨(dú)提出來(lái)當(dāng) y其余列要么當(dāng)外部特征、要么直接舍棄要求多變量預(yù)測(cè)就整表進(jìn)特征。這份工程把三套數(shù)據(jù)都配好了切換只需要改代碼里的 csv 路徑。2.2 歸一化與劃分順序數(shù)據(jù)泄露是期末課設(shè)的第一個(gè)坑很多人在這一步翻車讀 csv 之后先對(duì)整個(gè) DataFrame 做 MinMaxScaler再切訓(xùn)練集和測(cè)試集。這個(gè)順序會(huì)讓測(cè)試集的 min/max 信息提前暴露給訓(xùn)練過(guò)程訓(xùn)練時(shí)相當(dāng)于偷看到了未來(lái)序列的分布測(cè)試 RMSE 虛低等答辯現(xiàn)場(chǎng)換一段新數(shù)據(jù)預(yù)測(cè)立刻露餡。正確做法是先按時(shí)間切分再分別歸一化scaler 只在訓(xùn)練集上 fit。import pandas as pd from sklearn.preprocessing import MinMaxScaler df pd.read_csv(data/pollution.csv, index_col0, parse_datesTrue) # 前 80% 時(shí)間做訓(xùn)練后 20% 做測(cè)試時(shí)間序列不能隨機(jī) shuffle split int(len(df) * 0.8) train_df, test_df df.iloc[:split], df.iloc[split:] scaler MinMaxScaler(feature_range(0, 1)) scaled_train scaler.fit_transform(train_df) # 只在訓(xùn)練集上 fit scaled_test scaler.transform(test_df) # 測(cè)試集只 transformfit_transform 和 transform 的分工是這套流程的核心fit 學(xué)的是訓(xùn)練集的 min 和 maxtransform 只是套用測(cè)試集一旦參與 fit就等同于提前看到了未來(lái)數(shù)據(jù)的取值范圍。歸一化完成后再做滑窗喂給 LSTM 的每個(gè)窗口都在同一尺度下梯度更新才穩(wěn)定。2.3 滑動(dòng)窗口lookback 是整天作業(yè)里最值得調(diào)的參數(shù)LSTM 不是把整條序列直接丟進(jìn)網(wǎng)絡(luò)而是構(gòu)造用過(guò)去 lookback 個(gè)時(shí)間步預(yù)測(cè)下一個(gè)時(shí)間步的樣本。我一般會(huì)把滑窗函數(shù)單獨(dú)抽出來(lái)方便后面換 lookback 做對(duì)照實(shí)驗(yàn)import numpy as np def make_sequences(data, lookback24): X, y [], [] for i in range(len(data) - lookback): X.append(data[i:i lookback]) # 過(guò)去 24 個(gè)時(shí)刻 y.append(data[i lookback]) # 未來(lái) 1 個(gè)時(shí)刻 return np.array(X), np.array(y) lookback 24 X_train, y_train make_sequences(scaled_train, lookback) X_test, y_test make_sequences(scaled_test, lookback) print(X_train.shape, y_train.shape)輸出形狀是 (樣本數(shù), lookback, 特征數(shù)) 和 (樣本數(shù), 特征數(shù))。lookback 的選擇必須跟著采樣粒度走ETTh1 是小時(shí)級(jí)、預(yù)測(cè)下一天24 起步想看周周期拉 168ETTm1 是 15 分鐘級(jí)、一天有 96 步取 48 或 96 更合理pollution 小時(shí)級(jí)24 小時(shí)是默認(rèn)起點(diǎn)。lookback 太大訓(xùn)練變慢且容易過(guò)擬合太小學(xué)不到周期這筆賬用驗(yàn)證集跑兩組對(duì)照再定。pollution.csv 原始數(shù)據(jù)存在缺失值常見(jiàn)做法是先沿時(shí)間方向 ffill 前向填充、再丟掉頭部空行最后歸一化df df.ffill().dropna()3. 模型實(shí)現(xiàn)RNN.py、RNN_gpu.py、Transformer.py 三份代碼分別承擔(dān)什么角色3.1 基礎(chǔ) RNN 為什么打不過(guò) LSTM先弄懂門控在干什么這份工程里有 RNN.py 和 RNN_gpu.py 兩個(gè)文件?;A(chǔ) RNN 的短板在于梯度沿時(shí)間步逐層相乘序列一長(zhǎng)梯度要么小到消失、要么大到爆炸結(jié)果模型對(duì)窗口早期信息幾乎沒(méi)記憶。LSTM 用遺忘門、輸入門、輸出門配合 sigmoid 和 tanh決定哪些信息扔掉、哪些寫進(jìn)長(zhǎng)期記憶梯度在細(xì)胞狀態(tài)路徑上有相對(duì)平緩的通道長(zhǎng)序列也能穩(wěn)定訓(xùn)練。課設(shè)把 LSTM 當(dāng)主角不是因?yàn)樗拍钚露峭瑯拥臄?shù)據(jù)和訓(xùn)練輪數(shù)下驗(yàn)證 loss 通常比基礎(chǔ) RNN 低一截。拿到源碼后建議按角色分工理解RNN.py 跑 baselineRNN_gpu.py 是 LSTM 或 GRU 的 GPU 加速版本裝好 GPU 版 TensorFlow 后直接跑Transformer.py 是答辯加分項(xiàng)。先跑通 LSTM 版本再回頭補(bǔ) baseline 和 Transformer 的對(duì)比報(bào)告才有內(nèi)容可寫。3.2 搭一個(gè)能出成果的 LSTMunits、return_sequences、dropout 怎么設(shè)工程里的 LSTM 是雙層的典型課設(shè)結(jié)構(gòu)第一層輸出完整時(shí)間步給第二層第二層只留最后一個(gè)時(shí)間步接全連接from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense, Dropout n_features X_train.shape[2] model Sequential([ LSTM(64, return_sequencesTrue, input_shape(lookback, n_features), dropout0.2), LSTM(32, dropout0.2), Dense(n_features) ]) model.compile(optimizeradam, lossmse, metrics[mae]) model.summary()參數(shù)含義逐個(gè)說(shuō)清楚第一個(gè) LSTM 的 units64 是隱藏神經(jīng)元數(shù)return_sequencesTrue 表示輸出每個(gè)時(shí)間步的隱藏狀態(tài)給下一層第二層 return_sequences 不設(shè)默認(rèn) False只輸出最后一步的向量再接 Dense。input_shape(lookback, n_features)即滑窗長(zhǎng)度和特征數(shù)。dropout 放在 LSTM 內(nèi)部抑制過(guò)擬合課設(shè)從 0.2 起步穩(wěn)妥。優(yōu)化器 adam、損失 mse 是回歸預(yù)測(cè)的默認(rèn)組合mae 作為輔助評(píng)估指標(biāo)。單變量預(yù)測(cè)時(shí) n_features1多變量時(shí)是 8 或更多Dense 輸出維度跟著改。模型保存的約定是 model 目錄放權(quán)重文件state 目錄放訓(xùn)練狀態(tài)或歸一化 scaler 信息model.save(model/lstm_pollution.h5)3.3 Transformer.py 的定位對(duì)照實(shí)驗(yàn)怎么做才不顯得堆材料Transformer 對(duì)時(shí)間序列的優(yōu)勢(shì)是并行處理整個(gè)窗口用自注意力直接建模任意兩個(gè)時(shí)間步的關(guān)系。這類課設(shè)工程里的 Transformer.py 通常是簡(jiǎn)化版編碼器結(jié)構(gòu)位置編碼、多頭注意力、前饋網(wǎng)絡(luò)、層歸一化。答辯時(shí)用白板畫清楚輸入先加位置編碼再過(guò)多頭注意力層注意力權(quán)重表示第 3 小時(shí)的油溫變化會(huì)強(qiáng)烈影響第 20 小時(shí)的預(yù)測(cè)——這是 LSTM 很難直觀解釋的一點(diǎn)。from tensorflow.keras.layers import Layer, MultiHeadAttention, LayerNormalization, Dense class TransformerBlock(Layer): def __init__(self, d_model64, num_heads4, ff_dim128): super().__init__() self.att MultiHeadAttention(num_headsnum_heads, key_dimd_model) self.ffn Sequential([ Dense(ff_dim, activationrelu), Dense(d_model), ]) self.layernorm1 LayerNormalization(epsilon1e-6) self.layernorm2 LayerNormalization(epsilon1e-6) def call(self, inputs): attn_output self.att(inputs, inputs) # 自注意力 out1 self.layernorm1(inputs attn_output) # 殘差 層歸一化 out2 self.layernorm2(out1 self.ffn(out1)) return out2注意 Transformer 對(duì)數(shù)據(jù)量的要求比 LSTM 高這份工程在 pollution.csv 上能出合理結(jié)果是因?yàn)樾蛄虚L(zhǎng)度和樣本量正好夠用。換更小的數(shù)據(jù)集時(shí)先降 d_model 和 num_heads否則訓(xùn)練 loss 壓不下去。做對(duì)照組時(shí)固定同一批數(shù)據(jù)、同一個(gè) lookback、同一個(gè) scaler只換模型結(jié)構(gòu)答辯老師才挑不出毛病。4. 完整復(fù)現(xiàn)路徑從配環(huán)境、跑通三份代碼到畫出預(yù)測(cè)曲線4.1 環(huán)境準(zhǔn)備Python 版本與依賴清單工程里帶著 .idea 目錄用 PyCharm 直接打開(kāi)項(xiàng)目根目錄即可運(yùn)行配置都在包里不用手動(dòng)建環(huán)境再逐個(gè)配參數(shù)。Python 建議用 3.8 到 3.10TensorFlow 2.x 在這幾個(gè)版本下最穩(wěn)定。依賴就四件套pip install numpy pandas matplotlib scikit-learn tensorflow只跑 LSTM 的話CPU 版 TensorFlow 完全夠用要跑 RNN_gpu.py 的 GPU 路徑需要確認(rèn)機(jī)器的 CUDA 和 cuDNN 版本跟 TensorFlow 匹配。遇到 Python 版本太新裝不上 TensorFlow 的情況最省事的解法是建一個(gè) 3.10 以下的虛擬環(huán)境再在這個(gè)環(huán)境里重裝依賴。4.2 按 README 順序跑通三套模型README.md 里每一步截圖都放好了照著順序執(zhí)行就行python RNN.py # baseline python RNN_gpu.py # GPU/CPU 均可跑內(nèi)部自動(dòng)判斷設(shè)備 python Transformer.py # 對(duì)照模型每個(gè)腳本獨(dú)立運(yùn)行輸出統(tǒng)一寫到 model 和 state 目錄。第一次跑建議只跑 RNN_gpu.py確認(rèn)數(shù)據(jù)路徑和 TensorFlow 版本沒(méi)問(wèn)題后再補(bǔ)跑另外兩個(gè)。腳本里寫的是相對(duì)路徑 data/ETTh1.csv解壓后如果把數(shù)據(jù)文件移走了會(huì)直接報(bào)文件不存在先檢查當(dāng)前工作目錄。4.3 訓(xùn)練參數(shù)速查表與調(diào)參順序參數(shù)常見(jiàn)值說(shuō)明lookback24 / 48 / 96 / 168滑窗長(zhǎng)度小時(shí)級(jí)數(shù)據(jù) 24 起步units32 / 64 / 128第一層 LSTM 神經(jīng)元數(shù)dropout0.1 - 0.3防過(guò)擬合課設(shè) 0.2 起步batch_size16 / 32 / 64越大批次訓(xùn)練越快但可能收斂到較差解epochs50 - 150配合早停使用lossmse / mae回歸任務(wù)默認(rèn) mseoptimizeradam學(xué)習(xí)率 0.001 起步調(diào)參順序我習(xí)慣先固定 lookback配上 epochs 和早停再動(dòng) units最后才碰 dropout。一上來(lái)同時(shí)改三個(gè)參數(shù)最后訓(xùn)完根本說(shuō)不清效果變化是誰(shuí)帶來(lái)的。4.4 訓(xùn)練完看什么loss 曲線和真實(shí)值預(yù)測(cè)值曲線README 截圖里最核心的圖是真實(shí)值和預(yù)測(cè)值的曲線對(duì)比。自己驗(yàn)證時(shí)用這段代碼出圖import matplotlib.pyplot as plt inv_pred scaler.inverse_transform(pred.reshape(-1, n_features)) inv_true scaler.inverse_transform(y_test.reshape(-1, n_features)) plt.figure(figsize(12, 4)) plt.plot(inv_true[:200], labeltrue) plt.plot(inv_pred[:200], labelpred) plt.legend() plt.title(LSTM Prediction vs True) plt.show()pred 是模型輸出的歸一化值畫圖前必須用訓(xùn)練時(shí)的 scaler 反歸一化回去否則縱軸范圍只有 0-1跟真實(shí)值完全對(duì)不上。反歸一化之前要把 pred reshape 成 (樣本數(shù), 特征數(shù)) 再調(diào) inverse_transform。兩條曲線趨勢(shì)一致、局部波動(dòng)有一點(diǎn)相位差是正常的看到預(yù)測(cè)曲線幾乎是平移的直線說(shuō)明訓(xùn)練環(huán)節(jié)出了問(wèn)題大概率是數(shù)據(jù)泄露或滑窗構(gòu)造錯(cuò)了下一章逐個(gè)排查。5. 避坑實(shí)錄這份源碼復(fù)現(xiàn)路上最常見(jiàn)的 5 個(gè)翻車點(diǎn)5.1 預(yù)測(cè)曲線是一條筆直的躺平線現(xiàn)象訓(xùn)練 loss 還在降驗(yàn)證 loss 也正常畫出來(lái)的預(yù)測(cè)曲線卻像把上一天的值平移了一下變化極小。原因絕大多數(shù)情況是歸一化和劃分順序做反了scaler 在切分前對(duì)整個(gè)數(shù)據(jù)集 fit造成數(shù)據(jù)泄露也可能是 lookback 太短模型退化成只學(xué)會(huì)復(fù)制最近一個(gè)點(diǎn)還有可能是 Dense 輸出維度對(duì)應(yīng)不上特征數(shù)模型擬合到均值上去。解決回到第 2 章的流程確認(rèn) scaler 只在訓(xùn)練集上 fit把 lookback 從 24 往上調(diào)試 48、96逼模型看更長(zhǎng)歷史檢查數(shù)據(jù)有沒(méi)有排序錯(cuò)亂的行時(shí)間序列所有操作都不能 shuffle。5.2 inverse_transform 報(bào) ValueError維度對(duì)不上現(xiàn)象報(bào)錯(cuò)類似 Found input variables with inconsistent numbers of samples或者 reshape 時(shí)長(zhǎng)度正好差一個(gè) lookback。原因訓(xùn)練集和測(cè)試集構(gòu)造滑窗后樣本數(shù)不一致測(cè)試樣本數(shù)等于原始測(cè)試行數(shù)減 lookback畫圖和計(jì)算指標(biāo)時(shí)拿錯(cuò)長(zhǎng)度。解決所有涉及 y_test 和 pred 的地方統(tǒng)一用同一個(gè)切片長(zhǎng)度predict 返回的結(jié)果先 reshape 成 (n_samples, n_features)再傳給 scaler.inverse_transform。5.3 模型構(gòu)建直接報(bào) incompatibleexpected ndim3, found ndim2現(xiàn)象構(gòu)建 Sequential 時(shí)TensorFlow 報(bào) Input 0 of layer lstm is incompatible: expected ndim3, found ndim2。原因LSTM 要求輸入三維格式是 (樣本數(shù), lookback, 特征數(shù))把二維數(shù)組直接丟進(jìn)去了說(shuō)明滑窗沒(méi)做或數(shù)據(jù)被 reshape 壓平了。解決打印 X_train.shape 確認(rèn)是三維滑窗函數(shù)沒(méi)寫對(duì)回第 2 章重新構(gòu)造多變量預(yù)測(cè)時(shí)把 n_features 和 Dense 輸出維度對(duì)齊。5.4 驗(yàn)證 loss 先降后升訓(xùn)練 loss 還在掉現(xiàn)象前幾十個(gè) epoch 兩條 loss 一起降往后驗(yàn)證 loss 開(kāi)始反彈訓(xùn)練 loss 卻繼續(xù)走低。原因典型過(guò)擬合。LSTM 參數(shù)量不小pollution 這類數(shù)據(jù)量也就幾千行訓(xùn)練太久模型把訓(xùn)練集噪聲當(dāng)成了規(guī)律。解決把 dropout 加到 0.2 以上加早停是更省事的辦法patience 設(shè) 10-15監(jiān)控 val_loss連續(xù)沒(méi)改善就回滾到最佳權(quán)重from tensorflow.keras.callbacks import EarlyStopping early_stop EarlyStopping(monitorval_loss, patience10, restore_best_weightsTrue) model.fit(X_train, y_train, validation_data(X_test, y_test), epochs100, batch_size32, callbacks[early_stop])5.5 加載保存的模型后預(yù)測(cè)全 NaN現(xiàn)象訓(xùn)練完保存了 model/lstm_pollution.h5換個(gè)腳本重新加載預(yù)測(cè)輸出大面積 NaN。原因加載和訓(xùn)練用了不同版本的 TensorFlow或者保存的是自定義 Transformer 層、加載腳本沒(méi)注冊(cè)對(duì)應(yīng)的層定義另一個(gè)常見(jiàn)原因是歸一化前的數(shù)據(jù)本身帶 NaN訓(xùn)練時(shí)表面正常保存時(shí)權(quán)重已經(jīng)被污染。解決加載和訓(xùn)練必須同一環(huán)境自定義層對(duì)象要在加載腳本里先 import 進(jìn)來(lái)回到第 2 章df.ffill().dropna() 先把數(shù)據(jù)清干凈再歸一化。這條習(xí)慣能躲掉九成 NaN 鬧鬼。6. 把作業(yè)從能跑改到能答辯多步預(yù)測(cè)、回歸指標(biāo)和 baseline 對(duì)照6.1 單步改多步滾動(dòng)預(yù)測(cè)和它的誤差累積單步預(yù)測(cè)是用過(guò)去 24 小時(shí)預(yù)測(cè)下 1 小時(shí)答辯時(shí)老師通常會(huì)追問(wèn)能不能預(yù)測(cè)未來(lái) 24 小時(shí)。最小改動(dòng)是滾動(dòng)預(yù)測(cè)把上一步的預(yù)測(cè)結(jié)果當(dāng)成新窗口輸入循環(huán) 24 次。def forecast(model, last_window, steps24): preds [] window last_window.copy() for _ in range(steps): p model.predict(window[np.newaxis, :, :], verbose0)[0] preds.append(p) window np.concatenate([window[1:], p[np.newaxis, :]], axis0) return np.array(preds)window 形狀是 (lookback, n_features)每預(yù)測(cè)一步把窗口往前推一格末尾補(bǔ)上剛預(yù)測(cè)的值。多步預(yù)測(cè)的坑是誤差累積第 24 步的誤差遠(yuǎn)大于第 1 步答辯時(shí)主動(dòng)承認(rèn)這一點(diǎn)反而顯得你理解序列預(yù)測(cè)的本質(zhì)。6.2 回歸三件套R(shí)MSE、MAE、R2 出一張指標(biāo)表光有曲線不夠看答辯還需要指標(biāo)表。計(jì)算后按 RMSE、MAE、R2 排三行直接進(jìn)報(bào)告from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score rmse mean_squared_error(inv_true, inv_pred, squaredFalse) mae mean_absolute_error(inv_true, inv_pred) r2 r2_score(inv_true, inv_pred) print(fRMSE{rmse:.3f}, MAE{mae:.3f}, R2{r2:.3f})新版 sklearn 里 squaredFalse 是老版 mean_squared_error 的替代寫法老接口會(huì)報(bào)警告但不影響數(shù)值。R2 接近 1 說(shuō)明擬合好負(fù)值說(shuō)明模型比直接預(yù)測(cè)均值還差指標(biāo)表里順手把 baseline 也算上。6.3 樸素 baseline讓 LSTM 的優(yōu)勢(shì)有對(duì)照答辯被問(wèn)憑什么說(shuō) LSTM 有效時(shí)最實(shí)在的回答是給一個(gè)基線用過(guò)去 24 小時(shí)的均值當(dāng)預(yù)測(cè)結(jié)果算同一套 RMSE、MAE 對(duì)比。通常 LSTM 能把 RMSE 壓到基線的一半左右這個(gè)數(shù)字比講任何原理都有說(shuō)服力。建議做實(shí)驗(yàn)時(shí)固定同一個(gè) scaler 和后處理流程算出 LSTM、RNN baseline、Transformer 三行指標(biāo)形成一張干干凈凈的對(duì)比表課程報(bào)告直接把表貼進(jìn)去。這套工程解壓后對(duì)照 README 用省掉的配置時(shí)間能把三個(gè)模型都跑一遍。從那以后我每次跑序列預(yù)測(cè)課設(shè)都強(qiáng)制自己先打印數(shù)據(jù)行列數(shù)、確認(rèn)歸一化只在訓(xùn)練集上 fit、再檢查滑窗 shape三個(gè)檢查項(xiàng)過(guò)完才談?wù){(diào)參這套流程幫我避開(kāi)了絕大多數(shù)翻車現(xiàn)場(chǎng)希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取