機械学習とかコンピュータビジョンとか

CVやMLに関する勉強のメモ書き。

CornerNet: Detecting Objects as Paired Keypointsを読んだのでメモ.

はじめに

CornerNet: Detecting Objects as Paired Keypointsを読んだのでメモ.

気持ち

現状のアンカーベースのobject detectorは,大量のアンカーを用意する必要があるのとハイパーパラメータが多くなるという課題があるのでそこを解決したいというもの.そこで,物体の左上の座標と右下の座標をヒートマップとして出力するCornerNetを提案.中心座標を回帰する場合は4点分の情報が必要だがcornerなら2点で済むから簡単であるはずという仮説にも基づいているらしい.

CornerNet

CornerNetのメインのアイディアとしてはbounding boxの左上,右下をkeypointsとして,そのkeypointsのペアを物体として検出するというもの.イメージとしてはConvolutional Pose Machine(CPM)などのやり方を応用した感じ.

CornerNetは,左上のkeypointsのheatmapを出力するモジュールと右下を出力するモジュール,その他にkeypointsのペアを決めるのに使う埋め込みベクトルを出力するモジュールとbounding boxを決定する際の補助に使うoffsetを出力するモジュールから成り立つ.

Cornerの検出

Cornerの検出のためのheatmapは,bounding boxの左上,右上それぞれ用意され,各heatmapはクラス数Cのチャネルを持つ.ただし背景クラスのheatmapは無く,各heatmapはcornerが有るか無いかの2値分類器として学習される.このとき,正解のcornerをmapの中の唯一1点として与えるのは当然筋がよく無いので,CPM等と同様アノテーションの座標を中心としてガウス分布に従う広がりを持たせたものを正解として学習する.具体的には\exp\left(-\frac{x^2+y^2}{2\sigma^2}\right)として正解の値を作る.\sigmaは正解の矩形とのIoUから決まる半径の1/3に設定したとのこと.半径は,半径以内に収まる点をcornerとして作った矩形と正解矩形とのIoUがt以上になる様に決められ,実験は[t=0.7]で行ったらしい.

p_{cij}をクラスcのheatmapの(i,j)ピクエルのスコアとして,y_{cij}を正解の値とする.目的関数を以下のfocal lossとして学習する.

\displaystyle
L_{det}=-\frac{1}{N}\sum_{c=1}^C\sum_{i=1}^H\sum_{j=1}^W\left\{\begin{matrix}
(1-p_{cij})^\alpha\log(p_{cij})\:\:\:\mathrm{if}\:y_{cij}=1\\
(1-y_{cij})^\beta(p_{cij})^\alpha\log(1-p_{cij})\:\mathrm{otherwise}
\end{matrix}\right.

Nは画像中の物体の数で,\alpha,betaはハイパーパラメータで\alpha=2,\beta=4で実験を行なったとのこと.

基本的にCNNは空間方向の情報の集約と計算コストの削減のためにpoolingの様なdownsamplingの操作が入り,出力は元画像より小さくなる.すなわちdownsamplingのスケールをnとすれば出力の空間方向のサイズは(\lfloor\frac{x}{n}\rfloor,\lfloor\frac{y}{n}\rfloor)となる.そのため,heatmapからbounding boxを作り出して元の画像の座標値に直す際に多少なり精度が落ちる.この精度の劣化は小さい物体ほど顕著に現れるため,こんお問題を解決するために,次の様なlocation offsetsの推定を行う.

\displaystyle
\mathbf{o}_k=\left(\frac{x_k}{n}-\lfloor\frac{x_k}{n}\rfloor,\frac{y_k}{n}-\lfloor\frac{y_k}{n}\rfloor\right)

\mathbf{o}_kがoffsetでx_k,y_kは推定されたcorner kのx,y座標.heatmapはカテゴリごとに出力されるのに対し,このoffsetはカテゴリ関係なく一つのcornerに対して1つ出力される.学習は次のsmooth L1 Lossによって行われる.

\displaystyle
L_{off}=\frac{1}{N}\sum_{k=1}^N\mathrm{SmoothL1Loss}(\mathbf{o}_k,\hat{\mathbf{o}}_k)

Cornerの統合

一般的に一つの画像に対し複数の物体が存在しているため,cornerも複数検出される.そのため,左上のcornerと右下のcornerのペアを決定しなければならない.そこで,各cornerごとに埋め込みベクトルを出力させ,その埋め込みベクトル間の距離を使ってグルーピングを行う.

e_{t_k}を物体kの左上のcornerのembedding,e_{b_k}を右下のcornerのembeddingとする.embeddingの次元は1次元とし,学習には次の"pull" lossと"push" lossを使った.

\displaystyle
L_{pull}=\frac{1}{N}\sum_{k=1}^N\left[(e_{t_k}-e_k)^2+(e_{b_k}-e_k)^2\right]\\
L_{push}=\frac{1}{N(N-1)}\sum_{k=1}^N\sum_{j=1\\j\neq k}^N\max(0,\delta-|e_k-e_
j|)

e_ke_{t_k},e_{b_k}の平均で\deltaは1に設定したとのこと.

Corner Pooling

Cornerを使った検出の課題として,斜めに置かれた棒などの矩形を出す際に,cornerの付近に検出対象の物体が写ってなくてcornerを推定するための根拠がない場合がある(論文Fig. 2参照).なのでcornerを決めるためには水平方向,垂直方向の情報を集約する必要があるため,ここではそれを実現するためにcorner poolingを提案する.

f_t,f_lをtop-left corner pooling layerの入力の特徴マップとし,f_{t_{ij}},f_{l_{ij}}f_t,f_l(i,j)ピクセルのベクトルとする.H\times Wの特徴マップが与えられたとき,corner pooling layerは(i,j)から(i,H)(i,j)から(W,j)の間でmax-poolをする.これは次の様に表現できる.

\displaystyle
t_{ij}=\left\{\begin{matrix}
\max(f_{t_{ij}},t_{(i+1)j})\:\mathrm{if}\:i\lt H\\
f_{tH_j}\:\:\:\:\:\mathrm{otherwise}
\end{matrix}\right.\\
l_{ij}=\left\{\begin{matrix}
\max(f_{l_{ij}},l_{i(j+1)})\:\mathrm{if}\:j\lt W\\
f_{l_iW}\:\:\:\:\:\mathrm{otherwise}
\end{matrix}\right.

Bottom-right cornerに関しても(0,j)から(i,j)(i,0)から(i,j)間のmax-poolとして同様に定義ができる.

学習について

モデルの構成については省略.簡単にはbackboneにhourglass networkを使い,出力のブランチは論文Fig. 7にのってる.

入力画像の解像度は511\times511で出力の解像度は128\times128.データ拡張として,random horizontal flipping, random scaling, random cropping and random color jitteringを使用.検出で使われる一般的な拡張方法.最適化はAdamを使い,以下のコスト関数を最小化する様学習.

\displaystyle
L=L_{det}+\alpha L_{pull}+\beta L_{push}+\gamma L_{off}

\alpha,\betaは0.1で\gammaは1に設定.\alpha,\betaを1以上にすると性能が低下するらしい.バッチサイズは49で500k iteration学習.学習率は2.5\times 10^{-4}から始め,250k回学習した段階で2.5\times 10^{-5}に減衰させる.

まとめ

SoTAモデルと比較して精度はほぼほぼトップ.個人的にdenseなシーンでどれくらい機能するか気になるところ.一般的な検出器はdenseなシーンだとNMSで矩形が統合されて検出率が落ちるけどこっちはこっちでcornerが統合されてダメになるのかどうか.とは言え物体検出の論文で久しぶりに大きな変化があった気がする.