前回は同じ値で何度も学習させたら100回以内に収束していました。
今回はちゃんと違うデータを渡して関数の近似が出来るのかやってみます。
ちょっと変えたところ
前回最終段はただのSUMでしたが、そうすると誤差がより伝搬しないと思ったので(最終段で値の調整がかなり効くので)最終段も普通のノードにしました。
下の画像で言うと黄色いのが全てシグモイド関数で動き、赤いのが重み付けの存在する経路です。
x^2
最終段をシグモイド関数にしたことで出力範囲が0~1となりました。増幅してもいいですが、とりあえずx^2におけるx=0~1の範囲で学習させてみます。
これが結果です。左下のがプロットしたもので、赤がx^2の曲線で、緑がニューラルネットワークの出力です。
教師データはx^2の0~1にある等間隔な100個のデータです。100このデータを回して使って1000回やった結果(同じデータは10回使われていることになります)がこれになります。
グラフを見ると全く近似できてないですね。わずかに右肩上がりにはなってますが。
同じデータなら30回もやれば同じ値になったのに(前回ね)全くだめですね。
プログラムがおかしいのかと思ってさんざん見なおしたんですが、どうも回数の問題だったようです。10倍にして10,000回やってみます
割と近似できてますね。およそ5,000回目ぐらいで収束し始めているのが分かります。
こんなにやらなきゃいけないんですね^^;
レイヤー数を下げてみる
ちょっとレイヤー数を下げてみようと思いました。
いきなり曲線っぽくなってますね。レイヤーが少ないほうが柔軟に対応するんでしょうか。
回数を上げてみましょう。
10,000回にしてみました。さっきのレイヤー数の時は5,000回ぐらいで収束していきましたが、今回は1,000回ぐらいでかなり収束していますね。さらに10倍にしてみましょう。
おぉ。こんなに近似できるもんなんですね。あんなに簡単な回路なのにね(笑)
まぁ、学習量は半端無いわけですがそれでもすごい。
sin(x)
x^2だとキレイすぎるのでsin(x)をやってみました。sin(x)/2+0.5の関数を近似してみます。
レイヤー数は少ない方にしてみましょう。10,000回やった結果がこちら
それっぽいですね。でもx^2のときは10,000回やったらほぼ似てたのに、それに比べて大分ズレてますね。さらに10倍の100,000回にしてみましょう。
割りといい感じです。やっぱり最初の方はちょっと微妙ですが、かなり近いですね。
こんな簡単な回路でもここまで近似できるんですね。
速度的な話
何秒ぐらいかかったのか見てみます。さっきのレイヤーを減らした方でみてみましょう。
ちなみに重み付けできる経路は12ですね。
100,000回で
0.037208 sec
でした。1秒でおよそ 2,687,594回出来そうですね。
教師データはその都度計算してますから、x^2の計算も100,000回してるのですが、まぁ大したことはないでしょう。
100,000回で
0.060529 sec
でした。重み付けできる経路数が12から21になってますからこんなもんでしょうか。
FPGAでの実装に向けて
今回はfloatを使ってますが、浮動小数はめんどくさそうですね。signed shortとかでちょっと実装しなおしてみましょうか。
コメントを残す
コメントを投稿するにはログインしてください。