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レイヤーを用いることで高速化が期待できる。