# Object Detection - RetinaNet
> [name=謝朋諺(Adam Hsieh)]
> [time=Fri, Mar 13, 2020 12:01 PM]
###### tags: `paper`
---
## Reference
> [[翻译] RetinaNet: Focal Loss for Dense Object Detection](http://www.mclover.cn/blog/index.php/archives/375.html)
> [RetinaNet论文理解](https://blog.csdn.net/wwwhp/article/details/83317738)
> [物件偵測 - RetinaNet 介紹](https://medium.com/@gino6178/%E7%89%A9%E4%BB%B6%E5%81%B5%E6%B8%AC-retinanet-%E4%BB%8B%E7%B4%B9-dda4100673bb)
> [RetinaNet 讀後整理](https://medium.com/@kimujan/retinanet-%E8%AE%80%E5%BE%8C%E6%95%B4%E7%90%86-af821dcd4558)
> [【detectron】RetinNet网络输入理解](https://blog.csdn.net/Mr_health/article/details/84887015)
> [论文解读 | 目标检测 RetinaNet:Focal Loss for Dense Object Detection](http://bbs.cvmart.net/articles/1292)
---
# Focal Loss for Dense Object Detection
[論文連結](https://arxiv.org/pdf/1708.02002.pdf)
{%pdf https://arxiv.org/pdf/1708.02002.pdf %}
## Outline
> [TOC]
## 摘要重點
- 我們發現前景與背景類別有極度的不平衡,這也是造成 one stage 的檢測器檢測不準的原因。
- 解決這類的類別不平衡問題方法是:重新設置標準的交叉熵 loss,以降低分配給分類良好樣本的 loss。
- Focal Loss 僅專注訓練在那些很少但很難被分類的樣本上,以防止大量且容易分類的負樣本主導了檢測器的訓練。
- 我們最好的模型基於 ResNet101-FPN 的 backbone,在 COCO test-dev 上取得 39.1 AP 的成績,但只有 5 fps 的速度。
## Focal Loss
- Focal Loss 旨在解決 one-stage 物體檢測情況,在這種情況下,訓練期間**前景**和**背景**類別之間存在極大的不平衡(例如 **1:1000**)。 我們從二元分類的交叉熵(CE)損失開始介紹 Focal Loss:$$CE(p,y)=\left\{
\begin{array}{cc}
-log(p) & if\ y=1\\
-log(1-p) & otherwise. \\
\end{array}
\right.$$
上面的 $y\in \{\pm1\}$ 代表真實的類別,而 $p\in[0,1]$ 則是模型預測 $y=1$ 的機率,定義為:$$p_t=\left\{
\begin{array}{cc}
p & if\ y=1\\
1-p & otherwise,
\end{array}
\right.$$
可表達成 $CE(p,y)=CE(p_t)=-log(p_t)$
:::success
:notebook_with_decorative_cover: 舉例(來自[物件偵測 - RetinaNet 介紹](https://medium.com/@gino6178/%E7%89%A9%E4%BB%B6%E5%81%B5%E6%B8%AC-retinanet-%E4%BB%8B%E7%B4%B9-dda4100673bb)):
- 假設目前有 1 個前景被分類為前景的機率是 0.8,100 個背景中每一個背景被分為前景的機率為 0.01,則 $$loss=-log(0.8)+100\times (-log(1-0.01))=0.53339055325$$
- 假設有 1 個前景,並且偵測前景的機率上升到 0.9 $$loss=-log(0.9)+100\times (-log(1-0.01))=0.4822380308$$
- 假設有 1 個前景,並且偵測前景的機率下降到 0.7 $$loss=-log(0.7)+100\times (-log(1-0.01))=0.59138250023$$
- 假設前景偵測為前景的機率不動,但是背景偵測為前景的機率改為 0.001 時: $$loss=-log(0.8)+100\times (-log(1-0.001))=0.14036119041$$
- 神奇的是 LOSS 也下降了,這時候就可能發生優化==每個背景預測為前景的機率降低==而已,但這並不是我們想看到的情況。
:::
### Balanced Cross Entropy
- 解決類別不平衡的常用方法就是對每個類別加上權重變數 $\alpha \in [0,1]$,為每個類別加入超參數 $\alpha$,可寫為 $$CE=-\alpha_tlog(p_t)$$ 也可以視為我們 focal loss 實驗的一個 baseline。
### Focal Loss Definition
- 雖然 $\alpha$ 平衡了正/負樣本的重要性,但他並沒有區分簡單/困難的樣本。
- 本文建議重塑 Loss Function 來降低簡單例子的權重,並且著重在較困難的反例,以數學表示就是增加一個調節因子:$(1-p_t)^{\gamma}$ 在標準的 cross-entropy 公式裡面,其中 $\gamma$ 為可調整的焦距參數 $\gamma\geq0$,整個公式可表示為:$$FL(p_t)=-(1-p_t)^\gamma log(p_t)$$

:::info
:bulb: "Focal Loss" 在不同 $\gamma$ 值下的表現。
:::
- 如上圖,在 $\gamma \in [0,5]$,可以發現有兩個性質在 Focal loss 中:
1. 當一個 sample 被分類錯誤且 $p_t$ 很小時,調節因子就接近為 1,因此 loss 不會受到影響;當 $p_t \rightarrow 1$ 則該調節因子變為 0,本來就分很好的例子權重就會被下降。
2. Focusing 參數 $\gamma$ 可以很平滑地降低簡單 sample 的權重,當 $\gamma=0$ 時,Focal Loss 就等於 Cross-Entropy,我們發現 $\gamma=2$ 的時候在我們實驗中效果最好。
- 最終在實務上,我們使用 $\alpha$-balanced 變數在 Focal Loss 中:$$FL(p_t)=-\alpha_t(1-p_t)^\gamma log(p_t)$$
我們發現使用這個 $\alpha$-balanced 之後 Accuracy 有些許提升。
- 另外我們發現最後的 loss 層若能==將計算 $p$ 的結果與 sigmoid 做結合==,對數值有較穩定的表現。
:::success
:notebook_with_decorative_cover: 以上面例子再重算一次:
- 假設目前有 1 個前景被分類為前景的機率是 0.8,100 個背景中每一個背景被分為前景的機率為 0.01,則 $$loss=-(0.2)\times log(0.8)+100\times (-(0.01)\times log(1-0.01))=0.023746808$$
- 假設有 1 個前景,並且偵測前景的機率上升到 0.9 $$loss=-(0.1)\times log(0.9)+100\times (-(0.01)\times log(1-0.01))=0.00894055445$$
- 假設有 1 個前景,並且偵測前景的機率下降到 0.7 $$loss=-(0.3)\times log(0.7)+100\times (-(0.01)\times log(1-0.01))=0.05083539339$$
- 假設前景偵測為前景的機率不動,但是背景偵測為前景的機率改為 0.001 時: $$loss=-(0.2)\times log(0.8)+100\times (-(0.001)\times log(1-0.001))=0.01942545377$$
- 可以看到比起上面未加入 weighting factor,我們這邊會更著重在前景分類機率下降的誤差而不是較簡單的後景分類機率下降的誤差。
:::
### Class Imbalance and Model Initialization
- 在二分類模型的初始化在 $y=1\ \ or\ -1$ 時的機率是相等的,但在這種情況下若資料中存在類別失衡的狀況,頻繁出現的類別會主宰總 Loss。
- 為了解決這問題,便把最後一層用於分類的 CNN 層的 bias 改為 $b=-log((1-\pi)/\pi)$,==使模型對稀有類別的 sample 的估計機率是較低的==,在本文中是設置 $\pi=0.01$。
- 我們發現這可以類別不平等的狀態下提高 Cross-Entropy 和 Focal Loss 的穩定性。
### Class Imbalance and Two-stage Detectors
- 兩階段的 Detector 訓練經常使用 Cross-Entropy 而不是使用 $\alpha$-balance 或是本文提出的 loss。
- Two-stage Detectors 較常使用兩種機制來解決類別失衡的問題:
1. **Two-Stage Cascade**:將無限的物件可能位置限縮到只有 1000~2000 個,而且都是對應於真實的物件位置而非隨機取樣,因而消除了很多簡單 negative 的 sample。
2. **Biased Minibatch Sampling**:通常使用偏差採樣法來創建 minibatch,比例大概會是 1:3,有點類似隱性的 $\alpha$-balance 因子。
- 但在本文透過 **Focal Loss** 可以直接在 One-Stage 中就解決這個問題。
## RetinaNet Detector
- RetinaNet 是一個聯合網路,由 ==Backbone== 以及一個==分類==子網路跟一個 ==BBOX 位置回歸==子網路所組成。

:::info
:bulb: One-Stage 的 RetinaNet 架構
- 在 FPN 網路之上使用 ResNet 架構。
- RetinaNet 在主幹網路外在附加了兩個子網路,一個用於分類 anchor box。
- 另一個負責回歸到標記過的 BBOX。
- 網路刻意設計得比較簡單,這樣就可以專注在 Focal Loss 上。
:::
**Feature Pyramid Network Backbone:**
- 採用 Feature Pyramid Network(FPN) 作為主要骨幹。
- FPN 具有 top-down 的路徑和橫向連接出特徵,因此可以構建一個多尺度的金字塔網路。
- 如上圖所示,我們在 ResNet 上構建一個 $P_3-P_7$ 的金字塔網路,其中 $P_l$ 的 $l$ 指的是在金字塔的第幾個 Level,而每個 Level 都比輸入影像的解析度小 $2^l$。
- 所有的金字塔 Layer 的 Channel 都是 $C=256$ 個 channels。
**Anchors:**
- 本文使用的類似 RPN 變形有平移不變性的 Anchor Boxes,這些 Anchor Boxes 在等級 $P_3$ 到 $P_7$ 的面積是從 $32^2$ 到 $512^2$。
- 在每個金字塔的 Level 下使用三個長寬比 $\{1:2,\ 1:1,\ 2:1\}$,除此之外還另外添加了三個縮放比例 $\{2^0,\ 2^{1/3},\ 2^{2/3}\}$,這樣每層就會==有 9 個 Anchors==,綜合所有 Level 它們覆蓋輸入影像 32 ~ 813 pixels 的範圍。
:::success
:notebook_with_decorative_cover: 來自[【detectron】RetinNet网络输入理解](https://blog.csdn.net/Mr_health/article/details/84887015) 對 Anchor Box 的深度解釋
- 假設以 $P_2$ ~ $P_6$ 的 FPN 網路為例(訓練圖片大小為 $1024\times1024$,其餘參數皆為默認)
| Layer | stride | anchor sizes | anchor 長寬比 | 生成的 Anchor 個數 |
| ----- | ----------- | ------------ | ------------- | --------------------- |
| P2 | 4 ($2^2$) | 32 | 0.5, 1, 2 | $(1024/4)^2*3=196608$ |
| P3 | 8 ($2^3$) | 64 | 0.5, 1, 2 | $(1024/8)^2*3=49152$ |
| P4 | 16 ($2^4$) | 128 | 0.5, 1, 2 | $(1024/16)^2*3=12288$ |
| P5 | 32 ($2^5$) | 256 | 0.5, 1, 2 | $(1024/32)^2*3=3072$ |
| P6 | 64 ($2^6$) | 512 | 0.5, 1, 2 | $(1024/16)^2*3=768$ |
- 若以 RetinaNet 的 $P_3$ ~ $P_7$ 為例:
| Layer | stride | scales | anchor_sizes | ratios | 生成的 Anchor 個數 |
| ----- | ---------- | ------------------------------- | ----------------------------------------------------------- | ------------------- | --------------------- |
| P3 | 8 ($2^3$) | $2^0$<br>$2^{1/3}$<br>$2^{2/3}$ | $8*2^0*4=32$ $8*2^{1/3}*4=40.317$ $8*2^{2/3}*4=50.796$ | $1/2$<br>$1$<br>$2$ | $(1024/8)^2*9=147456$ |
| P4 | 16 ($2^4$) | $2^0$<br>$2^{1/3}$<br>$2^{2/3}$ | $16*2^0*4=64$ $16*2^{1/3}*4=80.634$ $16*2^{2/3}*4=101.592$ | $1/2$<br>$1$<br>$2$ | $(1024/16)^2*9=36864$ |
| P5 | 32 ($2^5$) | $2^0$<br>$2^{1/3}$<br>$2^{2/3}$ | $32*2^0*4=128$ $32*2^{1/3}*4=161.268$ $32*2^{2/3}*4=203.184$ | $1/2$<br>$1$<br>$2$ | $(1024/32)^2*9=9216$ |
| P6 | 64 ($2^6$) | $2^0$<br>$2^{1/3}$<br>$2^{2/3}$ | $64*2^0*4=256$ $64*2^{1/3}*4=322.536$ $64*2^{2/3}*4=406.368$ | $1/2$<br>$1$<br>$2$ | $(1024/64)^2*9=2304$ |
| P7 | 128 ($2^7$) | $2^0$<br>$2^{1/3}$<br>$2^{2/3}$ | $128*2^0*4=512$ $128*2^{1/3}*4=645.072$ $128*2^{2/3}*4=812.736$ | $1/2$<br>$1$<br>$2$ | $(1024/128)^2*9=576$ |
- 從上表這邊就可以看出為何他寫到可以偵測的物件 pixels 為 32 ~ 813。
- 另外若把全部的 anchor boxes 數量加總可得到 196,416。
:::
- 每個 Anchor 分配到一個長度為 **K** 的 one-hot 分類向量,以及 4 個回歸框的目標值。
- 將 Anchor 與 Ground Truth 之間的 IOU 超過 0.5 的標記為前景,$[0,0.4)$ 的標記為背景,$[0.4,0.5)$ 則在訓練時忽略他。
**Classification Subnet:**
- 分類子網路預測 $A$ 個 Anchor 以及 $K$ 個類別機率。
- 分類子網路是接在每個 FPN 之後的小型 FCN(Fully Convolutional Network)。
- 分類子網路由 4 個 $3\times3$ 的 CNN 層組合(每個 CNN 層帶有 C 個濾波器並接上 ReLU),緊接著 $KA$ channel 的 $3\times3$ CNN 層,最後用 sigmoid 來輸出每個空間位置的 $KA$ 的二元預測。
- 在本文中我們使用 $C=256$、$A=9$。
**Box Regression Subnet:**
- 與分類子網路前面相同一樣有 4 個 $3\times3$ 的 CNN 層組合,但在最後是輸出 $W*H*4*A$ 的 CNN 層,表示共有 $W*H$ 個 anchor point,一個 anchor point 有 $A$ 個 anchor box,而 4 個輸出是預測 anchor point 和實體框之間的相對偏移量。
### Inference and Training
**Inference:**
- 由 ResNet-FPN 主網路、一個分類子網路和一個 BBOX 回歸子網路所組成。
- 為了加快速度,我們將檢測器的信心閾值設為 0.05 之後,只解碼每個 FPN Level 中最多 1000 個分數最高的 BBOX。
- 最後對所有結果進行 NMS ($\geq 0.5$)
**Focal Loss:**
- 我們發現 **Focal Loss** 中的 $\gamma=5$ 效果是最好的,而且從實驗中還發現當 $\gamma\in[0.5,5]$ 擁有很強的穩定性。
- 訓練時 Focal Los 直接應用到所有 ~ 100 anchor 中,最後將所有的 Loss 相加再除以正樣本的數量來進行標準化。
- 這邊之所以不除以 anchor 數量,是由於大部分的 BBOX 都是易負樣本,而且在 Focal Loss 上這些樣本只會產生極小的 Loss 值,所以可以忽略不計。
**Initialization:**
- 本文使用 ResNet-50-FPN 和 ResNet-101-FPN 當作骨幹做實驗,兩者皆在 ImageNet1k 上做過預訓練。
- 新增的 FPN 層則由 FPN 論文中的方式進行初始化。
- 除了RetinaNet 子網路的最後一層,其他所有新增的層都採用 $\sigma=0.01$ 的高斯分佈和 $bias=0$ 來進行初始化。
- 子網路的最後一層 CNN,我們設置初始權重仍然是高斯分布的 $\sigma=0.01$,但在 Bias 則設為 $bias=-log((1-\pi)/\pi)$,在所有實驗 $\pi$ 都設為 $0.01$,原因如前面提到的,這樣背景就會輸出很小的 Loss,前景會輸出很大的 Loss,從而阻止背景在訓練前期產生巨大的干擾 Loss。
**Optimization:**
- 使用 SGD 進行訓練,並且同時使用 8 張 GPU 對一個 minibatch 16 張圖片進行訓練,也就是每張卡跑 2 張圖片。
- 所有模型都使用初始 Learning Rate 為 0.01。
- 共跑 90K 次的訓練,並在 60K 和 80K 週期時進行 10 倍的 Learning Rate 下降。
- Image Augmentation 只做水平翻轉。
- Weight Decay 為 0.0001,momentum 為 0.9。
- 訓練 Loss 是 ==Focal Loss== 和 ==BBOX 標準 $L_1$ smooth 回歸 Loss== 的總和。
- 訓練時間大概是 10 - 35 小時。
## Experiments
- 使用 COCO Dataset 做實驗,用 *COCO trainval35k* 做訓練跟驗證,其中 *80k* 為訓練,*40k* 的驗證資料有 *35k* 做驗證,另外 *5k* 來坐後面實驗研究,但對於本文的主要結果,是使用 *COCO test-dev* 來做的。
### Training Dense Detection
- 對於所有實驗都使用帶有 FPN 的 ResNet-50 與 ResNet-101 來做實驗。
- 對於所有模型的簡化實驗都是使用 600 pixels 的影像大小來訓練或測試。
**Network Initialization:**
- 我們一開始有嘗試使用標準的 Cross-Entropy 來訓練,但這方法很快就失敗了,網路無法在訓練時收斂,但若簡單地在最後一層加上先驗機率 $\pi=0.01$,這個初始化方法就能使 ResNet-50 在 COCO 上生成 30.2 的 AP。
**Balanced Cross Entropy:**
<div style='text-align:center'>
<img src='https://i.imgur.com/wv1mKwg.png' width='50%'>
</div>
- 下一個嘗試就是增加了 $\alpha$-balanced 的 Cross-Entropy Loss,在 $\alpha=0.75$ 的時候可以比原本高 0.9 的 AP 值。
**Focal Loss:**

<div style='text-align:center'>
<img src='https://i.imgur.com/RzxSRd1.png' width='50%' >
</div>
- Focal Loss 引入了 Focusing parameter $\gamma$ 來調整關注的程度,如果 $\gamma=0$ 就等同於 Cross-Entropy,如上表,在 $\gamma=2$ 時可以提升 2.9 AP。
- 在上表的實驗可以發現找到較高的 $\gamma$ 所搭配的最佳 $\alpha$ 都會比較小。
**Analysis of the Focal Loss:**

:::info
:bulb: model 對不同 $\gamma$ 值的表現,左邊是前景右邊是背景。
- 對於 Positive 例子,更改 $\gamma$ 值對 loss 分佈影響很小。
- 對於 Negative 例子,增加 $\gamma$ 值會使 loss 集中在困難的例子上。
:::
- 我們使用默認的 600 pixels 作為輸入,$\gamma=2$ 訓練出的 ResNet-101 模型來做實驗。
**Online Hard Example Mining (OHEM):**
- OHEM 用於優化 two-stage 檢測器的訓練,經過計算 Loss 值後使用 NMS,再挑選 highest-loss 樣本組成 minibatches,其中 NMS 的閾值與 batch size 都是可以調整的。
- 在 minibatch 中保持正負比 $1:3$,結果如下表。
<div style='text-align:center'>
<img src='https://i.imgur.com/5cuJhKu.png'>
</div>
- 不管怎麼樣他的效果都沒有 Focal Loss 好,因此 Focal Loss 更適合用於 Dense Detector。
**Hinge Loss:**
- 我們也曾經嘗試對 $p_t$ 使用 Hinge Loss,對 $p_t$ 值大於某個閾值的樣本 Loss 值設為 0,但訓練過程不穩定,因此也未使用。
### Model Architecture Design
**Anchor Density:**
- 由於 Two-Stage 的檢測器可以通過 Region Pooling (ROI Pooling) 對邊框的任何位置、尺寸、長寬比歸類。
- 而 One-Stage 檢測器最重要的設計主軸之一應該就是 Anchor 的密度,該用多少的 Anchors 來覆蓋不同的尺寸和長寬比。
<div style='text-align:center'>
<img src='https://i.imgur.com/osmNBGL.png'>
</div>
- 如上表所示,大概在 2 種 scale 跟 3 種長寬比效果是最好的,再多也不會更好,這也意味著已經飽和了。
**Speed versus Accuracy:**

- 較大的 Backbone 的確會有較準的準度,但也會耗費更多時間,如上表所示。

:::info
:bulb: COCO test-dev 上的速度與 AP 結果比較。
- 由於有 Focal Loss 因此可以簡單地使用 one-stage RetinaNet Detector 來超越其他 one-stage 或 two-stage model。
- 我們以五種不同比例 (400-800 pixels) 的 ResNet50-FPN (藍色圓形),以及 ResNet101-FPN (橙色菱形)來做比較。
:::
- 從上面圖表中可看出我們的 RetinaNet 是超越目前現有方法的上限打破低精度的限制。
- ResNet101-FPN 在 600 像素中的準確度與 ResNet101-FPN Faster R-CNN 差不多,速度上來說 Faster R-CNN 大概在 172 毫秒,但 RetinaNet 可到 122 毫秒 (Nvidia M40 GPU)。
- 使用更大比例尺,RetinaNet 可以超越所有 Two-Stage 得 model 的準確度且還更快。
- 如果為了要更快地運行,ResNet50-FPN 只有在 500 pixels 的時候勝過 ResNet101-FPN。
### Comparison to State of the Art

:::info
:bulb: Object detection single-model 在 COCO test-dev 結果
- 上面的 model 是使用 RetinaNet-101-800。
:::
- 上表的模型比前一節表格的 model 更長了 1.5 倍,但獲得了 1.3 AP 的改進。
- 若把 Backbone 更換為 ResNeXt 可以在往上調升 1.7 AP,超過 40 的 AP 值。