機械学習
Keras
TensorFlow

TensorFlowで電力使用量予測 with Keras

はじめに

これまでSciKit-learnを使って電力使用量を予測する例を何度か公開してきましたが、今回はTensorFlowを使って似たようなことをするサンプルを作ってみました。

参考記事:機械学習で電力需要を予測してみる パート2

環境構築

テスト環境

  • MacBook Pro Mid 2012
  • Python 3.5.1 with Anaconda 4.1.0
  • TensorFlow 1.0.1
  • Keras 2.1.2

Anacondaのインストール

以下のURLより、自分のPC環境に適合するものをダウンロードしてインストール

https://www.anaconda.com

TensorFlowのインストール

以下のコマンドを実行

  • CPU版
$ pip install tensorflow
  • GPU版
$ pip install tensorflow-gpu

Kerasのインストール

以下のコマンドを実行

$ pip install keras

Jupyterの起動

以下のコマンドを実行

$ jupyter notebook

新しいファイルを作成して、以下のコードを実行

データ取得

電力データ

以下のURLより中国電力にて公開されている電力使用量データをダウンロード
http://www.energia.co.jp/jukyuu/download.html

※2016年度と2017年度のデータを取得

気象データ

中国電力管内にある主要都市として、岡山と広島をとりあげることとし、岡山と広島の気象データをダウンロード
※ 予測精度を向上させるために、他の主要都市の気温データを追加しても良いと思います

以下のURLより気温データをダウンロード
http://www.data.jma.go.jp/gmd/risk/obsdl/index.php

※1時間おきの気温データを電力データと同じ期間にあわせて取得

データ読込

ライブラリ読込

import pandas as pd

%matplotlib inline

電力データ

df_kw = pd.read_csv("juyo-2016.csv",encoding="Shift_JIS",skiprows=1)
df_kw["MW"] = df_kw["実績(万kW)"] * 10

df_kw["DATETIME"] = df_kw.index.map(lambda _: pd.to_datetime(df_kw.DATE[_] + " " + df_kw.TIME[_]))

# 可視化
df_kw["MW"].plot(figsize=(15,4))

001.png

気象データ

def read_temp(filename):
    df_temp = pd.read_csv(filename,encoding="Shift_JIS",skiprows=4)
    df_temp.columns = ["DATETIME","TEMP","品質情報","均質番号"]
    df_temp.DATETIME = df_temp.DATETIME.map(lambda _: pd.to_datetime(_))
    return df_temp

# 岡山
df_temp_okym = read_temp("data_okayama-2016.csv")
df_temp_okym.rename(columns = {'TEMP':'TEMP_okym'}, inplace=True)

# 広島
df_temp_hrsm = read_temp("data_hiroshima-2016.csv")
df_temp_hrsm.rename(columns = {'TEMP':'TEMP_hrsm'}, inplace=True)

# 可視化
df_temp_okym.TEMP_okym.plot(figsize=(15,4))
df_temp_hrsm.TEMP_hrsm.plot(figsize=(15,4))

[岡山の気温データ]
002.png

[広島の気温データ]
003.png

データ加工

電力と気温のデータを結合

# データの複製
df = df_kw.copy()
# 岡山の気温を結合
df = df.merge(df_temp_okym,how="inner", on="DATETIME")
# 広島の気温を結合
df = df.merge(df_temp_hrsm,how="inner", on="DATETIME")

# 月、週、時間の値を個別に取得
df["MONTH"] = df.DATETIME.map(lambda _: _.month)
df["WEEK"] = df.DATETIME.map(lambda _: _.weekday())
df["HOUR"] = df.DATETIME.map(lambda _: _.hour)

欠損データの削除

# null値の削除
df = df.dropna()

One-hotエンコーディング

cols = ["MONTH","WEEK","HOUR"]
for col in cols:
    df = df.join(pd.get_dummies(df[col], prefix=col))

学習

x_cols = ["TEMP_okym","TEMP_hrsm"] + df.columns.tolist()[14:]

X = df[x_cols]
y = df["MW"]

# ラベル付きデータをトレーニングセット (X_train, y_train)とテストセット (X_test,y_test)に分割
from sklearn import model_selection

X_train, X_test, y_train, y_test = model_selection.train_test_split(X, y, test_size=.2, random_state=42)

# 正規化
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
scaler.fit(X_train)

X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)

# Keras読込
from keras.models import Sequential
from keras.layers import Dense
from keras.wrappers.scikit_learn import KerasRegressor

# モデル生成用関数
def reg_model():

    reg = Sequential()

    reg.add(Dense(10, input_dim=len(x_cols), activation='relu'))
    reg.add(Dense(16, activation='relu'))
    reg.add(Dense(1))

    reg.compile(loss='mean_squared_error', optimizer='adam', metrics=['accuracy'])
    reg.summary()

    return reg

# モデルの取得
model = KerasRegressor(build_fn=reg_model, epochs=200, batch_size=16, verbose=0)

# 学習
model.fit(X_train, y_train)

# スコア(参考値)
model.score(X_test, y_test)

検証

# 二乗平方根で誤差を算出
mse = mean_squared_error(y_test, y_pred)
print("KERAS REG RMSE : %.2f" % (mse ** 0.5))

# 予測値の取得
y_pred = model.predict(X_test)

# 可視化
pd.DataFrame({"pred":y_pred, "act":y_test})[:100].reset_index(drop=True).plot(figsize=(15,4))

誤差の出力は「KERAS REG RMSE : 349.74」で、予測結果のグラフは以下のとおり。

004.png

...なんだかあってそう(^-^)

予測

2017年度データを予測し、確認する。

# 電力データを読込
df_kw = pd.read_csv("juyo-2017.csv",encoding="Shift_JIS",skiprows=1)

# 岡山のデータを読込
df_temp_okym = read_temp("data_okayama-2017.csv")
df_temp_okym.rename(columns = {'TEMP':'TEMP_okym'}, inplace=True)

# 広島のデータを読込
df_temp_hrsm = read_temp("data_hiroshima-2017.csv")
df_temp_hrsm.rename(columns = {'TEMP':'TEMP_hrsm'}, inplace=True)

# データ加工
df_kw.columns = ["DATE","TIME","万kW"]
df_kw["MW"] = df_kw["万kW"] * 10
df_kw["DATETIME"] = df_kw.index.map(lambda _: pd.to_datetime(df_kw.DATE[_] + " " + df_kw.TIME[_]))

# データ結合
df = df_kw.copy()
df = df.merge(df_temp_okym,how="inner", on="DATETIME")
df = df.merge(df_temp_hrsm,how="inner", on="DATETIME")

# 追加データ作成
df["MONTH"] = df.DATETIME.map(lambda _: _.month)
df["WEEK"] = df.DATETIME.map(lambda _: _.weekday())
df["HOUR"] = df.DATETIME.map(lambda _: _.hour)

# 欠損データ削除
df = df.dropna()

# One-hotエンコーディング
cols = ["MONTH","WEEK","HOUR"]
for col in cols:
    df = df.join(pd.get_dummies(df[col], prefix=col))

# テストデータの不足分を補完
for col in x_cols[2:]:
    if not col in df.columns:
        df[col] = 0

# 7月の電力使用量を予測
df_pred = df[df.MONTH==7]

# 予測用データ
X = df_pred[x_cols].as_matrix().astype('float64')
y = df_pred["MW"].as_matrix().astype('int').flatten()

# 正規化
X = scaler.transform(X)

# 予測値の取得
y_pred = model.predict(X)

# 二乗平方根で誤差を算出
mse = mean_squared_error(y, y_pred)
print("KERAS REG RMSE : %.2f" % (mse ** 0.5))

# 可視化
pd.DataFrame({"pred":y_pred, "act":y}, index=df_pred.index).plot(figsize=(15,4),ylim=(4000,12000))

誤差の出力は「KERAS REG RMSE : 368.87」で、予測結果のグラフは以下のとおり。

005.png

良いかも(^-^)

参考資料

http://blueomega.jp/20171221_predict_kw_with_temp_by_tensorflow.html