はじめに
まずは,動かしてみたいので,全結合層のみの一層ないし二層のニューラルネットワークを作ってみたいと思います。機械学習は専門ではないので,以下の文献を参考にしました。1冊目は数式の説明が端折られているので,2冊目で補った格好です。
- 斎藤康毅著「ゼロから作るDeep Learning」(オライリー)第4章・第5章
- 岡谷貴之著「深層学習」(講談社サイエンティフィク)P.41~P.48
といっても,ほとんど文献の内容を焼き直しただけなので,プロデルっぽいところだけ説明したいと思います。
プロデルっぽいところ
【推定:行列】と【正解:行列】の交差エントロピー誤差を求める手順
(((正解に((推定に0.0001を全部足したもの)を対数関数で処理したもの)をかけたもの)を推定の大きさ(1)で全部割ったもの)の各列の和の各行の和)に-1を全部かけたものを返す。
終わり
「(((正解に((推定に0.0001を全部足したもの)を対数関数で処理したもの)をかけたもの)を推定の大きさ(1)で全部割ったもの)の各列の和の各行の和)に-1を全部かけたものを返す。」
えらくややこしくて頭のスタックがパンクしそうですが,日本語として読めなくもない文になっていますね!
それから,出力層の部分はこんな感じです。
ソフトマックスに損失関数もくっつけたやつとは
【行列T】を持つ。
【行列Y】を持つ。
【損失】を持つ。
はじめの手順
終わり
自分が【X:行列】を【T:行列】で順伝播させる手順
行列Tは,T。
行列Yは,Xをソフトマックスで処理したもの。
損失は,行列Yと行列Tの交差エントロピー誤差。
損失を返す。
終わり
【自分】が逆伝播させる手順
行列Yから行列Tを引いたものを行列Tの大きさ(1)で全部割ったものを返す
終わり
終わり
「ソフトマックスに損失関数もくっつけたやつ」という日本語らしいネーミングが可能になっています。クラス名だけならマルチバイト文字を指定できる言語もありますが,これに動詞がくっつくのがプロデルの醍醐味だと思いました。
ニューラルネットを作る
では,一層,つまり行列1つだけを使ったニューラルネットを書いてみたいと思います。
一層とは
+パラメータ:配列
【層】は,{}。
はじめ(入力の大きさ,出力の大きさ)の手順
パラメータは,{}。
パラメータ(1)は,行列(入力の大きさ,出力の大きさ)を作ったもの。
パラメータ(1)をランダム化する。
パラメータ(2)は,行列(1,出力の大きさ)を作ったもの。
層(1)は,全結合層(パラメータ(1),パラメータ(2))を作ったもの。
層(2)は,ソフトマックスに損失関数もくっつけたやつを作ったもの。
終わり
自分で【入力:行列】から推定する手順
(層の個数-1)回,【カウンタ】にカウントして繰り返す。
入力は,層(カウンタ)が入力を順伝播させたもの。
繰り返し終わり。
入力を返す。
終わり
自分で【正解:行列】が正解で【入力:行列】における損失を計算する手順
【推定結果】は,自分で入力から推定したもの
層(層の個数)が推定結果を正解で順伝播させたものを返す。
終わり
自分で【正解:行列】が正解で【入力:行列】における勾配を計算する手順
自分で正解が正解で入力における損失を計算する。
【出力】は,層(層の個数)が逆伝播させたもの。
(層の個数-1)回,【カウンタ】にカウントして繰り返す
出力は,層(層の個数-カウンタ)が出力を逆伝播させたもの。
繰り返し終わり
【勾配:配列】。
勾配は,{}。
勾配(1)は,層(1)の行列dW。
勾配(2)は,層(1)の行列dB。
勾配を返す。
終わり
終わり
「ゼロから~」のように,
パラメータ(「W1」)
勾配(「B1」)
などと辞書を使っても動きます(今回は諸事情で配列にぶち込んでいます)。
隠れ層の初期値を適当にランダム化していますが,望ましい初期値の論文がありますので,変える場合は行列.rdrの該当の手順を変えて実現することになります。