ナニゴケをアップデートしました (Ver. 1.10.0)
ナニゴケのNNを新しくしました。
ナニゴケ – 苔の種類を判別するWEBアプリ
https://www.nanigoke.net/
今回は、判別可能な種に、「キンシゴケ」、「ススキゴケ」、「ヒメタチゴケ」、「ヒメハイゴケ」、「ミヤマハイゴケ」が追加されました。32000枚だったTrainのデータ数は、36000枚になっています。TensorFlow.jsも最新のバージョンにしておきました。
今回は、それ以外にもいくつかの大きな変更を行いましたので、以下だらだらと書いていきます。
その1。今までは、全面1回、辺の長さ90%で中央1回、辺の長さ80%で一番左上、右上、左下、右下の4回の計6回のpredictの出力を平均して、それをユーザに見せていました。それを今回は、全面を何もしない、左右フリップ、90度回転、270度回転の4回、辺の長さ75%で一番左上、右上、左下、右下の4回、辺の長さ50%で一番左上、右上、左下、右下の4回の計12回としました。また、今までは出力を平均するときに、predictに使用した範囲の「面積(辺の長さ^2)の比」で加重平均していたのですが、これを「辺の長さ^1.5の比」で加重平均するようにしました。狭い範囲でpredictした結果を、今までよりは重視するということです。さらにここまでのことに関連して、predictの回数が増えて重くなったことを緩和するために、NNへの入力の解像度を268×268から236×236へと少し落としました。細部を見ないと判別するのが困難な蘚苔類で、入力の解像度を大きく下げるのは、基本的に私はとても危ないと思っているのですが、今回は、辺の長さ50%というかなり狭い範囲でのpredictを追加しましたので、実質的には今までと同じか、もしくは少ししっかりと細部を見るようになっていると思います。細かい話ですが、今回のこういった変更が可能なように、学習データを作る部分(もう一番分かりやすいところでは、写真の撮り方)でもいろいろ対応をしています。
その2。NNの入力直後の畳み込みを何回か重ねてからAverage Poolingで1/2にダウンサイズしていた箇所に並行して、先にAverage Poolingで1/2にダウンサイズしてから畳み込みを何回か重ねるパスも用意して、後ろで合流させるようにしました。高周波成分を少しとばしてから見てみることも必要かということで、ほんのりOctConv風味、1×1のConv/3×3のConv/2×2のSENet/1×1のSENetの一番真ん中を補完するイメージでもあります。上にも少し書きましたが、蘚苔類の画像分類はもうこれ以上は無いのではと思えるぐらいに、「テクスチャだけ見とけばいいんだよ」なタスクだと私は感じていますが、それはロスなどの数字を改善することだけを目的とした場合に顕著なだけで、実際にユーザが使ってくれる時のことを考えると話はそこまで単純ではありません。ナニゴケみたいなサービスは、「正解したら100点、不正解なら0点」ってことはなく、判別を間違えた時も、その後、ユーザが図鑑を見たりとか他の人に聞いたりとかアクションがあって、そのアクションに良い影響のあるアウトプットをしないといけないと思います。ところが、ナニゴケの間違え方を見ていると、「本当に本当にテクスチャだけしか見てないのね…」って言いたくなるようなことが多くて、これは一般的な人間の感覚とはかなり異なるので、ユーザからナニゴケが間違った理由を推測しづらい。そして、結果的にそれは使いにくいってことになると思います。と言った考えがあるので、数字が悪くならない限り使いたいと思っていたネットワークの構成の変更だったのですが、パラメータが増えたからかなんなのか、数字も少し良くなりましたので迷わず採用しました。また、これに関連して、Data Augmentationで少しぼかしを掛けるようにしました。これはもっと早くやっとけば良かった… なぜだか少し重すぎるような気がしていたのですが、当然ながら別にいうほどではなかったです。
その3。NNの学習時に、今現在119ある「ナニゴケで判別することができる特定の種」を、3%の確率で「このWEBアプリでは未分類の苔」として学習することにしました。ユーザが実際にナニゴケを使ってくれた時に、かなりの確率でそれはナニゴケでは判別できない種であることがあるはずなのですが、今までのNNでは、なかなか「このWEBアプリでは未分類の苔」とは答えてくれなかったので、こういう対応になりました。今までもこの問題はかなり気にしていて、もっと小手先の対策をいくつかしていたのですが、それぞれ、改善する程度が小さすぎる、もしくは別の弊害があるなどと思ったので、もう少し真面目にと(「真面目に」って言って嘘を教えるのですが…(笑))、こういう対策になりました。自分自身でも実際にナニゴケを使ってみて、今後はまた、3%という数字を変更していく可能性があります。
その4。学習時の最適化方法として、SGDなSAM(Sharpness-Aware Minimization)を使用しました。そして、劇的に数字が良くなりました(スゴイ!)。ここ最近は、手元のデータに対するロスがもうそれほど大きくはなかったので、あんまり真剣にこの辺りを探ったりはしていなかったのですが、こいつは大きかった… 今後、ナニゴケを続ける中で、学習方法に関するこれ以上おいしい知見が降ってくることはもう無いでしょう。これにて終了って感じです。ASAM(Adaptive Sharpness-Aware Minimization)も試してみましたが、SAMをはっきり超えるハイパーパラメータが見つかりませんでした。でも、もういいです(笑)。
同じようなことを繰り返し繰り返し書くことがこのブログでは本当に多いのですが、学習データを充実させる以外にできることは、もう本当にほとんど無くなったような気がします。仕方ありませんので、バカは無駄に頭を使わずに、二本付いている足で外を歩いてきたいと思います。