けやみぃアーカイブ

CV勉強中の大学生のアウトプットです

物体検出アルゴリズムSSDで顔検出に挑戦(続き)

このQiitaの記事の続きです。 qiita.com Qiitaのアカウントを2つ登録してると思い込んで片方だけ退会しようとしたら、実際はアカウントは1つでこの記事を書いたアカウントも消えてしまったのでブログ開設してみました。

先に言ってしまうと今回もうまくいなかったけど…その後の試行錯誤について書きたいと思います。

何がダメだったのか

Qiitaの方にも載せましたが、最初に学習させたモデルの結果画像です。

f:id:kym384:20200501074701p:plainf:id:kym384:20200501074659p:plainf:id:kym384:20200501074656p:plain
顔検出結果1
画像はすべて学習データでもあるFDDBデータセットFDDB : Main)のものを使用しています。 他にもいろいろな画像で試してみた結果わかったことは…

  • 1枚目のように顔が大きめに写っている画像は大きな誤差はない
  • 2枚目のように複数人が写ってる画像は全員分検出されていない
  • 3枚目のように小さめの顔が写っている画像はバウンディングボックス(青四角)の大きさ自体は顔と一致しているものの、位置がかなりずれている

ここらへんです。ただ学習自体は損失も下記のグラフのように下がってることから全くの失敗というわけではないと思って、「SSDのネットワークの出力→バウンディングボックスの変換過程が間違っているのではないか?」と考えました。

f:id:kym384:20200501134441p:plain
最初の学習時の損失グラフ
というわけでコードを見直し。今回のコードは最近買ったこちらの書籍のを使わせていただいています。 www.amazon.co.jp 今回は顔検出なので検出する物体のクラス数(本書ではcatやpersonなど20種類)など一部改変する必要があったためコピペしたわけではなく、PyTorchの勉強も兼ねて写経しました。つまり、写す過程でどこか間違ったのだと思いました。

しかしどこにも間違っている箇所は見つからず…。

「わんち見逃してるだけなのか…?」とか思いましたが、ここであることに気づきます。今回僕が勝手に変えたクラス数などの定数に関してはすべて辞書型配列にひとまとめにして、その辞書型配列を全てネットワークの引数として渡して各パラメータを決定させていました。つまり、ここの値さえ変えれば著者の実装と同じものになり、著者が提供してくれている学習済みモデルが使えるはずです。

というわけで学習済みモデルをダウンロードし、中身がOrderedDictという辞書型配列の構造になってるのでキーの文字列を自分のモデルと同じように改変することで自分のモデルで読み込めるようにしました。そして著者がテスト用に使っている画像と同じ画像を入力してみたのがこちら。

f:id:kym384:20200501074707p:plain
馬と人
(面倒くさかったのでクラスによって色を変えるといった処理はしてません。)

バウンディングボックスの位置はしっかりあってます。従って、僕のモデルはSSDの出力がおかしくて、当初考えてたSSDの出力→バウンディングボックスの変換の過程は間違っていなかったことがわかりました。

再学習させる

以上のことからSSDの学習自体がうまくいってないことがわかったので再学習させます。学習に関して、Qiitaの方ではこう書きました。

最適化関数は本書では学習済みモデルを使って転移学習をさせていたためかSGDを使用していますが、ここでは一から学習させるためにAdam(lr=0.0001, beta1=0.9, beta2=0.999)を使用しました。

が、これは嘘っぱちで、本書の方では最初の特徴抽出用のVGG以外はしっかりとHeの初期値で重みを初期化したうえで、SGDを使って一から学習させていました。誤読して申し訳ないです。

本書に従って、再学習の方でも同じパラメータでSGDを使います。(学習データやネットワークの構造は変化させてません。)

あとは、記録用のlossの値について。Qiitaの方ではepochごとの和としたせいで最初の方が馬鹿でかくなっているため、今回はミニバッチごとの平均lossをとることにしました。200epoch回して、グラフはこんな感じ。

f:id:kym384:20200501081346p:plain
損失グラフ

結果

最終的にlossは0.05くらいまで下がり、まあまあいいのでは…?という期待を持ちながらいざ画像を入力…!

f:id:kym384:20200501081745p:plainf:id:kym384:20200501081748p:plainf:id:kym384:20200501081752p:plainf:id:kym384:20200501081755p:plain
顔検出結果2
失敗!!

相変わらず複数人の検出はできてないくせに、ドアップの場合はほぼ完璧です。1枚目とか最初の学習時とほぼ同じだし…。もしかして教師データの変換か損失関数の計算が間違ってる…?(これ以上やるのは面倒くさい…)

SSDって本当はもっと高性能なのに。まあ学習時間増やせばもっとマシにはなるんだろうけど、1日費やしてダメだったので諦めることにします。物体検出ならYOLOとか、顔検出ならMTCNNとかDeep Learningで顔検出する方法は他にもあるし、そのうちどっちも試したいと思います。PyTorchの文法の練習になっただけ良しとさせてください…。