機械学習、深層学習が流行り始めて随分たった。
いろんなWebページで資料がたくさん出ているけど、読んでいるとイマイチピンとこないことが多かった。
それって、いちから実践してないからなんだろうなぁと思って、いろんな資料を見ながらフルスクラッチしてみた。
正直、解説ページって数式や図解してるんだけど、図解がいまいちあってないとか数式なんか難しく分解したり、いろんな変数だしてきて、「えっへん!」って感じで見るのも疲れるし・・・
要は作って完成すれば理解できたと思えばいいんでしょ。
そこで、ひとまず目標をCNNで犬猫判別とした。
ちょっと、流行からは遅れてるけどね。
学習データはオックスフォード大学の下記のURLから取得した。
まずはデータ作りだ。
ダウンロードした画像から犬と猫の顔部分だけ抜き出すPHPを書いて、せっせと作業を行った。
わたしゃ、基本的に使う言語はPHP、C、Verilog HDLの言語に絞ってるんだよね。
PythonとJavaはわからないし、JavaScriptは使うけどここでNode.jsを持ちだしてやるような作業じゃないし。
昔はPerl、C、VHDLだったけど、Cだけまだ現役って感じかな。
もっと昔はPerl、独自メーカ言語、回路図だったけど・・・
脱線したけど、犬猫画像を50枚ずつ用意した。
犬猫判別と犬を前に持ってきたんだけど、犬=NG、猫=OKの判別を作る。
まずは、パーセプトロン部分を書いてみた。
まぁ、ここは簡単だよね。
バックプロパゲーション部分を書いてみた。
これも簡単だよね。
畳込みを書いてみた。
これも簡単だよね。
プーリング部分を書いてみた。
これも簡単だよね。
じゃぁ、何が難しいのさぁ〜!!!
ざっくり、作ってみるとメモリリークの嵐が発生・・・
まぁ、適当に書いたからなぁ・・・(^-^;
いろいろ、あんなことやこんなことしながらデバッグしてメモリリークを無くして、さて学習させてみよう。
あれ?
いきなり、学習データが飛んでいく。
重みがあさっての方向に向いていくぞ・・・
ひとまず、CNNのレイヤ数や学習係数、フィルタなどの値をいぢってみる。
デバッグを乱数でやってるから一貫性がなくてわからなくなってるんだな・・・
重みやフィルタの乱数を固定化してから確認しよう・・・
あれ、まだ、メモリリークしてるわ(^-^;
また、あれよこれよ本当にメモリリークが無くなった。
CNNも16→32→64で構成してみた。
そしたら、こんどはmallocできないでやんのぉ〜。
今度はメモリ使用量の調整を開始・・・
そんなこんなしながらなんとかmallocも落ち着いた。
CNNの数は仕方ないので2→4→8で動かしている。
う〜ん、数回目で重みがあさっての方向を向いてしまう。
なんでぇ〜?
バックプロパゲーション中におかしくなるようだなぁ。
CNNの最後の全結合層は中間層+出力層で、出力層側の学習をやめてみた。
そしたら、ちゃんと学習していく。
なかなか収束しないけど、いい方向に向かっている。
と、いうことは出力層の学習コードに間違いがあるんだろう。
出力層の学習のデバッグが一番長引いた。
なかなか、解決できない。
しかし、中間層だけ学習させればいずれ学習が収束できるところまではわかった。
これは大きな収穫だ。
ただ、出力層の学習が気持ち悪い。
いろいろ、考えてみると中間層の学習で出力層の学習後の重みを使用していたのが原因だった。
出力層の学習前の中間層の重みを使用しなければいけなかったのだ。
これ書いてるところ少なくない?
やっぱり、こういうの最初から作ってみないと理解できないよ。
これで学習が収束するなぁ〜
レッツゴー!
あれ、また、重みがあさっての方向に向いてしまった。
ここからは係数調整だな。
勉強係数が大きすぎるんだろう。
減らしたら学習が収束した。
わぁ〜い!!!
犬猫を50枚ずつを繰り返して重み係数を作成する。
枚数が少ないのはさておき・・・
だいたい、3,800回弱繰り返したところでそこそこ良い係数が出た。
これを元に、別の犬猫画像を10枚ずつ入れてみると・・・
正解率が60%ぐらいと悪い。
なんでだろうと、テスト画像を観てみると・・・
犬の画像でも遠目で見ると人間でも猫に間違えるのがあった。
そりゃ、正解率悪いわ。
チョイスしたデータが悪かった・・・(^-^;