TCN-RNN电力负荷预测模型实战
2026/6/9 0:52:06 网站建设 项目流程

不是 TCN 和 RNN 各写各的,而是让它们在一根管子里干活——前面用膨胀卷积抓长周期规律,后面用循环网络补时序依赖。跑了一组电力负荷数据,MAPE 压到了个位数,代码和数据都整理好了。


一、为什么要折腾这个组合

时间序列预测是个老话题了,但电力负荷预测有它的特殊性:周期性明显(每天早高峰、晚高峰)、突发波动多(天气骤变、节假日效应)、多变量耦合(温度、湿度、电价同时影响)。

单独用 RNN 族模型(LSTM/GRU)的问题在于——序列一长,梯度该消失还是消失,靠门控机制只是"缓解"而非"根治"。单独用 TCN(Temporal Convolutional Network)呢?膨胀卷积确实能把感受野拉得很长,计算也比 RNN 快,但它对局部时序的细腻变化不够敏感。

所以思路很直白:串起来用。TCN 先过一遍,把长程特征抽出来;再接一层 SimpleRNN,把相邻时间步的依赖关系补上。不是啥惊天动地的创新,但工程上确实好用。


二、模型长什么样

核心结构就四层,一目了然:

Input(时间步=5, 特征数=多变量) ↓ TCN(nb_filters=128, kernel_size=3, dilations=[1,2,4]) ↓ return_sequences=True,保留时序维度 SimpleRNN(units=50, return_sequences=False) ↓ 压成固定长度向量 Dense(10) + LeakyReLU(α=0.3) ↓ Dense(n_out, activation='linear') ↓ 预测值(反归一化后即为实际负荷)

拆开说几个关键点:

2.1 TCN 层:用空洞把视野撑开

CNN 做序列最大的痛点是感受野受限——你要看 100 步之前的信息,普通卷积得叠几十层。TCN 的精髓在于dilated convolution(膨胀卷积):每隔几个点采一个样,卷积核物理大小不变,但"看到"的范围指数级扩大。

本模型里dilations=[1, 2, 4]的含义:

  • 第一层 dilation=1:普通卷积,相邻点都看
  • 第二层 dilation=2:隔一个点看一个,感受野翻倍
  • 第三层 dilation=4:隔三个点看一个,感受野再翻倍

三层下来,有效感受野覆盖1+2×(3−1)×(1+2+4)=291 + 2 \times (3-1) \times (1+2+4) = 291+2×(31)×(1+2+4)=29个时间步,而实际卷积核只用了3×3=93 \times 3 = 93×3=9个参数。

公式:膨胀卷积的输出
F(s)=∑i=0k−1f(i)⋅xs−d⋅iF(s) = \sum_{i=0}^{k-1} f(i) \cdot x_{s - d \cdot i}F(s)=i=0k1f(i)xsdi
其中kkk是卷积核大小,ddd是膨胀系数,sss是当前时间步。

2.2 SimpleRNN 层:补上"相邻"的细腻度

可能有人问:为什么不用 LSTM?因为 TCN 已经用多层膨胀卷积把长程依赖处理得差不多了,后面只需要补充短程时序的连贯性。SimpleRNN 计算快、参数少、不容易过拟合,在这个位置反而是合适的。

SimpleRNN 的前向公式:

ht=tanh⁡(Wxhxt+Whhht−1+bh)h_t = \tanh(W_{xh} x_t + W_{hh} h_{t-1} + b_h)ht=tanh(Wxhxt+Whhht1+bh)

WxhW_{xh}Wxh是输入权重,WhhW_{hh}Whh是隐状态转移矩阵,bhb_hbh是偏置。每次更新隐状态hth_tht时,都把当前输入xtx_txt和上一时刻状态ht−1h_{t-1}ht1揉在一起。

2.3 输出层:LeakyReLU 防神经元"死掉"

Dense(10) 后面跟的是LeakyReLU(α=0.3)而非常见的 ReLU。原因是:ReLU 在负数区域梯度为零,一旦某个神经元输出恒为负,它就不再更新(所谓的"dying ReLU")。LeakyReLU 给负数区域一个小斜率(0.3),保证梯度始终能传回去。

LeakyReLU(x)=max⁡(0,x)+α⋅min⁡(0,x)\text{LeakyReLU}(x) = \max(0, x) + \alpha \cdot \min(0, x)LeakyReLU(x)=max(0,x)+αmin(0,x)

最后 Dense 层用linear激活(回归任务标配),输出维度由n_out决定——单步预测就是 1,多步预测就多几个。


三、数据怎么处理

3.1 滑窗构造样本

时间序列预测的第一步永远是把连续序列切成监督学习的样本对。代码里的data_collation函数设计得挺灵活:

  • 取前n_inn\_inn_in个时间步的所有特征 → 压平成一维向量
  • 取接下来n_outn\_outn_out个时间步的目标列→ 作为标签
  • 每隔scroll_windowscroll\_windowscroll_window步滑动一次,共取num_samplesnum\_samplesnum_samples个样本

示例:原始数据 7 行×\times×4 列(3 特征 + 1 目标),设n_in=2, n_out=2, scroll_window=1,则生成 3 组样本:

输入(2步×4列展平=8维)输出(未来2步的目标值)
第1-2行全部特征第3-4行的目标值
第2-3行全部特征第4-5行的目标值
第3-4行全部特征第5-6行的目标值

支持四种模式:单/多输入 × 单/多步输出,靠改参数就能切换。

3.2 归一化:先切分再缩放

这里有个容易被忽视的细节——必须先划分训练集/测试集,再分别做归一化。如果反过来,先用全部数据 fit 了 MinMaxScaler,测试集的信息就会"泄露"到训练过程中,评估结果会虚高。

# 正确做法Xtrain,Xtest,Ytrain,Ytest=train_test_split(values)# 先切m_in.fit_transform(Xtrain)# 用训练集 fitm_in.transform(Xtest)# 测试集只 transform,不 fit

MinMaxScaler 的变换公式:

xscaled=x−xmin⁡xmax⁡−xmin⁡x_{\text{scaled}} = \frac{x - x_{\min}}{x_{\max} - x_{\min}}xscaled=xmaxxminxxmin

反归一化就是把公式倒过来用,预测结果映射回原始量纲。


四、训练与评估配置

参数取值说明
输入时间步n_in5用前 5 个时刻预测未来
输出步数n_out1单步预测
训练/测试比例85% / 15%1000 个样本中 850 个用于训练
归一化方式MinMaxScaler缩放到 [0,1] 区间
优化器Adam默认学习率 0.001
损失函数MSE均方误差1n∑(yi−y^i)2\frac{1}{n}\sum(y_i - \hat{y}_i)^2n1(yiy^i)2
评估指标MAE平均绝对误差
Batch Size32
Epochs60
验证集比例25%训练集里再划 1/4 做验证
TCN 卷积核数128
TCN 卷积核大小3
TCN 膨胀系数[1, 2, 4]
SimpleRNN 单元数50
LeakyReLU 斜率0.3

评估用了五个指标,各有所长:

  • MSE / RMSE:对大误差敏感(平方放大),适合评估极端偏差
  • MAE:对误差一视同仁,直观好理解
  • MAPE:百分比形式,跨量纲可比,但不适合真值接近 0 的场景
  • :衡量模型比"瞎猜均值"强多少,越接近 1 越好

MAPE 的计算:

MAPE=1n∑i=1n∣yi−y^iyi∣×100%\text{MAPE} = \frac{1}{n} \sum_{i=1}^{n} \left| \frac{y_i - \hat{y}_i}{y_i} \right| \times 100\%MAPE=n1i=1nyiyiy^i×100%


五、运行环境与依赖

硬性要求:

Python >= 3.7 TensorFlow >= 2.0 (Keras 已内置) keras-tcn (pip install keras-tcn) scikit-learn pandas / numpy / matplotlib openpyxl (如需读取 .xlsx) prettytable (表格打印) mplcyberpunk (可视化风格,可选) qbstyles (同上,可选)

一块普通 GPU 就能跑(CPU 也行,60 个 epoch 几分钟的事)。训练过程中会输出每个 epoch 的 loss 和 val_loss,看着两条曲线收束的走势判断要不要加 epoch 或调学习率。


六、应用场景——不只是电力负荷

虽然示例数据是电力负荷,但凡是多变量时间序列预测的活,这套框架都能直接迁移:

  • 新能源功率预测:风电/光伏出力受风速、辐照度、温度等多因素影响,且波动剧烈,TCN 的长程建模能力正好派上用场
  • 交通流量预测:路网传感器数据,上下游路段互相影响,多变量输入是天然需求
  • 水质/空气质量监测:多种污染物浓度耦合,排放源与扩散延迟带来时序依赖
  • 量化金融:价量关系、多品种联动,序列长且信噪比低,膨胀卷积比 RNN 更抗噪

需要调整的地方主要是n_in(看你的数据周期多长)和dilations(感受野要覆盖一到两个完整周期)。


七、一点实操经验

跑这套代码踩过几个坑,列出来省得别人再踩:

  1. CSV 编码:中文数据文件默认可能不是 UTF-8,代码里用的gb2312,Windows 上导出的表格尤其注意这一点
  2. TCN 的return_sequences:接 RNN 时必须设为True,否则时序维度被压掉,RNN 拿什么来"循环"?
  3. 反归一化别忘了:预测出来的值是 [0,1] 区间的,不反归一化直接算 MAPE 会得到一个离谱的数字
  4. 滑窗步长scroll_window设成 1 会让相邻样本高度重叠,虽然样本数多了但也不是没代价——验证集和训练集可能"长得太像",导致验证 loss 虚低

八、总结

TCN + SimpleRNN 这个组合谈不上多新颖,但它务实:TCN 管全局周期,RNN 管局部细节,两层 Dense 做非线性映射,结构简单、训练快、可解释性不差。对大多数工业场景的时序预测需求,精度和效率的平衡点拿捏得刚好。

有一个 Bonus:因为 TCN 可以并行计算(不像 RNN 必须串行),推理阶段的速度比纯 LSTM/GRU 快不少,这对需要实时预测的上线场景很友好。


📎 获取方式

完整代码 + 示例数据集已打包

文件包含:TCN-RNN 模型完整代码、电力负荷预测示例数据、一键运行脚本、可视化模块。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询