ゼロから作るDeep Learning
1層ニューラルネットワークへのバイアスと活性化関数の追加
昨今注目を集めているAI(人工知能)を学びたいと思い立ち、ディープラーニング(Deep Learning、深層学習)と呼ばれるAIの数理モデルである多層構造のニューラルネットワークを書籍「ゼロから作るDeep Learning ―Pythonで学ぶディープラーニングの理論と実装」を参考にを独習していきたいと思います。本書籍ではプログラミング言語としてPythonが利用されていますが、本項ではJavaScriptで実装していきます。
目次
- 準備1:行列の和と積を計算する関数の実装
- 準備2:ベクトルと行列の積を計算する関数の実装
- 準備3:多変数関数の数値微分と極小値の探索
- 1.1層ニューラルネットワークの実装(バイアスなし、活性化関数なし、学習なし)
- 2.1層ニューラルネットワークへのバイアスと活性化関数の追加
- 3.1n1型2層ニューラルネットワークの実装(学習なし)
- 4.1変数関数を学習させてみる1:勾配法による学習計算アルゴリズム
- 5.1変数関数を学習させてみる2:勾配法による学習計算アルゴリズムの実装
- 6.1変数関数を学習させてみる3:ニューロン数による学習効果の違い
- 7.誤差逆伝搬法(バックプロパゲーション)の導出
- 8.順伝播型ニューラルネットワーク「FFNNクラス」の実装(JavaScript)
- 9.三角関数のサンプリング学習(WebWorkersによる並列計算)
- 10.学習後の各層ニューロンの重みの可視化
- 11.層数とニューロン数による学習効果の違い
バイアスと活性化関数を加えたモデル
前項のモデルにバイアスと活性化関数を加えたモデルを示します。 活性化関数は旧層のニューロン値から新しい層のニューロン値を決定する関数、バイアスは活性化関数に与える引数に加える値を意味します。
計算アルゴリズム
上記のモデルにおける入力層(0層目)に対する出力層(1層目)のニューロン値は次の計算式で与えられます。
この関係式を行列で表すと次の通りです。
ただし、Fはベクトルの各成分ごとに作用させることを意味するとします。
JavaScriptによる実装
上記のモデルに対応したニューラルネットワークをコンストラクタの第二引数にバイアス、第三引数に活性化関数を与えることでNNクラスを定義します。 第二引数に与えるバイアスBは第一要素に層番号、第二要素にニューロン番号で表現される多重配列です。 また、第三引数に与える活性化関数には関数そのものを与えます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | //ニューラルネットワーク var NN = function ( W, B, AF ){ //重み this .W = W; //W.length : 層数 //W[].length : 列(後ニューロン数) //W[][].length : 行(前ニューロン数) //バイアス this .B = B; //活性化関数 this .AF = AF; //ニューロンの初期化 this .X = []; for ( var i = 0; i < W.length; i++ ){ this .X[ i ] = []; for ( var j = 0; j < W[ i ][ 0 ].length; j++ ){ this .X[ i ][ j ] = 0; } } //出力層 this .X[ W.length ] = []; for ( var j = 0; j < W[ W.length-1 ].length; j++ ){ this .X[ W.length ][ j ] = 0; } } //入力層(0層目ニューロン値)へのインプット NN.prototype.setInput = function ( Input ){ for ( var i = 0; i < Input.length; i++ ){ this .X[ 0 ][ i ] = Input[ i ]; } } //出力層へのアウトプット NN.prototype.getOutput = function (){ //各層ニューロン値の計算 for ( var i = 0; i < W.length; i++ ){ this .multiplayMatrixVector ( this .W[ i ], this .X[ i ], this .X[ i+1 ] ); this .addVectors ( this .X[ i+1 ], this .B[ i ], this .X[ i+1 ] ); this .adoptAF( this .X[ i+1 ], this .X[ i+1 ] ) } return this .X[ this .X.length -1 ]; } //行列×ベクトルの計算 NN.prototype.multiplayMatrixVector = function ( M, V, C ){ C = C || []; var Mgyou = M.length; var Mretu = M[ 0 ].length; for ( var i = 0; i < Mgyou; i++ ){ C[ i ] =0; for ( var j = 0; j < Mretu; j++ ){ C[ i ] += M[ i ][ j ] * V[ j ]; } } return C; } //ベクトルの和 NN.prototype.addVectors = function ( V1, V2, V3 ){ V3 = V3 || []; for ( var i = 0; i < V1.length; i++ ){ V3[ i ] = V1[ i ] + V2[ i ]; } return V3; } //活性化関数の実行 NN.prototype.adoptAF = function ( V_in, V_out ){ V_out = V_out || []; for ( var i = 0; i < V_in.length; i++ ){ V_out[ i ] = this .AF( V_in[ i ] ); } return V_out; } |
計算チェック
上記のNNクラスに次の重み、バイアス、活性化関数を与えて計算して、コンソール(「F12」で表示)に出力します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | //入力層 var X0 = [ 1, 2, 3]; //重み var W = []; W[ 0 ] = [ [ 0.1, 0.1, 0.1 ], //W^{(0)}_{00}, W^{(0)}_{01}, W^{(0)}_{02} [ 0.2, 0.2, 0.2 ] //W^{(0)}_{10}, W^{(0)}_{10}, W^{(0)}_{12} ]; //バイアス var B = [ [ 10, 20, 30 ], //B^{(0)}_0, B^{(0)}_{1}, B^{(0)}_{2} ]; //活性化関数 var AF = function ( x ){ return Math.sqrt(x); } //ニューラルネットワークの生成 var nn = new NN( W, B, AF ); //入力層へのインプット nn.setInput( X0 ); //出力層へのアウトプット nn.getOutput(); //結果の表示 console.log( nn.X[1] ); //出力[3.255764119219941, 4.604345773288535] |