拓端tecdat|python用支持向量機(jī)回歸(SVR)模型分析用電量預(yù)測(cè)電力消費(fèi)
原文鏈接:http://tecdat.cn/?p=23921
原文出處:拓端數(shù)據(jù)部落公眾號(hào)
本文描述了訓(xùn)練支持向量回歸模型的過(guò)程,該模型用于預(yù)測(cè)基于幾個(gè)天氣變量、一天中的某個(gè)小時(shí)、以及這一天是周末/假日/在家工作日還是普通工作日的用電量。
關(guān)于支持向量機(jī)的快速說(shuō)明
支持向量機(jī)是機(jī)器學(xué)習(xí)的一種形式,可用于分類或回歸。盡可能簡(jiǎn)單地說(shuō),支持向量機(jī)找到了劃分兩組數(shù)據(jù)的最佳直線或平面,或者在回歸的情況下,找到了在容差范圍內(nèi)描述趨勢(shì)的最佳路徑。
對(duì)于分類,該算法最大限度地減少了對(duì)數(shù)據(jù)進(jìn)行錯(cuò)誤分類的風(fēng)險(xiǎn)。
對(duì)于回歸,該算法使回歸模型在某個(gè)可接受的容差范圍內(nèi)沒(méi)有獲得的數(shù)據(jù)點(diǎn)的風(fēng)險(xiǎn)最小化。
導(dǎo)入一些包和數(shù)據(jù)
import pandas as pd # 對(duì)于數(shù)據(jù)分析,特別是時(shí)間序列
import numpy as np # 矩陣和線性代數(shù)的東西,類似MATLAB
from matplotlib import pyplot as plt # 繪圖
Scikit-learn是Python中的大型機(jī)器學(xué)習(xí)包之一。
from sklearn import svm
from sklearn import cross_validation
from sklearn import preprocessing as pre
在此隨機(jī)插入更好的數(shù)據(jù)可視化。
# 設(shè)置顏色
graylight = '#d4d4d2'
gray = '#737373'
red = '#ff3700'
我在這個(gè)模型中使用的數(shù)據(jù)是通過(guò)公寓中安裝的智能電表中獲得的。
USAGE "字段給出了該小時(shí)內(nèi)的用電度數(shù)。
elec.head(3)
Out[5]:
天氣數(shù)據(jù)提取。
weather.head()
?
預(yù)處理
合并電力和天氣
首先,我們需要將電力數(shù)據(jù)和天氣數(shù)據(jù)合并到一個(gè)數(shù)據(jù)框中,并去除無(wú)關(guān)的信息。
# 合并成一個(gè)Pandas數(shù)據(jù)框架
pd.merge(weather, elec,True, True)
# 從數(shù)據(jù)框架中刪除不必要的字段
del elec['tempm'], elec['cost']
# 將風(fēng)速轉(zhuǎn)換為單位
elec['wspdm'] * 0.62
elec.head()
?
fig = plt.figure(figsize=[14,8])
elecweather['USAGE'].plot
我想將典型的工作日與周末、假日和在家工作的日子區(qū)分開來(lái)。所以現(xiàn)在所有的正常工作日都是0,所有的假期、周末和在家工作的日子都是1。
分類變量:平日與周末/假期/在家工作日
## 將周末和節(jié)假日設(shè)置為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)
更多的分類變量:一周中的一天,小時(shí)
在這種情況下,一天中的每個(gè)小時(shí)是一個(gè)分類變量,而不是連續(xù)變量。做分析時(shí),需要對(duì)一天中的每一個(gè)小時(shí)進(jìn)行 "是 "或 "否 "的對(duì)應(yīng)。
# 為一天中的每個(gè)小時(shí)創(chuàng)建新的列,如果index.hour是該列對(duì)應(yīng)的小時(shí),則分配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]
時(shí)間序列:需要附加上以前的用電需求的歷史窗口
由于這是一個(gè)時(shí)間序列,如果我們想預(yù)測(cè)下一小時(shí)的能耗,訓(xùn)練數(shù)據(jù)中任何給定的X向量/Y目標(biāo)對(duì)都應(yīng)該提供當(dāng)前小時(shí)的用電量(Y值,或目標(biāo))與前一小時(shí)(或過(guò)去多少小時(shí))的天氣數(shù)據(jù)和用量(X向量)。
# 在每個(gè)X向量中加入歷史用量
# 設(shè)置預(yù)測(cè)的提前小時(shí)數(shù)
hours = 1
# 設(shè)置歷史使用小時(shí)數(shù)
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)
分成訓(xùn)練期和測(cè)試期
由于這是時(shí)間序列數(shù)據(jù),定義訓(xùn)練期和測(cè)試期更有意義,而不是隨機(jī)的零星數(shù)據(jù)點(diǎn)。如果它不是一個(gè)時(shí)間序列,我們可以選擇一個(gè)隨機(jī)的樣本來(lái)分離出一個(gè)測(cè)試集。
# 定義訓(xùn)練和測(cè)試期
train_start = '18-jan-2014'(訓(xùn)練開始)。
train_end = '24-march-2014'.
test_start = '25-march-2014'(測(cè)試開始)。
test_end = '31-march-2014'。
# 分成訓(xùn)練集和測(cè)試集(仍在Pandas數(shù)據(jù)幀中)。
xtrain = elec_and_weather[train_start:train_end]。
del xtrain['US']
del xtrain['time_end']
ytrain = elec_and_weather['US'][train_start:train_end] 。
將訓(xùn)練集輸出成csv,看得更清楚。
X_train_df.to_csv('training_set.csv')
scikit-learn包接收的是Numpy數(shù)組,而不是Pandas DataFrames,所以我們需要進(jìn)行轉(zhuǎn)換。
# 用于sklearn的Numpy數(shù)組
X_train = np.array(X_train_df)
標(biāo)準(zhǔn)化變量
所有的變量都需要進(jìn)行標(biāo)準(zhǔn)化。該算法不知道每個(gè)變量的尺度是什么。換句話說(shuō),溫度一欄中的73的值看起來(lái)會(huì)比前一小時(shí)的千瓦時(shí)使用量中的0.3占優(yōu)勢(shì),因?yàn)閷?shí)際值是如此不同。sklearn的預(yù)處理模塊中的StandardScaler()將每個(gè)變量的平均值去除,并將其標(biāo)準(zhǔn)化為單位方差。當(dāng)模型在按比例的數(shù)據(jù)上進(jìn)行訓(xùn)練時(shí),模型就會(huì)決定哪些變量更有影響力,而不是由任意的比例/數(shù)量級(jí)來(lái)預(yù)先決定這種影響力。
訓(xùn)練SVR模型
將模型擬合訓(xùn)練數(shù)據(jù)!
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ù)測(cè)和測(cè)試
計(jì)算下一小時(shí)的預(yù)測(cè)(預(yù)測(cè)?。┪覀冾A(yù)留了一個(gè)測(cè)試數(shù)據(jù)集,所以我們將使用所有的輸入變量(適當(dāng)?shù)目s放)來(lái)預(yù)測(cè) "Y "目標(biāo)值(下一小時(shí)的使用率)。
# 使用SVR模型來(lái)計(jì)算預(yù)測(cè)的下一小時(shí)使用量
SVRpredict(X_test_scaled)
# 把它放在Pandas數(shù)據(jù)框架中,以便于使用
DataFrame(predict_y)
繪制測(cè)試期間的實(shí)際和預(yù)測(cè)電力需求的時(shí)間序列。
# 繪制預(yù)測(cè)值和實(shí)際值
plt.plot(index,y_test_df,color='k')
plt.plot(predictindex,predict_y)
重新取樣的結(jié)果為每日千瓦時(shí)
### 繪制測(cè)試期間的每日總千瓦時(shí)圖
y_test_barplot
ax.set_ylabel('每日總用電量(千瓦時(shí))')
# Pandas/Matplotlib的條形圖將x軸轉(zhuǎn)換為浮點(diǎn),所以需要找回?cái)?shù)據(jù)時(shí)間
ax.set_xticklabels([dt.strftime('%b %d') for dt in
誤差測(cè)量
以下是一些精度測(cè)量。
len(y_test_df)
均方根誤差
這實(shí)際上是模型的標(biāo)準(zhǔn)誤差,其單位與預(yù)測(cè)變量(或這里的千瓦時(shí))的單位相同。
calcRMSE(predict_y, y_test_df)
平均絕對(duì)百分比誤差
用這種方法,計(jì)算每個(gè)預(yù)測(cè)值和實(shí)際值之間的絕對(duì)百分比誤差,并取其平均值;計(jì)量單位是百分比。如果不取絕對(duì)值,而模型中又沒(méi)有什么偏差,你最終會(huì)得到接近零的結(jié)果,這個(gè)方法就沒(méi)有價(jià)值了。
errorsMAPE(predict_y, y_test_df)
平均偏置誤差
平均偏差誤差顯示了模型的高估或低估情況。初始SVM模型的平均偏差誤差為-0.02,這表明該模型沒(méi)有系統(tǒng)地高估或低估每小時(shí)的千瓦時(shí)消耗。
calcMBE(predict_y, y_test_df)
變異系數(shù)
這與RMSE類似,只是它被歸一化為平均值。它表明相對(duì)于平均值有多大的變化。
這與RMSE類似,只是它被歸一化為平均值。它表明相對(duì)于平均值有多大的變化。
plot45 = plt.plot([0,2],[0,2],'k')
最受歡迎的見(jiàn)解
1.在python中使用lstm和pytorch進(jìn)行時(shí)間序列預(yù)測(cè)
2.python中利用長(zhǎng)短期記憶模型lstm進(jìn)行時(shí)間序列預(yù)測(cè)分析
3.使用r語(yǔ)言進(jìn)行時(shí)間序列(arima,指數(shù)平滑)分析
4.r語(yǔ)言多元copula-garch-模型時(shí)間序列預(yù)測(cè)
5.r語(yǔ)言copulas和金融時(shí)間序列案例
6.使用r語(yǔ)言隨機(jī)波動(dòng)模型sv處理時(shí)間序列中的隨機(jī)波動(dòng)
7.r語(yǔ)言時(shí)間序列tar閾值自回歸模型
8.r語(yǔ)言k-shape時(shí)間序列聚類方法對(duì)股票價(jià)格時(shí)間序列聚類
9.python3用arima模型進(jìn)行時(shí)間序列預(yù)測(cè)