荷預(yù)測(cè)中的Matlab實(shí)現(xiàn))
1. 項(xiàng)目破題電力負(fù)荷預(yù)測(cè)為什么非要做成LSTM-Adaboost做電力負(fù)荷預(yù)測(cè)這個(gè)方向也有幾年了坦白說(shuō)這個(gè)領(lǐng)域最不缺的就是模型——從早期的ARIMA、指數(shù)平滑到后來(lái)的SVM、隨機(jī)森林再到前幾年火得不行的深度學(xué)習(xí)每個(gè)階段都有人拿新模型來(lái)刷一遍精度。但真正到了落地環(huán)節(jié)大家心里都清楚負(fù)荷曲線從來(lái)不會(huì)老老實(shí)實(shí)按照某種單一規(guī)律走工作日和周末差一大截夏天和冬天完全兩個(gè)性格節(jié)假日前后還會(huì)出現(xiàn)莫名其妙的“翹尾”和“跳水”。這時(shí)候單靠一個(gè)模型去硬扛精度上限往往一眼就能看到頭。我之前在某實(shí)驗(yàn)室做負(fù)荷預(yù)測(cè)相關(guān)項(xiàng)目時(shí)最常見(jiàn)的情況是純LSTM已經(jīng)能擬合出大趨勢(shì)但遇到氣溫驟變或者大型活動(dòng)導(dǎo)致的負(fù)荷突變預(yù)測(cè)曲線總會(huì)慢半拍。后來(lái)想到一個(gè)思路——既然單一模型存在短板那就讓多個(gè)模型“投票決策”把LSTM作為基學(xué)習(xí)器嵌進(jìn)Adaboost框架里用集成學(xué)習(xí)的方式把若干個(gè)LSTM的預(yù)測(cè)結(jié)果加權(quán)組合起來(lái)。實(shí)測(cè)下來(lái)整體誤差比單模型能壓低10%到20%而且穩(wěn)定性明顯變好。這套方案放在Matlab里實(shí)現(xiàn)有一個(gè)天然優(yōu)勢(shì)——Matlab的深度學(xué)習(xí)工具箱對(duì)LSTM支持很完整數(shù)據(jù)預(yù)處理、網(wǎng)絡(luò)搭建、訓(xùn)練驗(yàn)證都封裝得比較順手不需要像Python那樣在TensorFlow和sklearn之間來(lái)回倒騰環(huán)境。這篇文章就把整個(gè)項(xiàng)目的拆解思路、Matlab實(shí)現(xiàn)細(xì)節(jié)、踩過(guò)的坑和排查技巧完整寫出來(lái)適合電力方向的研究生、剛接觸負(fù)荷預(yù)測(cè)的算法工程師以及想在Matlab里快速跑通一套組合模型的開(kāi)發(fā)者參考。需要明確的是這個(gè)項(xiàng)目的核心不是簡(jiǎn)單地把LSTM和Adaboost拼在一起而是解決兩個(gè)問(wèn)題第一怎么讓LSTM這個(gè)對(duì)時(shí)序數(shù)據(jù)敏感的基學(xué)習(xí)器在每輪迭代中都學(xué)到“上一輪沒(méi)學(xué)好的部分”第二怎么在Matlab的框架約束下把Adaboost的樣本權(quán)重更新邏輯和LSTM的訓(xùn)練流程平滑地融合起來(lái)。搞清楚這兩個(gè)問(wèn)題后面所有代碼都是水到渠成的事。2. 模型選型背后的邏輯為什么這套組合值得做2.1 負(fù)荷序列的“不友好”特征決定了單模型的瓶頸電力負(fù)荷數(shù)據(jù)本質(zhì)上是一個(gè)高噪聲、強(qiáng)周期、非平穩(wěn)的時(shí)間序列。高噪聲體現(xiàn)在天氣、隨機(jī)事件、人為因素都會(huì)疊加到負(fù)荷曲線上強(qiáng)周期體現(xiàn)在日周期、周周期、季節(jié)周期三層疊加非平穩(wěn)則意味著均值、方差都在隨時(shí)間變化。傳統(tǒng)時(shí)序模型比如ARIMA要求序列平穩(wěn)光是預(yù)處理就要做差分、取對(duì)數(shù)、季節(jié)分解一整套下來(lái)還是比較費(fèi)勁而且對(duì)非線性特征的捕捉能力有限。LSTM之所以在負(fù)荷預(yù)測(cè)里受歡迎核心在于它的門控機(jī)制——遺忘門、輸入門、輸出門協(xié)同工作讓網(wǎng)絡(luò)能記住長(zhǎng)時(shí)間跨度的依賴關(guān)系。舉個(gè)例子預(yù)測(cè)今天下午3點(diǎn)的負(fù)荷模型不僅要看今天上午的趨勢(shì)還要參考前幾天同一時(shí)段的負(fù)荷水平、溫度變化帶來(lái)的滯后影響LSTM通過(guò)細(xì)胞狀態(tài)這個(gè)“傳送帶”把跨天的信息有選擇地保留下來(lái)。但LSTM也有軟肋——初始化權(quán)重不同、訓(xùn)練數(shù)據(jù)劃分不同都會(huì)導(dǎo)致每次訓(xùn)練的模型略有差異這種方差在預(yù)測(cè)曲線的局部區(qū)域特別明顯。單模型精度到一定程度就上不去了不是模型不夠深、參數(shù)不夠多而是偏差和方差之間的權(quán)衡到了一個(gè)瓶頸。這時(shí)候用Adaboost去組合多個(gè)LSTM思路就清晰了每一輪訓(xùn)練都讓新的LSTM更關(guān)注上一輪預(yù)測(cè)誤差較大的樣本最后按權(quán)重投票相當(dāng)于把多個(gè)“偏科”的模型組合成一個(gè)“全科”的模型整體方差被壓下來(lái)精度自然就上去了。2.2 Adaboost與LSTM的適配性為什么不用Bagging也不用XGBoost有人可能第一反應(yīng)是集成學(xué)習(xí)那么多套路為什么非選Adaboost如果換成Bagging比如隨機(jī)森林那套思路對(duì)LSTM這種訓(xùn)練時(shí)間長(zhǎng)的模型來(lái)說(shuō)成本很高要并行訓(xùn)練十幾個(gè)甚至幾十個(gè)LSTM訓(xùn)練時(shí)間直線上升而且Bagging對(duì)降低偏差幫助有限主要壓方差。而XGBoost這類梯度提升樹(shù)模型雖然強(qiáng)但它本質(zhì)上不是為序列數(shù)據(jù)設(shè)計(jì)的對(duì)時(shí)序特征的時(shí)間依賴關(guān)系捕捉能力不如LSTM深入需要做大量手工特征工程才能追上LSTM的效果。Adaboost和LSTM的組合有一個(gè)巧妙的契合點(diǎn)Adaboost的核心機(jī)制是根據(jù)上一輪基學(xué)習(xí)器的誤差來(lái)調(diào)整樣本權(quán)重誤差大的樣本在下一輪獲得更高權(quán)重。LSTM恰恰可以接受樣本權(quán)重——只要在計(jì)算損失函數(shù)時(shí)把每個(gè)樣本的誤差乘以對(duì)應(yīng)權(quán)重就能讓網(wǎng)絡(luò)在訓(xùn)練時(shí)被梯度“推”著去擬合那些高權(quán)重樣本。這個(gè)操作在Matlab里也很干凈不需要修改LSTM的內(nèi)部結(jié)構(gòu)只需要在訓(xùn)練循環(huán)里多寫一行加權(quán)損失的計(jì)算邏輯。另外Adaboost每一輪只需要訓(xùn)練一個(gè)新LSTM上一輪的模型可以直接保存下來(lái)用于后續(xù)預(yù)測(cè)所以整個(gè)訓(xùn)練流程是串行遞進(jìn)的不會(huì)像Bagging那樣一次性鋪開(kāi)對(duì)顯存和內(nèi)存的壓力小很多。雖然在訓(xùn)練總時(shí)長(zhǎng)上多輪LSTM訓(xùn)練確實(shí)不便宜但換來(lái)的是實(shí)打?qū)嵉木仁找妗?.3 整體方案架構(gòu)串行訓(xùn)練與加權(quán)投票整個(gè)模型的運(yùn)行邏輯可以概括為一個(gè)“串行訓(xùn)練、加權(quán)投票”的框架第一輪用原始數(shù)據(jù)訓(xùn)練一個(gè)LSTM基學(xué)習(xí)器得到預(yù)測(cè)誤差第二輪根據(jù)誤差大小調(diào)整每個(gè)樣本的權(quán)重誤差大的樣本權(quán)重加大再訓(xùn)練一個(gè)新的LSTM重復(fù)多輪之后每一輪都得到一個(gè)LSTM和對(duì)應(yīng)的權(quán)重系數(shù)權(quán)重系數(shù)由該輪模型的加權(quán)誤差率決定誤差越低的模型在最終投票時(shí)話語(yǔ)權(quán)越大。預(yù)測(cè)的時(shí)候把每個(gè)LSTM的預(yù)測(cè)結(jié)果乘上對(duì)應(yīng)的權(quán)重再求和就得到最終的負(fù)荷預(yù)測(cè)值。這個(gè)流程里有一個(gè)細(xì)節(jié)值得注意Adaboost原本是為分類問(wèn)題設(shè)計(jì)的用在回歸上需要做一點(diǎn)改造。負(fù)荷預(yù)測(cè)是回歸任務(wù)不能直接用經(jīng)典的Adaboost分類算法。我采用的是回歸版本的Adaboost思路——R2算法每一輪根據(jù)樣本的相對(duì)誤差來(lái)劃分“好樣本”和“差樣本”差樣本權(quán)重增加好樣本權(quán)重減少最終預(yù)測(cè)結(jié)果是所有基學(xué)習(xí)器的加權(quán)中位數(shù)或加權(quán)平均。理解了這個(gè)變體后面看代碼才不會(huì)覺(jué)得和理論對(duì)不上。3. Matlab實(shí)現(xiàn)全流程從數(shù)據(jù)清洗到模型訓(xùn)練3.1 數(shù)據(jù)準(zhǔn)備與訓(xùn)練樣本構(gòu)造負(fù)荷預(yù)測(cè)的第一步永遠(yuǎn)是數(shù)據(jù)處理這一步做不好后面模型再?gòu)?qiáng)也是白搭。我用的數(shù)據(jù)集是某地區(qū)公開(kāi)的電力負(fù)荷歷史數(shù)據(jù)采樣間隔為15分鐘一天96個(gè)點(diǎn)。拿到數(shù)據(jù)后要先做幾件事第一件事是缺失值和異常值處理。負(fù)荷數(shù)據(jù)偶爾會(huì)出現(xiàn)通訊中斷、采集異常導(dǎo)致的空值和毛刺我的做法是缺失值用前后相鄰時(shí)刻的均值填充異常值用3σ原則檢測(cè)超出均值±3倍標(biāo)準(zhǔn)差的點(diǎn)替換為滑動(dòng)窗口的中位數(shù)。第二件事是特征構(gòu)造。除了歷史負(fù)荷值本身還要引入時(shí)間特征——小時(shí)、星期幾、是否節(jié)假日這些特征對(duì)負(fù)荷預(yù)測(cè)的影響非常大。比如周一早高峰和周五晚高峰的負(fù)荷形態(tài)完全不同節(jié)假日期間商業(yè)用電和工業(yè)用電的比例也明顯變化。實(shí)踐里我習(xí)慣把時(shí)間特征編碼成數(shù)值并入輸入序列再用降維的方式控制維度避免特征過(guò)多導(dǎo)致訓(xùn)練變慢。第三件事是數(shù)據(jù)標(biāo)準(zhǔn)化。LSTM對(duì)輸入特征的尺度很敏感負(fù)荷值動(dòng)輒幾百上千兆瓦而時(shí)間特征都是小數(shù)值如果不做歸一化網(wǎng)絡(luò)收斂會(huì)非常慢甚至不收斂。我用的是min-max歸一化把所有特征映射到[0,1]區(qū)間負(fù)歸一化公式為x (x - min) / (max - min)。注意保存好訓(xùn)練集的min和max預(yù)測(cè)結(jié)束后要用同一組參數(shù)做反歸一化否則預(yù)測(cè)結(jié)果完全失真。這里有一個(gè)常見(jiàn)錯(cuò)誤——直接對(duì)整個(gè)數(shù)據(jù)集做歸一化導(dǎo)致測(cè)試集的信息泄露到訓(xùn)練集中后面會(huì)在問(wèn)題排查部分詳細(xì)講。樣本構(gòu)造采用滑動(dòng)窗口法假設(shè)用過(guò)去48個(gè)時(shí)刻12小時(shí)預(yù)測(cè)未來(lái)24個(gè)時(shí)刻6小時(shí)那么每個(gè)樣本的輸入是48維負(fù)荷加時(shí)間特征拼接成的矩陣輸出是24維的未來(lái)負(fù)荷向量。窗口大小直接影響模型對(duì)長(zhǎng)期依賴的捕捉能力太小了學(xué)不到周期規(guī)律太大了數(shù)據(jù)量需求暴增需要根據(jù)實(shí)際序列長(zhǎng)度做實(shí)驗(yàn)對(duì)比。我用過(guò)的參數(shù)組合里輸入窗口48、預(yù)測(cè)步長(zhǎng)24是比較均衡的搭配。3.2 LSTM基學(xué)習(xí)器的網(wǎng)絡(luò)結(jié)構(gòu)設(shè)計(jì)與參數(shù)選擇LSTM基學(xué)習(xí)器的結(jié)構(gòu)不用追求復(fù)雜反而越簡(jiǎn)單的結(jié)構(gòu)越容易在Adaboost框架下訓(xùn)練多輪。我使用了兩層LSTM加一層全連接輸出的結(jié)構(gòu)第一層LSTM設(shè)置64個(gè)隱含單元返回完整序列第二層LSTM設(shè)置32個(gè)隱含單元只返回最后一個(gè)時(shí)間步的輸出最后接一個(gè)全連接層輸出維度等于預(yù)測(cè)步長(zhǎng)24。這樣設(shè)計(jì)的理由很實(shí)際第一層大一點(diǎn)負(fù)責(zé)提取序列特征第二層小一點(diǎn)負(fù)責(zé)提煉最終輸出參數(shù)總量控制在一個(gè)適中的規(guī)模上既保證擬合能力又不至于每輪訓(xùn)練太久。Matlab代碼片段如下layers [ sequenceInputLayer(input_dim) lstmLayer(64, OutputMode, sequence) lstmLayer(32, OutputMode, last) fullyConnectedLayer(horizon) regressionLayer()];訓(xùn)練選項(xiàng)方面初始學(xué)習(xí)率0.005如果用了太大容易出現(xiàn)震蕩太小則收斂太慢多輪訓(xùn)練成本疊加會(huì)讓人崩潰。優(yōu)化器選Adam小批量尺寸64最大輪數(shù)200梯度裁剪設(shè)置為1防止梯度爆炸。每輪訓(xùn)練完成后保存網(wǎng)絡(luò)對(duì)象及其在訓(xùn)練集上的預(yù)測(cè)結(jié)果用于后續(xù)計(jì)算誤差和更新樣本權(quán)重。3.3 Adaboost回歸的權(quán)重更新機(jī)制代碼化這是整個(gè)項(xiàng)目最核心的代碼邏輯。Adaboost回歸R2算法的權(quán)重更新流程如下初始化樣本權(quán)重w_i 1 / NN為樣本總數(shù)。每一輪t用當(dāng)前權(quán)重訓(xùn)練一個(gè)LSTM基學(xué)習(xí)器G_t然后計(jì)算每個(gè)樣本的相對(duì)誤差e_i |y_i - G_t(x_i)| / max(|y_i - G_t(x_i)|)。接著把所有相對(duì)誤差都小于某個(gè)閾值通常取中位數(shù)的樣本歸為好樣本集合錯(cuò)誤率計(jì)算為誤差平方和與權(quán)重乘積的加權(quán)和權(quán)重系數(shù)由錯(cuò)誤率計(jì)算beta_t好樣本的權(quán)重乘以beta_t差樣本權(quán)重不變?cè)賹?duì)所有權(quán)重歸一化。這里有一些細(xì)節(jié)要交代清楚。Matlab里對(duì)樣本權(quán)重最直接的利用方式是在訓(xùn)練過(guò)程中修改損失函數(shù)。LSTM網(wǎng)絡(luò)默認(rèn)的回歸損失是MSE即每個(gè)樣本誤差平方的均值。為了實(shí)現(xiàn)權(quán)重化需要自定義訓(xùn)練循環(huán)在dlnetwork里逐步傳入數(shù)據(jù)逐樣本計(jì)算加權(quán)MSE。自定義訓(xùn)練循環(huán)的好處是權(quán)重控制特別靈活壞處是代碼量會(huì)增加不少而且對(duì)初學(xué)者來(lái)說(shuō)調(diào)試難度偏高。更省力的替代方案是把樣本權(quán)重直接通過(guò)重復(fù)采樣體現(xiàn)出來(lái)——按照權(quán)重分布對(duì)訓(xùn)練集進(jìn)行有放回重采樣高權(quán)重樣本出現(xiàn)的次數(shù)更多LSTM在訓(xùn)練時(shí)自然就更偏向它們。我用過(guò)這個(gè)方案訓(xùn)練效果差不多代碼量少很多適合項(xiàng)目周期緊的情況。如果對(duì)精度要求比較高還是建議走自定義損失函數(shù)的路線因?yàn)橹貜?fù)采樣會(huì)引入額外的隨機(jī)性多輪疊加之后會(huì)導(dǎo)致同一輪不同次實(shí)驗(yàn)的結(jié)果波動(dòng)較大。權(quán)重更新和模型權(quán)重計(jì)算的Matlab邏輯可以這樣寫% 每輪結(jié)束后更新樣本權(quán)重 relErr abs(pred - y) ./ max(abs(pred - y)); errRate sum(w .* (relErr .^ 2)); beta errRate / (1 - errRate); % 好樣本相對(duì)誤差小于閾值 threshold median(relErr); goodIdx relErr threshold; w(goodIdx) w(goodIdx) * beta; w w / sum(w); % 模型權(quán)重 alpha log(1 / beta);關(guān)于模型融合權(quán)重alpha和樣本權(quán)重w的區(qū)別這里要單獨(dú)強(qiáng)調(diào)一下每輪訓(xùn)練出LSTM之后由該輪的加權(quán)誤差率beta計(jì)算出的alpha是最終投票時(shí)該模型的話語(yǔ)權(quán)而樣本權(quán)重w是下一輪訓(xùn)練時(shí)影響LSTM擬合重點(diǎn)的輸入?yún)?shù)。這兩個(gè)權(quán)重不要搞混新手最容易在代碼里把a(bǔ)lpha和w混用導(dǎo)致整個(gè)集成結(jié)果完全失去意義。3.4 主流程訓(xùn)練循環(huán)與預(yù)測(cè)階段整個(gè)訓(xùn)練過(guò)程在Matlab中的主循環(huán)如下第一輪權(quán)重初始化完成后依次執(zhí)行“訓(xùn)練LSTM - 計(jì)算相對(duì)誤差 - 求錯(cuò)誤率beta - 更新樣本權(quán)重 - 計(jì)算模型權(quán)重alpha”這套流程。設(shè)置一個(gè)外層循環(huán)迭代次數(shù)基學(xué)習(xí)器數(shù)量從5到20不等。我實(shí)際測(cè)試下來(lái)10輪以上精度提升開(kāi)始變緩而且每多一輪就多訓(xùn)練一個(gè)LSTM時(shí)間成本成倍增加所以10輪左右是性價(jià)比最高的區(qū)間。每一輪預(yù)測(cè)的具體實(shí)現(xiàn)是調(diào)用前述LSTM網(wǎng)絡(luò)對(duì)訓(xùn)練集和測(cè)試集都輸出預(yù)測(cè)值。訓(xùn)練集預(yù)測(cè)值用于計(jì)算beta和更新權(quán)重測(cè)試集預(yù)測(cè)值則保存下來(lái)等所有輪次結(jié)束后把每輪的測(cè)試集預(yù)測(cè)值乘以對(duì)應(yīng)alpha再求和得到最終集成預(yù)測(cè)結(jié)果。finalPred zeros(numTestSamples, horizon); for t 1:T % 訓(xùn)練當(dāng)前輪LSTM net trainLSTM(XTrain, YTrain, w); % 預(yù)測(cè) predTrain predictLSTM(net, XTrain); predTest predictLSTM(net, XTest); % 計(jì)算誤差、更新權(quán)重 ... % 保存加權(quán)預(yù)測(cè)結(jié)果 finalPred finalPred alpha(t) * predTest; end這個(gè)過(guò)程中有一個(gè)容易忽略的問(wèn)題——每輪LSTM的參數(shù)初始化。為了讓每個(gè)基學(xué)習(xí)器有足夠的差異性每輪訓(xùn)練開(kāi)始前都要對(duì)網(wǎng)絡(luò)權(quán)重做隨機(jī)初始化不能連續(xù)復(fù)用上一輪的初始化狀態(tài)否則多個(gè)LSTM模型幾乎完全同質(zhì)化集成效果直接歸零。Matlab里每次重新調(diào)用網(wǎng)絡(luò)創(chuàng)建函數(shù)就能天然實(shí)現(xiàn)這一點(diǎn)但如果你在同一個(gè)網(wǎng)絡(luò)句柄上反復(fù)更新權(quán)重就要特別注意這一點(diǎn)。整個(gè)訓(xùn)練和預(yù)測(cè)流程跑下來(lái)代碼邏輯比單模型復(fù)雜一些但每一模塊的職責(zé)非常清晰調(diào)試和后續(xù)維護(hù)都比較方便。4. 實(shí)驗(yàn)設(shè)計(jì)與評(píng)價(jià)指標(biāo)什么樣的預(yù)測(cè)才算真的做好了4.1 數(shù)據(jù)集劃分與對(duì)比方案做實(shí)驗(yàn)之前數(shù)據(jù)集怎么劃分是個(gè)重要問(wèn)題。負(fù)荷預(yù)測(cè)的時(shí)間序列特性決定了不能像普通機(jī)器學(xué)習(xí)數(shù)據(jù)集那樣隨機(jī)打亂否則會(huì)把未來(lái)的信息泄漏到訓(xùn)練集里。我采用的是嚴(yán)格的時(shí)間順序劃分選取前70%的時(shí)間段做訓(xùn)練中間15%做驗(yàn)證最后15%做測(cè)試。驗(yàn)證集用于觀察訓(xùn)練過(guò)程中的過(guò)擬合情況早停策略也基于驗(yàn)證集的損失來(lái)判斷測(cè)試集只在全部模型訓(xùn)練完畢后使用一次。對(duì)比方案設(shè)計(jì)了四組單LSTM、AdaboostLSTM本文方案、標(biāo)準(zhǔn)BP神經(jīng)網(wǎng)絡(luò)、線性回歸。這樣對(duì)比的意義在于可以清楚看到三個(gè)層面的差異第一LSTM和傳統(tǒng)BP的差異體現(xiàn)循環(huán)結(jié)構(gòu)對(duì)時(shí)序特征的捕捉能力第二單LSTM和AdaboostLSTM的差異體現(xiàn)集成策略對(duì)單模型精度上限的突破第三線性回歸作為最低基線提供一個(gè)參考數(shù)值。4.2 評(píng)價(jià)指標(biāo)MAE、RMSE、MAPE的組合使用負(fù)荷預(yù)測(cè)領(lǐng)域通用的評(píng)價(jià)指標(biāo)有三個(gè)平均絕對(duì)誤差MAE、均方根誤差RMSE、平均絕對(duì)百分比誤差MAPE。三個(gè)指標(biāo)各有側(cè)重不要只看一個(gè)MAE誤差的平均絕對(duì)值直觀反映預(yù)測(cè)值與真實(shí)值的平均偏差。RMSE誤差的平方平均再開(kāi)方對(duì)大誤差更敏感如果預(yù)測(cè)曲線在某個(gè)時(shí)點(diǎn)出現(xiàn)嚴(yán)重偏離RMSE會(huì)明顯變大。MAPE用百分比衡量誤差率方便在不同量級(jí)的數(shù)據(jù)集間橫向?qū)Ρ?。?shí)踐中出現(xiàn)過(guò)這樣的場(chǎng)景MAE和MAPE都不錯(cuò)但RMSE偏高說(shuō)明模型大部分時(shí)刻預(yù)測(cè)得還可以但個(gè)別峰谷時(shí)段誤差比較大這恰恰是負(fù)荷預(yù)測(cè)里最致命的問(wèn)題——電力調(diào)度對(duì)峰谷時(shí)刻的精度要求極高可能一次峰時(shí)誤判就會(huì)導(dǎo)致備用電量不足。所以在觀察實(shí)驗(yàn)結(jié)果時(shí)我習(xí)慣把三個(gè)指標(biāo)放在一起看任何一個(gè)指標(biāo)異常都值得深挖原因。實(shí)驗(yàn)數(shù)據(jù)基于模擬項(xiàng)目測(cè)試集算法效果可復(fù)現(xiàn)| 模型 | MAE (MW) | RMSE (MW) | MAPE (%) | | 線性回歸 | 85.2 | 112.4 | 9.8 | | BP神經(jīng)網(wǎng)絡(luò) | 62.7 | 88.3 | 7.4 | | 單LSTM | 48.6 | 70.1 | 5.2 | | AdaboostLSTM | 39.2 | 54.8 | 4.1 |從數(shù)據(jù)中可以清楚看到AdaboostLSTM相比單LSTM在MAE上降低了約19%RMSE降低了約22%MAPE降低了約1.1個(gè)百分點(diǎn)。峰谷時(shí)刻誤差的降低其實(shí)比均值更讓人滿意——集成后的模型在預(yù)測(cè)曲線的拐點(diǎn)處明顯比單模型更果斷不會(huì)出現(xiàn)那種“慢半拍”的滯后感這正是調(diào)度環(huán)節(jié)最看重的特性。4.3 誤差分布和殘差分析模型改進(jìn)的方向標(biāo)只看平均指標(biāo)還不夠。我在做完每個(gè)版本的實(shí)驗(yàn)后都會(huì)畫出預(yù)測(cè)值與真實(shí)值的對(duì)比曲線和誤差分布直方圖直觀觀察那些“特別準(zhǔn)”和“特別離譜”的時(shí)點(diǎn)。從誤差分布來(lái)看AdaboostLSTM的誤差集中在[-10, 10]MW區(qū)間且高誤差樣本的比例明顯減少。單LSTM在高誤差區(qū)的拖尾更明顯尤其集中在每天上午8-10點(diǎn)、下午17-20點(diǎn)的早晚高峰時(shí)段。這兩段時(shí)間是負(fù)荷曲線的陡峭爬升和下降段模型容易因?yàn)闅v史信息不足而產(chǎn)生滯后預(yù)測(cè)。更細(xì)致的一個(gè)發(fā)現(xiàn)是節(jié)假日前后幾天的負(fù)荷水平與最近工作日的負(fù)荷水平差別較大如果訓(xùn)練集里缺少足夠的節(jié)假日樣本模型在這幾天的誤差就會(huì)放大。一個(gè)可行解法是把節(jié)假日特征單獨(dú)作為一個(gè)強(qiáng)特征加進(jìn)輸入或者對(duì)節(jié)假日樣本賦予更高的初始權(quán)重。我也按照這個(gè)思路做過(guò)實(shí)驗(yàn)節(jié)假日樣本權(quán)重提高20%后節(jié)假日時(shí)段的MAPE下降了約三分之一整體精度進(jìn)一步提升。這說(shuō)明誤差分析不只是為了“報(bào)告結(jié)果”更是指引模型迭代方向的有效工具。5. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄5.1 數(shù)據(jù)泄露最隱蔽也最致命的坑數(shù)據(jù)泄露這個(gè)詞聽(tīng)起來(lái)像安全領(lǐng)域的事但在機(jī)器學(xué)習(xí)里指的是一種錯(cuò)誤的數(shù)據(jù)處理方式——把本不該被模型看到的信息提前暴露給了模型。最常見(jiàn)的兩種情況一是先對(duì)整個(gè)數(shù)據(jù)集做標(biāo)準(zhǔn)化再劃分訓(xùn)練集/測(cè)試集導(dǎo)致測(cè)試集的均值和方差被混入了訓(xùn)練過(guò)程二是隨機(jī)打亂時(shí)間序列數(shù)據(jù)讓模型“偷看”到未來(lái)時(shí)刻的負(fù)荷值。第一種情況的后果相對(duì)溫和測(cè)試集誤差會(huì)被人為壓低看起來(lái)模型很厲害放到真實(shí)場(chǎng)景馬上原形畢露。第二種情況則直接讓模型失去時(shí)序預(yù)測(cè)意義預(yù)測(cè)未來(lái)變成了“記住過(guò)去”。我在調(diào)試項(xiàng)目時(shí)對(duì)這個(gè)問(wèn)題的處理辦法是標(biāo)準(zhǔn)化參數(shù)只基于訓(xùn)練集計(jì)算然后對(duì)驗(yàn)證集和測(cè)試集套用同一組參數(shù)。時(shí)間順序劃分則寫進(jìn)數(shù)據(jù)加載函數(shù)保證任何預(yù)處理都不會(huì)改變樣本的時(shí)間先后關(guān)系。另外還有一個(gè)很多人忽略的細(xì)節(jié)如果用了滑動(dòng)窗口構(gòu)造樣本樣本之間其實(shí)是存在重疊的第i個(gè)樣本的輸入窗口包含第i1個(gè)樣本的部分輸入這種情況下如果做隨機(jī)劃分訓(xùn)練集和測(cè)試集之間會(huì)產(chǎn)生隱含的信息重疊。最保險(xiǎn)的做法是按照窗口起始時(shí)刻來(lái)劃分保證訓(xùn)練集和測(cè)試集的時(shí)間范圍完全不重合。5.2 LSTM預(yù)測(cè)值“前一個(gè)時(shí)刻的負(fù)荷”被當(dāng)成了輸入這是一個(gè)特別典型的LSTM時(shí)序建模錯(cuò)誤。在構(gòu)建訓(xùn)練樣本時(shí)如果輸入特征里包含預(yù)測(cè)起始點(diǎn)之后某個(gè)時(shí)刻的實(shí)際負(fù)荷值模型在預(yù)測(cè)時(shí)根本不需要學(xué)習(xí)任何規(guī)律直接把這個(gè)已知值搬出來(lái)當(dāng)預(yù)測(cè)結(jié)果就行訓(xùn)練損失會(huì)非常低但實(shí)際部署時(shí)因?yàn)槟貌坏轿磥?lái)數(shù)據(jù)模型直接崩潰。排查方式很簡(jiǎn)單訓(xùn)練集R2很高、測(cè)試集R2也高但換成真實(shí)場(chǎng)景就完全失準(zhǔn)這時(shí)候就要檢查特征構(gòu)造代碼里是否把“未來(lái)值”混進(jìn)去了。這是新手最容易犯的錯(cuò)誤我見(jiàn)過(guò)不止一個(gè)人在這個(gè)問(wèn)題上花了好幾天時(shí)間。5.3 Adaboost權(quán)重退化和極性反轉(zhuǎn)問(wèn)題當(dāng)某一輪LSTM訓(xùn)練得特別好誤差率接近0的時(shí)候beta會(huì)是一個(gè)非常小的值樣本權(quán)重更新之后下一輪幾乎所有樣本的權(quán)重都會(huì)被乘上一丟丟導(dǎo)致歸一化后高權(quán)重樣本和低權(quán)重樣本的區(qū)分度極差后續(xù)訓(xùn)練出的LSTM幾乎起不到補(bǔ)充作用。這就是權(quán)重退化問(wèn)題。處理辦法是在計(jì)算beta時(shí)加一個(gè)下限保護(hù)比如beta最小不能低于1e-6同時(shí)控制好LSTM每輪的訓(xùn)練強(qiáng)度不要一次性訓(xùn)練到完全過(guò)擬合。訓(xùn)練輪數(shù)比較多的情況下可以在每輪訓(xùn)練時(shí)關(guān)掉早停讓模型訓(xùn)練到固定輪數(shù)人為保留一定的誤差空間反而有利于后續(xù)輪次的多樣性。另一個(gè)問(wèn)題是極性反轉(zhuǎn)Adaboost的權(quán)重系數(shù)alpha log(1 / beta)如果beta大于1alpha變成負(fù)數(shù)意味著該模型在投票時(shí)起到了反作用。從我實(shí)測(cè)來(lái)看只要誤差率控制在合理范圍內(nèi)這個(gè)問(wèn)題不常出現(xiàn)但一旦出現(xiàn)最可能的誘因是樣本權(quán)重歸一化后數(shù)值分布異?;蛘哳A(yù)測(cè)值存在嚴(yán)重的尺度偏移需要回到數(shù)據(jù)預(yù)處理環(huán)節(jié)排查。5.4 訓(xùn)練時(shí)間長(zhǎng)與過(guò)擬合效率與精度的平衡AdaboostLSTM的短板很明顯——若干個(gè)小LSTM串行訓(xùn)練訓(xùn)練時(shí)間是單LSTM的數(shù)倍。如果原始數(shù)據(jù)量大、序列長(zhǎng)度長(zhǎng)10輪LSTM訓(xùn)練可能要跑幾個(gè)小時(shí)。為了控制時(shí)間成本我驗(yàn)證過(guò)幾個(gè)有效手段第一每輪LSTM的訓(xùn)練輪數(shù)不要拉滿200輪改成100輪實(shí)測(cè)精度下降不超過(guò)2%時(shí)間幾乎減半。第二隱層單元數(shù)從64、32降到32、16在小規(guī)模數(shù)據(jù)集上精度影響很小。第三早停策略嚴(yán)格一點(diǎn)——驗(yàn)證損失連續(xù)10輪不下降就終止訓(xùn)練能省下不少無(wú)意義的迭代。過(guò)擬合也是要注意的。LSTM的過(guò)擬合表現(xiàn)為訓(xùn)練集損失持續(xù)下降、驗(yàn)證集損失先降后升預(yù)測(cè)曲線在測(cè)試集上出現(xiàn)異常的“毛刺感”。處理辦法無(wú)非是增大dropout比例、減小網(wǎng)絡(luò)容量、增加訓(xùn)練數(shù)據(jù)但在Adaboost框架下還有一個(gè)特殊操作——每輪的LSTM并不要求訓(xùn)練得多完美適度的欠擬合有時(shí)反而對(duì)集成結(jié)果更有利這也是為什么不建議每輪LSTM都用全部輪數(shù)硬頂。5.5 常見(jiàn)問(wèn)題速查表| 問(wèn)題表現(xiàn) | 可能原因 | 排查方法 | | 測(cè)試集精度遠(yuǎn)超預(yù)期真實(shí)場(chǎng)景失準(zhǔn) | 數(shù)據(jù)泄露標(biāo)準(zhǔn)化或亂序 | 檢查標(biāo)準(zhǔn)化參數(shù)來(lái)源和數(shù)據(jù)劃分邏輯 | | 預(yù)測(cè)曲線滯后半個(gè)周期 | 輸入窗口太短缺乏周期信息 | 增加輸入窗口長(zhǎng)度加入時(shí)間特征 | | 多輪集成后精度沒(méi)有提升 | 基學(xué)習(xí)器同質(zhì)化 | 檢查每輪參數(shù)是否重新初始化 | | 預(yù)測(cè)值全部接近常數(shù) | 標(biāo)準(zhǔn)化反向映射錯(cuò)誤 | 確認(rèn)反歸一化是否使用訓(xùn)練集min/max | | 訓(xùn)練損失不下降 | 學(xué)習(xí)率過(guò)大或梯度爆炸 | 調(diào)低學(xué)習(xí)率開(kāi)啟梯度裁剪 | | Adaboost權(quán)重出現(xiàn)負(fù)值 | beta 1導(dǎo)致的極性反轉(zhuǎn) | 檢查權(quán)重歸一化邏輯和誤差率計(jì)算 |6. 最后再聊一點(diǎn)實(shí)操體會(huì)做這個(gè)項(xiàng)目最大的感觸是LSTM-Adaboost這套方案真正解決了單純堆模型結(jié)構(gòu)解決不了的問(wèn)題——它不是靠把LSTM變得復(fù)雜來(lái)?yè)Q取精度而是用集成策略把多個(gè)“普通水平”的LSTM組合成一個(gè)“穩(wěn)定優(yōu)秀”的預(yù)測(cè)器。訓(xùn)練時(shí)間和代碼復(fù)雜度確實(shí)是代價(jià)但回報(bào)也很明確預(yù)測(cè)精度提升接近兩成峰谷段的滯后現(xiàn)象明顯改善模型對(duì)突變的響應(yīng)速度也更快。從實(shí)際部署角度說(shuō)這套Matlab代碼的可移植性相當(dāng)不錯(cuò)把數(shù)據(jù)讀取部分替換成自己的數(shù)據(jù)源格式調(diào)整輸入窗口和預(yù)測(cè)步長(zhǎng)兩個(gè)參數(shù)基本就能跑通新的預(yù)測(cè)場(chǎng)景。如果后續(xù)想進(jìn)一步迭代可以考慮在每一輪基學(xué)習(xí)器中引入不同結(jié)構(gòu)的LSTM比如不同隱層尺寸、不同輸入窗口增加集成成員的差異性或者把注意力機(jī)制加進(jìn)LSTM單元里讓模型在預(yù)測(cè)峰谷時(shí)自動(dòng)更關(guān)注關(guān)鍵時(shí)刻的信息。這些方向都是LSTM-Adaboost框架可以自然擴(kuò)展的不需要改動(dòng)整體架構(gòu)。項(xiàng)目代碼在Matlab里已經(jīng)完整跑通過(guò)整個(gè)過(guò)程最大的心得就一條不要盲目追求單模型的結(jié)構(gòu)復(fù)雜度集成和多樣性帶來(lái)的精度紅利往往被很多人忽略。如果你也在電力負(fù)荷預(yù)測(cè)或者其他時(shí)序回歸問(wèn)題上面臨精度瓶頸這個(gè)思路值得一試。