ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

ML-For-Beginners 实战:使用支持向量回归(SVR)构建时间序列预测模型,并在新数据集上完成建模、评估与调参任务

ML-For-Beginners 实战:使用支持向量回归(SVR)构建时间序列预测模型,并在新数据集上完成建模、评估与调参任务 ML-For-Beginners 实战使用支持向量回归SVR构建时间序列预测模型并在新数据集上完成建模、评估与调参任务【免费下载链接】ML-For-Beginners12 weeks, 26 lessons, 52 quizzes, classic Machine Learning for all项目地址: https://gitcode.com/GitHub_Trending/ml/ML-For-Beginners本文是 Microsoft ML-For-Beginners 课程「Time Series Forecasting with Support Vector Regressor」7-TimeSeries/3-SVR/README.md的配套实战指南围绕课程结课任务「A new SVR model」translations/en/7-TimeSeries/3-SVR/assignment.md展开。你将完整走通一条从数据加载、切分、缩放、时间步重塑到 SVR 训练与 MAPE 评估的流水线并在此基础上学会如何用一份全新数据集独立重建模型、调节超参数与 timesteps最终交付一份可打分的 notebook。读完本文你不仅能复现课程中 MAPE 约 1.3% 的电力负荷预测结果还能掌握一套可迁移到任意单变量时间序列的 SVR 建模方法论。一、任务全景assignment 究竟要求做什么「A new SVR model」这份作业文档虽然篇幅不长却是一份定义清晰的动手型任务其核心要求如下见 translations/en/7-TimeSeries/3-SVR/assignment.md用全新数据重建 SVR 模型在已经跟随课程构建过一个 SVR 模型的基础上选择一份新的时间序列数据集例如高校公开的时间序列数据集不能直接复用课程自带的energy.csv在 notebook 中完整记录工作每一步都要有文字注释说明为什么这么做可视化数据与模型至少包含原始数据图、训练/测试划分图、训练集预测图与测试集预测图用合适的图形与 MAPE 评估精度将预测曲线与实际曲线叠加绘制并打印 MAPE 指标实验超参数与 timesteps调整gamma、C、epsilon等超参数尝试不同的时间步timesteps观察对测试集精度的影影。该任务还附带一份评分量表Rubric是自我检查的硬标准标准优秀Exemplary合格Adequate需改进Needs Improvement综合notebook 中构建、测试并解释了 SVR 模型含可视化与明确的精度说明notebook 缺少注释或包含 bug提交的 notebook 不完整任务文本说明其脱胎于 7-TimeSeries/2-ARIMA/assignment.md 的作业框架因此完成前建议先掌握上一课 ARIMA 的数据准备流程。要完成这份作业首先必须吃透课程讲义中如何构建一个 SVR 模型的完整代码路径下面按流水线逐一展开。二、SVR 为什么适合时间序列预测在动手之前先厘清三个关键概念课程讲义 7-TimeSeries/3-SVR/README.md 的 Introduction 部分有系统阐述回归Regression有监督学习技术从给定输入集合预测连续值本质是在特征空间中拟合一条覆盖最多数据点的曲线或直线支持向量机SVM一类用于分类、回归与异常检测的有监督模型表现为特征空间中的一个超平面——分类时它充当决策边界回归时它充当最佳拟合线SVM 通常借助核函数Kernel把数据映射到更高维空间使其更容易分离支持向量回归SVRSVM 家族中用于回归任务的分支目标是找到包含最多数据点的最佳拟合线在 SVM 语境下即超平面。为什么用 SVR 而非 ARIMA上一课的 ARIMA 是统计学的经典线性方法对时间序列预测非常成功但现实中的时间序列普遍存在非线性线性模型难以刻画。SVR 天然具备处理数据非线性关系的能力因此成为时间序列预测中 ARIMA 的有力补充。这正是本课把 SVR 引入时间序列场景的根本动机。三、运行环境与数据准备3.1 两个 notebook 的定位课程在 7-TimeSeries/3-SVR 目录下提供了两份 notebookworking/notebook.ipynb练习版关键实现处以None占位例如timestepsNone、model None供学习者自行填写solution/notebook.ipynb完整答案版包含所有实现与运行输出可作为自检参考。作业要求用全新数据重建模型实操中建议以 solution 版为模板替换数据源后重新走通全流程。3.2 依赖导入课程数据加载与评估函数统一封装在 7-TimeSeries/common/utils.py 中因此 notebook 首先要把仓库根目录加入模块搜索路径import sys sys.path.append(../../)随后导入全部依赖import os import warnings import matplotlib.pyplot as plt import numpy as np import pandas as pd import datetime as dt import math from sklearn.svm import SVR from sklearn.preprocessing import MinMaxScaler from common.utils import load_data, mape3.3 数据加载的底层实现load_data封装在 common/utils.py 中其实现逻辑值得逐行理解def load_data(data_dir): Load the GEFCom 2014 energy load data energy pd.read_csv(os.path.join(data_dir, energy.csv), parse_dates[timestamp]) # Reindex the dataframe such that the dataframe has a record for every time point # between the minimum and maximum timestamp in the time series. This helps to # identify missing time periods in the data (there are none in this dataset). energy.index energy[timestamp] energy energy.reindex(pd.date_range(min(energy[timestamp]), max(energy[timestamp]), freqH)) energy energy.drop(timestamp, axis1) return energy关键点数据集来自GEFCom 2014 能源负荷数据data/energy.csv包含timestamp、load、temp三列小时级粒度覆盖约 2012-01-01 至 2014-12-31parse_dates[timestamp]把时间列解析为datetime类型reindex(pd.date_range(..., freqH))以小时为频率重建完整时间轴用于暴露缺失时段该数据集并无缺失这是对数据完整性的一次显式校验最后丢弃timestamp列让datetime索引成为 dataframe 的唯一索引。调用与预览energy load_data(../../data)[[load]] energy.head(5)load 2012-01-01 00:00:00 2698.0 2012-01-01 01:00:00 2558.0 2012-01-01 02:00:00 2444.0 2012-01-01 03:00:00 2402.0 2012-01-01 04:00:00 2403.0绘制 2012 年 1 月至 2014 年 12 月的全部负荷数据直观感受序列的周期性日周期、季节周期energy.plot(yload, subplotsTrue, figsize(15, 8), fontsize12) plt.xlabel(timestamp, fontsize12) plt.ylabel(load, fontsize12) plt.show()四、训练集与测试集划分防止未来信息泄漏时间序列建模与普通监督学习的切分有本质区别测试集必须严格位于训练集之后否则模型会从未来时间段偷看答案造成虚假的高精度即过拟合式错觉。课程采用如下切分策略7-TimeSeries/3-SVR/README.md 的 Create training and testing datasets 一节训练集2014-09-01 至 2014-10-31两个月测试集2014-11-01 至 2014-12-31两个月注意讲义代码中以2014-12-30作为测试起始哨兵实际切片时用 test_start_dt取得整个 12 月。定义边界train_start_dt 2014-11-01 00:00:00 test_start_dt 2014-12-30 00:00:00可视化两段数据的衔接关系energy[(energy.index test_start_dt) (energy.index train_start_dt)][[load]].rename(columns{load:train}) \ .join(energy[test_start_dt:][[load]].rename(columns{load:test}), howouter) \ .plot(y[train, test], figsize(15, 8), fontsize12) plt.xlabel(timestamp, fontsize12) plt.ylabel(load, fontsize12) plt.show()五、过滤与缩放把数据投影到 (0, 1) 区间SVR 对特征尺度非常敏感不同量纲的特征会直接扭曲核函数计算的相似度因此必须先缩放再训练。本课使用MinMaxScaler把负荷数据线性映射到 (0, 1) 区间。按时间范围过滤出训练集与测试集train energy.copy()[(energy.index train_start_dt) (energy.index test_start_dt)][[load]] test energy.copy()[energy.index test_start_dt][[load]] print(Training data shape: , train.shape) print(Test data shape: , test.shape)Training data shape: (1416, 1) Test data shape: (48, 1)对训练集执行fit_transform拟合最小值/最大值并同时完成变换scaler MinMaxScaler() train[load] scaler.fit_transform(train)对测试集只执行transform——这是极易踩坑的一步缩放器必须沿用训练集上拟合出的 min/max绝不能对测试集重新拟合否则就泄漏了测试集的分布信息test[load] scaler.transform(test)六、时间步timesteps重塑把序列变成监督样本SVR 本身不认识时间需要把单变量时间序列构造成[batch, timesteps]形式的二维输入用前timesteps-1个时刻的值预测第timesteps个时刻的值。课程取timesteps 5即用前 4 小时预测第 5 小时。先把 DataFrame 转成 numpy 数组# Converting to numpy arrays train_data train.values test_data test.values设定时间步timesteps5用嵌套列表推导把序列切成长度为 5 的滑动窗口并取[:, :, 0]丢弃多余维度train_data_timestepsnp.array([[j for j in train_data[i:itimesteps]] for i in range(0,len(train_data)-timesteps1)])[:,:,0] train_data_timesteps.shape(1412, 5)测试集同理test_data_timestepsnp.array([[j for j in test_data[i:itimesteps]] for i in range(0,len(test_data)-timesteps1)])[:,:,0] test_data_timesteps.shape(44, 5)切分输入与输出前timesteps-1列为x最后一列为yx_train, y_train train_data_timesteps[:,:timesteps-1],train_data_timesteps[:,[timesteps-1]] x_test, y_test test_data_timesteps[:,:timesteps-1],test_data_timesteps[:,[timesteps-1]] print(x_train.shape, y_train.shape) print(x_test.shape, y_test.shape)(1412, 4) (1412, 1) (44, 4) (44, 1)形状变化的规律值得记牢样本数 原始长度 − timesteps 11416−51141248−5144特征数 timesteps − 14。七、构建并训练 SVR 模型7.1 模型定义与超参数课程选用RBF 核并把gamma、C、epsilon分别设为 0.5、10、0.05model SVR(kernelrbf,gamma0.5, C10, epsilon 0.05)fit之后打印的模型对象完整展示了全部默认参数solution/notebook.ipynb 中的运行输出SVR(C10, cache_size200, coef00.0, degree3, epsilon0.05, gamma0.5, kernelrbf, max_iter-1, shrinkingTrue, tol0.001, verboseFalse)这些参数的含义与调参方向如下表参数本课取值作用调参直觉kernelrbf核函数类型可选linear、poly、rbf、sigmoidRBF 善于捕捉非线性关系线性核适合近似线性序列gamma0.5RBF 核的宽度系数控制单个样本的影响力半径过大易过拟合、过小易欠拟合是调参重点C10正则化参数权衡训练误差与模型复杂度C 越大越贴近训练点但泛化风险升高epsilon0.05不敏感带宽度带内误差不计入损失越大模型越宽松可提高鲁棒性但降低贴合度degree3默认仅对poly核有效使用多项式核时调整tol0.001默认迭代停止的容差一般保持默认cache_size200默认核矩阵缓存MB数据量大时可增大7.2 拟合与预测训练model.fit(x_train, y_train[:,0])预测训练集与测试集reshape(-1,1)保证输出为列向量y_train_pred model.predict(x_train).reshape(-1,1) y_test_pred model.predict(x_test).reshape(-1,1) print(y_train_pred.shape, y_test_pred.shape)(1412, 1) (44, 1)至此模型已经构建完成下一步是评估。八、评估逆缩放、时序图与 MAPE8.1 把数据还原到原始量纲预测值是在 (0,1) 区间上产生的评估前必须用同一个scaler做逆变换才能与实际负荷兆瓦级对比# Scaling the predictions y_train_pred scaler.inverse_transform(y_train_pred) y_test_pred scaler.inverse_transform(y_test_pred) print(len(y_train_pred), len(y_test_pred))# Scaling the original values y_train scaler.inverse_transform(y_train) y_test scaler.inverse_transform(y_test) print(len(y_train), len(y_test))8.2 对齐时间戳由于第一个输出由前timesteps-1个值生成绘图时间轴要从第timesteps-1个索引之后开始train_timestamps energy[(energy.index test_start_dt) (energy.index train_start_dt)].index[timesteps-1:] test_timestamps energy[test_start_dt:].index[timesteps-1:] print(len(train_timestamps), len(test_timestamps))1412 448.3 训练集评估叠加绘制实际值红与预测值蓝并打印 MAPEplt.figure(figsize(25,6)) plt.plot(train_timestamps, y_train, color red, linewidth2.0, alpha 0.6) plt.plot(train_timestamps, y_train_pred, color blue, linewidth0.8) plt.legend([Actual,Predicted]) plt.xlabel(Timestamp) plt.title(Training data prediction) plt.show()print(MAPE for training data: , mape(y_train_pred, y_train)*100, %)MAPE for training data: 1.7195710200875551 %8.4 测试集评估plt.figure(figsize(10,3)) plt.plot(test_timestamps, y_test, color red, linewidth2.0, alpha 0.6) plt.plot(test_timestamps, y_test_pred, color blue, linewidth0.8) plt.legend([Actual,Predicted]) plt.xlabel(Timestamp) plt.show()print(MAPE for testing data: , mape(y_test_pred, y_test)*100, %)MAPE for testing data: 1.2623790187854018 %测试集 MAPE 约 1.26%说明模型在未见过的数据上表现良好。8.5 全量数据集评估最后把 2012-2014 年全部数据过一遍模型检验整体拟合水平# Extracting load values as numpy array data energy.copy().values # Scaling data scaler.transform(data) # Transforming to 2D tensor as per model input requirement data_timestepsnp.array([[j for j in data[i:itimesteps]] for i in range(0,len(data)-timesteps1)])[:,:,0] print(Tensor shape: , data_timesteps.shape) # Selecting inputs and outputs from data X, Y data_timesteps[:,:timesteps-1],data_timesteps[:,[timesteps-1]] print(X shape: , X.shape,\nY shape: , Y.shape)Tensor shape: (26300, 5) X shape: (26300, 4) Y shape: (26300, 1)# Make model predictions Y_pred model.predict(X).reshape(-1,1) # Inverse scale and reshape Y_pred scaler.inverse_transform(Y_pred) Y scaler.inverse_transform(Y)plt.figure(figsize(30,8)) plt.plot(Y, color red, linewidth2.0, alpha 0.6) plt.plot(Y_pred, color blue, linewidth0.8) plt.legend([Actual,Predicted]) plt.xlabel(Timestamp) plt.show()print(MAPE: , mape(Y_pred, Y)*100, %)MAPE: 2.0572089029888656 %8.6 MAPE 的定义源码级评估指标mape封装在 common/utils.pydef mape(predictions, actuals): Mean absolute percentage error predictions np.array(predictions) actuals np.array(actuals) return (np.absolute(predictions - actuals) / actuals).mean()即平均绝对百分比误差先逐点计算|预测 − 实际| / 实际再取均值。之所以在打印时乘以 100是为了把小数换算成百分比读数。该指标无量纲、可跨数据集比较是作业中判断模型精度的统一标尺。九、完成「A new SVR model」作业的分步指引理解了上述全流程后按以下步骤在新数据集上独立完成任务步骤 1选择新数据集。从课程建议的公开时间序列数据集如高校维护的经典时间序列数据集合中挑选一份单变量序列可以是气温、流量、销量等任意连续量。注意数据集应具备足够长度至少数百个时间点以便切分后训练集仍有充足的滑动窗口样本。步骤 2搭建 notebook 骨架。以 working/notebook.ipynb 为模板其中None占位即练习点或直接参考 solution/notebook.ipynb 的完整实现把数据路径替换为新数据并为每个单元补充中文注释说明这一步做了什么、为什么。步骤 3复用数据流水线。依次完成加载数据 → 全量可视化 → 按时间顺序划分训练/测试集 →MinMaxScaler缩放 → timesteps 滑动窗口重塑。若新数据不是小时粒度需同步调整pd.date_range的freq参数与时间切分边界。步骤 4训练与评估。用 RBF 核构建SVR模型拟合后在训练集、测试集、全量数据三处分别绘制实际 vs 预测对比图并打印 MAPE。若新数据特征差异大gamma0.5, C10, epsilon0.05未必最优需要进入下一步调参。步骤 5超参数实验。对gamma如 0.1/0.5/1/5、C如 1/10/50/100、epsilon如 0.01/0.05/0.1做网格式对比以测试集 MAPE 最低为选优准则在 notebook 中记录每组结果的表格或对比图。步骤 6timesteps 实验。把timesteps从 5 改为 3、7、12、24 等值观察窗口长度对预测精度的影影窗口太短捕捉不到周期太长则引入噪声并显著减少样本数样本数 长度 − timesteps 1。步骤 7对照 Rubric 自查。对照前文的评分量表逐项核验模型是否构建、测试、解释齐全可视化是否覆盖数据与预测MAPE 是否明确陈述注释是否完整、代码是否可运行全部满足即为优秀Exemplary档。十、进阶挑战与注意事项换核函数分别用linear、poly、sigmoid核训练同一份数据对比各自在测试集上的 MAPE 与训练耗时理解核函数选择对非线性拟合能力的影响警惕过拟合训练集 MAPE1.72%与全量 MAPE2.06%均略高于测试集说明模型在见过的数据上拟合更好这是正常现象若训练集误差远低于测试集误差则应增大C或减小gamma的正则化倾向需要反思缩放的一致性测试集只能用训练集拟合出的 scaler 做transform全量评估时也沿用同一 scaler这是保证评估公正性的底线数据粒度适配本课数据为小时级若新数据为日级或分钟级timesteps的语义前 N 个小时/天/分钟需随之调整可视化图的尺寸也建议相应缩放。通过本作业你将真正掌握数据清洗 → 缩放 → 滑动窗口构样 → SVR 训练 → 逆缩放评估 → 超参数搜索这一完整闭环这套方法可平滑迁移到能源、交通、零售等绝大多数单变量时间序列预测场景。【免费下载链接】ML-For-Beginners12 weeks, 26 lessons, 52 quizzes, classic Machine Learning for all项目地址: https://gitcode.com/GitHub_Trending/ml/ML-For-Beginners创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进