測:超越LSTM與ARIMA的建模與調(diào)參指南)
簡介2022年第十屆泰迪杯B題電力負(fù)荷預(yù)測完整方案基于AutoTS自動化時間序列框架以Python實現(xiàn)數(shù)據(jù)清洗、建模與預(yù)測。相較于LSTM、ARIMA等傳統(tǒng)模型AutoTS在擬合精度與預(yù)測準(zhǔn)確度上表現(xiàn)更優(yōu)適合備戰(zhàn)泰迪杯等數(shù)據(jù)挖掘競賽、從事電力負(fù)荷預(yù)測或時間序列分析的研究者參考。資源共25個文件含13個CSV數(shù)據(jù)與預(yù)測結(jié)果文件、8個IPYNB分步建模與分析筆記、3個PY執(zhí)行腳本及1個XLS匯總表壓縮包僅2.31MB目錄按題目結(jié)構(gòu)組織便于檢索復(fù)用。已有1442人瀏覽學(xué)習(xí)。包內(nèi)覆蓋第一大問與第二大問各小問的完整處理流程包括AutoTS模型調(diào)用、參數(shù)調(diào)優(yōu)、未來三個月每日負(fù)荷預(yù)測結(jié)果以及大工業(yè)、普通工業(yè)、商業(yè)等分類用電的有功功率預(yù)測輸出。可直接對照代碼修改數(shù)據(jù)路徑與參數(shù)快速復(fù)現(xiàn)賽題方案也可遷移至其他電力負(fù)荷或時間序列預(yù)測任務(wù)中。1. 泰迪杯 B 題的 Auto TS 方案為什么它能同時贏過 LSTM 與 ARIMA2022 年第十屆泰迪杯 B 題這類賽題望文生義就知其敏感給一份歷史序列讓你預(yù)測未來一段時間的走勢。過往多數(shù)參賽隊伍的第一反應(yīng)是上 LSTM第二反應(yīng)是拉 ARIMA 做差分兩條路各有各的坑。LSTM 對數(shù)據(jù)量和調(diào)參極度敏感小樣本序列上經(jīng)常學(xué)到噪聲ARIMA 則被階數(shù)選擇困住p、d、q 三參數(shù)全靠 ACF/PACF 圖硬猜猜錯一步整體報廢。而標(biāo)題里這個 Auto TS 方案本質(zhì)是把“模型選擇超參尋優(yōu)誤差評估”全部交給自動化管線在一個搜索空間里同時跑完多種候選模型再按設(shè)定準(zhǔn)則挑最優(yōu)。它在擬合程度和精確度上同時壓過 LSTM 和 ARIMA不是玄學(xué)而是它在有限樣本、單變量時序這種典型賽題場景里恰好避開了兩類對手最致命的短板。這篇文章不打算復(fù)刻某份比賽源碼而是把這條 Auto TS 路線的建模邏輯、必調(diào)參數(shù)和驗證方法拆開講透讓拿到同類題的人能直接套用。2. Auto TS 在時間序列里到底做了什么從模型搜索到自動調(diào)參2.1 你不需要在 ARIMA 和 ETS 之間二選一讓 Auto TS 替你搜索傳統(tǒng)時序建模的痛點在于“選型靠經(jīng)驗”。拿到序列先畫圖目測有沒有趨勢、有沒有季節(jié)性然后決定用 ARIMA 還是指數(shù)平滑接著再為 ARIMA 定階。這一套流程在賽題時間壓力下非常容易出錯序列長度不夠時 ACF/PACF 圖全是毛刺差分階數(shù) d 取 1 還是 2 完全靠手感seasonal 周期判斷錯了模型直接殘差爆炸。Auto TS 把這件事變成了搜索問題。以開源的 AutoTS 庫為例它內(nèi)置了 ARIMA、ETS、Theta、TBATS、GluonTS 等多個候選模型族自動生成一組候選配置比如 ARIMA(2,1,2) 配季節(jié)性周期 7、ETS 配乘法趨勢、Theta 配 0.3 平滑參數(shù)然后用時間序列交叉驗證逐一評估最后按你指定的指標(biāo)MAE、RMSE、MAPE 等選出最優(yōu)模型。你不需要預(yù)先知道數(shù)據(jù)是加法還是乘法季節(jié)性也不需要手工定 p、d、q把候選空間交給搜索器比你肉眼猜要穩(wěn)得多。我一般會先跑一次最小配置的 Auto TS看它選出哪個模型族、哪個參數(shù)組合這個結(jié)果本身就暴露了序列的結(jié)構(gòu)特征。比如它選了 ETS 的乘法季節(jié)性說明序列的波動幅度隨水平值放大選了帶差分的 ARIMA說明序列非平穩(wěn)。這一手信息比你自己去畫圖猜來得快也更有依據(jù)。2.2 你真的讀懂“精確度比 LSTM 高”嗎幾種誤差口徑的意義標(biāo)題里說的“精確度更高”落到代碼層面其實是某個誤差指標(biāo)更小但“哪個指標(biāo)”直接決定結(jié)論是否成立。回歸預(yù)測常見四個口徑MAE 是絕對誤差的平均RMSE 放大離群點的懲罰MAPE 是百分比誤差適合對比不同量級的序列但真實值接近 0 時它會爆炸SMAPE 是 MAPE 的對稱版本賽題常用的還有它。Auto TS 評估時默認(rèn)按訓(xùn)練集內(nèi)部做交叉驗證來選模型這個內(nèi)部指標(biāo)和你最后對外報告的指標(biāo)一旦不一致會出現(xiàn)“模型選優(yōu)用的 MAE最終答辯卻匯報 MAPE”的錯位。我在某次模擬項目X里就干過這事Auto TS 內(nèi)部優(yōu)化用 RMSE選出一個對尖峰特別敏感的模型結(jié)果換到 MAPE 上一看被另一個候選模型甩開一大截。所以拿到 Auto TS 的模型后不要直接用它的內(nèi)置指標(biāo)對外匯報要用同一套測試集、同一個誤差口徑重新算一遍。表格對比 LSTM、ARIMA、Auto TS 在賽題里的典型表現(xiàn)時我習(xí)慣固定三個維度測試集長度一致、預(yù)測起點一致、誤差公式一致否則對比表沒有意義。后面第 6 章會專門講這個公平對比怎么做。2.3 環(huán)境準(zhǔn)備與庫選型pmdarima、statsforecast 與 autots 的取舍賽題環(huán)境一般只給 Python 基礎(chǔ)包Auto TS 相關(guān)的庫需要自己裝。常見的三個選擇pmdarima 只做 ARIMA 的自動定階本質(zhì)是 auto_arima不算完整的 Auto TSstatsforecast 的 AutoARIMA、AutoETS 性能好、速度快但搜索策略偏單模型AutoTS 庫覆蓋面廣能同時搜多個模型族適合比賽這種“不知道哪個模型好用”的場景。我的建議是主力用 AutoTS 庫做整體搜索拿到它的最優(yōu)模型后再把同樣配置塞給 statsforecast 復(fù)算一次當(dāng)交叉驗證。兩個庫對同一組參數(shù)的評價邏輯略有差異結(jié)果互相印證時更可信。安裝時注意環(huán)境隔離這幾個庫對 NumPy 版本有要求我吃過虧在新環(huán)境里裝完 AutoTSimport 時報 libgomp 相關(guān)的錯最后是重建虛擬環(huán)境、指定 NumPy 的某個兼容版本才跑通。代碼塊只貼最關(guān)鍵的安裝與版本核對命令賽題服務(wù)器一般離線建議提前把 wheel 文件下載好傳進(jìn)去pip install autots python -c import autots; print(autots.__version__)邏輯說明第一行安裝 AutoTS 主包它會連帶拉起 pandas、scikit-learn 等依賴第二行核對版本號確認(rèn)安裝成功再往下走。參數(shù)說明這里沒有額外參數(shù)重點是確認(rèn) import 不報錯。3. 數(shù)據(jù)準(zhǔn)備把 B 題原始序列整理成 Auto TS 能直接吃的格式3.1 時間列對齊、缺失值填補(bǔ)與異常點處理賽題給的數(shù)據(jù)往往不是干凈的 DataFrame常見情況是日期列是字符串、時間間隔不均勻、中間有缺失日期。AutoTS 對輸入格式要求很明確必須是一個 pandas DataFrame包含一列時間可以是 datetime 類型和一列數(shù)值時間列做索引列名最好是英文。先統(tǒng)一轉(zhuǎn)換時間列再把缺失的日期補(bǔ)出來。import pandas as pd df pd.read_csv(b_data.csv, parse_dates[date]) df df.set_index(date).sort_index() df df.asfreq(D) # 把時間軸對齊到每天 df[value] df[value].interpolate(methodlinear).fillna(methodffill) df df[df[value] 0] # 賽題值域通常為正過濾異常負(fù)值邏輯說明parse_dates 在讀取時就把時間列轉(zhuǎn)成 datetime 類型set_index 把時間列設(shè)為索引后面 AutoTS 按索引頻率推斷周期asfreq(D) 強(qiáng)制把缺失的日期補(bǔ)出來補(bǔ)出來的行 value 是 NaNinterpolate 用線性插值填掉缺口最后過濾掉明顯的負(fù)值異常點。參數(shù)說明頻率D表示按天對齊如果數(shù)據(jù)是小時級改成Hinterpolate 的 method 可以換time對時間索引做插值更自然但速度慢一些。這里有個特別注意AutoTS 內(nèi)部會把索引的頻率當(dāng)成季節(jié)周期的參考頻率不統(tǒng)一時它推算的 season_length 會錯。我見過一個案例數(shù)據(jù)本身是工作日數(shù)據(jù)索引里卻有周末日期導(dǎo)致模型識別出 7 天周期實際業(yè)務(wù)周期是 5 天。所以對齊頻率后務(wù)必用 df.index.freq 看一眼推斷結(jié)果不對就直接手動指定。3.2 平穩(wěn)性檢驗與差分讓 Auto TS 少走彎路Auto TS 內(nèi)部對部分模型會自動做平穩(wěn)性處理但它不會替你做“要不要差分”的決策提前做好可以讓搜索空間更小、結(jié)果更穩(wěn)。用 ADF 檢驗做一個快速判斷from statsmodels.tsa.stattools import adfuller result adfuller(df[value].dropna()) print(ADF p-value:, result[1]) if result[1] 0.05: df[value] df[value].diff().dropna()邏輯說明ADF 檢驗的原假設(shè)是序列非平穩(wěn)p 值小于 0.05 才拒絕原假設(shè)、認(rèn)為序列平穩(wěn)。p 大于 0.05 時我們對原序列做一階差分把差分后的序列喂給模型。參數(shù)說明diff() 默認(rèn)一階差分如果一階差分后還不平穩(wěn)執(zhí)行第二次 diff()但絕大多數(shù)賽題序列一階差分足夠adfuller 的 autolag 參數(shù)默認(rèn)是AIC自動選滯后階數(shù)一般不用動。做完差分后預(yù)測結(jié)果要記得還原AutoTS 的 forecast 輸出的是差分后的值你得用最后一期真實值把差分值累加回去。這個還原步驟漏掉的人不少。我一般把最后一期真實值單獨(dú)存一個變量預(yù)測完直接加回去省得回頭對不上。3.3 訓(xùn)練集、驗證集、測試集的切分窗口時序預(yù)測的切分不能隨機(jī)打亂必須按時間先后切。常見做法是最后 N 個點做測試集測試集前面的 M 個點做驗證集剩下全做訓(xùn)練集。AutoTS 在內(nèi)部做交叉驗證時會自己切驗證集但對外報告時你需要一份“真正沒見過”的測試集用來最終評估模型。test_len 30 val_len 20 train_end - (val_len test_len) val_end -test_len train df.iloc[:train_end] val df.iloc[train_end:val_end] test df.iloc[val_end:]邏輯說明把序列末尾 30 個點留給測試末尾往前 20 個點留給驗證前面全部是訓(xùn)練。AutoTS 先用 train 擬合、在 val 上選模型確認(rèn)最優(yōu)模型后再用 trainval 重新擬合并預(yù)測 test。這種三切分的好處是你在 val 上挑模型時不會碰 test最后 test 的誤差才是可信的對外指標(biāo)。參數(shù)說明test_len 和 val_len 的比例可以考慮數(shù)據(jù)長度數(shù)據(jù)有 365 天時測試集給 30 天是合理區(qū)間取太多訓(xùn)練數(shù)據(jù)不夠取太少測試結(jié)論沒有統(tǒng)計意義。三切分的另一個價值是它可以暴露過擬合。如果 AutoTS 在 val 上誤差很小、在 test 上突然放大說明搜索出的模型對訓(xùn)練段過度擬合你就該回頭限制模型復(fù)雜度比如把搜索次數(shù)調(diào)低、候選模型精簡。4. Auto TS 建模與必調(diào)參數(shù)一份可直接套用的核心代碼4.1 快速跑通最小模型三行代碼拿到第一個預(yù)測結(jié)果先把最小可跑的代碼貼出來確認(rèn)環(huán)境沒問題再談?wù){(diào)參。AutoTS 庫的建模接口大致如下from autots import AutoTS model AutoTS( forecast_length30, frequencyD, constraintmedium, ensembleauto, ) model.fit(df, future_forecast_length30) pred model.predict()邏輯說明AutoTS 在 fit 階段搜索候選模型predict 階段輸出未來 30 天的預(yù)測。constraint 控制搜索空間大小medium 是折中檔complex 會更耗時間但可能搜到更優(yōu)模型。ensembleauto 會讓模型在最后嘗試把多個候選結(jié)果做加權(quán)組合通常能小幅提升精度。參數(shù)說明forecast_length 是單次預(yù)測長度必須和賽題要求一致frequency 建議寫成D或取決于數(shù)據(jù)的最小間隔。這一段代碼不調(diào)任何高級參數(shù)直接拿默認(rèn)搜索空間跑。跑通之后看兩個對象一個是 model.best_model_name告訴你搜索器認(rèn)為最優(yōu)的模型族是什么另一個是 model.best_model_params記錄具體參數(shù)。這兩個字段是你后面手工調(diào)參的出發(fā)點。如果 best_model_name 始終是 Naive 或 SeasonalNaive說明數(shù)據(jù)里沒有足夠信號別繼續(xù)加大搜索力度先回頭檢查預(yù)處理。4.2 打開自動搜索selection 與 forecast_length 等的組合調(diào)整AutoTS 的核心參數(shù)其實是 num_validations 和 model_list。num_validations 控制交叉驗證的折數(shù)默認(rèn) 3意思是把訓(xùn)練段切成 3 份滾動驗證。折數(shù)越大、評估越穩(wěn)但耗時線性增長。model_list 可以傳一個具體列表只搜索你指定的模型族比如 [ARIMA, ETS, Theta]減少搜索范圍換取速度。from autots import AutoTS model AutoTS( forecast_length30, frequencyD, model_list[ARIMA, ETS, Theta], num_validations5, constraintmedium, ensembleauto, metricsmape, ) model.fit(df, future_forecast_length30) pred model.predict()邏輯說明這段代碼把候選模型收窄到三個主流模型族把交叉驗證折數(shù)提高到 5并把模型優(yōu)選的誤差指標(biāo)設(shè)為 smape。交給比賽場景這幾個參數(shù)是對精度影響最明顯的。參數(shù)說明metric 可選 mae、rmse、smape 等選哪個要和你對外報告口徑一致model_list 里寫模型名必須匹配庫內(nèi)置的名字大小寫敏感寫錯會直接報 KeyError。ensembleauto 保留軟融合如果比賽要求可解釋性改成 none 可以只輸出單模型。這里要提醒一句forecast_length 不必等于賽題要預(yù)測的總長度如果你的數(shù)據(jù)支持多步遞歸預(yù)測可以先做短預(yù)測再滾動外推實際效果通常比一次性預(yù)測 60 天更穩(wěn)因為誤差不會在后段滾雪球。我一般把 forecast_length 設(shè)成 20 到 30 天然后滾動重復(fù) predict 拼接結(jié)果。4.3 模型如何被選中cross_validation 與誤差準(zhǔn)則的閱讀方法AutoTS 的模型選擇機(jī)制是把訓(xùn)練段分成 num_validations 份每份末端都有一小段被當(dāng)作驗證段模型在這個多段驗證上計算誤差誤差最小者被選為最優(yōu)。也就是說fit 完成后 model.best_model_name 給出的模型是在你訓(xùn)練段內(nèi)部的“滾動考試”里成績最好的不代表在你切的 val 集合上一定最好。所以手動對賬這一步值得做。用下面代碼看它在 val 上的表現(xiàn)val_pred model.predict() val_true val[value].values from sklearn.metrics import mean_absolute_error print(mean_absolute_error(val_true, val_pred.forecast[value].values))邏輯說明predict 一次得到整個 forecast 對象取其中的預(yù)測列和 val 的真實值比較。這段代碼只算 MAE只是讓你感知模型在你獨(dú)立預(yù)留的 val 上表現(xiàn)幾何。參數(shù)說明val_pred.forecast 是 DataFrame列名與訓(xùn)練時指定列名一致如果你在 fit 時加了 future_forecast_length預(yù)測長度會覆蓋 forecast_length 的設(shè)定對賬時注意長度是否匹配。這一步對賬是我個人習(xí)慣里很重要的一環(huán)發(fā)現(xiàn) AutoTS 內(nèi)部驗證誤差和 val 誤差差 30% 以上就說明搜索過程過擬合了訓(xùn)練段直接換參數(shù)或縮搜索空間。反推回去“精確度比 LSTM 高”的結(jié)論只有在這個對齊之后再匯報才站得住。5. Auto TS 常見問題與排查四個最容易翻車的環(huán)節(jié)5.1 現(xiàn)象數(shù)據(jù)看著干凈但 Auto TS 預(yù)測全是平移某個同學(xué)拿一份周度銷售數(shù)據(jù)跑 AutoTS訓(xùn)練段擬合得完美預(yù)測輸出卻是一條水平線數(shù)值接近訓(xùn)練段最后一周的均值。原因不是模型壞了而是模型選了 Naive 或 SeasonalNaiveNaive 的輸出就是“最后觀測值無限往后復(fù)制”。AutoTS 是誠實的數(shù)據(jù)里沒有強(qiáng)趨勢或周期性時它認(rèn)為最穩(wěn)的預(yù)測就是平移。解決思路分兩步先看 best_model_name確認(rèn)是不是 Naive如果是檢查預(yù)處理階段是否把趨勢信息抹掉了比如誤做了一階差分或者填充缺失值時把尖峰都填平了。還原趨勢后重新搜索一般會跳出 Naive。5.2 現(xiàn)象模型訓(xùn)練特別慢幾分鐘都沒反應(yīng)AutoTS 在 constraintcomplex 且 model_list 不限制時會搜索幾十上百個模型配置每個配置都要跑交叉驗證分鐘級的等待是常態(tài)不是死機(jī)。但比賽時間寶貴不應(yīng)該讓它空轉(zhuǎn)。解決方法是收緊 search 范圍model_list 只保留三四個模型族constraint 降到 mediumnum_validations 降到 3。經(jīng)驗上先跑一次小搜索確定“哪個模型族方向是對的”再針對這個模型族放大搜索比一次性全量搜索快得多效果也不差。5.3 現(xiàn)象驗證集很準(zhǔn)測試集整段偏移AutoTS 在你預(yù)留的 val 上 MAE 小得很漂亮換到 test 上預(yù)測曲線整體高出一截。這個偏移常見原因是訓(xùn)練段和測試段之間有一個結(jié)構(gòu)性突變比如序列最后一段疊加了一次促銷或政策影響而訓(xùn)練段沒有這類樣本。AutoTS 的模型沒有外部變量通道除非你在 fit 里傳入額外回歸特征它只能沿用歷史模式外推遇到突變天然會偏。處理思路是檢查最后一段和前面的分布差異如果突變是已知事件把事件區(qū)間從訓(xùn)練段剔除用更早的數(shù)據(jù)重新擬合如果是不可知的那任何模型都救不了匯報時把這個限制寫清楚。5.4 現(xiàn)象指標(biāo)比 LSTM 高、圖形卻更難看的詭異情況RMSE 和 MAE 這類指標(biāo)只考察“逐點誤差”不考察“曲線形狀”。AutoTS 選出的模型可能逐點誤差小但相位滯后或波峰波谷對不上畫圖看著就是別扭而 LSTM 擬合出的曲線形狀更像雖然逐點誤差大。遇到這種局面我的做法是加一個形狀對比指標(biāo)比如計算預(yù)測和真實值的一階差分的相關(guān)性。相關(guān)性高說明走勢方向捕捉準(zhǔn)確比單一誤差數(shù)字更接近評委關(guān)心的“趨勢預(yù)測”。如果 AutoTS 贏在誤差、輸在形狀考慮在模型列表里加入 momentum 類模型或者直接改用 ensemble 把多個模型的預(yù)測做加權(quán)形狀通常會變自然。6. 實測對比Auto TS 與 LSTM、ARIMA 的誤差表怎么讀才可信6.1 同切分、同時段、同指標(biāo)對比的公平性怎么保證“Auto TS 精確度比 LSTM 和 ARIMA 高”這句話要變成可信結(jié)論必須回到對比實驗本身。常見錯誤是 LSTM 用最后 30 天做測試ARIMA 卻用最后 20 天AutoTS 又換了一個提前量最后擺一個誤差表出來誰也沒法復(fù)現(xiàn)。我推薦的對比框架是三固定預(yù)測起點一致、預(yù)測長度一致、誤差公式一致。起點一致的意思是三個模型的訓(xùn)練段結(jié)束位置相同LSTM 在第九十天開始預(yù)測ARIMA 和 AutoTS 也必須從第九十天開始。預(yù)測長度一致是大家都在同一段 test 上評估而不是各自挑遠(yuǎn)點。誤差公式一致是你匯報時全部用 MAPE或者全部用 RMSE不要 LSTM 用 MAE、ARIMA 用 RMSE自己給自己湊最有利口徑。放一張參考誤差表說明它的格式和邊界再做一次實驗就能用同樣的模板填模型MAERMSEMAPE%ARIMA12.415.88.7LSTM10.914.27.3Auto TS9.612.16.4這張表的數(shù)字不是某個項目的固定結(jié)論只表達(dá)一種“可復(fù)現(xiàn)的對比格式”。三個模型的測試區(qū)間完全一樣誤差才算可比。我在實踐里得到的結(jié)論是Auto TS 在小樣本單變量序列上贏 LSTM 并不稀奇因為 LSTM 在小樣本下很難學(xué)到有效的長期依賴反而被噪聲帶偏但真實業(yè)務(wù)里 LSTM 更適合多變量、長序列場景那又是另一套對比方法了。6.2 一個驗證小技巧用隨機(jī)游走當(dāng)基線讓提升率現(xiàn)出原形最后再給一個我常用的驗證習(xí)慣無論用哪個模型做預(yù)測先跑一個“隨機(jī)游走”基線作為底線。隨機(jī)游走就是“下一期等于本期”它等價于 Naive 模型。如果 AutoTS 連隨機(jī)游走都贏不過那說明數(shù)據(jù)里沒有可利用的信號任何復(fù)雜模型的“高精度”都只是過擬合的幻覺。naive_pred test[value].shift(1) naive_mae mean_absolute_error(test[value][1:], naive_pred[1:]) model_mae mean_absolute_error(test[value], pred.forecast[value].values) print(Naive MAE:, naive_mae) print(Model MAE:, model_mae)邏輯說明shift(1) 產(chǎn)生“用上一期真實值當(dāng)預(yù)測值”的序列去掉第一個空值后和模型誤差對比。如果 model_mae naive_mae你的精心調(diào)參就是在陪跑。參數(shù)說明mean_absolute_error 來自 sklearn.metrics注意對齊長度test 去掉第一個點后長度要和預(yù)測長度完全一致長度不匹配時 sklearn 會報警。我自己的一個習(xí)慣是把所有候選模型的精度提升率都在這個基線上算一遍提升率 naive_mae - model_mae/ naive_mae。這個數(shù)字比“誰比誰高 0.5”更直觀評委也更容易接受。順便說AutoTS 快速驗證階段的默認(rèn)輸出里其實就包含 Naive 模型一旦發(fā)現(xiàn)它排在榜首我通常直接停掉搜索回去看數(shù)據(jù)不再往模型上砸時間。這句話聽著像廢話但我在項目里救過不止一次。希望幫到你。本文還有配套的精品資源點擊獲取