"BOKU"のITな日常

還暦越えの文系システムエンジニアの”BOKU”は新しいことが大好きです。

レイヤーの出力を眼で見て確認(Affine、Sigmoid、Tanh、ReLu)/Neural Network Consoleの使い方

プレゼン用の資料を作るのに各レイヤーのアウトプットをグラフで視覚化してみたら、ちょっと面白いなと思ったので、今回のテーマにしてます。

f:id:arakan_no_boku:20190326212937j:plain

 

代表的なレイヤー

 

ディープラーニングで最もベーシック、かつ、代表的なレイヤーは全結合(Affine)と活性化関数(SigmoidとかTanhとか)です。

仕組とかについては、こちらで解説を書いたりしてます。

arakan-pgm-ai.hatenablog.com

arakan-pgm-ai.hatenablog.com

 

理屈だけではピンとこないので視覚化する

 

ただ、理論で理解しても、ピンとこないところがあります。

なので、実際の処理結果を目視できるようにモニタしてみます。

Neural Network Consoleだと、SquaredError を使い、Max Epoch 0 で学習・評価実行すると、その直前のレイヤーまでの加工結果をモニタすることができるんですね。

f:id:arakan_no_boku:20180819142726j:plain

f:id:arakan_no_boku:20180819142814j:plain

これは実に面白くて。

自分もよく、数式や言葉の説明だけでイメージがつかみづらい時に「勉強を兼ねて」これで遊んでます。

 

InputのCSVファイルのグラフ

 

Inputデータは、1.0~0.0 の間でランダムに発生させた実数を256列並べたものにします。

それをExcelのグラフで表示して視覚的に確認できるようにしてます。

 

元データはこれです。

f:id:arakan_no_boku:20180819143229j:plain

 

結果モニタの方法

 

学習・評価実行した結果は、プロジェクトファイル(sdcprojファイル)を保存したフォルダのプロジェクト名.filesフォルダの下の評価実行日時から生成された名前のフォルダ(以下図の赤枠のような)の下にできる「output.csv」に出力されてます。

f:id:arakan_no_boku:20180819143827j:plain

それをEXCELにはりつけて、グラフにしてます。

 

Affine(全結合層)を通したらどんな感じか

 

Affine層だけを通した加工結果を見てみたいと思います。

f:id:arakan_no_boku:20180819152625j:plain

初期値はデフォルトの「NormalAffineGlorot」です。

初期値については以下の記事で書いてますので、繰り返しませんので、興味のある方は後で見てもらえると嬉しいです。

arakan-pgm-ai.hatenablog.com

 

初期値にはマイナスの値もある

 

ポイントは初期値の元には「平均0.0 分散1.0であるガウス関数」なので、Affineの中で掛け合わされる重みには「マイナスの実数」もあるということです。

なので、元データに負の数がなくても、Affineを通した途端に、マイナスを含んだ値に加工される・・ということなんですね。

結果はこうなります。

f:id:arakan_no_boku:20180819152703j:plain

 

活性化関数を通した結果を見てみる

 

活性化関数には色々と種類があります。

代表的なのが「Tanh」「Sigmoid」「ReLU」です。

ネットワークを組む時、このどれを使うと適切なんだろうと、慣れないうちは結構悩みました。

これも、加工結果を視覚化すると特徴がはっきりして、判断の助けになります。

 

まずはTanh(ハイポリックタンジェント

 

こいつは「-1.0 から 1.0の範囲に収める」活性化関数です。

f:id:arakan_no_boku:20180819153637j:plain

レイヤーリファレンスの図だとこんな感じ。

f:id:arakan_no_boku:20180819153410j:plain

だから、今回のようにAffineを通した結果がすでに-1.0~1.0に収まっているようなデータだと、それほど変化しません。

f:id:arakan_no_boku:20180819153541j:plain

 

Sigmoidに入れ替えてみます

 

Sigmoidは「0.0~1.0の間に収める」ように計算します。

f:id:arakan_no_boku:20180819153858j:plain

レイヤーリファレンスだとこんな感じ。

f:id:arakan_no_boku:20180819154001j:plain

マイナスの数字がなくなるわけですから、Affineの変換結果からは劇的に変わります。

f:id:arakan_no_boku:20180819154111j:plain

なんか、Inputの状態(非負)に戻して、なだらかにした感じです。

 

次はReLUでやってみよう

 

ReLUは、「マイナスなら出力しない=0、プラスはそのまま出力する」です。

f:id:arakan_no_boku:20180819154905j:plain

レイヤーリファレンスだとこう。

f:id:arakan_no_boku:20180819154537j:plain

予想してみると。

Affineの出力でマイナスの部分が間引かれた感じになるだけになりそうです。

実際がこう。

f:id:arakan_no_boku:20180819154927j:plain

ほぼ予想通りのグラフですね(笑)

 

視覚で確認できるとわかりやすい

 

この方法は、加工結果を視覚でつかめるのが面白いところです。

ネットワークを考える時、次の層につながる出力がこんな感じの形になっているはずだから・・とイメージしながら考えるのと、何のイメージもなく、ただ闇雲にレイヤーを重ねていくのとでは雲泥の差があります。

自分の作成した元データがどのような形なのか?

次の層に伝える活性化関数のアウトプットはどのような形で渡すと、速く収束して、精度をあげられそうか・・とか、形をイメージして仮説をたてながらやってみると、結果を見た時の面白さが違います。

おお!予想通り!なのか。

予想と全然違う!なのか。

どっちにしても、同じ勉強でやるにしても、楽しいほうがいいですから。

途中まで、SquaredError とMax Epoch 0 を使って、Outputの形を確認しながら、ネットワークの検討をするというのは、たまにやってみたらいいんじゃないのかな?

そう自分は思ってます。

ではでは。