リカレント・ニューラル・ネットワーク(Recurrent Neural Network, RNN)っていう、時系列に対するDeep Learningやりたい

はじめに

前々からDeep Learning系、特にその時系列への応用に興味があって、それにはリカレント・ニューラル・ネットワーク(Recurrent Neural Network, 以下RNN)ってのを理解する必要があるのは知っていたが、@yamano氏から


というありがたいアドバイスを頂戴した。それに基づいてググりはじめると、Stuttgart(シュトゥットガルト)大学というドイツにある、たぶん日本でいう東工大的なポジションの大学が開発している、ニューラルネット関連の実装をたくさん詰め込んだライブラリ

が元々あって、それをラップしてRから叩けるようにしたものが、

というライブラリということがわかった。

RSNNSパッケージを使ってみる

上に書いたように、このパッケージ(ライブラリ)に入っている実装は、RNNに限らないようだが、興味あるのはRNNなのでそれをやる。Rのパッケージにくっついてくるマニュアルを読み込むとどうやら「jordan」関数ってのがあって、これを使うとよさそうだ。似たようなものとしてElman networkというのもあるらしい。詳細は原著

  • Jordan, M. I. (1986), ’Serial Order: A Parallel, Distributed Processing Approach’, Advances in Connectionist Theory Speech 121(ICS-8604), 471-495.
  • Elman, J. L. (1990), ’Finding structure in time’, Cognitive Science 14(2), 179–211.

を漁るか、Stuttgart Neural Network Simulatorのマニュアルを読まないとだめだな。どちらも「partially recurrent networks」と記述されていて、「なんでpartially?」ってのが気になってる。まぁ、とりあえず

  • 興味持つ⇒動かす⇒ロジックを調べる⇒より興味を持つ⇒より興味を持って動かす⇒・・・

ってことで、パッケージに入っている例のコードを少し改変して動かしてみる。

#パッケージ入れる
install.packages("RSNNS")
library(RSNNS)
library(dplyr)
#データ読み出す
data(snnsData)
#snnsDataデータを入力と出力で分解
inputs  <- snnsData$laser_1000.pat[,1]
outputs <- snnsData$laser_1000.pat[,2]
#更にトレーニング・
patterns <- splitForTrainingAndTest(inputs, outputs, ratio=0.15)
#size:隠れ層のユニット数
#learnFuncParams:学習関数に対するパラメーター
#linOut:活性化関数をリニア(TRUE)にするかロジスティックにするか(FALSE)
modelJordan <- patterns %>% with({
  jordan(inputsTrain, targetsTrain,
    size=c(8), learnFuncParams=c(0.1), maxit=100,
    inputsTest=inputsTest, targetsTest=targetsTest, linOut=FALSE)})

ここで、デフォルトの学習関数は

によると、

  • JE_BP: Standard Backpropagation for partial recurrent networks

となっているが、これが単純なバックプロパゲーションでやってますよーという意味だと思われる。この辺を理解するにもRのパッケージじゃなくて直接Stuttgart Neural Network Simulatorのマニュアルを読まないとだめだな。で、この学習に使われるパラメーターがlearnFuncParamsで設定していると。

また、ここで使っている元々のデータは「カオス状態にあるアンモニア(NH3)レーザーの強度のデータ」だそうな。これは、公式サイトからソースを落としてきて、その中に入ってる「laser.README」というファイルに記述がある。

計算結果(modelJordan変数)を描画する用のplot関数も入っているが、中のコードを見た感じ通常のPLOT関数+αな印象。また、フィッティング結果が結構上方にバイアスかかってるように見えるんだが、こんなもんなのだろうか?

#適当に結果を描画
plotIterativeError(modelJordan) #1
plotRegressionError(patterns$targetsTrain, modelJordan$fitted.values) #2
plotRegressionError(patterns$targetsTest, modelJordan$fittedTestValues) #3
plot(inputs[1:100], type="l") #4
lines(outputs[1:100], col="red")
lines(modelJordan$fitted.values[1:100], col="green")

#1の結果(繰り返し毎に加重残差二乗和が減っていきますよー的なもの)

#2の結果(トレーニングデータ(実データ) v.s. その予測値。黒線は45度線(100%HITの場合これ)、赤線は(予測~実データの単回帰直線))

#3の結果(テストデータ(実データ) v.s. その予測値。黒線は45度線(100%HITの場合これ)、赤線は(予測~実データの単回帰直線))

#4の結果(黒線:入力値、赤線:実データ(出力)、緑線:予測値)