家庭用戶的用電預測

家庭用戶的用電預測

用電量能夠反映一個國家經濟發展的水平,對用電量進行全面的理解有助於減小家庭的電費支出。對企業而言,對用電量全面的理解有助於提升經營的效率。對於政府而言,全面的瞭解用電量能夠減小政府對發電,供電等須要的基建投資,爲政府對當地經濟發展制定更好更全面的規劃。html

鑑於智能電錶的興起以及太陽能電池板等發電技術的普遍採用,有大量的用電數據可供選擇。該數據表明了功率的相關變量,這些變量又可用於建模甚至預測將來的電力消耗。像長期短時間記憶網絡(LSTM)這樣的神經網絡可以處理多個輸入變量的問題。這在時間序列預測中具備很大的益處,而傳統的線性方法難以適應多變量或多輸入預測問題。前端

第一步 準備工做

在本教程中,您將瞭解如何在 Keras 深度學習庫中開發多變量時間序列預測的 LSTM 模型。完成本教程後,您將知道:python

  • 如何將原始數據集轉換爲可用於時間序列預測的類型
  • 如何搭建解決多變量時間序列預測問題的 LSTM 模型
  • 如何作出預測並將結果從新調整到原始單位

特徵介紹react

  1. date: 日期格式爲 dd/mm/yy
  2. time: 時間格式爲 hh:mm:ss
  3. Global_active_power: 家庭消耗的總有功功率(千瓦),在交流電路中,電源在一個週期內發出瞬時功率的平均值(或負載電阻所消耗的功率),稱爲"有功功率"
  4. Global_reactive_power: 家庭消耗的總無功功率(千瓦),在具備電感或電容的電路中,在每半個週期內,把電源能量變成磁場(或電場)能量貯存起來,而後,再釋放,又把貯存的磁場(或電場)能量再返回給電源,只是進行這種能量的交換,並無真正消耗能量,咱們把這個交換的功率值,稱爲" 無功功率"
  5. voltage: 平均電壓(伏特)
  6. Global_intensity: 平均電流強度(安培)
  7. sub_metering_1: 廚房的有功功率
  8. sub_metering_2: 用於洗衣機等電器的有功功率
  9. sub_metering_3: 空調熱水器等電器的有功功率

這裏咱們使用的是時間序列預測模型,利用歷史數據來預測以後的 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()
複製代碼

屏幕快照 2019-05-17 下午1.26.02.png
咱們能夠看出 Global_active_power 大於 Global_reactive_power, voltage 基本穩定在 233 伏特。

# 瞭解數據的分佈
df.describe()
複製代碼

屏幕快照 2019-05-17 下午1.38.15.png
咱們能夠經過上表瞭解數據的分佈特徵,好比均值和方差,還有最小值等等。

處理缺失值

在原始計量數據,特別是用戶電量抽取過程當中,發現存在缺失現象。若將這些值拋棄掉,會嚴重影響用電預測的結果。爲了達到較好的建模效果,須要對缺失值進行處理。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()
複製代碼

output_21_0.png
output_21_1.png

# 對 '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()
複製代碼

output_23_0.png
output_24_0.png
咱們能夠看出每月電壓平均值變化幅度很是小,基本保持穩定。

# 下面咱們比較對不一樣特徵以天進行重採樣的數值
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()
複製代碼

output_26_0.png

# 下面咱們看看 ‘Global_active_power‘ 數值分佈狀況
sns.distplot(df['Global_active_power']);
複製代碼

output_27_0.png

能夠看出家庭消耗的總有功功率主要集中在 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()
複製代碼

output_30_0.png

# 查看 'Voltage' 和 'Global_active_power' 之間的關係
sns.jointplot(x='Voltage', y='Global_active_power', data=data_returns)  
plt.show()
複製代碼

output_31_0.png

從上面的兩個圖中能夠看出 '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)
複製代碼

屏幕快照 2019-05-17 下午1.55.12.png
屏幕快照 2019-05-17 下午1.55.58.png
從上面能夠看出,採用重採樣技術能夠改變特徵之間的相關性, 這對於特徵工程很是重要。

第四步 多變量LSTM預測模型

在可使用深度學習以前,必須將時間序列預測問題調整爲監督學習問題,造成輸入和輸出序列對,利用前一時間的 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)
複製代碼

搭建 LSTM 模型

模型架構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))
複製代碼

output_54_1.png
咱們能夠看出模型的收斂速度很快。

第五步 模型評估

預測模型對訓練集進行預測而獲得的準確率並不能很好地反映預測模型對將來的性能,爲了有效判斷一個預測模型的性能表現,須要一組沒有參加預測模型創建的數據集,並在該模型上評價預測模型的準確率,這組獨立的數據集叫作測試集。在測試集進行預測而且評估,咱們怎樣對模型進行性能衡量?

迴歸問題的評價指標:一般用相對/絕對偏差,平均絕對偏差,均方偏差,均方根偏差等指標來衡量,分類問題的評價指標:準確率,精確率,召回率,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()
複製代碼

output_60_0.png

第六步 思考,如何進一步的改進模型?

能不能進一步的改進模型呢?下面提出了一些可能的改進模型的方案,有興趣的話能夠試一試哦。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 人工智能俱樂部 是由網站的研發與產品設計團隊發起、致力於下降人工智能開發與使用門檻的俱樂部。團隊具有大數據處理分析、可視化與數據建模經驗,已承擔多領域智能項目,具有從底層到前端的全線設計開發能力。主要研究方向爲大數據管理分析與人工智能技術,並以此來促進數據驅動的科學研究。目前俱樂部每週六在杭州舉辦以機器學習爲主題的線下技術沙龍活動,不按期進行論文分享與學術交流。但願能匯聚來自各行各業對人工智能感興趣的朋友,不斷交流共同成長,推進人工智能民主化、應用普及化。

image.png
相關文章
相關標籤/搜索