NeuralNetwork on Scratch(隠れ層の増やし方)
いままでの記事はこちら。
NeuralNetwork on Scratch(隠れ層の増やし方)
NeuralNetwork on Scratchは初期状態では隠れ層は「隠れ層_1」と「隠れ層_n」の2層ですが、増やすこともできます。今回はその方法を説明します。
学習機 スプライト
変数の作成
学習機スプライトに隠れ層2用の変数を作成します。「変数を作る」で [隠れ層_2の数] 変数を作成してください。変数のスコープは「このスプライトのみ」にしておきます。
また、「リストを作る」で次のリストを作りましょう。スコープは「すべてのスプライト用」にします。
リスト名 | スコープ | 意味 |
---|---|---|
G_隠れ層_2_U | すべてのスプライト用 | 隠れ層2の出力(活性化前) |
G_隠れ層_2_Z | すべてのスプライト用 | 隠れ層2の出力(活性化後) |
G_隠れ層_2_バイアス | すべてのスプライト用 | 隠れ層2のバイアス |
G_隠れ層_2_重み | すべてのスプライト用 | 隠れ層2の重み |
変数の表示
[隠れ層_2の数] は表示状態にし「大きな表示」で表示しておきましょう。場所はこのあたりで。
「初期化」定義
「初期化」 のブロック定義に 「[隠れ層_2の数]を()にする」 ブロックを追加します。初期値は適当な値にします。今回は「5」にしました。
「隠れ層_2の重みとバイアスを初期化」定義を作成
「隠れ層_2の重みとバイアスを初期化」 定義を作成してください。
定義の中身は 「隠れ層_nの重みとバイアスを初期化」 定義を複製しましょう。複製したら 「隠れ層_n」 の部分をすべて 「隠れ層_2」 に変更します。また、「隠れ層_nの重みとバイアスを初期化」 定義内の 「隠れ層_1の数」 を 「隠れ層_2の数」 に変更してください。(2か所あります。)
最後に 「重みとバイアスを初期化」 定義に 「隠れ層_2の重みとバイアスを初期化」 定義ブロックを追加しましょう。
順伝播、逆伝播の処理に組み込む
新しいメッセージ 「順伝播_隠れ層_2」 と 「逆伝播_更新_隠れ層_2」 を作って、順伝播と逆伝播の処理に組み込みましょう。作ったメッセージの処理内容は後で作成します。
「順伝播」 定義と 「逆伝播と更新」 定義に作ったメッセージの呼び出しブロック 「(順伝播_隠れ層_2)を送って待つ」 と 「(逆伝播_更新_隠れ層_2)を送って待つ」 を組み込みます。あわせて 「[呼び出し元]を(順_隠れ層_2)にする」 ブロック、「[呼び出し元]を(逆_隠れ層_2)にする」 ブロックも追加しておきます。これは、行列の次元数が合わなくて計算できなかった時に、どの部分の処理でエラーとなったかを特定する際に利用するためのものです。
順_隠れ層 スプライト
上で作成した 「順伝播_隠れ層_2」 の処理を作っていきましょう。
「リストコピー(隠れ層_2)」の作成
「リストコピー(隠れ層_2)」 定義を作成してください。
定義の中身は 「リストコピー(隠れ層_1)」 定義の内容を複製しましょう。複製したら 「G_隠れ層_1_重み」 を 「G_隠れ層_2_重み」 に、「G_隠れ層_1_バイアス」 を 「G_隠れ層_2_バイアス」 に変更します。
「結果をコピー(隠れ層_2)」の作成
「結果をコピー(隠れ層_2)」 定義を作成してください。
定義の中身は 「結果をコピー(隠れ層_1)」 定義の内容を複製しましょう。複製したら 「G_隠れ層_1_U」 を 「G_隠れ層_2_U」 に、「G_隠れ層_1_Z」 を 「G_隠れ層_2_Z」 に変更します。
「[順伝播_隠れ層_2]を受け取ったとき」イベント
「[順伝播_隠れ層_2]を受け取ったとき」 の処理を次のように作成してください。
これで、順_隠れ層 スプライトの修正は完了です。
逆_隠れ層 スプライト
最後に 「逆伝播_更新_隠れ層_2」 の処理を作っていきましょう。
「リストコピー(隠れ層_2)」の作成
「リストコピー(隠れ層_2)」 定義を作成してください。
定義の中身は 「リストコピー(隠れ層_n)」 定義の内容を複製してください。複製したら 「G_隠れ層_n_重み」 を 「G_隠れ層_2_重み」 に、「G_隠れ層_n_バイアス」 を 「G_隠れ層_2_バイアス」 に、「G_隠れ層_n_U」 を 「G_隠れ層_2_U」 に変更します。
「リストコピー(隠れ層_n)」の修正
「リストコピー(隠れ層_n)」 定義の中身を一部修正します。「G_隠れ層_1_Z」 を 「G_隠れ層_2_Z」 に変更してください。逆伝播では「出力層」→「隠れ層_n」→「隠れ層_2」→「隠れ層_1」の順に誤差が伝播するためです。
「結果をコピー(隠れ層_2)」の作成
「結果をコピー(隠れ層_2)」 定義を作成してください。
定義の中身は 「結果をコピー(隠れ層_n)」 定義の内容を複製しましょう。複製したら 「G_隠れ層_n_重み」 を 「G_隠れ層_2_重み」 に、「G_隠れ層_n_バイアス」 を 「G_隠れ層_2_バイアス」 に変更します。
「[逆伝播_更新_隠れ層_2]を受け取ったとき」イベント
「[逆伝播_更新_隠れ層_2]を受け取ったとき」 の処理を次のように作成してください。
これで、逆_隠れ層 スプライトの修正は完了です。
完成
これで隠れ層が3層のニューラルネットワークができました!この方法で層をもっと増やすこともできますが、その分、学習に時間がかかるようになりますのでご注意くださいね。
試しに何かのデータを学習させてみましょう。まずは「アヤメの分類」あたりがよいと思います。(やり方は前の記事を参照。)
動きがおかしかったら…
正しく計算できていない可能性があります。順_隠れ層 スプライトと逆_隠れ層 スプライトを表示状態にして再度[学習開始]してみましょう。
行列計算が正しくできていないと下のようなメッセージが表示されます。ここでは、順伝播の隠れ層2層目の行列和の計算が正しくできていないと言われています。5x10行列と3x10行列を足そうとしていて、次元数が異なるためエラーとなっています。(行列の足し算は同じ次元でなければいけないので、両方とも 5x10次元 もしくは 3x10次元 になっていないといけません。なお、ここで「10」はバッチサイズです。)
「U=行列和(U, バイアス)」 定義を見ると、U と バイアス を足そうとしているので、隠れ層2_U もしくは 隠れ層_2_バイアス の次元数がおかしそうだとあたりがつきます。隠れ層2のユニット数は今回「5」にしているので、バイアスも 5xバッチサイズ 次元になっていなければいけないところ、なぜか 3x10 になっています。どうやら 隠れ層2のバイアス の設定が誤ってるみたいですね。「隠れ層_2の重みとバイアスを初期化」 定義ブロックを確認してみましょう。
隠れ層_2の数 とすべきところが 隠れ層_nの数 になっちゃってますね。「隠れ層_nの重みとバイアスを初期化」 定義を複製して隠れ層2用に修正する際に修正し忘れてしまったようです。正しく修正しましょう。
修正したら[学習開始]してみましょう。今度はちゃんと学習できましたね。
【関連記事】
【Scratchプロジェクト】
NeuralNetwork_on_Scratch_2 (全部入り)
Base_NeuralNetwork_on_Scratch_2 (基本部分のみ)
Discussion