时间序列预测中的支持向量回归器 在上一课中,你学习了如何使用ARIMA模型进行时间序列预测。现在,我们将研究一种用于预测连续数据的回归模型——支持向量回归器(SVR)。 课前测验 简介 在本课程中,你将发现如何使用[SVM:Support Vector Machine](https://zh.wikipedia.org/wiki/支持向量机)来构建回归模型,即SVR:支持向量回归器。 SVR 在时间序列中的应用 [^1] 在理解SVR在时间序列预测中的重要性之前,这里有一些你需要了解的重要概念: 回归:监督学习技术,用于根据给定的一组输入预测连续值。其想法是在特征空间中拟合一条曲线(或直线),使其包含尽可能多的数据点。点击此处了解更多。
在上一课中,你学习了如何使用ARIMA模型进行时间序列预测。现在,我们将研究一种用于预测连续数据的回归模型——支持向量回归器(SVR)。
在本课程中,你将发现如何使用[SVM:Support Vector Machine](https://zh.wikipedia.org/wiki/支持向量机)来构建回归模型,即SVR:支持向量回归器。
在理解SVR在时间序列预测中的重要性之前,这里有一些你需要了解的重要概念:
在上一课中,你学习了ARIMA,这是一种非常成功的统计线性方法,用于预测时间序列数据。然而,在许多情况下,时间序列数据具有非线性特性,这不能被线性模型映射。在这种情况下,SVM考虑数据中的非线性能力使SVR在时间序列预测中表现出色。
数据准备的第一步与上一课中的ARIMA相同。
打开本课程中的[/working](https://github.com/microsoft/ML-For-Beginners/tree/main/7-TimeSeries/3-SVR/working)文件夹并找到[notebook.ipynb](https://github.com/microsoft/ML-For-Beginners/blob/main/7-TimeSeries/3-SVR/working/notebook.ipynb)文件。2
运行笔记本并导入必要的库:2
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, mape
将/data/energy.csv文件中的数据加载到Pandas数据框中并查看:2
energy = load_data('../../data')[['load']]
绘制从2012年1月到2014年12月的所有可用能源数据:2
energy.plot(y='load', subplots=True, figsize=(15, 8), fontsize=12) plt.xlabel('timestamp', fontsize=12) plt.ylabel('load', fontsize=12) plt.show()

现在,让我们构建我们的SVR模型。
现在你的数据已经加载完毕,你可以将其分为训练集和测试集。然后,你需要重塑数据以创建基于时间步长的数据集,这对于SVR是必需的。你将在训练集上训练模型。在模型训练完成后,你需要在训练集、测试集以及整个数据集上评估其准确性,以查看整体性能。你需要确保测试集覆盖的时间段晚于训练集,以确保模型不会从未来的时间段获取信息(这种情况称为过拟合)。
分配一个时间段,即2014年9月1日至2014年10月31日作为训练集。测试集将包括2014年11月1日至2014年12月31日的时间段:2
train_start_dt = '2014-11-01 00:00:00' test_start_dt = '2014-12-30 00:00:00'
可视化差异:2
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'}), how='outer') \ .plot(y=['train', 'test'], figsize=(15, 8), fontsize=12) plt.xlabel('timestamp', fontsize=12) plt.ylabel('load', fontsize=12) plt.show()

现在,你需要通过过滤和缩放数据来准备训练数据。过滤数据集,只保留所需的时间段和列,并进行缩放以确保数据投影到区间0,1。
过滤原始数据集,仅包括指定时间段的数据,并只包括所需的“负载”列加上日期:2
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)
缩放训练数据,使其范围在(0, 1)之间:2
scaler = MinMaxScaler() train['load'] = scaler.fit_transform(train)
现在,你将缩放测试数据:2
test['load'] = scaler.transform(test)
对于SVR,你将输入数据转换为形式 [batch, timesteps]. So, you reshape the existing train_data and test_data,这样就会有一个新的维度,表示时间步长。
# Converting to numpy arrays train_data = train.values test_data = test.values
在这个例子中,我们取 timesteps = 5。因此,模型的输入是前4个时间步的数据,输出将是第5个时间步的数据。
timesteps=5
使用嵌套列表推导式将训练数据转换为二维张量:
train_data_timesteps=np.array([[j for j in train_data[i:i+timesteps]] for i in range(0,len(train_data)-timesteps+1)])[:,:,0] train_data_timesteps.shape
(1412, 5)
将测试数据转换为二维张量:
test_data_timesteps=np.array([[j for j in test_data[i:i+timesteps]] for i in range(0,len(test_data)-timesteps+1)])[:,:,0] test_data_timesteps.shape
(44, 5)
从训练和测试数据中选择输入和输出:
x_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)
现在,是时候实现SVR了。要了解更多信息,可以参考此文档。对于我们的实现,我们遵循以下步骤:
fit() functionpredict() 函数定义模型现在我们创建一个SVR模型。在这里,我们使用RBF核,并将超参数gamma、C和epsilon分别设置为0.5、10和0.05。
model = SVR(kernel='rbf',gamma=0.5, C=10, epsilon = 0.05)
model.fit(x_train, y_train[:,0])
SVR(C=10, cache_size=200, coef0=0.0, degree=3, epsilon=0.05, gamma=0.5, kernel='rbf', max_iter=-1, shrinking=True, tol=0.001, verbose=False)
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)
你已经构建好了SVR!现在我们需要评估它。
为了评估,首先我们需要将数据缩放到原始比例。然后,为了检查性能,我们将绘制原始和预测的时间序列图,并打印MAPE结果。
缩放预测和原始输出:
# 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))
我们从数据集中提取时间戳,显示在图表的x轴上。请注意,我们使用前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 44
绘制训练数据的预测图:
plt.figure(figsize=(25,6)) plt.plot(train_timestamps, y_train, color = 'red', linewidth=2.0, alpha = 0.6) plt.plot(train_timestamps, y_train_pred, color = 'blue', linewidth=0.8) plt.legend(['Actual','Predicted']) plt.xlabel('Timestamp') plt.title("Training data prediction") plt.show()

打印训练数据的MAPE
print('MAPE for training data: ', mape(y_train_pred, y_train)*100, '%')
MAPE for training data: 1.7195710200875551 %
绘制测试数据的预测图
plt.figure(figsize=(10,3)) plt.plot(test_timestamps, y_test, color = 'red', linewidth=2.0, alpha = 0.6) plt.plot(test_timestamps, y_test_pred, color = 'blue', linewidth=0.8) plt.legend(['Actual','Predicted']) plt.xlabel('Timestamp') plt.show()

打印测试数据的MAPE
print('MAPE for testing data: ', mape(y_test_pred, y_test)*100, '%')
MAPE for testing data: 1.2623790187854018 %
你在测试数据集上得到了非常好的结果!
# 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_timesteps=np.array([[j for j in data[i:i+timesteps]] for i in range(0,len(data)-timesteps+1)])[:,:,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', linewidth=2.0, alpha = 0.6) plt.plot(Y_pred, color = 'blue', linewidth=0.8) plt.legend(['Actual','Predicted']) plt.xlabel('Timestamp') plt.show()

print('MAPE: ', mape(Y_pred, Y)*100, '%')
MAPE: 2.0572089029888656 %
非常好的图表,展示了准确度良好的模型。做得很好!
timesteps值,让模型回溯以进行预测。本课介绍了SVR在时间序列预测中的应用。要了解更多关于SVR的内容,可以参考这篇博客。scikit-learn文档提供了更全面的SVM、SVR和不同核函数及其参数的解释。
声明:
本文件灏天文库团队进行了翻译。尽管我们力求准确,但请注意,翻译可能包含错误或不准确之处。原文档以其原始语言为准。我们不对因使用此翻译而产生的任何误解或误译负责。