LoginSignup
40
47

More than 5 years have passed since last update.

TensorFlowで電力使用量予測 with Keras

Last updated at Posted at 2017-12-21

はじめに

これまで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環境に適合するものをダウンロードしてインストール

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)

検証

from sklearn.metrics import mean_squared_error

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

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

# 可視化
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

良いかも(^-^)

参考資料

40
47
7

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
40
47