简介:面向高校学生与期末大作业场景,一套基于 Python 深度学习的多特征电力负荷预测课程设计项目,覆盖从数据预处理、特征构造、LSTM 模型训练到预测结果可视化的完整流程,也适合深度学习入门者进行项目实践。压缩包仅 8 个文件,包含 3 个 Python 脚本、2 个 CSV 数据文件、1 个 Excel 文件、1 个 Markdown 说明和 1 个使用说明 txt,整体约 831KB,结构清晰,下载后无需修改即可直接运行。目前已有 481 人学习,适合作为课程设计或期末考核的高分参考。具体来看,项目提供 data_processing.py 数据预处理、lstm_predict.py 负荷预测主程序、data_show.py 可视化脚本,并配套 raw_data.csv、power.csv 等原始数据,以及 README 和使用说明文档,便于快速理解多特征怎么构造、数据如何清洗、模型怎样搭建与评估。对想要快速完成并拓展深度学习电力预测任务的学习者,这是一份可直接复用的完整实践。
1. 电力负荷预测不是玄学:这类课程设计源码包到底能帮你省多少事
「电力负荷预测」课程设计压缩包,打开后一般是一套 python 代码加一份 CSV 数据。拿到这类包的人,多半卡在毕设或课设中段:知道深度学习能预测负荷,但不清楚多特征怎么拼进网络,更怕训练完画出的预测曲线是一条平直线。这个方向的本质不复杂:把历史负荷和气象、日期、节假日等外部变量一起喂给神经网络,让它学会未来一段时间的负荷走势。它适合电力相关专业的学生、刚入门的能耗预测工程师,以及想尽快拿到一份可复现基线的人。源码包的价值不在跑通,而在给你一条能改、能讲、能应对答辩的完整链路:数据对齐、滑窗构造、模型训练、指标评估,每一步都值得自己重写。下面按我做负荷预测的顺序,把这个方向拆开讲清楚。
2. 先把数据集看明白:负荷数据的时间尺度和多特征对齐决定模型上限
2.1 电力负荷数据的三种时间尺度:15 分钟、1 小时、1 天怎么选
很多人翻车,不是模型选错,而是没先问一句:这份 CSV 里的负荷是多长时间采一个点。采样密度直接决定你能预测多远、窗口该设多长、特征怎么对齐。15 分钟采样一天有 96 个点,适合短时调度和需求响应,窗口设 96 就能覆盖一整天,但缺测和异常点也更密。1 小时采样一天 24 个点,是课程设计最常见的选择,窗口 24 或 48 就能覆盖日周期,训练快、特征对齐也容易。日采样一年才 365 个点,样本量太小,深度学习优势发挥不出来,用传统时序方法往往更贴合,除非你有多年数据。
我拿到数据后不急着建模,先用 pandas 按时间列排序,检查采样间隔有没有跳变。间隔跳变比缺测更隐蔽——如果某天少了两个 15 分钟点,直接按行切窗口会把不同时刻的数据错位拼到同一行。另一个常见问题是时区:CSV 里时间如果是北京时间,但天气数据用的是世界标准时间,两者对不上,预测结果会整体偏移一小时。这种问题在曲线图上很难一眼看出来,因为形状是对的,只有按小时聚合误差时才会暴露。
| 数据粒度 | 常见窗口长度 | 常见预测步长 | 典型场景 |
|---|---|---|---|
| 15 分钟 | 96(1 天) | 1-16 个点 | 短时调度、需求响应 |
| 1 小时 | 24-168 | 1-24 小时 | 课程设计主流配置 |
| 1 天 | 30-365 | 1-7 天 | 月度规划,样本量少需谨慎 |
表格里的窗口长度是经验值,不是硬性规定。关键判断标准是:窗口至少要覆盖一个完整日周期,也就是 24 个点或 96 个点;如果数据有明显的工作日/周末差异,窗口再拉长到一周效果更好。但窗口每翻一倍,样本量会相应减少,训练时间也会变长,课程设计里不建议一上来就追长窗口。
2.2 多特征对齐的四个边界:缺测、异常尖峰、节假日、滑动窗口切割
多特征在负荷预测里通常指这几类:历史负荷本身、温度、湿度或风速、时刻编码(小时序号、星期几、是否节假日)。它们的采样频率经常不一样——气象站数据往往是小时级,负荷可能是 15 分钟级,对齐时要么重采样到同一频率,要么把低频特征前向填充。低频特征不能直接后向填充,因为天气预报本质上只知道过去和当前时刻的值,未来时刻的天气在真实场景里是预报值,不能拿实测值来填,否则又是一种数据泄漏。
import pandas as pd import numpy as np # 读入原始数据,负荷与气象分开是常态 df_load = pd.read_csv("load.csv", parse_dates=["time"]) # 负荷: time, load_kw df_weather = pd.read_csv("weather.csv", parse_dates=["time"]) # 气象: time, temp, hum # 1) 统一重采样到小时级,取均值是为了压掉采样噪声 df_load = df_load.set_index("time").resample("1h").mean().reset_index() df_weather = df_weather.set_index("time").resample("1h").ffill() # 气象缺测用前向填充 # 2) 时间特征:小时序号 + 星期几 + 节假日标记 df = pd.merge(df_load, df_weather, on="time", how="left") df["hour"] = df["time"].dt.hour df["weekday"] = df["time"].dt.weekday df["holiday"] = df["time"].dt.date.isin(holiday_dates).astype(int) # holiday_dates 需自行维护 # 3) 处理异常尖峰:超过 3 倍滚动标准差的位置替换为前后均值 roll_mean = df["load_kw"].rolling(24, center=True).mean() roll_std = df["load_kw"].rolling(24, center=True).std() mask = np.abs(df["load_kw"] - roll_mean) > 3 * roll_std df.loc[mask, "load_kw"] = roll_mean[mask] print(df.describe())这段脚本解决的是对齐问题而不是建模问题。重采样到 1 小时意味着你放弃了 15 分钟粒度的高频信息,换来的是气象特征能直接对齐;前向填充处理缺测是保守做法,如果缺测段超过 6 小时,我会直接删掉而不是填充。异常尖峰的阈值 3 倍滚动标准差是基于负荷数据的经验值,工业负荷在换班或设备启停时会产生尖峰,不处理会让模型为了拟合尖峰而牺牲整体曲线形状。
节假日特征值得单独说。法定节假日调休带来的「周末上班、工作日放假」模式,让负荷曲线和普通星期几完全不同。如果你不想维护一个完整节假日列表,至少要把「是否周末」放进特征;想效果好一点,就加上节前一天和节后一天的标记。很多课程设计数据只给了两三年,节假日样本本身很少,模型很难自己学出来,显式特征比让网络隐式学习靠谱得多。
2.3 滑动窗口怎么切:预测步长先于窗口长度决定
切窗口时有个顺序容易搞反:先想清楚要预测未来 1 小时还是未来 24 小时,再回头定窗口长度。预测步长由题目要求决定,窗口长度是为这个目标服务的。预测未来 1 小时,用过去 24 小时作为窗口通常够了;预测未来 24 小时,一般需要过去一周的负荷形态。多特征场景下,窗口内每个时间点都包含全部特征,而不是只把负荷拼在一起,这一点新手特别容易漏。
def make_samples(df, feature_cols, target_col, window=24, horizon=1): X, y = [], [] data = df[feature_cols].to_numpy() target = df[target_col].to_numpy() for i in range(len(data) - window - horizon + 1): X.append(data[i:i+window, :]) # 窗口内的所有特征 y.append(target[i+window:i+window+horizon]) # 未来 horizon 个点的负荷 return np.array(X), np.array(y) # 使用示例:window=24, horizon=1,预测未来 1 小时 X, y = make_samples(df, feature_cols, "load_kw", window=24, horizon=1) print("X shape:", X.shape) # (样本数, 窗口长度, 特征数) print("y shape:", y.shape) # (样本数, 预测步长)逻辑说明:X 的第一个维度是样本数,第二个维度是窗口长度,第三个维度是特征数,深度学习模型的输入张量就是这个三维结构。y 取的是窗口之后 horizon 个点的真实负荷值,要特别注意这里不要让窗口包含 y 所在的时间段,否则就是数据泄漏。参数上 window 和 horizon 是两个独立参数,horizon 设为 24 时,y 的形状会变成 (样本数, 24),这对应多步预测;如果只想预测下一个点,horizon 保持 1 就能让任务简单很多。
切完窗口后我习惯随机抽几个样本,人工检查窗口内第一个时间点是否确实是前一行的下一小时。这个检查只需要一分钟,但能避免很多后续训练时的怪象。尤其是跨年数据,如果 12 月 31 日最后一段被硬拼进 1 月 1 日的窗口,模型会学到一条根本不存在的负荷曲线。
3. 模型选型:LSTM、TCN 还是 Transformer,多特征负荷预测的取舍
3.1 为什么 LSTM 是这类课程设计的默认答案
负荷序列有典型的日周期和周周期,LSTM 这类循环网络天然适合按时间步展开,把上一个时刻的隐状态传给下一个时刻,能捕捉这种规律。相比 TCN 和 Transformer,LSTM 在样本量几千到几万的小数据集上更容易训练可控,不容易出现注意力矩阵学偏的问题。所以课程设计源码包里最常见的主模型就是 LSTM 或它的变体 BiLSTM。
选 LSTM 还有一个现实理由:代码短。一个两层的 LSTM 加一个全连接输出层,PyTorch 里 30 行以内能写完,调试时想看中间隐状态也方便。TCN 的膨胀卷积需要调 kernel size、dilation、padding 一堆参数,对新手不友好;Transformer 则需要位置编码和更长的训练轮次才能在负荷预测上超过 LSTM。课程设计的核心目标是在有限时间内拿出一套完整方案,而不是追求零点几个百分点的指标提升。
3.2 把多特征喂进 LSTM:输入张量的 shape 与滑窗构造
LSTM 的输入是三维张量,形状为 (batch_size, sequence_length, input_size)。其中 sequence_length 是窗口长度,input_size 是每个时间点的特征数。很多人第一次跑通源码后想自己加特征,结果在 shape 上报错,就是因为没理解第三个维度是「特征数」而不是「样本数」。加了温度、湿度、节假日之后,input_size 从 1 变成 5 甚至 10,模型本身不用改,只要把输入张量的最后一维对好就行。
import torch import torch.nn as nn class MultiFeatureLSTM(nn.Module): def __init__(self, n_features, hidden_size=64, num_layers=2, horizon=1): super().__init__() self.lstm = nn.LSTM( input_size=n_features, hidden_size=hidden_size, num_layers=num_layers, batch_first=True, dropout=0.2 ) self.fc = nn.Linear(hidden_size, horizon) def forward(self, x): # x: (batch, window, n_features) out, _ = self.lstm(x) # out: (batch, window, hidden_size) out = out[:, -1, :] # 取最后一个时间步的隐状态 return self.fc(out) # (batch, horizon) model = MultiFeatureLSTM(n_features=5, hidden_size=64, num_layers=2, horizon=1) print(model)这里 n_features=5 对应一个简化多特征配置:负荷、温度、湿度、小时序号、是否周末。hidden_size=64 是课程设计级别的常见选择,再大容易过拟合;num_layers=2 能学到稍复杂的非线性关系,到 3 层以上在小数据集上收益很小。取最后一个时间步的隐状态而不是所有时间步的输出,是因为要预测的是未来负荷,只需要模型读完整个窗口后的综合信息。如果你做多步预测,可以在 fc 层把输出维度改成 horizon,而不是在 LSTM 里循环预测。
如果你要冲高分,可以试试 BiLSTM。双向结构让模型同时看窗口内「之前」和「之后」的负荷变化,对捕捉早晚高峰的对称形状有帮助。要注意的是,BiLSTM 要求整个窗口完整输入后才能输出,不适合在线滚动预测;课程设计里预测未来一段时间的离线任务完全可以用,但如果演示的是实时预测,单向 LSTM 更合适。多步预测也有两种做法:直接多步是把全连接层输出维度设为 horizon,一次吐出未来 24 小时的预测值;滚动多步是用预测值喂回输入继续预测下一步,误差累积更严重,负荷场景里我一般不推荐后者。
3.3 三行配置对比:单序列基线、多特征 LSTM、Transformer 的参数量与效果边界
为了让你对选型有直观感受,这里给一张常用配置对比,说明各自的适用边界,而不是抬杠谁一定最好。
| 方案 | 输入特征 | 参数量量级 | 训练时长(小时级数据) | 适用边界 |
|---|---|---|---|---|
| 单序列 LSTM | 仅历史负荷 | 约 1-2 万 | 几分钟 | 适合拖底基线、Debug 用 |
| 多特征 LSTM | 负荷+气象+日期 | 约 2-4 万 | 十几分钟 | 课程设计主推,性价比高 |
| Transformer | 同多特征 | 约 5-10 万 | 半小时以上 | 数据量大(10 万+ 样本)才有优势 |
Transformer 在负荷预测上不是不能打,但它的 attention 需要大量样本才能学出「每周一上午负荷偏高」这种规律。课程设计的数据集往往只有几千到几万条,跑 Transformer 常常出现训练集损失降得很漂亮、验证集波动很大的现象,也就是过拟合。我一般会把它放在「改进方向」里提一句,而不是作为主模型。从工程角度看,多特征 LSTM 兼顾了可解释性和训练速度,你可以做特征消融——把温度、湿度依次去掉看指标变化,也能在 CPU 上十分钟内完成一轮训练。真到了需要把预测结果接到调度系统里的生产场景,LSTM 的推理时延也远低于 Transformer。
4. 训练与验证:用 7:2:1 切分还是按时间滚动,别把未来数据漏进训练集
4.1 时间序列切分的特殊性:随机打乱是翻车第一步
普通机器学习里,随机划分训练集和测试集是标准操作,但时间序列不行。相邻时刻的负荷高度相关,如果随机打乱,模型会「偷看」到未来一段时间的信息,测试集就失去了意义。最常见的翻车现场是:模型在一个随机划分的数据集上 MAPE 只有 2%,看起来很漂亮,但老师要求按时间顺序预测未来一周,结果曲线完全跟不上真实负荷。
推荐的切分方式是按时间顺序:前 70% 训练、中间 10% 验证、后 20% 测试。验证集用来挑轮次和调参,测试集只在最终评估时用一次。如果你把测试集也用来调参,最后的指标就是自欺欺人——答辩时老师只要问一句「这个误差是在哪个数据集上算的」,就会露馅。更严格的做法是滚动切分:每训练一轮把测试窗口往后移,模拟真实预测场景,但课程设计里 7:2:1 已经足够。
提示:如果数据带有明显的季节趋势,只按前 70% 连续切分可能让测试集与训练集的季节分布差异过大,常见做法是再做一次滚动评估来交叉验证结论。
4.2 复现训练脚本:损失函数、学习率、早停与归一化反算
训练脚本通常是这个结构:先归一化,再构造 DataLoader,然后进入训练循环,每个 epoch 结束在验证集上评估一次,验证损失下降才保存模型。下面这份脚本可以直接抄到你的项目里,但要注意几个顺序问题。
import torch import torch.optim as optim from torch.utils.data import DataLoader, TensorDataset # 归一化要在切分之后做,只用训练集的统计量 mean = X_train.mean(axis=(0, 1)) # 按特征维度算均值 std = X_train.std(axis=(0, 1)) + 1e-8 X_train_norm = (X_train - mean) / std X_val_norm = (X_val - mean) / std y_mean, y_std = y_train.mean(), y_train.std() y_train_norm = (y_train - y_mean) / y_std y_val_norm = (y_val - y_mean) / y_std train_loader = DataLoader(TensorDataset(torch.tensor(X_train_norm, dtype=torch.float32), torch.tensor(y_train_norm, dtype=torch.float32)), batch_size=64, shuffle=True, drop_last=True) model = MultiFeatureLSTM(n_features=X_train.shape[2], hidden_size=64, num_layers=2, horizon=1) optimizer = optim.Adam(model.parameters(), lr=1e-3) scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, factor=0.5, patience=5) criterion = nn.MSELoss() best_val = float("inf") for epoch in range(60): model.train() for xb, yb in train_loader: optimizer.zero_grad() pred = model(xb) loss = criterion(pred.squeeze(), yb) loss.backward() optimizer.step() model.eval() with torch.no_grad(): val_pred = model(torch.tensor(X_val_norm, dtype=torch.float32)) val_loss = criterion(val_pred.squeeze(), torch.tensor(y_val_norm, dtype=torch.float32)) scheduler.step(val_loss) if val_loss < best_val: best_val = val_loss torch.save(model.state_dict(), "best_model.pt") if epoch % 10 == 0: print(epoch, loss.item(), val_loss.item())这段代码有几个容易被忽略的点。归一化必须放在切分之后,并且只能使用训练集的 mean 和 std,否则验证集的信息会通过统计量泄漏进训练过程;y 也要单独做归一化,不能直接用 X 的统计量,因为它们的尺度完全不同。batch_size=64 是常见值,数据量小时可以用 32;shuffle=True 在训练时是允许的——这里打乱的是样本之间的顺序,样本内部的窗口仍然按时间排列,所以不构成时间泄漏。
学习率用 ReduceLROnPlateau,验证损失连续 5 个 epoch 不降就减半,这比固定学习率更省心。模型每轮验证一次,只在验证损失变好时保存权重,这样即使后续轮次过拟合,手里仍有最佳版本。这就是我常说的后悔药:训练到第 60 轮时验证集飘了,但你不需要重新跑,直接加载 best_model.pt 即可。训练轮次 60 对小时级数据通常够用;如果数据量大,可以按验证损失早停,不必死等 60 轮。
4.3 评价指标:MAE、RMSE、MAPE 在负荷预测里的解读
训练结束要算三个指标:MAE、RMSE、MAPE。它们看问题的角度不一样:MAE 是平均绝对误差,单位与负荷一致,最直观;RMSE 放大尖峰误差,适合评估最坏情况;MAPE 是百分比误差,便于在不同数据集间对比,但负荷接近零时会被放大到离谱的值。
from sklearn.metrics import mean_absolute_error, mean_squared_error def evaluate(y_true, y_pred): y_true = y_true * y_std + y_mean # 反归一化回真实负荷值 y_pred = y_pred * y_std + y_mean mae = mean_absolute_error(y_true, y_pred) rmse = mean_squared_error(y_true, y_pred, squared=False) nz_mask = y_true > 0.05 * y_mean # 低负荷时刻不参与 MAPE mape = np.mean(np.abs((y_true[nz_mask] - y_pred[nz_mask]) / y_true[nz_mask])) * 100 return mae, rmse, mape mae, rmse, mape = evaluate(y_val.numpy(), val_pred.squeeze().numpy()) print(f"MAE={mae:.2f} kW, RMSE={rmse:.2f} kW, MAPE={mape:.2f}%")反归一化是新手最容易漏的一步。模型训练时用的是归一化后的数值,预测出来的也是归一化值,必须乘以训练时保存的 y_std 再加 y_mean 才能得到真实负荷。MAPE 加了一个保护条件,只对大于 5% 平均负荷的样本计算,这是行业里的常见做法,因为凌晨低负荷时段绝对误差很小,但百分比误差会非常大,把整体 MAPE 拉得很高,不能真实反映模型质量。
指标算出来怎么用?如果 MAE 相对平均负荷在 5% 以内,说明模型抓到了主要模式;RMSE 明显大于 MAE 说明存在少数预测得很差的尖峰样本;MAPE 偏大而 MAE 正常,多半是低负荷时段拖累。答辩时能把这三个指标的关系讲清楚,比堆一堆花哨曲线更能让老师认可。
5. 避坑与调试:5 个让新手最容易翻车的细节
这几条是我在帮学生调这类课程设计项目时最常碰到的,按出现频率排序。每条都按现象、原因、解决三个层次写,方便对照。
5.1 数据泄漏:滑窗里混进了未来值
现象:训练集指标非常好,验证集也不差,一到测试集就崩;或者做滚动预测时误差越来越大。这类泄漏在气象特征上尤其隐蔽,因为天气数据如果用了实测值而不是预报值,相当于模型提前知道了未来天气。
原因:最常见的泄漏有两种。一是归一化统计量把测试集信息混进去了——先用全部数据算 mean 和 std 再切分,等于让模型偷看了未来的分布;二是滑窗构造时把预测目标也放进了窗口特征列,特征里包含「下一时刻负荷」,标签也是「下一时刻负荷」,模型直接抄答案,验证和测试当然对不上。
解决:我的固定流程是:先切分,再只对训练集 fit 归一化统计量,验证集和测试集仅 transform;构造窗口时让 y 的起始位置严格等于窗口末尾的下一个时间点。保险起见加一行断言assert np.all(X[:, -1, load_col] <= y[:, 0]),确保窗口最后时刻不晚于预测目标时刻。这一行断言能拦住大部分粗心导致的泄漏。
5.2 归一化范围不对导致预测是平直线
现象:预测曲线是一条几乎水平的直线,数值接近训练集均值,完全没有早晚高峰的形状。很多人在这一步就开始怀疑模型坏了,其实问题多半出在数据处理。
原因:最常见的是只归一化了 X 没归一化 y,或者归一化 y 时用错了统计量。另一个原因是特征尺度差异过大——负荷数值是几千,温度只有几十,模型把所有注意力都放在负荷上,输出自然趋于保守的平均值。最后一层激活函数也可能导致这个问题:如果输出层接了 sigmoid 或 tanh,输出被限制在 [0,1] 或 [-1,1] 区间,而标签没压缩到这个范围,反归一化后只能落在均值附近。
解决:X 按特征维度归一化,y 单独归一化;同时检查输入特征是否包含温度这种小尺度变量,必要时对每个特征分别标准化,而不是统一用一个 scaler。输出层直接接线性层,不加激活函数,回归任务不需要把输出压到某个区间。画预测曲线时,如果验证集上是一条平直线,先查这两处,比调模型参数快得多。
5.3 日期特征没编码成周期性,节假日预测全偏
现象:周一到周五的预测误差小,周末误差大;或者长假期间预测严重偏离实际。负荷曲线在节假日的形状和普通工作日完全不同,但模型好像完全没有意识到这一点。
原因:小时序号和星期几是周期变量,直接当整数喂进模型会学出「0 点和 23 点差异 23」这种错误关系。节假日被简单地当作 0/1 标志,但节假日前后一天的负荷形态与平时完全不同,单靠一个二值特征表达不了这种过渡。
解决:小时序号和星期几用正弦余弦编码,比如sin(2πh/24)和cos(2πh/24),保留周期性;节假日特征扩成三列:节前 1 天、节假日当天、节后 1 天,让模型能区分调休和平时的边界。这个改动一般能明显改善节假日样本的误差,而且实现成本很低,就是在特征工程里多构造两列。
5.4 GPU 显存不足时 batch 与 window 怎么取舍
现象:一跑训练就报错,提示 CUDA out of memory。这在课程设计里大多发生在窗口设成 168 且特征数超过 10 的情况下。
原因:窗口长度 168、特征数 20、batch_size 64 的组合会让 LSTM 在反向传播时占用大量显存,尤其是 num_layers 较大时。LSTM 的反向传播需要保存每个时间步的中间状态,窗口越长、隐层越大,显存占用成倍上涨。
解决:先把 batch_size 降一半,从 64 降到 32;再考虑缩短窗口到 72 或 48;最后才是减少特征数。注意,缩短窗口会牺牲模型对长期周期的记忆能力,所以优先降 batch。如果你还在 CPU 上跑,干脆把 hidden_size 降到 32,训练速度能快不少。显存问题本质上是用空间换时间,课程设计的数据量不大,CPU 上多等几分钟通常可以接受。
5.5 源码跑通但数字对不上:随机种子与框架版本
现象:同一个人、同一份数据,第一次跑 MAPE=4.2%,第二次跑变成 4.8%,排错半天找不到原因。更头疼的是,你换一台机器跑别人的源码,指标对不上,也不知道是代码问题还是环境问题。
原因:深度学习训练有随机性:参数初始化、DataLoader 打乱顺序、dropout,都会带来运气的成分。框架版本差异也会影响结果,PyTorch 1.x 和 2.x 在 LSTM 的底层实现上有数值差异,同一份代码可能跑出略微不同的指标。
解决:在训练脚本开头固定随机种子:random.seed(42)、np.random.seed(42)、torch.manual_seed(42),并在 DataLoader 里设置 generator。多个实验对比时,所有模型必须在同一随机种子和同一框架版本下跑,否则你比较的不是模型能力,而是运气。这个习惯养成后,「数字对不上」的排查时间能少一半。
6. 把课程设计变成可展示的项目:一份能自圆其说的 README 与三张图
源码跑通只是第一步,课程设计评分看的是你能不能把自己的工作讲清楚。我会建议你在项目里补三样东西:一份结构清晰的 README、两张预测效果图、一张误差分布图。
README 按这个顺序写:问题定义(预测未来 1 小时负荷,输入哪些特征)、数据处理流程(重采样、对齐、滑窗)、模型结构(LSTM 几层、hidden 多大)、训练配置(切分比例、学习率、早停)、结果表(MAE/RMSE/MAPE 三个指标)、复现命令(一行python train.py)。不要写大段原理介绍,老师更关心你做没做、结果多少。每一节控制在三五句话,能让人照着跑通就算合格。
三张图怎么选:第一张是测试集某连续 7 天的真实负荷与预测负荷对比曲线,能直观看到早晚高峰拟合得如何;第二张是 24 小时误差分布,按小时聚合 MAE,能看出凌晨是否更差;第三张是特征消融的柱状图,把温度特征去掉后 MAPE 上升了多少。有这三张图,答辩时每张图都能讲出两分钟的内容。
我自己的习惯是:跑完基线后先画误差分布图,而不是直接调模型。因为按小时聚合后的误差会告诉你该往哪个方向改进——如果凌晨误差最大,优先检查低负荷时段的归一化处理;如果午间误差最大,就该看温度特征是否对齐正确。这个习惯帮我在不少项目里省掉了无效调参的时间。记住,源码包只是起点,你把数据理解、模型选型和误差分析讲清楚,这门课就稳了。希望帮到你。
本文还有配套的精品资源,点击获取