codingecho

日々の体験などを書いてます

RNNと時系列データを使った気温の予測

時系列データをRNNで扱うサンプルです。過去の気温から未来の気温予想を予測します。

以下のサンプルはGoogle Colaboratory上で実行しています。

気象データセットのダウンロードします。

ちなみに !<command> のようにするとnotebook上でコマンドが使えます。

!wget https://s3.amazonaws.com/keras-datasets/jena_climate_2009_2016.csv.zip
!unzip jena_climate_2009_2016.csv.zip

ロードしてヘッダーとデータ数を確認します。

import os

fname = 'jena_climate_2009_2016.csv'

f = open(fname)
data = f.read()
f.close()

lines = data.split('\n')
header = lines[0].split(',')
lines = lines[1:]

print(header)
print(len(lines))
import numpy as np

float_data = np.zeros((len(lines), len(header) - 1))
for i, line in enumerate(lines):
  values = [float(x) for x in line.split(',')[1:]]
  float_data[i, :] = values

とりあえずプロットしてみます。縦軸は摂氏温度、横軸は10分ごとの時系列です。

from matplotlib import pyplot as plt

temp = float_data[:, 1]
plt.plot(range(len(temp)), temp)

f:id:ytanak:20190130075555p:plain
なんとなく周期性があることがわかりますね!

過去の期間(lookback)を見て、先のポイント(delay)を予測します。

def generator(data, lookback, delay, min_index, max_index, shuffle=False, batch_size=128, step=6):
    if max_index is None:
        max_index = len(data) - delay - 1
    i = min_index + lookback
    while 1:
        if shuffle:
            rows = np.random.randint(min_index + lookback, max_index, size=batch_size)
        else:
            if i + batch_size >= max_index:
                i = min_index + lookback
            rows = np.arange(i, min(i + batch_size, max_index))
            i += len(rows)

        samples = np.zeros((len(rows),
                           lookback // step,
                           data.shape[-1]))
        targets = np.zeros((len(rows),))
        for j, row in enumerate(rows):
            indices = range(rows[j] - lookback, rows[j], step)
            samples[j] = data[indices]
            targets[j] = data[rows[j] + delay][1]
        yield samples, targets

元のデータセットから学習、検証、テスト用のデータに分けます。

lookback = 1440
step = 6
delay = 144
batch_size = 128
train_gen = generator(float_data,
                      lookback=lookback,
                      delay=delay,
                      min_index=0,
                      max_index=200000,
                      shuffle=True,
                      step=step,
                      batch_size=batch_size)
val_gen = generator(float_data,
                    lookback=lookback,
                    delay=delay,
                    min_index=200001,
                    max_index=300000,
                    step=step,
                    batch_size=batch_size)
test_gen = generator(float_data,
                     lookback=lookback,
                     delay=delay,
                     min_index=300001,
                     max_index=None,
                     step=step,
                     batch_size=batch_size)

val_steps = (300000 - 200001 - lookback)

test_steps = (len(float_data) - 300001 - lookback)

Sequential を使ってRNNを構築して学習させます。

from tensorflow.keras.models import Sequential
from tensorflow.keras import layers
from tensorflow.keras.optimizers import RMSprop

model = Sequential()
model.add(layers.Flatten(input_shape=(lookback // step, float_data.shape[-1])))
model.add(layers.Dense(32, activation='relu'))
model.add(layers.Dense(1))
model.compile(optimizer=RMSprop(), loss='mae')
history = model.fit_generator(train_gen,
                              steps_per_epoch=500,
                              epochs=20,
                              validation_data=val_gen,
                              validation_steps=batch_size)
Epoch 1/20
500/500 [==============================] - 9s 19ms/step - loss: 1.5980 - val_loss: 0.4938
Epoch 2/20
500/500 [==============================] - 9s 17ms/step - loss: 0.5903 - val_loss: 0.3942

予測するには predict を使います。

d = next(train_gen)
x = d[0]
print(x[0:2].shape)
b = np.array(x[0:2])
model.predict(b)

参考

時系列データの扱い方はKeras作者のCholletさんの本に詳しく紹介されています。

Deep Learning with Python

Deep Learning with Python

日本語

PythonとKerasによるディープラーニング

PythonとKerasによるディープラーニング