物体認識論の課題を解くために
はじめに
こんにちは。マエカワと申します。
自分も取っている「物体認識論」という講義。MATLABを使って画像認識をしていく講義なのですが、その途中で出てくる、そして最終課題でも必要になってくるBag of Featureという考え方がとても分かりにくい。講義は毎回聞いてはいるのですが、とにかく分かりにくい。演習中にどんどん説明しちゃうもんだから、「聞く」と「プログラムを書く」を同時にできない人にとってはとても厳しいものがあります。
なので、今回BoF周りの考え方を一気に備忘録として書いていきたいと思います。難しいプログラムはなるべく書きません。概念だけ、理解の仕方だけふわっと書いていくつもりです。
それでは、お付き合いのほどよろしくお願いします。
以下、今回の目次です。順番に理解できるように書いていきますが、「こんなのもうわかってんだよ!」という方は目次のコンテンツをクリックして該当箇所に飛んでください。
CodeBook
BoFが何なのかを書く前に、まずはすべての根幹であるCodeBookについてです。これが理解できてないと、始まらない。
CodeBookですが、簡単に言ってしまえば「辞書」です。CodeBookの各列ベクトルが一つのカテゴリ(単語)を表していて、中に入っている値がそのカテゴリの特徴量(意味)を表しています。絵で描きましょう。
講義ページに書いてあるサンプルコードの最後でK-meansを適用しているのも、画像から得られたSIFT特徴量をカテゴライズするためだと考えれば自然です。
では、CodeBookのサイズ(列サイズ)とは何なのか。ここまで理解できれば、「単語の数」だということが理解できます。得られた大量の情報を何個の単語に分けるのか。このサイズが大きいほど、より正確なCodeBookが出来上がります。計算時間は半端ないですが。
ちなみに、CodeBookの行サイズは128です。これは、SIFT特徴量が一つにつき128次元のベクトルで出てきたことが関係しています。ただ、ここでは「単語一つにつき128個のパラメータがあるんだな」くらいに思っておいてください。
ここまでで覚えておくことは、
- CodeBookは辞書
- 列のサイズは「単語の数」
- 行のサイズは128
ということくらいです。
Bag of Feature
大本命のBoFです*1。まず最初に、一つの画像についてのBoFベクトルを手に入れるためのフローチャートを書いてみましょう。
- 「1×CodeBookのサイズ」の零ベクトルFを作る
- 画像ImgのSIFT特徴量を手に入れる
- SIFT特徴量一つとCodeBookを比べて、一番似ているところのインデックスidxを手に入れる
- F[idx]の値を1増やす
- 3. 4. を画像のSIFT特徴の数だけ繰り返す
最終的に手に入るのは「1×CodeBookのサイズ」のベクトルです。絵に描いてみましょう。
3番目の処理で列ベクトルどうしを比べることができるのは、CodeBookの行サイズとSIFT特徴量の行サイズがともに128だからですね。
課題ではこれを100枚、200枚の画像を使い、得られたBoFベクトルを転置して結合しました。その結果「CodeBookのサイズ×画像の数」のBoFベクトルを作り上げたわけです。
ここまで理解できれば、NN法、NB法の理解も速いはずです。
NN法、NB法に進む前に
これからNN法やNB法で未知の画像を分類していくわけですが、未知画像の何をもって比較していくのかという話をここで書いていきます。上で、「一つの画像についてのBoFベクトル」を手に入れるための方法を書きました。まさにこのフローチャートを未知画像に適用してあげればいいんです(2つ前の画像のフローチャートを未知画像にやっていきます)。
手に入った「1×CodeBookのサイズ」のベクトルと、BoFベクトルをNN法、NB法それぞれの方法で評価して、適応度の高い画像を選ぶという感じです。
講義課題では「簡単のため」と称して、学習に使った画像データを再分類しているのでわかりにくくなったのかもしれません。
Nearest Neighbor 法
NN法は、あらかじめ手に入れてあるBoFベクトルのうち、最も未知画像のBoFベクトル(1行のやつ)と似ているものを一つ選ぶという処理をしています。絵で描きましょう。
Naive Bayes 法
NB法は、迷惑メールを分類するところなどで使われています。確率計算が入ってくるので少し手間取るかもしれませんが、本質は簡単です。まずは、学習データの取得について順を追って書いていきます。
- ポジティブ・ネガティブ画像ごとにBoFベクトルを手に入れる
- 各要素に1を加える
- ポジティブ・ネガティブごとにBoFベクトルの行ベクトルの値をすべて足し合わせ、「CodeBookのサイズ×1」のベクトルを手に入れる
- 得られたベクトルの総和でもって各値を割る(これで、各要素の合計値が1になります/正規化)
- 全ての要素にlogをはかせる
ここまでで、学習は終了です。得られた二つのベクトルには、各カテゴリ(これはCodeBookのとき出てきたカテゴリです)に属する確率がlogをはいた状態で入っています。今度は、未知画像の処理です。
- 未知画像からBoFベクトル(1行のもの)を手に入れる
- 転置する
- 値が0以上の要素のインデックスを手に入れる
- 得られたインデックスと対応する、ポジティブ・ネガティブ各学習ベクトルの要素を足し合わせる(logをはいてるからできること)
- ポジティブ・ネガティブから出てきた値を比べる
- 大きいほうのカテゴリに分類
これで、未知画像を分類することができました。文字だけだとつらいので、絵に描いてみましょう。
こんな感じ。講義での方法では未知画像のBoFベクトルに少しでも値が入っていたら、学習データの確立を足し合わせています。未知画像のBoFベクトルについても正規化をして、頻度に関して分類していくともう少し高い精度が出るかもしれませんね。
メールの分類では、このポジティブネガティブが「スパム」「大学」「就活」などいろいろなカテゴリに分かれています。ですが、カテゴリが増えてもやることは同じなので何も怖くありません。学習ベクトルを出して、未知画像のBoFベクトルに応じて足し合わせていく。最終的に大きい値が出たものに分類。この流れがNB法です。
最後に
ここまで見ていただいてありがとうございます。自分なりに解釈して書いてみたので、専門の方が見たら「何だこいつ、ふざけているのか」とおしかりを受けてしまいそうです。自分も理解が追い付かず、右往左往していたのでご容赦いただきたいものです。コメントに「ここはこうじゃね?」とか書いていただくと、自分へのフィードバックになりとてもありがたいです。
MATLABでコードを書くにしても、仕組みが分かっていなければ何も始まりません。詰まっている人がコードを書く上での助けになってくれれば幸いです。それではこの辺で。
読んでいただいた方に感謝を
マエカワ
*1:課題ではいきなりBoFWという新しい知識が出てきて、思わずIEDのパソコンをたたきたくなりました。