次は3層のNeural Networkをより’実践的に’です。
どの様に実践的なのかは、私自身、まだまだ分っていませんが、この後も学習を進めると判って来るのだと思います。 今は、指導書 [参考文献1)] のままに進めることにします。
1.Neural Networkの信号伝達の実装
行列による線形変換と活性化関数(シグモイド関数)を組み合わせることになります。 目的とする信号伝達の最終的な全体フローは下のFig. V-1 です。
前回は、バイアスの①を上部に描いていましたが、多層をプログラム描写するのに下に描いた方が楽なので変更しています。 プログラムの紹介は本篇の後半にして、Neural Networkの各層毎に紹介します。
1) 入力層から第1層への重み付け和
第1層は2入力のXに重み付けWを付けてバイアスBを加えて出力Aとします。
第1層へのフロー は 下のFig. V-2 となりました。
変数の肩に括弧()の中に層を示しています。 肩文字(1)は1層目の伝達と第1層の出力であることを示しています。
一方、線形伝達Wの添字は2桁で表現され、10の桁(前の数)は出力変数の番号に対応して、1の桁(後)は入力変数の番号に対応します。(記事9も参照) 各ベクトルおよび行列の要素は
となり、 eq.(V-1)を各要素の行列式に置き換えると
となります。
例として、各要素に値として、
を与えると、
となります。 しかし、この式を見ても、何が起こっているのか良く分からない。 そこで、少し意味のある事を考えてみます。 記事5 (基本的な使い方 Matplotlib インストール) で Pythonの導入として Sin、Cos曲線を描きました。 この値をx、y平面として描くことにします。 周期を4倍程度にして、径を少しずつ小さくすると螺旋になります。
これを、ネットワークで変化させます。 まずは、拡大と回転の処理を加えます。
aの3番目を決定するWの3列目のw13とw23は0にしておきます。 下記のWの行列は、ほぼ、x2の軸方向に1.5倍して反時計回りに約30度の回転に当たります(回転行列の式の説明は省略)。 BはX1方向に0.3移動、X2方向に0.2移動になります。 結果の2次元部分(a1,a2)を元の螺旋(黒)に重ねて表示(青)します。
次に、Wの3列目(w13, w23) と、Bと3番目(b3)を決めて、Aの3番目(a3)を計算します。 a3を高さとすると、3次元での配置になります。 matplotlibの3次元描画で描きます。 初期値 X (黒)と出力 A(緑) となります。 結果は斜めの螺旋になりました。 結果を見えるようにしたので、少しは理解が深まったように思えます。
2)第1層をActive関数で変換
次の変換として、 出力Aに Active(活性)関数を適用します。 Active関数はh()として表現してします。 フロー図ではActive関数のinとoutの全体を大きな円で囲みます。
Active関数としてシグモイド関数を用意します。 シグモイド関数は記事8:活性化関数 (ディープラーニング StepⅡ) で紹介しています。
シグモイド関数でAを変換した結果Zを赤いプロットで3次元グラフに重ねます。
プロットは 黒 : X , 緑 : A , 赤 : Z になります。
シグモイド関数の出力範囲は 0≦Z≦1 となるので、小さくまとまっています。
3) 第2層と第3層の設計
・ 第2層
第2層の設定は、第1層目のフロー と同じように繰り返しますが、Z(1)が入力とします。
今度は3要素のZ(1)が入力となり、出力のA(2)は2要素になります。 従って、W(1)は2行3列、バイアスBも2要素とないます。 行列式では
になります。 さらに、活性化関数h()を適用してZ(2)に変換をします。 フロー図は次の様になります。
Fig(V-4)になります。
第3層は第2層の結果Z(2)を入力として バイアスB(3)を加えて出力A(3)とします。
第3層では活性関数を使わないで、変化のない恒等関数σ()を適用するそうです。 ( なぜかは未だ解りませんが、ここはテキストのままに進めることにします。) これでフローは終了して、 最初にFig.V-1に示した処理フローの完了となります。
これで、ニューラルネットワークの実装が出来たということになります。
第2層目以降の変換に、どんな意味を持たせるかはニューラルネットワークの勉強を進めれば判って来るのでしょう。
以下で、各プログラムの紹介と簡単な説明をします。 Fig.V-1に示した処理プログラムも作りました。
@@@@@@@@@@@@@@@@@@@@@@@@@
2. プログラムの紹介と説明
ここからは、作ったプログラムとその簡単な説明をします。 上記の説明では、実装処理とネットワークでの図解をしてきましたが、 ここでは、自作した以下の3つのプログラムの紹介になります。
・ ネットワークの図を描画するプログラム
・ 第1層処理結果の3次元グラフ化プログラム
・ 3層のニューラルネットワークプログラム
1)ネットワークの図を描画するプログラム
ニューラルネットワーク(Fig.V-1)を描くプログラムです。
このプログラムで個人的に苦心したポイントを紹介しておきます。
<1>類似する描画の分離
描くのは変数記号(a,x,w,b)と、丸、矢印を組み合わせたものでしたので、 類似の描画を関数でまとめました。 試行錯誤して、
・各レベルでの記号を丸で囲んで描く : Plot_A
・多数の変数間をクロスする矢印での層間変化とバイアスを追加 : Plot_Network
・変数前後間のクロスのないアクティブ関数(&恒等関数)を示す矢印と大円 : Plot_Act
に分けました。 各関数のdefセクションの後に、メインセクションでは各変数記号を定義して、関数を組み合わせることで、1層から3層のフロー図にしました。
<2> 肩文字、添え字の大きさと位置
mathtext のデフォルト設定のままでは、 肩文字、添え字が大きすぎると感じました。 特にネットワークの記載に変数に小文字を使うと、肩文字や添え字の数字が殆ど同じ大きさになってしまいます。 (大文字の場合は、もう少し見場は良くなる。)
肩文字、添え字の大きさは元のフォントの70%らしいです。しかし、この縮小率はパラメータでは変更できないということです。 そこで、肩文字、添え字を2重にすることにより、ほぼ50%の大きさすることにしました。ただし、2重にすることで肩文字はさらに上に、添え字は下になります。 そこで、肩文字の上がり量と、添え字の下がり量をパラメータで調整します。 sup1=0.3(肩文字の上がり位置), sub1=sub2=0.1(添え字の下がり位置) に設定しています。 これ位で私の好みに近いものとなりました。
下の文字は、 左がデフォルトの肩文字と添え字、 右が調整後です。
<3>文字を丸で囲む
文字を丸で囲むには、textにBboxを追加すればいいのでが、文字の大きさで円の大きさが変わり、位置も調整してくれます。 Bbox は簡単なので使いたいのですが、全体の統一感や矢印の長さ調整が上手く出来ませんでした。 Scatterによる円の設定ならば中心位置を文字に一致させることが出来ました。 円の直径の2乗で設定するので、少し迷ったが、設定してしまえば楽になる。 なお、矢印との上下関係なども設定する必要があり、面の色(fc)やzorderの設定も勉強になりました。
<4>矢印の長さ
矢印を描く場合に、その長さにちょっとした苦心しました。 plt.arrowで始点と終点を設定すれば矢印は描けるが、円で囲んだ文字に合わせると、矢印と文字や円が重なってしまいます。 これに対して、矢印のレーヤーを指定します。 円がzorder=1 なので、矢印をzorder=0.9 と1より小さくしました。 小さい方が下になるので、始点側の円を白塗りにすることで重なった矢印を隠すことが出来ます。 終点側は隠すと矢印の矢先が消えてしまいます。このため、方向による調整が必要になる。 方向による調整は、角度(Siita)を三角関数で求め、円の半径の長さだけ短くします。 短くする割合は、x方向とy方向で異なるので、変換率:X_px、Y_px で調整です。 また、矢先の長さも考慮します。 plt.arrowは始点から終点までの線と、その先に矢先を付けているらしい。 従って、矢印の短くする分量は、円の半径と矢先の長さとなり、少し隙間を開けるのであればその長さも考慮した長さとします。
下の左図は、そのまま矢印の始点と終点にScatterで円を描いた場合です。 円と矢印が重なり、矢先も交差しています。 右図は、上記のような処理をして描いたものです。
2)第1層処理結果の3次元グラフ化プログラム
次は、第1層のニューラルネットワーク処理の結果を3次元グラフにしたプログラムです。3次元プロットのパッケージをインポートしています。
結果は
となります。 プログラムの各ラインにコメントを付けていますが、注意点は行列の転置でしょう。
このプログラムでは、行列の積を計算するのに、配列を転置します。 また、計算結果をグラフ化する時に再度転置して戻します。 pyplot でグラフを描く場合、 位置データ(x、y)について xの1次配列とyの位置配列を準備して、scatterやplotで描きます。一方で、行列計算はデータの組毎に行う必要が有ります。
今回のプログラムでは、プロット用に26個のxデータ配列とyデータ配列を作りました。x1、x2は2行26列のデータとなっています。一方で、ニューラルネットワークの行列計算では(x、y)として26行2列の配列を用意することになります。 この為に、ネットワーク計算に転置行列を作り、グラフにする時には再度転置して26行の配列に戻しています。 Numpy では .Tで簡単に転置できます。
3)3層のニューラルネットワークプログラム
最後に、3層のニューラルネットワークをプログラム実装したものを紹介します。 第2層、第3層の変換行列WとバイアスBは単に結果のグラフが見えるように適当に設定しただけです。
3. あとがき
ようやく、新しい記事を書き上げました。 フロー図を描こうとしていたら、肩文字と添え字のアンバランスが気になって、TeXの文字の位置や、ピクセルの関係を調べるのでかなりの時間を取ってしまいました。 文字のサイズと位置関係については番外編としての次回の記事で紹介したいと思います。
これまでは、Pythonのプログラミングテクを習得するのに手間取って、ディープラーニングの進みが遅くなっているように思えます。 いつの間にか、教本にしている「ゼロから作るDeep Learning 」も3冊目が出ています。今後は、少しは早く進めたいと思っています。
4.参考文献 / 参考リンク :
*1) このブログは教本として、ゼロから作るDeep Learning Pythonで学ぶディープラーニングの理論と実装 [ 斎藤 康毅 ] 【出版社: オライリージャパン 発売日: 2016/9/24 】 (ISBN-10:4873117585 ISBN-13:978-4873117584) を使っています。
2) 線形代数での行列については各種の専門書が有ります。 基本的で分かり易い本として 高校数学でわかる線形代数 (ブルーバックス) [ 竹内 淳 ] などがあります。
3) Pythonでの描画はmatplotlibを使用します。matplotlib サイト のチュートリアルは機能を調べるのには便利でした。 例えば、Tutorials » Annotations(注釈)辺りから調べます。https://matplotlib.org/tutorials/text/annotations.html#sphx-glr-tutorials-text-annotations-py
* ) 独学ではなかなか進まない方は、やはり有料になりますが、専門セミナーを受けられることをお勧めします。
__ __ __~~~( ゜〈‶ __ __ __ ~~( ゜〈‶ 🐭 "〉゜ )~~python __ __ __
0コメント