用電量能夠反映一個國家經濟發展的水平,對用電量進行全面的理解有助於減小家庭的電費支出。對企業而言,對用電量全面的理解有助於提升經營的效率。對於政府而言,全面的瞭解用電量能夠減小政府對發電,供電等須要的基建投資,爲政府對當地經濟發展制定更好更全面的規劃。html
鑑於智能電錶的興起以及太陽能電池板等發電技術的普遍採用,有大量的用電數據可供選擇。該數據表明了功率的相關變量,這些變量又可用於建模甚至預測將來的電力消耗。像長期短時間記憶網絡(LSTM)這樣的神經網絡可以處理多個輸入變量的問題。這在時間序列預測中具備很大的益處,而傳統的線性方法難以適應多變量或多輸入預測問題。前端
在本教程中,您將瞭解如何在 Keras 深度學習庫中開發多變量時間序列預測的 LSTM 模型。完成本教程後,您將知道:python
特徵介紹react
這裏咱們使用的是時間序列預測模型,利用歷史數據來預測以後的 Global_active_power。網絡
# 將txt文檔讀入並轉換爲 csv 文件格式
df = pd.read_csv(path, sep=';',
parse_dates={'dt' : ['Date', 'Time']}, infer_datetime_format=True,
low_memory=False, na_values=['nan','?'], index_col='dt')
複製代碼
上面代碼執行了如下操做:1)將 'Date' 和 'Time' 兩列合併爲 'dt'2)將上面的數據轉換爲時間序列類型,將時間做爲索引。架構
# 咱們查看前 5 條數據
df.head()
複製代碼
# 瞭解數據的分佈
df.describe()
複製代碼
在原始計量數據,特別是用戶電量抽取過程當中,發現存在缺失現象。若將這些值拋棄掉,會嚴重影響用電預測的結果。爲了達到較好的建模效果,須要對缺失值進行處理。app
# 找到全部有缺失值的列
total = df.isnull().sum().sort_values(ascending=False)
display(total)
# 用各列的均值填充缺失值
for j in range(0,7):
df.iloc[:,j] = df.iloc[:,j].fillna(df.iloc[:,j].mean())
# 查看是否還有缺失值
df.isnull().sum()
複製代碼
大部分真實的數據集都難以觀察,由於它們有不少列變量,以及不少行數據。理解信息這方面大量都依賴於視覺。查看數據基本等價於瞭解數據。然而,基本上咱們只能理解視覺上的二維或者三維數據,最好是二維。因此數據可視化可以幫助咱們提升對數據的理解。機器學習
對數據集中呈現的結構和相關性進行觀察,會讓它們易於理解。一個準確的機器學習模型給出的預測,應當可以反映出數據集中所體現的結構和相關性。要明確一個模型給出的預測是否可信,對這些結構和相關性進行理解是首當其衝的。函數
咱們可使用 resample 函數使特徵按不一樣單位進行聚合。例如:使用參數 'H' 調用此函數使時間索引的數據按小時聚合。下面咱們對 Global_active_power 按天進行聚合,並比較它的總和和平均值。 能夠看出,重採樣數據集的平均值和總和具備類似的結構。性能
# 對 Global_active_power 數據按天進行聚合,並比較均值和總和
df.Global_active_power.resample('D').sum().plot(title='Global_active_power resampled over day for sum')
plt.tight_layout()
plt.show()
df.Global_active_power.resample('D').mean().plot(title='Global_active_power resampled over day for mean', color='red')
plt.tight_layout()
plt.show()
複製代碼
# 對 'Global_active_power' 按季度進行聚合
df['Global_active_power'].resample('Q').mean().plot(kind='bar')
plt.xticks(rotation=60)
plt.ylabel('Global_active_power')
plt.title('Global_active_power per quarter (averaged over quarter)')
plt.show()
# 對'Voltage' 按月進行聚合
df['Voltage'].resample('M').mean().plot(kind='bar', color='red')
plt.xticks(rotation=60)
plt.ylabel('Voltage')
plt.title('Voltage per quarter (summed over quarter)')
plt.show()
複製代碼
# 下面咱們比較對不一樣特徵以天進行重採樣的數值
cols = [0, 1, 2, 3, 5, 6]
i = 1
groups=cols
# 統計以天進行重採樣的平均值
values = df.resample('D').mean().values
# 對每一個column進行繪圖
plt.figure(figsize=(15, 10))
for group in groups:
# 對每一個特徵添加子圖
plt.subplot(len(cols), 1, i)
# 進行繪圖
plt.plot(values[:, group])
# 添加標題
plt.title(df.columns[group], y=0.75, loc='right')
# 更換子圖位置
i += 1
plt.show()
複製代碼
# 下面咱們看看 ‘Global_active_power‘ 數值分佈狀況
sns.distplot(df['Global_active_power']);
複製代碼
能夠看出家庭消耗的總有功功率主要集中在 0-2kw 範圍內
# 查看 'Global_intensity' 和 'Global_active_power' 特徵之間的關係
data_returns = df.pct_change()
sns.jointplot(x='Global_intensity', y='Global_active_power', data=data_returns)
plt.show()
複製代碼
# 查看 'Voltage' 和 'Global_active_power' 之間的關係
sns.jointplot(x='Voltage', y='Global_active_power', data=data_returns)
plt.show()
複製代碼
從上面的兩個圖中能夠看出 'Global_intensity' 和 'Global_active_power' 是線性相關的。 但 'Voltage' 和 'Global_active_power' 的相關性較低, 這是機器學習所要觀察的。
# 對各特徵按月進行聚合
plt.title('resampled over month',size=15)
sns.heatmap(df.resample('M').mean().corr(),linewidths=0.1,vmax=1.0,
square=True, cmap=plt.cm.RdBu, linecolor='white', annot=True)
# 對各特徵按年進行聚合
plt.title('resampled over year',size=15)
sns.heatmap(df.resample('A').mean().corr(),linewidths=0.1,vmax=1.0,
square=True, cmap=plt.cm.RdBu, linecolor='white', annot=True)
複製代碼
在可使用深度學習以前,必須將時間序列預測問題調整爲監督學習問題,造成輸入和輸出序列對,利用前一時間的 Global_active_power 和其餘特徵預測當前時間的 Global_active_power。
# 下面咱們對 ‘Global_active_power' 向前移動一個單位
df['Global_active_power'].resample('h').mean().shift(1)
# 下面咱們對 ‘Global_active_power' 向後移動一個單位
df['Global_active_power'].resample('h').mean().shift(-1)
複製代碼
由於這裏咱們預測 ‘Global_active_power' 不只用到過去時間的 ‘Global_active_power' 還會用到其餘的特徵,好比:'Voltage‘,這時候咱們把此類問題叫作多變量時間序列預測。下面咱們展現將時間序列問題轉換爲監督學習問題的過程。
def series_to_supervised(data, n_in=1, n_out=1, dropnan=True):
n_vars = 1 if type(data) is list else data.shape[1]
dff = pd.DataFrame(data)
cols, names = list(), list()
# 輸入序列(t-n, ... t-1)
for i in range(n_in, 0, -1):
cols.append(dff.shift(i))
names += [('var%d(t-%d)' % (j+1, i)) for j in range(n_vars)]
# 預測序列 (t, t+1, ... t+n)
for i in range(0, n_out):
cols.append(dff.shift(-i))
if i == 0:
names += [('var%d(t)' % (j+1)) for j in range(n_vars)]
else:
names += [('var%d(t+%d)' % (j+1, i)) for j in range(n_vars)]
# 組合起來
agg = pd.concat(cols, axis=1)
agg.columns = names
# 丟掉NaN
if dropnan:
agg.dropna(inplace=True)
return agg
複製代碼
咱們將數據以小時進行聚合,這樣也能夠減小計算時間,能夠快速得到測試模型的結果。 咱們以小時進行聚合(原始數據以分鐘爲單位)。這將把數據大小從 2075259 減小到 34589,但依然保持數據的總體結構。
# 將數據按小時聚合
df_resample = df.resample('h').mean()
df_resample.shape
複製代碼
數據歸一化處理是數據挖掘的一項基礎工做。不一樣指標每每具備不一樣的量綱,數值間的差異可能很大,不進行處理可能會影響數據分析的結果。爲了消除指標間的量綱和取值範圍差別的影響,須要進行標準化處理,將數據按照比例進行縮放,使之落入特定的區域,以便於進行綜合分析。
一樣咱們必須對用戶電量的各指標進行處理,這裏咱們用到最小最大規範化。
# 把全部特徵進行規範化
values = df_resample.values
# 特徵歸一化
scaler = MinMaxScaler(feature_range=(0, 1))
scaled = scaler.fit_transform(values)
# 轉化爲監督問題
複製代碼
# 轉化爲監督問題
reframed = series_to_supervised(scaled, 1, 1)
# 刪除不須要的特徵
reframed.drop(reframed.columns[[8,9,10,11,12,13]], axis=1, inplace=True)
print(reframed.head())
複製代碼
這裏,咱們將前三年的數據做爲訓練集,後一年的樣本做爲測試集,並將數據改成 3 維格式。
# 對樣本集拆分紅訓練集和測試集
values = reframed.values
n_train_time = 365*24*3
train = values[:n_train_time, :]
test = values[n_train_time:, :]
train_X, train_y = train[:, :-1], train[:, -1]
test_X, test_y = test[:, :-1], test[:, -1]
# 把數據轉換爲3維
train_X = train_X.reshape((train_X.shape[0], 1, train_X.shape[1]))
test_X = test_X.reshape((test_X.shape[0], 1, test_X.shape[1]))
print(train_X.shape, train_y.shape, test_X.shape, test_y.shape)
複製代碼
模型架構1)LSTM 在第一個可見層中有 100 個神經元2)丟棄 20%,防止過擬合3)輸出層中 1 個神經元,用於預測 Global_active_power4)使用平均絕對偏差(MAE)損失函數和隨機梯度降低的 Adam 優化器5)該模型 epoch 爲 20,批次大小爲 70
# 搭建網絡模型
model = Sequential()
model.add(LSTM(100, input_shape=(train_X.shape[1], train_X.shape[2])))
model.add(Dropout(0.2))
model.add(Dense(1))
model.compile(loss='mean_squared_error', optimizer='adam')
# 訓練網絡
history = model.fit(train_X, train_y, epochs=20, batch_size=70, validation_data=(test_X, test_y), verbose=2, shuffle=False)
# 統計 loss 值
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'test'], loc='upper right')
plt.show()
# 作出預測
yhat = model.predict(test_X)
test_X = test_X.reshape((test_X.shape[0], 7))
複製代碼
預測模型對訓練集進行預測而獲得的準確率並不能很好地反映預測模型對將來的性能,爲了有效判斷一個預測模型的性能表現,須要一組沒有參加預測模型創建的數據集,並在該模型上評價預測模型的準確率,這組獨立的數據集叫作測試集。在測試集進行預測而且評估,咱們怎樣對模型進行性能衡量?
迴歸問題的評價指標:一般用相對/絕對偏差,平均絕對偏差,均方偏差,均方根偏差等指標來衡量,分類問題的評價指標:準確率,精確率,召回率,ROC曲線,混淆矩陣。
咱們將預測與測試數據集相結合,並反演縮放。以預測值和實際值爲原始尺度,咱們能夠計算模型的偏差分數。 在這種狀況下,咱們計算出與變量自己相同的單位產生偏差的均方根偏差(RMSE)。
#對預測值進行反演縮放
inv_yhat = np.concatenate((yhat, test_X[:, -6:]), axis=1)
inv_yhat = scaler.inverse_transform(inv_yhat)
inv_yhat = inv_yhat[:,0]
# 對真實值進行反演縮放
test_y = test_y.reshape((len(test_y), 1))
inv_y = np.concatenate((test_y, test_X[:, -6:]), axis=1)
inv_y = scaler.inverse_transform(inv_y)
inv_y = inv_y[:,0]
# 計算 RMSE
rmse = np.sqrt(mean_squared_error(inv_y, inv_yhat))
print('Test RMSE: %.3f' % rmse)
複製代碼
## 咱們比較下 200 小時真實值和預測值
aa=[x for x in range(200)]
plt.plot(aa, inv_y[:200], marker='.', label="actual")
plt.plot(aa, inv_yhat[:200], 'r', label="prediction")
plt.ylabel('Global_active_power', size=15)
plt.xlabel('Time step', size=15)
plt.legend(fontsize=15)
plt.show()
複製代碼
能不能進一步的改進模型呢?下面提出了一些可能的改進模型的方案,有興趣的話能夠試一試哦。1.在缺失值處理中利用其餘的插值方法2.使用複雜的模型3.調整 epoch 和 batch_size
今天咱們一塊兒製做了一個家庭用戶用電預測的應用,你們能夠在項目源碼地址 fork 這個項目www.momodel.cn:8899/explore/5cd…
咱們首先對數據進行預處理,處理缺失值;接着進行數據可視化,瞭解數據的結構和相關性;而後搭建 LSTM 模型,其中最爲關鍵的是將問題轉化爲監督學習問題;最後咱們對模型進行評估,並提出了優化模型的建議。
使用咱們的模型一樣也能夠預測溫溼度和股價等等,只須要略加修改就行,來作出本身的應用吧。
參考資料:wenku.baidu.com/view/3973ba…blog.csdn.net/sinat_22510…blog.csdn.net/weixin_4065…www.jianshu.com/p/bebf8ca6a…
Mo(網址:momodel.cn)是一個支持 Python 的人工智能在線建模平臺,能幫助你快速開發、訓練並部署模型。
Mo 人工智能俱樂部 是由網站的研發與產品設計團隊發起、致力於下降人工智能開發與使用門檻的俱樂部。團隊具有大數據處理分析、可視化與數據建模經驗,已承擔多領域智能項目,具有從底層到前端的全線設計開發能力。主要研究方向爲大數據管理分析與人工智能技術,並以此來促進數據驅動的科學研究。目前俱樂部每週六在杭州舉辦以機器學習爲主題的線下技術沙龍活動,不按期進行論文分享與學術交流。但願能匯聚來自各行各業對人工智能感興趣的朋友,不斷交流共同成長,推進人工智能民主化、應用普及化。