python用支持向量机回归(SVR)模型分析用电量预测电力消费

本文描述了训练支持向量回归模型的过程,该模型用于预测基于几个天气变量、一天中的某个小时、以及这一天是周末/假日/在家工作日还是普通工作日的用电量。

由Kaizong Ye,Coin Ge撰写

支持向量机是机器学习的一种形式,可用于分类或回归。尽可能简单地说,支持向量机找到了划分两组数据的最佳直线或平面,或者在回归的情况下,找到了在容差范围内描述趋势的最佳路径。

对于分类,该算法最大限度地减少了对数据进行错误分类的风险。

对于回归,该算法使回归模型在某个可接受的容差范围内没有获得的数据点的风险最小化。

×

关于使用SVM进行回归分析的介绍很少,在这里,我们讨论一下SVR的理论知识,并对该方法有一个简明的理解。

SVR简单介绍

SVR全称是support vector regression,是SVM(支持向量机support vector machine)对回归问题的一种运用。所以在介绍SVR之前,我们先简单的来了解一下什么是SVM。

SVM

SVM与logistic分类器类似,也是一种二类分类模型,其基本模型定义为特征空间上的间隔最大的线性分类器,其学习策略便是间隔最大化,最终可转化为一个凸二次规划问题的求解。

对于下面一个数据集,有两类分别使用×和○来表示。那么我们想要找到一条曲线来区分这两类。可想而知,这样的曲线存在无数条,如何找到那一条最优的曲线呢?那就是要找到间隔(Gap)最大的那一条曲线,然后我们就可以根据这条曲线来分类了。而这条曲线,我们称为超平面。图中加粗的×与○,我们则称这些向量为支持向量。

而实际上,我们很少会遇到上面的情况,能直接使用一条直线将数据分类,更多的时候,数据无法通过直线来分类。比如下面这种情况:

当然了,这都不是事,既然在二维上该数据无法使用线性分类,那我们就将数据映射到更高维上,在高维上构造超平面,从而完成分类。

这就是为什么将上面的直线称为超平面。

所以对于非线性的模型,我们需要:使用非线性映射将数据投影至特征空间;

在特征空间使用线性分类器;

看似很简单,但是我们在映射时,就会发现当变量增多时,映射到高维空间的维度是呈指数增长的,计算起来十分困难,这时候就需要核函数(kernel function)了。核函数也是将特征从低维到高维进行转换,但是它是先在低维上进行计算,实际的分类效果表现在高维上。这样,我们就避免了在高维上复杂的计算,仍得到相同的结果。

一些常用的核函数:多项式核

高斯核

线性核

好了,SVM就简单介绍到这里。更多理论的推导或者其他更深的理论,请自行查阅!

接下来,我们来看看SVR又是怎么回事。

我们知道,最简单的线性回归模型是要找出一条曲线使得残差最小。同样的,SVR也是要找出一个超平面,使得所有数据到这个超平面的距离最小。

前面说了,SVR是SVM的一种运用,基本的思路是一致,除了一些细微的区别。使用SVR作回归分析,与SVM一样,我们需要找到一个超平面,不同的是:在SVM中我们要找出一个间隔(gap)最大的超平面,而在SVR,我们定义一个ε,如上图所示,定义虚线内区域的数据点的残差为0,而虚线区域外的数据点(支持向量)到虚线的边界的距离为残差(ζ)。与线性模型类似,我们希望这些残差(ζ)最小。所以大致上来说,SVR就是要找出一个最佳的条状区域(2ε宽度),再对区域外的点进行回归。

对于非线性的模型,与SVM一样使用核函数(kernel function)映射到特征空间,然后再进行回归。


导入一些包和数据

import pandas as pd # 对于数据分析,特别是时间序列
import numpy as np # 矩阵和线性代数的东西,类似MATLAB
from matplotlib import pyplot as plt # 绘图


视频

R语言广义相加模型(GAM)在电力负荷预测中的应用

探索见解

去bilibili观看

探索更多视频

Scikit-learn是Python中的大型机器学习包之一。

from sklearn import svm
from sklearn import cross_validation
from sklearn import preprocessing as pre

在此随机插入更好的数据可视化。

# 设置颜色
graylight = '#d4d4d2'
gray = '#737373'
red = '#ff3700'

我在这个模型中使用的数据是通过公寓中安装的智能电表中获得的。

USAGE “字段给出了该小时内的用电度数。

elec.head(3)

Out[5]:

fig = plt.figure(figsize=\[14,8\])

elecweather\['USAGE'\].plot

在r语言中使用GAM(广义相加模型)进行电力负荷时间序列分析

阅读文章



视频

支持向量机SVM、支持向量回归SVR和R语言网格搜索超参数优化实例

探索见解

去bilibili观看

探索更多视频

我想将典型的工作日与周末、假日和在家工作的日子区分开来。所以现在所有的正常工作日都是0,所有的假期、周末和在家工作的日子都是1。

分类变量:平日与周末/假期/在家工作日

## 将周末和节假日设置为1,否则为0
elecwea\['Day'\] = np.zeros

# 周末
elecwea\['Atypical_Day'\]\[(elecwea.index.dawe==5)|(elecwea.index.dawe==6)\] = 1

# 假期,在家工作日
假期 = \['2014-01-01','2014-01-20'\]
workhome = \['2014-01-21','2014-02-13','2014-03-03','2014-04-04'\]

for i in range(len(holiday)):
    elecwea\['Day'\]\[elecwea.index.date==np.datetime64(holidays\[i\])\] = 1
for i in range(len(workhome)):
    elecwea\['Day'\]\[elecwea.index.date==np.datetime64(workhome\[i\]) \] = 1
 
elecwea.head(3)


随时关注您喜欢的主题


更多的分类变量:一周中的一天,小时

在这种情况下,一天中的每个小时是一个分类变量,而不是连续变量。做分析时,需要对一天中的每一个小时进行 “是 “或 “否 “的对应。

# 为一天中的每个小时创建新的列,如果index.hour是该列对应的小时,则分配1,否则分配0

for i in range(0,24):
    elecweat\[i\] = np.zeros(len(elecweat\['USAGE'))
    elecweat\[i\]\[elecweat.index.hour==i\] = 1
    
# 例子 3am
elecweat\[3\]\[:6\]

时间序列:需要附加上以前的用电需求的历史窗口

由于这是一个时间序列,如果我们想预测下一小时的能耗,训练数据中任何给定的X向量/Y目标对都应该提供当前小时的用电量(Y值,或目标)与前一小时(或过去多少小时)的天气数据和用量(X向量)。

# 在每个X向量中加入历史用量

# 设置预测的提前小时数
hours = 1

# 设置历史使用小时数
hourswin = 12


for k in range(hours,hours+hourswin):
    
    elec\_weat\['USAGE-%i'% k\] = np.zero(len(elec\_weat\['USAGE'\])

    
    
for i in range(hours+hourswi,len(elecweat\['USAGE'\]))。)
    
    for j in range(hours,hours+hourswin):
        
        elec\_weat\['USAGE-%i'% j\]\[i\] = elec\_weat\['USAGE\]i-j\] 。

        
elec_weat.head(3)

由于这是时间序列数据,定义训练期和测试期更有意义,而不是随机的零星数据点。

分成训练期和测试期

如果它不是一个时间序列,我们可以选择一个随机的样本来分离出一个测试集。

# 定义训练和测试期
train_start = '18-jan-2014'(训练开始)。
train_end = '24-march-2014'.
test_start = '25-march-2014'(测试开始)。
test_end = '31-march-2014'。
# 分成训练集和测试集(仍在Pandas数据帧中)。

xtrain = elec\_and\_weather\[train\_start:train\_end\]。
del xtrain\['US'\]
del xtrain\['time_end'\]


ytrain = elec\_and\_weather\['US'\]\[train\_start:train\_end\] 。

将训练集输出成csv,看得更清楚。

X\_train\_df.to\_csv('training\_set.csv')

scikit-learn包接收的是Numpy数组,而不是Pandas DataFrames,所以我们需要进行转换。

# 用于sklearn的Numpy数组

X\_train = np.array(X\_train_df)

标准化变量

所有的变量都需要进行标准化。该算法不知道每个变量的尺度是什么。换句话说,温度一栏中的73的值看起来会比前一小时的千瓦时使用量中的0.3占优势,因为实际值是如此不同。sklearn的预处理模块中的StandardScaler()将每个变量的平均值去除,并将其标准化为单位方差。当模型在按比例的数据上进行训练时,模型就会决定哪些变量更有影响力,而不是由任意的比例/数量级来预先决定这种影响力。

训练SVR模型

将模型拟合训练数据!

SVR\_model = svm.SVR(kernel='rbf',C=100,gamma=.001).fit(X\_train\_scaled,y\_train)
print 'Testing R^2 =', round(SVR\_model.score(X\_test\_scaled,y\_test),3)

预测和测试

计算下一小时的预测(预测!)我们预留了一个测试数据集,所以我们将使用所有的输入变量(适当的缩放)来预测 “Y “目标值(下一小时的使用率)。

# 使用SVR模型来计算预测的下一小时使用量
 SVRpredict(X\_test\_scaled)

# 把它放在Pandas数据框架中,以便于使用
DataFrame(predict_y)

绘制测试期间的实际和预测电力需求的时间序列。

# 绘制预测值和实际值

plt.plot(index,y\_test\_df,color='k')
plt.plot(predictindex,predict_y)

重新取样的结果为每日千瓦时

### 绘制测试期间的每日总千瓦时图


y\_test\_barplot
ax.set_ylabel('每日总用电量(千瓦时)')

# Pandas/Matplotlib的条形图将x轴转换为浮点,所以需要找回数据时间
ax.set_xticklabels(\[dt.strftime('%b %d') for dt in

误差测量

以下是一些精度测量。

len(y\_test\_df)

均方根误差

这实际上是模型的标准误差,其单位与预测变量(或这里的千瓦时)的单位相同。

calcRMSE(predict\_y, y\_test_df)

平均绝对百分比误差

用这种方法,计算每个预测值和实际值之间的绝对百分比误差,并取其平均值;计量单位是百分比。如果不取绝对值,而模型中又没有什么偏差,你最终会得到接近零的结果,这个方法就没有价值了。

errorsMAPE(predict\_y, y\_test_df)

平均偏置误差

平均偏差误差显示了模型的高估或低估情况。初始SVM模型的平均偏差误差为-0.02,这表明该模型没有系统地高估或低估每小时的千瓦时消耗。

calcMBE(predict\_y, y\_test_df)

变异系数

这与RMSE类似,只是它被归一化为平均值。它表明相对于平均值有多大的变化。

这与RMSE类似,只是它被归一化为平均值。它表明相对于平均值有多大的变化。

plot45 = plt.plot(\[0,2\],\[0,2\],'k')


可下载资源

关于作者

Kaizong Ye拓端研究室(TRL)的研究员。在此对他对本文所作的贡献表示诚挚感谢,他在上海财经大学完成了统计学专业的硕士学位,专注人工智能领域。擅长Python.Matlab仿真、视觉处理、神经网络、数据分析。

本文借鉴了作者最近为《R语言数据分析挖掘必知必会 》课堂做的准备。

​非常感谢您阅读本文,如需帮助请联系我们!

 
QQ在线咨询
售前咨询热线
15121130882
售后咨询热线
0571-63341498

关注有关新文章的微信公众号


永远不要错过任何见解。当新文章发表时,我们会通过微信公众号向您推送。

技术干货

最新洞察

This will close in 0 seconds