Google Colaboratoryを使ったRNNの動作確認その2(2022年3月30日)


1. はじめに

 YOLO・CNNといったニューラルネットワークを使った機械学習を勉強中の者です。この手のコモディティ化以前のテクノロジーの学習で障害となるのは、プラットフォームやソフトウェアライブラリ等がどんどんアップデートされているので、ほんのちょっと前に書かれた記事であっても、書かれた通りに動かすことができないという点です(筆者も度々遭遇して難儀しています)。
 つい昨晩、RNNに挑戦したところ、やはり参考にさせて頂いたサイト記事の通りには実行できず、いろいろとネット上を調べまわった結果、何とか動かすことができましたので、自分用の備忘録を兼ねて記録しておきたいと思います。その第2弾です。

2. 参考にさせて頂いたサイト記事

今度こそわかるぞRNN, LSTM編
https://qiita.com/kazukiii/items/df809d6cd5d7d1f57be3
更新日 2019年05月05日

3. テスト用データの作成プログラム

 今回もGoogle Chrome上でGoogle Colaboratoryを使います。
 オリジナルの記事では、乱数によりノイズを乗せたサインカーブをテストデータとして用い、それをRNNで学習させています。

3.0 ノイズ入りサインカーブ

 まずは、今回の動作確認に使用するノイズ入りサインカーブを作成するプログラムコードを入力し、試しに実行します。

import pandas as pd
import numpy as np
import math
import random
import matplotlib.pyplot as plt
import seaborn as sns

 # サイクルあたりのステップ数
steps_per_cycle = 80
 # 生成するサイクル数
number_of_cycles = 50

df = pd.DataFrame(np.arange(steps_per_cycle * number_of_cycles + 1),
 columns=["t"])
 # 一様乱数でノイズを発生させたsin波を生成
df["sin_t"] = df.t.apply(lambda x: math.sin(x * (2 * math.pi / 
 steps_per_cycle)+ random.uniform(-0.1, +0.1) ))

 # 2サイクルだけ抽出してプロット
df[["sin_t"]].head(steps_per_cycle * 2).plot()

 # 画像を保存
plt.savefig('sinecurveWithNoise.png')


 わかりやすくするために、オリジナルの記事より大きめのノイズを与えています。直感的にノイズの入ったサインカーブであることがわかるかと思います。

3.1 トレーニングデータ・テストデータの作成プログラム

 続いて、RNNプログラムに入力するデータを作成するプログラムです。30ステップを入力し、31ステップ目を推定するように、トレーニングデータとテストデータを作成するプログラムを入力し、実行します。サインカーブなので、ノイズの無いサインカーブが真値(正解)となります。

def _load_data(data, n_prev=30):  
    docX, docY = [], []

    for i in range(len(data) - n_prev):
        docX.append(data.iloc[i:i + n_prev].values)
        docY.append(data.iloc[i + n_prev].values)
    alsX = np.array(docX)
    alsY = np.array(docY)

    return alsX, alsY

def train_test_split(df, test_size=0.1, n_prev=30):  
    ntrn = round(len(df) * (1 - test_size))
    ntrn = int(ntrn)
    X_train, y_train = _load_data(df.iloc[0:ntrn], n_prev)
    X_test, y_test = _load_data(df.iloc[ntrn:], n_prev)

    return (X_train, y_train), (X_test, y_test)

(X_train, y_train), (X_test, y_test) = train_test_split(df[["sin_t"]])

4. 推論用RNNプログラムの実装と学習

4.1 トレーニング用プログラム

 次のコードを入力し実行すると学習が行われます。

from keras.models import Sequential  
from keras.layers.core import Dense, Activation  
from keras.layers.recurrent import LSTM

 # パラメータ
in_out_neurons = 1
hidden_neurons = 300
length_of_sequences = 30

model = Sequential()  
model.add(LSTM(hidden_neurons, batch_input_shape=(None, length_of_sequences, 
 in_out_neurons), return_sequences=False))  
model.add(Dense(in_out_neurons))  
model.add(Activation("linear"))  
model.compile(loss="mean_squared_error", optimizer="rmsprop")
model.fit(X_train, y_train, batch_size=600, epochs=15, validation_split=0.05)


 GPU無しで2分程度です。

4.1 推論用プログラム

 次のコードで推論を実行し、真値データと比較します。

 # 予測
predicted = model.predict(X_test)

 # 描写
dataf =  pd.DataFrame(predicted[:200])
dataf.columns = ["predict"]
dataf["input"] = y_test[:200]
dataf.plot()


 振幅がやや少ないですが、概ね推定に成功していると言えます。

5. おわりに

 オリジナル記事からの変更箇所は、modelのfitメソッドにおけるエポックの変数名です(nb_epoch → epochs)。オリジナル記事を書いて下さったkazukiiiさんに感謝致します。