Pythonプログラミング(リカレントネットによる時系列学習)
(このページは作成中)
でんき予報
東北電力では、電力利用状況についての情報公開と、それを節電につなげるための取り組みとして でんき予報というウェブページを設けている。 ページの下段には、東北6県と新潟県の最近数年間の時間ごとの電力消費量(万KWH)の実績データがCSV形式でダウンロードできるようになっている。 例えば、2018年度のデータ()は juyo_2018_tohoku.csv 等々。 CSVの内容は、以下のように、ヘッダ部分(2行)に続いて、年月日、時刻、実績が、行ごとにコンマで区切られている。
2019/1/1 3:02 UPDATE DATE,TIME,実績(万kW) 2018/1/1,0:00,903 2018/1/1,1:00,916 ...
ここでは、これらのデータを使って過去の電力量の推移をニューラルネットに学習させ、今後の需要予想を立ててみたい。
トレーニングデータの生成
電力の使用量は、過去の履歴に加え、時間帯や曜日にも左右されるはずである。
そこで、入力データ(説明変数)として、ここでは、
[曜日, 時刻, 電力量]
の3つを組にして与え、そこから、次(1時間先)の時間帯の電力量を予測することを目指す。
まず、ダウンロードしたCSVファイルを読み込んで、リストxdataにデータをセットするコードの例を示す:
import numpy as np
import codecs
import csv
import datetime
xdata=[]
with codecs.open('juyo_2018_tohoku.csv','r','Shift-JIS', 'ignore') as csvfile:
reader = csv.reader(csvfile, delimiter = ',')
cnt=0
for row in reader:
if cnt>1:
ymd=row[0].split('/')
wd=datetime.datetime(int(ymd[0]),int(ymd[1]),int(ymd[2])).weekday()
h=int( row[1].split(':')[0] )
p=float(row[2].strip())/1000.0
xdata.append([wd,h,p])
cnt=cnt+1
ファイル中に日本語文字が含まれている場合にも対応できるよう、codecsモジュールを用いて文字コードの処理をしながら、csvモジュール でCSVファイルを読み込む。
最初の2行を飛ばして、それ以後の行について、
- datetimeモジュールを使って日付から曜日を算出し、日曜は0, 月曜は1,といったように、曜日を数値に変換する。
- 時刻の箇所だけを切り出す
- 電力量は大きな数値となるため、それを1000で割った値を以後で用いるデータとする。
という処理を繰り返している。
続いて、xdataを切り出しながら、説明変数用と目的変数用のトレーニングデータ(それぞれ、x_trainとy_trainを生成する:
timestep=24
x_train = [ ]
y_train = [ ]
for i in range(len(xdata) - timestep ):
x = xdata[i: i+timestep]
y = xdata[i+timestep][2]
x_train.append(x)
y_train.append(y)
x_train = np.array(x_train, dtype=np.float32)
y_train = np.array(y_train, dtype=np.float32)
GRUを用いたモデルの作成
以下は、内部状態を128変数、入力がtimestep $\times 3$のGRUに、
32素子と1素子から成るフィードフォワードネットを繋いだモデルを生成するコードである。
from keras.models import Sequential from keras.layers import Dense,GRU model = Sequential() model.add(GRU(128,input_shape=(timestep,3), use_bias=True)) model.add(Dense(32, use_bias=True,activation='relu')) model.add(Dense(1, use_bias=True, activation='linear')) model.compile(loss='mean_squared_error', optimizer='Adam') model.summary()
学習とデータの保存
トレーニングデータセットを用いてネットワークを学習し、モデルと荷重をファイルに保存するコードの例が以下である。
epochs=1000
batch_size=32
model.fit(x_train, y_train,
epochs=epochs,
batch_size=batch_size)
scores = model.evaluate(x_train, y_train, verbose=0)
print(scores)
json_string=model.to_json()
with open("train.json","w") as f:
f.write(json_string)
model.save_weights("train.hdf5")
上記のステップを全てまとめたコード例を以下に示す:
# coding: utf-8
from keras.models import Sequential
from keras.layers import Dense,GRU
import numpy as np
import matplotlib.pyplot as plt
import codecs
import csv
import datetime
# データの読み込み
xdata=[]
with codecs.open('juyo_2018_tohoku.csv','r','Shift-JIS', 'ignore') as csvfile:
reader = csv.reader(csvfile, delimiter = ',')
cnt=0
for row in reader:
if cnt>1:
ymd=row[0].split('/')
wd=datetime.datetime(int(ymd[0]),int(ymd[1]),int(ymd[2])).weekday()
h=int( row[1].split(':')[0] )
p=float(row[2].strip())/1000.0
xdata.append([wd,h,p])
cnt=cnt+1
# トレーニングデータの生成
timestep=24
x_train = [ ]
y_train = [ ]
for i in range(len(xdata) - timestep ):
x = xdata[i: i+timestep]
y = xdata[i+timestep][2]
x_train.append(x)
y_train.append(y)
x_train = np.array(x_train, dtype=np.float32)
y_train = np.array(y_train, dtype=np.float32)
# モデルの生成
model = Sequential()
model.add(GRU(128,input_shape=(timestep,3), use_bias=True))
model.add(Dense(32, use_bias=True,activation='relu'))
model.add(Dense(1, use_bias=True, activation='linear'))
model.compile(loss='mean_squared_error', optimizer='Adam')
model.summary()
# 学習
epochs=1000
batch_size=32
model.fit(x_train, y_train,
epochs=epochs,
batch_size=batch_size)
scores = model.evaluate(x_train, y_train, verbose=0)
print(scores)
# 結果の保存
json_string=model.to_json()
with open("train.json","w") as f:
f.write(json_string)
model.save_weights("train.hdf5")
練習:ネットワークのトレーニング
上記のコードを実行し、モデルのデータ(train.js)、および、荷重データ(train.hdf5)を作成しなさい。
一般に、リカレントネットワークの学習においてはGPUによる高速化の恩恵が薄いため、環境によっては時間がかかるかもしれない。 GPU(CUDA)が使える環境の場合は、GRUレイヤーの代わりにCuDNNGRUレイヤーを用いることで高速化が期待できる。