9
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Deep Learning解析] 第二回 天気予報によりRNN

Last updated at Posted at 2018-08-02

RNNは深層学習の中でも結構難しいモデルである。time-step, feature-size, batch-sizeなどhyper-parametersで迷う人もおる。
今日、理解しやすくして天気予報を例にして時系列のデータでRNNを説明したいと思います。

データ

気象庁のDownloadサイトからある県の最近10年の天気を使います。(一回で10年のデータをDownloadできないので、わけってdownloadした方がいい)

データの洗い出し

import pandas as pd

train = pd.read_csv("./older.csv",sep=',')# older.csv は2009年からのデータになります、学習用
test = pd.read_csv("./new.csv",sep=',')# new.csv は2014年からのデータになります、テスト用

train=train.dropna()#データの中でNaN値がありますので、取りぬきます
test=test.dropna()#データの中でNaN値がありますので、取りぬきます

この時点でデータを見てみると

train.head()
Date Temp Total rainfall(mm) Day time(hour) Average wind speed(m/s) Average vapor pressure(hPa) Average cloud cover Average local atmospheric pressure(hPa)
0 2009/1/1 5.1 0.0 2.3 4.9 4.9 5.3 1013.4
1 2009/1/2 6.6 0.0 4.1 4.3 5.4 4.3 1018.6
2 2009/1/3 6.7 0.0 3.3 2.6 5.2 4.8 1023.2
3 2009/1/4 7.1 0.0 8.4 2.1 5.6 4.0 1021.7
4 2009/1/5 9.0 0.0 2.2 2.6 6.9 7.3 1019.0

plotしていましょう

train.plot(subplots=True, figsize=(18,28), layout=(7,1))

all.png

予測データの作り

Dateが温度との関係性が複雑なので、一様使わないと判断します、抜きます。

train=train.drop(["Date"], axis=1)
test=test.drop(["Date"], axis=1)

二日後の温度を予測するモデルをつくりますので、target dataを二日shiftをします


target_names = ['Temp']#予測したい特徴
shift_days = 2
Y_train = train[target_names].shift(-shift_days)
Y_test = test[target_names].shift(-shift_days)

shift.JPG

それの結果は、データの最後の二行がNaNなってしまう、それを抜きます。入力もそれに合わせます。

Y_train = Y_train.values[:-shift_days]
Y_test = Y_test.values[:-shift_days]
X_train_np = train.values[0:-shift_days]
X_test_np = test.values[0:-shift_days]

データの正規化

from sklearn.preprocessing import MinMaxScaler

x_scaler = MinMaxScaler()
x_train_scaled = x_scaler.fit_transform(X_train_np)
x_test_scaled = x_scaler.transform(X_test)#テストデータも同じ領域で正規化します(同じ正規器を使う)
num_train = x_train_scaled.shape[0]

y_scaler = MinMaxScaler()
y_train_scaled = y_scaler.fit_transform(Y_train)
y_test_scaled = y_scaler.transform(Y_test)#テストデータも同じ領域で正規化します(同じ正規器を使う)

validation_data = (np.expand_dims(x_test_scaled, axis=0),
                   np.expand_dims(y_test_scaled, axis=0))#評価用

RNN

def batch_generator(batch_size, sequence_length):
    while True:
        x_shape = (batch_size, sequence_length, num_x_signals)
        x_batch = np.zeros(shape=x_shape, dtype=np.float16)

        y_shape = (batch_size, sequence_length, num_y_signals)
        y_batch = np.zeros(shape=y_shape, dtype=np.float16)

        for i in range(batch_size):
            idx = np.random.randint(num_train - sequence_length)
            
            x_batch[i] = x_train_scaled[idx:idx+sequence_length]
            y_batch[i] = y_train_scaled[idx:idx+sequence_length]
        
        yield (x_batch, y_batch)

RNNで入力データは(batch, sequence_length, feature)になるので、↑のbatch_generatorを使って、batch_sizeごとにデータを分ける。

##シーケンス長28を使用します。これは、各ランダムシーケンスに1月の観測値が含まれていることを意味します。 1つの時間ステップは1日に対応するので、7つの時間ステップは1週間に対応し、7×4は1月に対応する。

batch_size = 32
sequence_length =  7 * 4
generator = batch_generator(batch_size=batch_size,
                            sequence_length=sequence_length)

RNN(GRU)作成
シーケンスの各タイムステップごとに128個の出力があるGated Recurrent Unit(GRU)のネットワークを追加します。The GRU が128個のoutputです、しかし私たちが予測したいのは温度だけなので、denseを使って1outputにまとめます. 出力データは[0,1]の間で正規化していますので、Sigmoidを使って予測範囲も[0,1]にしたほうが計算が下がります、reluとかはもつかいます、しかしtanhは使えないので(なぜ)気をつけてください(正規化の範囲が[0,1]なので)

from keras.models import Sequential
from keras.layers import Input, Dense, GRU, Embedding
from keras.optimizers import RMSprop


model = Sequential()
model.add(GRU(units=128,
              return_sequences=True,
              input_shape=(None, num_x_signals,)))
model.add(Dense(num_y_signals, activation='sigmoid'))
model.compile(loss="mse", optimizer='adam')

model.summary()
Layer (type)                 Output Shape              Param #   
=================================================================
gru_1 (GRU)                  (None, None, 128)         52224     
_________________________________________________________________
dense_1 (Dense)              (None, None, 1)           129       
=================================================================
Total params: 52,353
Trainable params: 52,353
Non-trainable params: 0
_________________________________________________________________
model.fit_generator(generator=generator,
                    epochs=5,
                    steps_per_epoch=100,
                    validation_data=validation_data)

天気予報
最後に学習したモデルを使って、予測してみましょう。

#This code credit goes to https://github.com/Hvass-Labs
def plot_comparison(start_idx, length=100, train=True):
    """
    Plot the predicted and true output-signals.
    
    :param start_idx: Start-index for the time-series.
    :param length: Sequence-length to process and plot.
    :param train: Boolean whether to use training- or test-set.
    """
    
    if train:
        # Use training-data.
        x = x_train_scaled
        y_true = Y_train
    else:
        # Use test-data.
        x = x_test_scaled
        y_true = Y_test
    
    # End-index for the sequences.
    end_idx = start_idx + length
    
    # Select the sequences from the given start-index and
    # of the given length.
    x = x[start_idx:end_idx]
    y_true = y_true[start_idx:end_idx]
    
    # Input-signals for the model.
    x = np.expand_dims(x, axis=0)

    # Use the model to predict the output-signals.
    y_pred = model.predict(x)
    
    # The output of the model is between 0 and 1.
    # Do an inverse map to get it back to the scale
    # of the original data-set.
    y_pred_rescaled = y_scaler.inverse_transform(y_pred[0])
    
    # For each output-signal.
    for signal in range(len(target_names)):
        # Get the output-signal predicted by the model.
        signal_pred = y_pred_rescaled[:, signal]
        
        # Get the true output-signal from the data-set.
        signal_true = y_true[:, signal]

        # Make the plotting-canvas bigger.
        plt.figure(figsize=(15,5))
        
        # Plot and compare the two signals.
        plt.plot(signal_true, label='true')
        plt.plot(signal_pred, label='pred')
        
        # Plot grey box for warmup-period.
        p = plt.axvspan(0, 1, facecolor='black', alpha=0.15)
        
        # Plot labels etc.
        plt.ylabel(target_names[signal])
        plt.legend()
        plt.show()

学習で使ったデータで予測します

plot_comparison(start_idx=1, length=1000, train=True)

train.png

テストデータで予測します

plot_comparison(start_idx=1, length=1000, train=False)

test.png

9
10
4

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
9
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?