FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

フルスクラッチから作るニューラルネットワーク(7. MNIST誤差逆伝搬法の実装)

msyksphinz.hatenablog.com

誤差逆伝搬法をC言語で実装していたのだが、Pythonの結果とどうしても合わない部分がある。それどころが、学習を続けていくとどんどん正解率が下がっていったのでデバッグをしていた。

ニューラルネットワークの難しいところは、ランダム要素が多すぎてどこが間違っているのか分かりにくいところだと思う。 実際、今回Pythonのコードで流した学習結果と演算結果が合うように調整していったのだが、なるべくPythonのコードもランダム性がなくなるように調整していったり、かなり苦労した。

  • 重みの初期値はPythonコードの初期値をファイルに書き出してC言語側にインポートする。
  • 訓練データの選択はPythonではランダムランダム選択しているが、C言語と同様にシーケンシャルにデータを取得する方法に変更。
  • 1ステップ毎に重み値をファイルに出力してC言語側と比較。
  • そもそも入力値とラベルが正しいのかファイルに書き出して比較

そうすると自分では正しいと思っていたコードに問題が出るわ出るわ。C言語側の正規化の部分が間違っていたり、配列が実は初期化できていなかったりと問題がたくさんあったが、どうにか修正して正常に動作するようになった。

github.com

学習の結果は以下のようになった。トレーニング数60000を超えたところで、90%を超える学習率になった。

問題はPythonコードに比べて処理が遅い気がする。Pythonより遅いのは問題だなあ。。。

./train_twolayernet
gcc -g twolayernet.c -o twolayernet -lm
gcc -g train_twolayernet.c -o train_twolayernet -lm
gcc -g train_twolayernet_float.c -o train_twolayernet_float -lm
2051
60000
28
28
2049
60000
=== TestNetwork ===
Correct = 1342
=== TestNetwork ===
Correct = 5293
=== TestNetwork ===
Correct = 6388
=== TestNetwork ===
Correct = 7874
=== TestNetwork ===
Correct = 8447
=== TestNetwork ===
Correct = 8637
=== TestNetwork ===
Correct = 8700
=== TestNetwork ===
Correct = 8865
=== TestNetwork ===
Correct = 8924
=== TestNetwork ===
Correct = 8907
=== TestNetwork ===
Correct = 8966
=== TestNetwork ===
Correct = 9053

f:id:msyksphinz:20170630022526p:plain