第四章:经典统计方法——持续法、ARIMA与卡尔曼滤波

各位同行,今天我们来聊聊风电功率预测里最经典的几个统计方法。说实话,虽然现在深度学习很火,但这些经典方法在实际工程中依然有不可替代的位置。我自己做项目时,经常先用它们打个底,再考虑要不要上复杂模型。

4.1 持续法(Persistance)——最简单的基线模型

持续法,说白了就是“现在啥样,未来还啥样”。它假设未来时刻的功率和当前时刻差不多。你可能会觉得这也太简单了吧?但别小看它,它可是所有预测模型的“照妖镜”。

核心思想:

P(t+Δt) = P(t)

其中 P(t) 是当前时刻的功率,Δt 是预测步长。

为什么它重要?

  • 它是评估其他模型好坏的基准线
  • 如果复杂模型连持续法都跑不过,那基本可以扔了
  • 在超短期预测(比如未来5-15分钟)中,持续法效果其实不错

我在项目中遇到过一件事:有个团队花了两周调一个LSTM模型,结果在15分钟预测上只比持续法好了3%。嗯,这投入产出比确实有点尴尬。所以我建议,做任何预测项目前,先把持续法跑出来,看看你的数据到底有多难预测。

实用技巧:

持续法虽然简单,但可以用来做数据质量检查。如果持续法的误差突然变大,往往意味着数据采集出了问题,或者天气发生了剧烈变化。我曾经用这个办法发现过一个风速仪故障,省了不少排查时间。

4.2 ARIMA模型——时间序列的经典武器

ARIMA,全称是自回归积分滑动平均模型。名字听着唬人,但拆开看就明白了:

  • AR(自回归):用过去的值预测未来的值
  • I(积分):对数据进行差分,让它变平稳
  • MA(滑动平均):用过去的预测误差来修正当前预测

ARIMA模型有三个关键参数:p、d、q。我刚开始学的时候也记不住,后来总结了个口诀:

参数 含义 怎么选
p 自回归阶数 看偏自相关函数(PACF)的截尾点
d 差分阶数 做单位根检验,直到数据平稳
q 滑动平均阶数 看自相关函数(ACF)的截尾点

ARIMA建模步骤:

  1. 数据预处理:检查缺失值、异常值,做差分让数据平稳
  2. 模型识别:通过ACF和PACF图初步确定p、q范围
  3. 参数估计:用AIC或BIC准则选择最优参数组合
  4. 模型检验:检查残差是否为白噪声
  5. 预测:用选定的模型做未来预测

下面是一个简单的Python实现示例:

import pandas as pd
import numpy as np
from statsmodels.tsa.arima.model import ARIMA
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
import matplotlib.pyplot as plt

# 假设我们有历史功率数据
# data = pd.read_csv('wind_power.csv')
# power_series = data['power']

# 1. 检查平稳性(这里假设已经平稳)
# 2. 画ACF和PACF图
# plot_acf(power_series)
# plot_pacf(power_series)
# plt.show()

# 3. 拟合ARIMA模型(p=2, d=1, q=2)
model = ARIMA(power_series, order=(2, 1, 2))
model_fit = model.fit()

# 4. 查看模型摘要
print(model_fit.summary())

# 5. 预测未来6个时间点
forecast = model_fit.forecast(steps=6)
print(forecast)

注意:风电功率数据通常有很强的季节性和非平稳性。直接用原始数据跑ARIMA效果往往不好。我习惯先做差分,或者用SARIMA(季节性ARIMA)来处理日周期和年周期。

4.3 卡尔曼滤波——动态系统的状态估计

卡尔曼滤波,这名字听起来就很高端。其实它解决的是一个很实际的问题:如何从带噪声的观测数据中,估计出系统的真实状态。

在风电预测中,卡尔曼滤波主要用在两个地方:

  • 数据滤波:去除风速、功率测量中的噪声
  • 状态估计:结合模型预测和实时观测,动态修正预测值

卡尔曼滤波的核心公式(简化版):

预测步骤:
  x_pred = A * x_prev + B * u
  P_pred = A * P_prev * A^T + Q

更新步骤:
  K = P_pred * H^T * (H * P_pred * H^T + R)^(-1)
  x_est = x_pred + K * (z - H * x_pred)
  P_est = (I - K * H) * P_pred

看着公式多,其实逻辑很清晰:先根据模型预测下一步状态,然后用实际观测值来修正这个预测。K就是卡尔曼增益,它决定了你更相信模型还是更相信观测。

在风电预测中的应用场景:

  • 风速滤波:风速仪数据常有随机噪声,卡尔曼滤波可以平滑数据
  • 功率预测修正:用实时功率数据修正NWP(数值天气预报)的预测结果
  • 参数自适应:在线估计模型参数,适应风场特性的变化

我曾经在一个海上风场项目中,用卡尔曼滤波把NWP的预测误差降低了约15%。做法很简单:把NWP的预测作为状态方程,把SCADA系统的实时功率作为观测值,然后做在线修正。效果立竿见影。

下面是一个简单的卡尔曼滤波实现:

import numpy as np

class KalmanFilter:
    def __init__(self, A, H, Q, R, x0, P0):
        self.A = A  # 状态转移矩阵
        self.H = H  # 观测矩阵
        self.Q = Q  # 过程噪声协方差
        self.R = R  # 观测噪声协方差
        self.x = x0  # 初始状态
        self.P = P0  # 初始协方差
    
    def predict(self):
        self.x = self.A @ self.x
        self.P = self.A @ self.P @ self.A.T + self.Q
        return self.x
    
    def update(self, z):
        y = z - self.H @ self.x  # 残差
        S = self.H @ self.P @ self.H.T + self.R
        K = self.P @ self.H.T @ np.linalg.inv(S)  # 卡尔曼增益
        self.x = self.x + K @ y
        self.P = (np.eye(len(self.x)) - K @ self.H) @ self.P
        return self.x

# 使用示例
# A = np.array([[1, 1], [0, 1]])  # 简单运动模型
# H = np.array([[1, 0]])
# Q = np.eye(2) * 0.01
# R = np.array([[0.1]])
# kf = KalmanFilter(A, H, Q, R, np.array([0, 0]), np.eye(2) * 100)
# 
# for z in measurements:
#     kf.predict()
#     x_est = kf.update(z)

调参经验:卡尔曼滤波的Q和R参数很关键。Q越大,说明你越不相信模型,滤波结果会更跟随观测值;R越大,说明你越不相信观测,结果会更平滑。我一般先用一段历史数据做离线调参,找到合适的Q和R比值,再上线运行。

4.4 三种方法的对比与选择

这三种方法各有适用场景,我整理了一个对比表:

方法 适用场景 优点 缺点
持续法 超短期预测(≤15分钟) 简单、快速、零成本 长期预测误差大
ARIMA 短期预测(15分钟-4小时) 理论基础扎实、可解释性强 对非平稳数据需要预处理
卡尔曼滤波 在线修正、数据滤波 实时性好、能融合多源数据 需要调参、模型假设较强

我个人习惯的做法是:先用持续法建立基线,然后用ARIMA做离线预测模型,最后用卡尔曼滤波做在线修正。这样三层结构下来,基本能覆盖大部分风电预测场景。

下面这张图展示了这三种方法在风电预测中的关系:

风电功率预测经典统计方法框架 历史功率数据 NWP气象数据 实时SCADA数据 持续法 超短期基线模型 ARIMA/SARIMA 短期离线预测 卡尔曼滤波 在线修正与滤波 超短期预测 (≤15分钟) 短期预测 (15分钟-4小时) 修正后预测 (实时更新) 三种方法可独立使用,也可组合形成多层级预测系统

好了,这一章的内容就到这里。经典统计方法虽然看起来不如深度学习“高大上”,但在实际工程中,它们往往更稳定、更可控。我建议你从持续法开始,逐步过渡到ARIMA和卡尔曼滤波,每一步都理解透彻了再往前走。

专注资料整理