久しぶりの更新となりました。これまでいくつかの言語で、代表的なDeep Learningの手法を実装をしてきましたが、今回はリカレントニューラルネットワーク(Recurrent Neural Networks: RNN)を実装してみたいと思います。言語は、初となるJavaScriptでトライしてみました。 完成したコードはGitHubのこちらのリポジトリにまとめてあります。 また、数式は以前にこちらにまとめましたので、理論部分についてはそちらを参考にしてください。
ではコードを紹介します。まずは核となる rnn.js から。
さて、ここで肝心なのが、冒頭にある math
です。これは Python で言うところの numpy のような挙動を目指すべく、いくつか線形代数計算で必要となるところの実装をまとめたものです。リポジトリ内の math ディレクトリに色々メソッドを書いています(ただし、まだまだWIPなところも多いです)。
似たようなライブラリには math.js がありますが、Matrix Object が個人的に扱いづらく、あくまでもPure Arrayで計算処理を行いたかったので、自分で実装しています。 math.array.zeros
や math.dot
, math.outer
など、 numpyっぽい書き方で線形代数演算が行えるようになるので、 RNNクラス の各メソッドも、割りと数式通りにスッキリ書くことができています。
また、出力層の活性化関数はsoftmax/sigmoid部分をコメントアウトして、単純な線形活性を用いていますが、これは今回予測したいタスク(後述)に合わせる形となっています。
さて、今回予測するのは、sin波です。Qiitaの記事でも見かけますが、手っ取り早くRNNの予測を試すにはうってつけのタスクです。0...t
の sin波 が与えられたときに、t+1
のsin波を予測します。 ただし、単純なsin波ではなく、-1 ~ 1 の一様分布に係数0.1をかけたノイズを波に足しています。これで予測を行ったのが下記のコード。
こちらは特段説明が必要なところはないかと思いますが、main
の最後の部分の出力を可視化してみると、きちんと(ノイズがまあまあ取り除かれた)sin波が描かれるのが分かるかと思います。
今回はとても単純なRNNをJavaScriptで実装しました。
$ npm install
$ node main.js
と実行すると結果が得られますが、せっかくJSで実装しているので、ブラウザで経過が見られるように変えていこうと思っています(他の手法も実装していきたい)。
また、現在CTOを務めているMICINという会社では、Angular2 や ReactNative でウェブ・アプリ開発をしており、こちらも js, ts 実装をしていますので、記事化していけるところはしていきたいと考えています。