原文鏈接:http://tecdat.cn/?p=23921
原文出處:拓端數據部落公眾號
本文描述了訓練支持向量回歸模型的過程,該模型用於預測基於幾個天氣變量、一天中的某個小時、以及這一天是周末/假日/在家工作日還是普通工作日的用電量。
關於支持向量機的快速說明
支持向量機是機器學習的一種形式,可用於分類或回歸。盡可能簡單地說,支持向量機找到了划分兩組數據的最佳直線或平面,或者在回歸的情況下,找到了在容差范圍內描述趨勢的最佳路徑。
對於分類,該算法最大限度地減少了對數據進行錯誤分類的風險。
對於回歸,該算法使回歸模型在某個可接受的容差范圍內沒有獲得的數據點的風險最小化。

導入一些包和數據
-
-
import pandas as pd # 對於數據分析,特別是時間序列
-
import numpy as np # 矩陣和線性代數的東西,類似MATLAB
-
from matplotlib import pyplot as plt # 繪圖
-
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]:

天氣數據提取。
-
-
weather.head()
![]()
![]()

預處理
合並電力和天氣
首先,我們需要將電力數據和天氣數據合並到一個數據框中,並去除無關的信息。
-
-
# 合並成一個Pandas數據框架
-
pd.merge(weather, elec,True, True)
-
-
# 從數據框架中刪除不必要的字段
-
del elec['tempm'], elec['cost']
-
-
# 將風速轉換為單位
-
elec['wspdm'] * 0.62
-
-
elec.head()
-
![]()

-
fig = plt.figure(figsize=[14,8])
-
-
elecweather['USAGE'].plot


我想將典型的工作日與周末、假日和在家工作的日子區分開來。所以現在所有的正常工作日都是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')


最受歡迎的見解
1.在python中使用lstm和pytorch進行時間序列預測
2.python中利用長短期記憶模型lstm進行時間序列預測分析
