皆さん
こんにちは、GMOアドマーケティングのS.Rです。
前回は 畳み込みニューラルネットワークの要約を投稿しました。皆さんいかがでしたでしょうか。今回は時系列データ(株価、機械翻訳なと)に一番使われてるモデルの一つ、再帰型ニューラルネットワーク(英語はRecurrent Neural Networkです、以下RNNと記載します)を皆さんへ紹介したいと思います。
機械学習の問題の種類
まずは機械学習の問題の種類を一緒に復習しましょう。機械学習の問題は目標によって主に分類問題と回帰問題に分かれます。
1、分類の問題:
分類対象の特徴と分類を確定した上に分類対象の学習データの学習として各対象の種類を予測する事です。良くある例は乳がん検査、手書き画像の認識、物体認識です。
2、回帰の問題:
分類対象の特徴と分類を確定し連続するデータの予測をすることです。良くある例は物件の値段の予測、オンライン広告のクリック率の予測です。
実際の応用にはこれらの二種類の問題だけではなく、学習データで時間の影響は考えていることがあるかとして時系列問題と非時系列問題を分けてます。
時系列問題
時間順序を追って取得されたデータは時系列データと呼ばれます。典型的なものとしては、年度ごとのある会社の売上高、1時間ごとの日本の首都の降水量、地球上で発生した地震の時刻と場所、震度などの記録、といったものが挙げられます。図1は時系列データの例の一つとして 1953年ー2009 年アメリカで結核の発生率 のデータです。
なぜ再帰型ニューラルネットワークが必要になるか
ある問題には時間を学習データにいらないと解決できません。一つの良い例は機械翻訳です。
例えば日本語から英語を翻訳するモデルを作りたいとする(図2)。
まずは入力した日本語文章の時間順序考えずに自動翻訳のモデルを設計しましよう。設計したモデルは図3です。
入力する文字列の長さが特定できないので自動翻訳する前に文字列を指定された長さで抽出しなければなりません。抽出する文字列の長いさによってモデルで取った翻訳の結果が違います。
図3は違う長さで抽出した文字列の翻訳結果です。この結果から見ると入力する文字列を全部モデルの入力データにしなければ入力文章の前後文の関係がなくなるので良い翻訳の結果を得られません。でも実際はこれは実現できません。原因は二つあります。
1モデルの計算にかかる計算力が高すぎるせいです。
2学習データの中に無駄な情報がたくさん入るので精度が良くありません。
再帰型ニューラルネットワークはこの二つ問題を解決するために提案されたモデルです。
再帰型ニューラルネットワークは通常のニューラルネットワークと違うある層の出力は、次の層の入力として利用されるだけでなく出力としても利用されます。また、各層の入力として、前の層の入力のみではなく、時系列のデータポイントも入力とします。図のように、一つのニューラルの出力を別のネットワークの入力として利用するような再帰的構造がRNNの名前の由来です。この形でRNNモデルは”記憶力”を持っています。データを処理する時に当時のデータだけではなく前に処理したことのあるデータとの関係も学習できます。
再帰型ニューラルネットワークで先程の例の文字列を処理する流れは図5になります。
KerasでRNNを構築
では早速 一緒に簡単なRNNを作りましょう。今回はRNNのモデルで三角関数SINをフィッティングすることです。今回の例はGoogleの無料クラウドサービスでやっております。
1 Colabのインスタンスを作る:
Colabの利用を始める最初のStepは、Colabのファイルを作ります。Google Driveの管理画面へ遷移し、新しいColabのファイルを作ります(図5)。
2Library をImportする:
1 2 3 4 5 6 7 |
import numpy as np import matplotlib.pyplot as plt from sklearn.model_selection import train_test_split from keras.layers.recurrent import SimpleRNN from keras.models import Sequential from keras.optimizers import Adam from keras.layers import Dense, Activation |
3 学習データを作成:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# データ準備 def noisy(Y, noise_range=(-0.05, 0.05)): noise = np.random.uniform(noise_range[0], noise_range[1], size=Y.shape) return Y + noise np.random.seed(0) x = np.arange(0, 100*2) x = np.cos(2.0 * np.pi * x / 100) rawdata = noisy(x, (-0.05, 0.05)) inputlen = 20 plt.plot(rawdata) plt.show() input=[] target=[] for i in range(0, len(rawdata) - inputlen): input.append( rawdata[i:i+inputlen] ) target.append( rawdata[i+inputlen] ) X = np.array(input).reshape(len(input), inputlen, 1) Y = np.array(target).reshape(len(input), 1) x, val_x, y, val_y = train_test_split(X, Y, test_size=int(len(X) * 0.2), shuffle=False) |
4RNNモデルを作る:
1 2 3 4 5 6 7 8 9 10 |
n_in = 1 n_hidden = 20 n_out = 1 epochs = 10 batch_size = 32 model=Sequential() model.add(SimpleRNN(n_hidden, input_shape=(inputlen, n_in), kernel_initializer='random_normal', return_sequences=True)) model.add(Dense(n_out, kernel_initializer='random_normal')) model.add(Activation('linear')) model.compile(loss='mean_squared_error', optimizer=Adam(lr=0.01, beta_1=0.9, beta_2=0.999)) |
5RNNモデルをフィッティングする:
1 2 3 4 5 6 7 8 9 10 11 12 |
in_ = x[:1] predicted = [None for _ in range(inputlen)] for _ in range(len(rawdata) - inputlen): out_ = model.predict(in_) in_ = np.concatenate( (in_.reshape(inputlen, n_in)[1:], out_), axis=0 ).reshape(1, inputlen, n_in) predicted.append(out_.reshape(-1)) plt.title('Predict sin wave') plt.plot(rawdata, label="original") plt.plot(predicted, label="predicted") plt.plot(x[0], label="input") plt.legend() plt.show() |
6 実行した結果:
上の図は学習データです、縦軸は関数値です横軸は時間です。下の図はRNNで予測した結果と本番のデータを比較する図です。縦軸、横軸の定義と上の図は同じです。青い図は本番のデータ、黄色の図は予測した値です。
まとめ
今回は再帰型ニューラルネットワークを紹介しました。
実際の機械学習系の業務に再帰型ニューラルネットワークを使う機会はたくさんあります。もし今回のブログが皆さんの畳み込みニューラルネットワークの理解にお役に立てば幸いです。