4、经典统计模型:移动平均(MA)、指数平滑(ES)、ARIMA模型原理与实现
各位工程师朋友,咱们今天聊聊发电量预测里最经典的几个统计模型。说实话,虽然现在深度学习很火,但我在实际项目中,很多时候反而是这些“老家伙”最管用。为什么?因为它们稳定、可解释性强,而且数据量不大的时候,效果往往比那些花里胡哨的神经网络要好。
我个人习惯,拿到一个发电量预测任务,第一件事不是上LSTM,而是先用这些经典模型跑一遍。这就像打仗前先派侦察兵,能帮你快速摸清数据的脾气。
4.1 移动平均(MA)——最简单的平滑器
移动平均,说白了就是取最近N个点的平均值来预测下一个点。你想想看,如果今天的发电量和过去几天的平均差不多,那这个方法就挺靠谱。
数学上很简单:
MA_t = (x_{t-1} + x_{t-2} + ... + x_{t-N}) / N
这里的N就是窗口大小。N越大,曲线越平滑,但反应越迟钝。N越小,越灵敏,但容易跟着噪声跑偏。
核心要点:移动平均的本质是低通滤波。它把高频的随机波动滤掉,只保留低频的趋势成分。
我在项目中遇到过一个问题:某光伏电站的发电量数据,用7天移动平均做预测,结果总是滞后一天。后来我意识到,移动平均天生就有滞后性——它用的是历史数据,当然跟不上突变。所以,移动平均更适合做趋势判断,而不是精确预测。
4.2 指数平滑(ES)——给历史数据“打折”
移动平均有个问题:它对窗口内的所有数据一视同仁。但直觉告诉我们,越近的数据应该越重要。指数平滑就是干这个的——它给每个历史数据分配一个权重,越近的权重越大,而且权重呈指数衰减。
简单指数平滑公式:
s_t = α * x_t + (1 - α) * s_{t-1}
这里的α是平滑系数,取值0到1之间。α越大,模型越关注近期数据;α越小,模型越平滑。
我的经验:α的取值很关键。我一般先用0.2试水,然后根据残差调整。如果预测值波动太大,就减小α;如果反应太慢,就增大α。没有固定值,全靠调参经验。
指数平滑还有两个进阶版本:Holt线性趋势模型(处理趋势)和Holt-Winters季节模型(处理趋势+季节)。对于发电量预测,季节模型特别有用——因为光伏发电有明显的日周期和年周期。
我曾经用Holt-Winters模型预测一个水电站的发电量,效果出奇的好。为什么?因为水电有很强的季节性规律——汛期发电多,枯水期发电少。这个模型正好抓住了这个特点。
4.3 ARIMA模型——统计预测的“瑞士军刀”
ARIMA全称是自回归积分滑动平均模型。名字听着吓人,但拆开看就明白了:
- AR(自回归):用过去的值预测现在的值。比如今天的发电量跟昨天、前天的发电量有关。
- I(积分):对数据进行差分,让非平稳数据变平稳。说白了就是“涨了多少”而不是“涨到多少”。
- MA(滑动平均):用过去的预测误差来修正当前的预测。
ARIMA(p,d,q)的三个参数:
| 参数 | 含义 | 如何确定 |
|---|---|---|
| p | 自回归阶数 | 看PACF图,截尾处 |
| d | 差分阶数 | 做单位根检验,直到平稳 |
| q | 滑动平均阶数 | 看ACF图,截尾处 |
避坑指南:我曾经犯过一个错误——直接用原始发电量数据跑ARIMA,结果模型死活不收敛。后来才发现,发电量数据有明显的趋势和季节成分,必须先做差分和季节调整。记住:ARIMA要求数据是平稳的!
4.4 代码实现——用Python跑一遍
光说不练假把式。咱们用Python的statsmodels库,把这三个模型都实现一遍。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from statsmodels.tsa.holtwinters import ExponentialSmoothing
from statsmodels.tsa.arima.model import ARIMA
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
# 模拟发电量数据(带趋势和季节)
np.random.seed(42)
dates = pd.date_range('2023-01-01', periods=365, freq='D')
trend = np.linspace(100, 150, 365)
seasonal = 20 * np.sin(2 * np.pi * np.arange(365) / 365)
noise = np.random.normal(0, 5, 365)
power = trend + seasonal + noise
# 1. 移动平均
def moving_average(data, window=7):
return data.rolling(window=window).mean()
ma_pred = moving_average(pd.Series(power), window=7)
# 2. 指数平滑(Holt-Winters)
model_es = ExponentialSmoothing(power, seasonal_periods=365, trend='add', seasonal='add')
fit_es = model_es.fit()
es_pred = fit_es.fittedvalues
# 3. ARIMA
# 先做差分让数据平稳
diff_power = np.diff(power, n=1)
# 看ACF和PACF图确定p和q
fig, (ax1, ax2) = plt.subplots(2, 1)
plot_acf(diff_power, ax=ax1)
plot_pacf(diff_power, ax=ax2)
plt.show()
# 假设p=2, d=1, q=2
model_arima = ARIMA(power, order=(2, 1, 2))
fit_arima = model_arima.fit()
arima_pred = fit_arima.fittedvalues
# 对比效果
plt.figure(figsize=(12, 6))
plt.plot(power, label='实际值', alpha=0.7)
plt.plot(ma_pred, label='移动平均(7天)', linewidth=2)
plt.plot(es_pred, label='指数平滑', linewidth=2)
plt.plot(arima_pred, label='ARIMA(2,1,2)', linewidth=2)
plt.legend()
plt.title('三种经典模型预测效果对比')
plt.show()
重要提醒:代码里的p、q参数我是随便写的。实际项目中,你必须通过ACF和PACF图来定阶。别偷懒,这一步省不了。
4.5 知识体系总览
下面这张图,是我自己总结的经典统计模型知识框架。你把它存下来,以后做预测时对照着看,思路会清晰很多。
4.6 实际应用中的选择策略
说了这么多,到底该用哪个?我给大家一个实用的决策流程:
- 先看数据量:少于100个点?别想ARIMA了,用移动平均或指数平滑就行。
- 再看平稳性:做ADF检验。如果p值大于0.05,说明数据不平稳,需要差分或做季节调整。
- 然后看模式:有明显周期性?用Holt-Winters。只有趋势?用Holt线性模型。纯随机?简单指数平滑就够了。
- 最后对比:用AIC或BIC选最优模型。别只看拟合效果,还要看预测效果——交叉验证不能少。
一个小技巧:我习惯把这三个模型都跑一遍,然后取它们的加权平均作为最终预测。虽然不严谨,但很多时候效果比单个模型要好。这叫“集成学习”的朴素版本,哈哈。
好了,经典统计模型就讲到这里。这些模型虽然“老”,但它们是理解时间序列预测的基础。你把这些吃透了,后面学深度学习模型会轻松很多。记住:地基不牢,楼盖不高。
公众号:蓝海资料掘金营,微信deep3321