SVM短期负荷预测完整例程:从特征工程到调参实战
简介基于SVM的电力系统短期负荷预测例程面向电力行业从业者、机器学习初学者及研究人员针对短期负荷预测中多因素耦合、非线性强等问题提供一种特征加权与SVM相结合的实践方案。与常规直接训练不同该例程在SVM训练前对各影响因素进行加权预处理突出历史负荷等关键特征降低弱相关因素的干扰从而有效提升预测精度。压缩包共2个文件包含1个MATLAB主程序和1个Excel数据文件整体仅19KB主程序覆盖数据读取、加权特征构造、训练/测试集划分、SVM建模、参数选择及误差评估等完整流程Excel中则提供了历史负荷及天气、节假日等影响因素数据。目前已有1133人学习下载适合用来自顶向下理解支持向量回归SVR原理也可作为直接运行的入门范例。通过本例程可快速复现实验掌握核函数选取与惩罚参数调优并在此基础上替换自己的数据或调整特征权重为改进负荷预测模型提供可扩展的参考。 我第一次正经做短期负荷预测是在一个电力公司的数据竞赛里。当时同行们一水儿地往LSTM、Transformer上堆我心里其实挺没底的。后来偶然用SVM支持向量机做了一版例程发现结果不仅不比那些复杂模型差训练速度还快了一个量级。后面我把这套例程整理成了可复用的脚本陆续有做配网规划、售电公司预测的朋友来问。这篇就写一份完整的SVM短期负荷预测例程从数据准备、特征构造到模型训练、调参和实际预测中的坑尽量把每一步的取舍讲透。如果你正要起步做负荷预测或者手里已经有一批历史负荷数据但不想一上来就上深度学习这份例程可以直接在你的项目里落地。它适合两类人一是刚接触电力预测的学生想快速看到一套能跑的完整流程二是需要先建立基线的工程师用SVM快速验证数据质量再决定要不要升级到更复杂的模型。1. 先搞清楚短期负荷预测到底是个什么预测问题1.1 模型要回答的问题电力系统短期负荷预测通常指预测未来几小时到几天的用电负荷值。放到数学上就是一个典型的回归问题给定历史负荷序列以及相关影响因素预测未来某个时刻的负荷数值。这个问题的特殊性在于负荷数据不是一堆独立样本而是带强时间相关性的序列。同样是下午两点工作日的负荷和周末的负荷差别很大同样是冬季寒潮来临前后的负荷曲线完全不同。所以做短期负荷预测本质上是在提取三层面的规律日内规律早晚高峰、午间低谷周期规律工作日/周末、季节变化突发事件影响节假日、极端天气、重大事件模型的作用就是把这些规律从历史数据里学出来再外推到未来。理解了这一点后面做特征构造就不会只盯着模型调参而是会去想哪些信息能帮助预测明天下午的负荷。1.2 为什么SVM在负荷预测里还没被淘汰我见过不少人在这个任务上一上来就上LSTM原因是时序数据就该用循环神经网络。但实际工程里SVM更准确说是SVR支持向量回归在小样本、特征明确的场景下表现非常稳定。SVM的核心思想是找一个最优超平面使样本到超平面的间隔最大。对于回归问题SVR要找一个函数让预测值与真实值的偏差尽量小同时保持函数尽量平滑。它有几个天然优势在高维特征空间里表现好不必担心特征稍微多一点就过拟合因为最终结果只由支持向量决定模型的泛化能力往往比经验风险最小化的模型更强核函数的存在让它能捕捉非线性关系负荷预测里的非线性特征正好适合用RBF核去拟合要说缺点也很明显经典SVR在大样本上训练速度会明显变慢。这也是为什么它适合做例程而不是海量数据生产系统的原因。如果你只有几万条小时级数据SVR完全够用如果数据到了百万条量级就得考虑随机森林或XGBoost这类更适合大样本的模型了。2. 输入端决定上限这份例程的数据准备与特征构造2.1 原始数据先处理好再谈建模很多初学者的通病是拿到数据直接扔进模型然后抱怨效果差。负荷预测的数据处理第一步是把三件事做干净时间索引必须是连续的缺失的时间点要么补全要么明确跳过。我用的是小时级数据如果某几个小时缺失最稳妥的方式是拉出完整时间轴把缺失值标出来再用前后同时刻的均值补齐。异常值要做平滑处理。负荷曲线里经常出现突然跌到0或者暴涨的毛刺这些大概率是采集装置故障或者通讯中断造成的不是真实用电行为。对这类点我习惯用前后24小时的同一时刻做中位数替换而不是简单用前后时刻均值——因为负荷在一天内有明显波动直接用相邻值会破坏日内曲线形态。数据格式上我建议整理成这样的长表字段说明datetime时间戳小时粒度load负荷值单位MWtemp气温单位摄氏度其他外部特征湿度、降雨量、节假日标记等如果你有别的天气字段可以一并加进来。但要注意SVM不是深度学习特征不是越多越好太多噪声特征反而会拉低精度。2.2 特征怎么造滞后特征、时间特征、天气特征我的经验是负荷预测的特征工程可以概括成一句话把时间规律变成模型看得懂的数值特征。下面是我在例程里用的几组核心特征。第一组是滞后特征。负荷序列自相关性极强某天的负荷往往和前几天的同一时刻高度相似。所以我构造了三个滞后项lag_1h前一小时负荷捕捉临近惯性lag_24h前一天同一时刻负荷捕捉日内周期lag_168h前一周同一时刻负荷捕捉周周期这三个滞后项是负荷预测里最有价值的特征基本能贡献大部分精度。第二组是时间特征。从时间戳里拆出小时、星期几、是否周末。小时和星期几要直接当数值用因为SVM对特征尺度是敏感的后面归一化后它们能表达这个样本出现在一天里的哪个阶段、一周里的哪个位置。是否周末作为0/1特征单独加入因为它对负荷水平的影响非常明显。第三组是天气特征。温度对负荷的影响最直接尤其是夏天空调和冬天采暖负荷。我在例程里直接用了当天温度和前一天同时刻温度前者表达当前的冷热程度后者帮助模型捕捉温度变化的趋势。另外提醒一句构造特征的时候一定要保证预测时刻能拿到这些值。比如lag_24h用的是前一天真实负荷这在当天做预测时是已知的温度可以用预报值但这就引入了第二个问题——天气预报的误差也会传导到负荷预测结果里。2.3 归一化SVM不吃原始量纲这一步看起来基础却是SVM能否收敛的关键。SVR对特征尺度非常敏感因为它的间隔计算依赖样本之间的距离如果一个特征的数值范围是0到100另一个是0到1后者在距离计算里几乎被淹没。我在例程里对全部特征用StandardScaler做标准化也就是减去均值、除以标准差。有一点必须注意标准化只允许在训练集上拟合再用训练集的均值和标准差去变换测试集。我见过不少人直接在全量数据上做标准化这在时间序列预测里属于信息泄漏——测试集的统计信息已经偷偷进入了训练过程表面上精度很高实际部署时立刻露馅。目标值负荷我在例程里没有单独归一化因为SVR对目标值的尺度并不敏感而且不归一化能直接读取预测的电力值方便算误差。如果你想对目标也做标准化记得预测完要反变换回原始量纲否则MAPE会算错。3. 例程代码逐段拆解从训练集划分到评价指标3.1 整体流程先理清这份例程的完整链路是读入数据、构造特征、按时间切分训练集和测试集、标准化、训练SVR、预测、反标准化如果做了、计算指标。下面给出可以直接跑通的核心代码。import numpy as np import pandas as pd from sklearn.svm import SVR from sklearn.preprocessing import StandardScaler from sklearn.model_selection import GridSearchCV from sklearn.metrics import mean_absolute_percentage_error, mean_squared_error示例用数据我会直接生成一段模拟负荷序列方便你跑通流程。真实项目里把这段换成自己的CSV读取即可。# 模拟一年小时级负荷数据真实项目请替换为自己的数据源 np.random.seed(42) n 24 * 365 time_idx pd.date_range(2024-01-01, periodsn, freqh) trend 0.02 * np.sin(2 * np.pi * np.arange(n) / (365 * 24)) 0.1 daily 0.3 * np.sin(2 * np.pi * np.arange(n) / 24 - 1) weekly 0.1 * np.sin(2 * np.pi * np.arange(n) / (24 * 7)) noise np.random.normal(0, 0.03, n) load 10 (trend daily weekly noise) * 5 temp 20 12 * np.sin(2 * np.pi * (np.arange(n) / (365 * 24)) 0.2) df pd.DataFrame({time: time_idx, load: load, temp: temp})3.2 特征构造与数据切分特征构造的代码看起来不多但每行都是踩过坑后确定的。df[hour] df[time].dt.hour df[dow] df[time].dt.dayofweek df[is_weekend] (df[dow] 5).astype(int) df[lag_1h] df[load].shift(1) df[lag_24h] df[load].shift(24) df[lag_168h] df[load].shift(168) df[temp_24h] df[temp].shift(24) df df.dropna().reset_index(dropTrue) features [hour, dow, is_weekend, temp, lag_1h, lag_24h, lag_168h, temp_24h] X df[features].values y df[load].values # 按时间顺序切分前80%训练后20%测试 split_idx int(len(df) * 0.8) X_train, X_test X[:split_idx], X[split_idx:] y_train, y_test y[:split_idx], y[split_idx:]这里有两点经验想多说一下。shift会引入NaN尤其shift(168)会让前168小时全部变成缺失值所以dropna要放在所有特征构造完成之后。另外数据切分必须按时间顺序不能随机切分。随机切分会把未来的数据混进训练集造成严重的数据泄漏这个问题在时间序列任务里几乎等于自杀。3.3 SVR模型搭建、训练与反归一化标准化和模型训练是这份例程最核心的部分。scaler StandardScaler().fit(X_train) X_train_scaled scaler.transform(X_train) X_test_scaled scaler.transform(X_test) model SVR(kernelrbf, C10, epsilon0.05, gammascale) model.fit(X_train_scaled, y_train) y_pred model.predict(X_test_scaled)这里我先固定了一个能用演示数据的参数组合C10、epsilon0.05、gammascale。判断一个SVR基线是否合理可以先看它在测试集上的MAPE到底落在什么范围。如果数据是模拟的MAPE可能在5%到10%之间真实负荷数据做得好可以压到3%以下。关于目标值归一化我在这个例程里故意不做因为直接看预测出来的电力值更直观。如果你对目标做了标准化预测完后一定要用scaler_y.inverse_transform恢复否则算出来的MAPE会是一个完全没意义的数值。3.4 评价指标不能只盯着一个MAPEmape mean_absolute_percentage_error(y_test, y_pred) * 100 rmse np.sqrt(mean_squared_error(y_test, y_pred)) print(fMAPE: {mape:.2f}%) print(fRMSE: {rmse:.2f} MW)MAPE是负荷预测行业最常用的指标之一它对小误差敏感度适中而且量纲无关方便不同模型横向比较。实际业务汇报里领导通常会问误差在百分之几说的就是MAPE。但我建议同时看RMSE。RMSE会放大较大误差的权重也就是说如果某一天预测效果特别差RMSE会明显升高。这个特性很有用当MAPE看起来不错但RMSE很高时说明模型在少数困难样本上翻了大车典型的就是节假日或极端天气日。我还会顺手打印几组典型时段的预测对比比如连续7天的每日预测曲线叠加。图和数字配合看才能发现模型系统性偏低的时段——这种结构性问题只看MAPE是看不出来的。4. 调参与避坑SVM负荷预测最容易翻车的几个地方4.1 C、epsilon、gamma到底在控制什么很多人调SVR参数就是拿GridSearchCV跑一遍其实把三个关键参数的作用理解了调参会更有方向。C是惩罚系数控制对训练误差的容忍度。C越大模型越不允许训练样本出错容易过拟合C越小模型越偏向平滑结构风险小但可能欠拟合。我在电力负荷场景里发现C通常取1到100之间比较合适默认的1.0往往偏小。epsilon是回归误差管的宽度意思是预测值和真实值偏差在这个宽度内就不计入损失。epsilon设得越小模型对精度的要求越苛刻容易让支持向量增多、训练变慢设得太大则预测曲线过于平滑尖峰全被削掉。对负荷数据epsilon从0.01到0.1之间去试比较合理。gamma只对RBF核有意义控制单个训练样本的影响范围。gamma越大每个样本的影响半径越小决策边界越复杂gamma越小模型越平滑。困惑最多的是gammascale这个选项它表示根据特征数量自动确定基准值是一个比较省心的起点。4.2 网格搜索别把三个参数一把抓一个容易踩的坑是同时网格搜索太多参数组合。假设C给5档、epsilon给5档、gamma给5档就是125组每组还要做5折交叉验证训练625个SVR模型。如果样本量到几万行半天跑不完。我用的是两阶段搜索。先用粗网格锁定大范围比如C取[0.1, 1, 10, 100]epsilon取[0.01, 0.05, 0.1]gamma取[scale, 0.01, 0.1]看看哪个区域效果最好。然后缩小范围做细搜索。这样既省时间又不至于漏掉最优区域。交叉验证要放在训练集上做测试集全程不能碰。我记得有一次调完参在测试集上MAPE特别漂亮后来回头检查才发现是网格搜索时忘了固定随机状态导致交叉验证的某折混进了测试集周边数据整套验证结果都不可信了。4.3 实际负荷预测最容易翻车的场景代码能跑通只是起点。真正把模型放到实际业务里有三个场景我几乎每次都会被问。第一个是节假日。春节、国庆这类长假的负荷模式完全不同于普通工作日历史数据的规律瞬间失效。处理办法之一是单独建一个节假日的特殊模型或者在特征里加节假日标记让模型至少知道今天不是普通的一天。很多实际项目里节假日样本太少SVM这类模型学不到规律这时候人工修正规则往往比重训模型更有效。第二个是预测曲线整体滞后。用滞后特征做预测时模型很容易学到当前值接近上一时刻值结果就是预测曲线比真实曲线晚一个时刻尤其在负荷急剧爬坡的早高峰时段。检查方法很简单把预测值和真实值画在同一个图上如果预测曲线形态完全正确但整体右移了一段基本就是滞后特征权重过大。缓解办法是调大epsilon、降低lag_1h的权重或者尝试用别的特征替代。第三个是温度突变日。前两天还是20度今天突然降到5度模型大概率低估负荷。因为训练数据里这种突变样本太少SVR为了保证整体平滑会把突变部分当作噪声处理掉。遇到这种场景单独做气象敏感负荷分析会比硬调模型参数有用。4.4 关于训练速度的一个实在建议SVR的时间复杂度大约在O(nn)到O(nn*n)之间n是样本量。样本量超过五万以后训练会明显变慢到了十万级普通电脑上做精细调参几乎没法等。我的经验是在数据集上先随机抽样两到三万条样本做参数初选确定参数范围后再全量训练。另外特征数量不要堆太多SVM在特征维度增加时支持向量数量也可能膨胀训练和预测都会变慢。如果后续数据量持续增长建议不要死守SVR可以横向对比随机森林或者XGBoost。它们的训练时间更可控而且对特征尺度和异常值的要求更低。SVM做一个可靠基线完全足够但生产系统要考虑的东西远比模型精度多。5. 扩展思路这份例程还能往哪个方向走模型本身跑通之后我建议你按下面的顺序做扩展。先引入更多外部特征。温度是最基本的湿度、风速、降雨量对部分地区的负荷影响也很大。如果做的是区域级负荷预测还可以把当地的经济活动指标、重要用户生产计划加进来。注意每加一个特征都要单独验证它对模型精度的边际贡献不能只堆特征。再试试多步预测。这份例程预测的是单点负荷实际业务需要未来24小时的完整曲线。你可以用滚动预测的方式用t时刻的真实特征预测t1然后把t1的预测值当作滞后特征继续预测t2。这个方案有个隐患——预测误差会逐步累积越长越不准。另一个思路是独立预测未来24个点的24个模型每个模型只预测固定时段训练数据用对应的历史同时段样本精度通常比滚动预测稳定。最后说句实在话不要一上来就追新技术。我在实际项目里见过太多LSTM跑不过精心调过的SVM的案例。不是LSTM不行而是小样本、强周期、特征清晰的负荷预测场景里SVM的归纳偏置正好合适。把这份例程吃透等你真正遇到深度学习才能解决的问题时自然知道该往哪走。本文还有配套的精品资源点击获取

相关新闻

最新新闻

日新闻

周新闻

月新闻