ザックリまとめ YOLACT++論文

# YOLACT++論文まとめ
- 本論文は2019年の12月にsubmitされたものです。[ArXivはこちら](https://arxiv.org/abs/1912.06218)
- YOLO(You Only Look Once)という物体認識を高速で行うモデルから派生した、YOLACT(You Only Look At CoefficienTs)の改善モデルです
- Instance Segmentationを高精度かつリアルタイムで行うことができる最初のモデル

![スクリーンショット 2020-01-23 14.32.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391968/110bfcbe-4943-0737-dab6-af3c4f04173c.png)

それでは早速見ていきましょう。(本記事の図は全て該当論文より引用したものです。)

※まとめというよりも、直訳とメモみたいになってしまいました。今後修正する可能性もありますので、ご意見・ご指摘お待ちしております。

# Abstract
- 本論文は畳み込みレイヤをベースにしたリアルタイム(＞30fps)のInstance Segmentationを可能にしました。(Titan Xpを利用)
- 本手法はInstance Segmentation(どのようなタスクかは[こちら](https://qiita.com/chobaken/items/3cb5f43ecff2d388f95b)のHTCというモデルの説明記事にありますので、よかったら見てみてください。)を二つのparallelなタスクに分解しています。
- 二つのタスクとは1)Prototype masksの生成と2)それらの組み合わせ方を学習します。(詳しくは後述)
- この手法は're-pool'をしないので、高品質なマスクを生成することができ、temporal stability for freeです。(temporal stability というのは動画のような連続的な画像群に対するロバストさのようなものだと思います。ROIに大きく依存するTwo-stageに比べて、予測されたボックスが違ってもprototypeに影響しないYOLACTの方がロバストだろう、と結果のところで述べられています。)
- 上記の考えに加えて、Fast-NMS、backboneの畳み込みにdeformable convolutionを採用したこと、損失関数の追加、re-scoring branchの追加なども行うことで精度の向上と高速化を行なっています。

# 補足説明
- 物体検出系列ではOne-stage手法とTwo-stage手法があります。
    - Two-stage手法は物体がありそうな場所(Region Of Interest)を1st stageのモデルが見つけた後に、ROIをクラス・マスクを判断・生成する2nd stageのモデルに流し込む手法です。(この処理は're-pool'と本論文内で呼ばれています。)
- Two-stage手法は、クラス・マスク処理部分の前に「それらしい部分」を判断するため、ROIが正しく得ることができれば、高精度な処理をすることできます。
- それに対して、One-stage手法は、入力画像をグリッドに分割して、検出と識別を同時に行います。're-pool'がSequentialな処理であるのに対して、こちらの処理はparallelです。
- One-stage手法は're-pool'しない分高速ですが、精度は劣ることが多く、またInstance Segmentationへの適用は今まであまり研究されてきていませんでした。
- また、どちらの手法も、入力画像から特徴量を抽出する部分をback boneと呼びます。back boneには色々なモデルを適用することができます。(よく用いられるものとしてはResNetやMobileNetなどがあります。)

物体検出の流れについて、[こちらの記事](https://qiita.com/mdo4nt6n/items/68dcda71e90321574a2b)がわかりやすくまとめていただいています。

# Introduction
- Two-stage手法は、その方法が本質的にSequentialであるため、高速化することが難しく、One-stage手法のInstance Segmentation方法への適用としてFCISというモデルがありますが、この手法は場所検出(localization)の後処理が多いために、処理全体でかかる時間は長くなってしまっていました。
- これらの問題に対応するために、明示的なlocalizationをスキップしたYOLACTを提案します。
- YOLACTは画像全体に対するPrototype maskの生成と、インスタンスごとにそれらのPrototype maskがどれだけ寄与するかを表現する係数の予測によって、画像全体のInstance Segmentationを行います。
- Prototype maskと係数を線型結合し、その出力をcropすることで最終的な出力となります。

![スクリーンショット 2020-01-22 16.25.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391968/b7307355-e16b-5b9b-8f52-7f03a52fcbd8.png)

- Prototype maskの数は分類するクラス数とは独立であり、YOLACTは「それぞれのインスタンスが、全てのカテゴリで共有しているprototypeを、どれくらいの割合で組み合わせるか」という分散表現を学習します。(prototype1を0.3,prototype2を0.7,,,という感じです。この0.3とか0.7がmask coefficientsと呼ばれるものです。)
- この手法は高速・高品質なマスクの生成・generalという三つの利点があります。generalというのは、prototypeを生成し、その組み合わせを学習するというやり方は他の物体検出手法でも応用しやすい、という意味になります。
- 本論文では、YOLACT++としてYOLACTをより改善したモデルを後ほど提案します。変更点としてはbackboneのネットワークにdeformable convolutionの適用することで、より柔軟かつ強力な特徴サンプリングが可能になっています。他にも高速なmask re-scoring branchの追加、FastNMSなどを行い、精度向上・高速化を行なっています。

# YOLACT
ここまでもなんども書いているように、YOLACTではInstance Segmentationを二つのタスクに分解して考えます。
気持ち的には「semantic vector」の生成を得意とする全結合層と「spatial」な特徴を捉えるのが得意な畳み込み層を組み合わせてprototype maskとmask coefficientsを生成します。

## Prototype generation
- prototype generation branch(proto net)はk個のprototype maskを画像全体に対して予測を行います。
- proto netはbackboneとくっつけてあり、最後の層はk個のchannelsを出力するようになっています。

![スクリーンショット 2020-01-22 17.00.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391968/b76b2517-a2c1-48f1-b1ac-58df34802ece.png)

- ここで注意したい点としては、通常のsemantic segmentationのように、prototype maskで損失を計算することはしない、ということです。prototypeに対して明示的には損失を設定しません。
- モデル設計において重要な点としては以下の二点になります。一つはbackboneの深いところを入力に利用すること、二つ目は高解像度のprototypeを生成することです。
- 一点目の利点としては、なんども畳み込みされている深い層は受容野が広く、ロバストなマスクを生成することができます。二つ目の利点としては小さな物体に対しても精度の高い処理ができます。
- protonetの他に重要な点としては、出力の範囲が限定しない(unbounded)ことです。これによりprotonetの自信がよく反映されます(明らかに背景だと思われる部分の検出など)。この点の実装としてReLuかno nonlinearity(シグモイド関数などの非線形関数の未利用)をオプションとして実装しています。本論文では解釈性を高めるためにReLuを採用しています。


## Mask Coefficients
- 典型的な物体検出手法としては、クラス分類をするbranchとバウンディングボックスの4座標を出力するbranchという二つのbranchを持っています。
- 上記の二つのbranchに加えて、YOLACTではmask coefficientsを予測するbranchを持ちます。

![スクリーンショット 2020-01-22 17.19.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391968/ff2deb63-4675-fe48-ed1b-9abd11c24f5b.png)

- 繰り返しになりますが、このmask coefficientsとprototype maskを組み合わせることで最終的なマスクを生成します。

## Mask Assembly
- Instance maskを生成するために、protonetとmask coefficientsを組み合わせます。
- この組み合わせ方としては、線型結合してシグモイドをかけるという処理を採用しています。

![スクリーンショット 2020-01-22 17.24.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391968/2676e685-5c1e-b627-4aef-e1b1d1556ff8.png)

- $P$は$h$×$w$×$k$の行列、$C$は$n$×$k$の行列です。$h,w$はheight,widthで、nはNMSをくぐり抜けたインスタンスの数であり、kはprototypeの数になります。
- この組み合わせ方法はもっと複雑にすることができますが、今回の目的は「高速化」なので、シンプルな実装を採用しました。

### Losses
- このモデルでは三つの損失を利用しています。クラス分類の損失$L_{cls}$と、バウンディングボックスの回帰の損失$L_{box}$、マスクの損失$L_{mask}$になります。マスク損失の計算には、assembleされたマスクと、ground truthのマスク間の、ピクセルごとのbinary closs entropyを計算します。

### Cropping Masks
- evaluationの際には、予測されたバウンディングボックスによってfinal maskをcropします。ボックスの外は０を適用します。
- 学習の際にはground truthのボックスでcropし、prototypeの中の小さな物体を保持するために、ground truthのボックス領域でマスク損失を割ります。(大きい物体ほどピクセル数が多くなるため、マスク損失も大きくなってしまいます。そこでground truthのボックス領域で割ることで、「ピクセルあたりの損失」みたいにして計算を行います。)


## Emergent Behavior(理解しにくかったので直訳)
- 私たちの手法は、驚くべきものです。なぜなら、インスタンスセグメンテーションに対する一般的なコンセンサスとして、FCNsは移動不変であり、タスクは移動vairnceを足す必要があるからです。(移動不変性を獲得するために、学習の際にはvarianceを追加したい、的なことだと思います。移動不変性(translation invariance)というのはある物体に対して、その向きや位置が変わっても同様に識別できることを意味します。)
- FCIS,MaskRCNNといった手法は明示的に移動varianceを足しています。それはdirectional mapsとposition-sensitive repoolingであったり、mask branchをTwo-stageの二段階目に配置することだったりします。そのため、mask branchはインスタンスの場所を特定することをしなくて済みます。(すでに考えるべき場所がROIとしてmask branchには与えられているため。)
- 私たちの手法では、移動varianceを足しているのは、final maskを予測されたバウンディングボックスでcropしているところだけです。
- しかし、私たちの手法はcropを抜いてもうまく動作すること実験からわかったため、croppingによって移動varianceが足されているわけではありません。
- YOLACTは、prototypesの活性の違いから、自分自身でインスタンスの場所特定の方法を学習していると言えます。

![スクリーンショット 2020-01-22 18.02.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391968/ccfb05bc-9d12-ff1c-0f9d-c1c2c7803e13.png)


- どのようにしてこれが可能かを見るために、ただの赤い画像を入力してprototypeのactivationを観察しました。「ただの赤い画像」はパディングなしではFCNで対応できません。
- なぜなら、もし畳み込みの出力がすべての場所で同じならば、畳み込みの出力は一つのピクセルになるからです。
- 一方で、ResNetのようなモダンなFCNsの中での、周縁部の定数パディングは、ネットワークが、「そのピクセルが、周縁部からどれだけの距離にあるのか」を見分ける力を与えます。
- この意味において、ResNetは「本質的に移動variant」であり、私たちの手法はこの性質をレバレッジしています。(図のb,cに対する活性を見るとわかります。)

- 多くのprototypesが、ある特定の'partitions'(区切り)を活性させていることが観察されます。
- これはつまり、prototypesは、対象とする画像の、非明示的な学習された境界の一部のみを活性させるということです。図の1-3がその例です。
- これらの、'partition maps'を組み合わせることにより、ネットワークは同じクラスに属する別のインスタンスを(たとえoverlappingしていても)見分けることができます。図のdの画像をみてください。緑の傘はprototype2からprototype3を引くこと(差分を取ること)で判別されます。

- さらに、学習された物体、prototypesはcompressibleです。(入力画像をコンパクトな量に変更している、ということか)
- これはつまり、もしprotonetが複数のprototypesの機能性を一つにまとめるものであれば、mask coefficients branchはどのシチュエーションにおいて、どの機能性が必要かを学習しているということです。例として、図のprototype2は区切りとしての役割を持つと同時に、左下のインスタンスに対して検出を行うものだとわかります。prototype3はその右側バージョンです。
- これは、実用の際において、モデルのprototypesの数が32という少ない数でも品質が低下しないことを示しています。(prototypesはコンパクトな表現を獲得しているので、少ないprototypesでもモデル全体としては十分な表現力を持つ、ということだと思います。)

- しかし一方で、prototypesを増やすことは多くの場合、非効率的な選択です。なぜなら組み合わせ方(mask coefficients)の予測が難しくなるからです。
- もしネットワークが大きな間違いを犯したとすると、線形活性化関数の性質から、生成されたマスクは消失してしまったり、他の物体からの漏れを含んでしまいます。
- したがって、ネットワークは正しいcoefficientsの予測を調整する役割を果たします。より多くのprototypesを追加することは、この調整を難しくします。
- 事実、実験してみると、prototypesの数が増えるに従い、ネットワークは単純で冗長な(周縁部レベルでの些末な差異を持つ)prototypesを追加することになりました。これは精度を多少は向上させましたが、それ以上のものは得られませんでした。

※この段落の主張としては、「最近のback boneはすでに移動不変性を獲得するための処理が入っているから、既往手法のように明示的に表現しなくていい」というものだと思います。backboneから送られてくる特徴量だけで上手く学習できている、という理解をしています。


# Backbone Detector
今回のモデルにおいて、特徴量抽出を行うbackboneに求めるものは、「良い特徴量」を出力すると同時に、できるだけ高速であることです。今回はRetinaNetを速度面で改善したものを利用しました。
具体的には、FPN構造を持つResNet-101をデフォルトに、RetinaNetを参考にして、モデル内の特徴量マップのサイズの削減などを行なっています。(本筋ではないので詳細は割愛します。)

# Other Improvements
ここでは、精度を大きく下げることなく高速化する手法・速度を遅くすることなく精度を上げる手法について議論します。

## FastNMS
- NMSというのは、はじめに検出された沢山のバウンディングボックスから、良さそうなものを選ぶ処理になります。(冗長性の削減)
- 通常のNMSだと、クラスごとに検出されたバウンディングボックスを、クラスの自信度に降順にソートします。その後、それぞれのdetectionは、IoU overlapが事前に決めた閾値よりも大きい値を持つものよりも小さい自信度のものを取り除きます。(自信度でソートし、IoUがある程度大きいものの自信度を基準にして取り除く)
- このSequentialな処理は高速ではありますが、リアルタイムの実行を目指す場合には大きな障害となります。

- そこで、本論文では全てのインスタンスを取り除くか保持するかを並列に処理する、Fast-NMSを紹介します。
- これを実現するために、すでに取り除かれたdetectiosも利用します。
- Fast-NMSでははじめにIoU行列X($c$×$n$×$n$)を作成します。nはクラスの自信度でソートした時のtop-nです。その後に対応するIoUが閾値よりも大きいdetectionsを全て削除します。(自信度でソートし、IoUを基準にして取り除く。)
- このFast-NMSの計算はシンプルな行列計算で行うことができるので、通常のNMSよりも計算効率が良くなります。
- 上記の計算方法は通常のNMSよりも、やや多くdetectionsを削減します。しかし、速度の上昇に対して精度の減少はそこまで大きくなりませんでした。

## Semantic Segmentation Loss
- Fast-NMSが精度を(多少)犠牲にして速度の向上を図る方法であるのに対し、この工夫は、速度に影響を与えずに精度を向上させる方法になります。
- 具体的には、学習時に考慮する損失を増やすことで、推論の際の速度には影響を与えない、という仕組みになります。
- ここで追加する損失はSemntic Segmentation Lossです。ただし、本論文はInstance Segmentationのタスクからアノテーションを行なったので、ground truthは厳密なSemantic Segmentationになっていないとのことです。(we do not enforce the standard one class per pixel)
- Semantic Segmentationを予測するために、学習の際は1×1でc channelの出力をする畳み込みを、backboneの最も大きな特徴量マップに直接追加しています。
- それぞれのピクセルは複数のクラスに分類されることが考えられるので、c channnelsそれぞれにシグモイド関数を適用しています。(c+1のソフトマックスだと、全クラス＋背景で正規化してしまう)


# YOLACT++
YOLACTはリアルタイムでInstance Segmentationを行うことができる優れたモデルですが、これをさらに向上させるために、いくつかの改善を施しました。

## Fast Mask Re-Scoring Network
- 既往研究(Mask Re-Scoring RCNN)で示唆されているように、モデルのクラスの自信度とマスクの品質には大きな隔たりが存在します。(高品質なマスクが必ずしもクラスの自信度が高くなくても良い)
- そこで、クラスの自信度とマスクの品質をより強く結びつけるような工夫を追加します。Mask Re-Scoring　RCNNでは予測したマスクと、そのマスクのground truthのIoUで回帰するモジュールを追加しています。
- 本論文では、予測されたマスクを、それらのground truthのIoUに基づいてrescoreするbranch(fast mask re-scoring branch)を追加しました。

![スクリーンショット 2020-01-23 13.52.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391968/5dde5680-5aca-daa8-d908-ade35bac65ff.png)

- 上記画像のように、このbranchはYOLACTの出力したcropped maskを入力にもち、それぞれの物体のクラスに対するmask IoUを出力します。
- そして、この予測されたmask IoUと対応するクラスの自信度を利用してre-scoringします。
- このbranchと既往研究の差として、1)入力がROIではなく、maskのみを利用していることと2)全結合層を持たないという点です。これらによって高速な処理が可能になっています。


## Deformable Convolution with Intervals
- Deformable Convolutionは畳み込みをかける位置も学習させる手法であり、柔軟な畳み込みが可能になります。
- Deformable Convolutionは通常の畳み込みよりも表現力が高いですが、その分速度は劣るため、backboneの全ての畳み込みをDeformableにするのではなく、特定の層だけを変更しています。

※Deformable Convolutionに関しての日本語資料として、[こちらのスライド](https://www.slideshare.net/YosukeShinya/active-convolution-deformable-convolution-convolution)が詳しいです。

## Optimized Prediction Head
- YOLACTはanchor-based backbone detectorに基づいているので、anchorのスケールと縦横比は重要なハイパーパラメータになります。
- 本論文では二つのバリエーションを試しています。1)スケールを固定し、縦横比を変更する([1,1/2,2]から[1,1/2,2,1/3,3]へ変更。)、2)縦横比を固定し、FPNに合わせてスケールを変更する([1x]から[1x,2x,3x]へ変更。)という二つです。それぞれ試してみたところ、multi-scale anchors per FPN(後者の変更)が精度と速度のトレードオフにおいて最適だったそうです。

## Results
結果の詳細は実際に論文を見ていただくのが良いと思いますので、冒頭に載せた特徴的なグラフのみ再度引用します。

![スクリーンショット 2020-01-23 14.32.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391968/110bfcbe-4943-0737-dab6-af3c4f04173c.png)

めっちゃ速い...

肝心の精度はと言うと...
![スクリーンショット 2020-01-23 14.38.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391968/366401a3-7c11-e767-85cc-1226eafa7feb.png)

こちらもパッと見は問題なさそうです。


# 感想・まとめ
- Instance Segmentationをprototypesの生成と、それぞれの重みの予測の二つのタスクに分解すると言うのは汎用性高そうだと思いました。
- 論文内でも述べられているように、モデル自体はシンプル(特にprototypesと重みの組み合わせ方)なので、ここをいじるともう少し違う結果・議論が出てくるのかなと思います。