# End-to-End Object Detection with Transformers
## 前言
- 使用transformer端到端的目標檢測,在以前的大多數detection model,最後都會需要過一個nms(非極大值抑制),因為他們都會生成很多預測框,所以要通過nms去除那些框,且nms也不一定在所有硬件都支持,所以一個端到端的系統是很重要的,這篇論文直接利用transformer全局建模的能力,把目標檢測看成一個集合預測的問題,不會輸出很多多餘的框
## 摘要
- 提出了一種將目標檢測視為直接集合預測問題的新方法。我們的方法簡化了檢測流程,有效地消除了許多手工設計的組件的需求,如非極大值抑制程序或錨點生成,這些組件明確地編碼了我們對任務的先驗知識
- 提出
- 提出了新的損失函數,通過二分圖匹配的方式,能夠強制模型輸出獨一無二的框
- 提出一個變換器編碼器-解碼器架構。給定一組固定的學習目標查詢,DETR通過推理對象之間的關係和全局圖像上下文,直接並行地輸出最終的預測結果(這邊因為是用decoder,並不需要做掩碼,所以是一次把所有框預測出來,並沒有順序問題)
- 在coco數據集與經過充分優化的Faster RCNN基線相當的準確性和運行時性能,但在當時目標檢測上,並不是最好的,甚至差了10個百分點,但想法很好,解決目標檢測很多的問題
- 在全景分割上,取得很好績效
## 介紹
- 物體檢測的目標是為每個感興趣的物體預測一組邊界框和類別標籤。現代檢測器以間接的方式解決這個集合預測任務,通過在大量的建議、錨點或窗口中心上定義代理回歸和分類問題,這些都沒有直接去做集合預測的任務,它們的性能受到後處理步驟的顯著影響(nms)
- 提出了一種直接的集合預測方法,以繞過代理任務

- 簡單來說
- 先用cnn抽出特徵圖
- 把它拉直,送進一個transformer架構,進一步學習全局信息
- 因為透過transformer全局建模的特徵,每個pixel都會跟所有其他pixel進行交互,也就是說,只會出一個框,不需要進行大量框的生成
- 這邊還有一個object query,也就是說,當有了圖像的特徵之後,還需要一個object query去限定要出幾個框,然後通過object query跟特徵圖進行大量交互,從而得到最後的框,這篇論文object query是100
- 匹配
- 透過二分圖匹配方法去計算loss,一旦決定好匹配關係之後,才會去計算分類跟bbox的loss
- 推理的時候就不必要去做二分圖匹配,直接用一個threshold去卡(置信度0.7),就可以了
- 模型大小跟速度跟faster-rcnn差不多,但雖然AP差不多,但是DETR對大物體的AP跟小物體的AP差很多,DETR對大物體表現好很多,這是歸功於transformer全局建模的能力,這樣無論物體有多大,都可以檢測出來,如果使用anchor的話,就會受限於anchor的大小
- DETR訓練時間特別慢,想要達到很好的效果需要訓練500個epoch,對於coco來說,通常只需要訓練幾個epoch
- DETR的設計理念可以輕鬆擴展到更複雜的任務。在我們的實驗中,我們展示了在預訓練的DETR之上訓練的簡單分割頭部,在全景分割[19]這項具有挑戰性的像素級識別任務上,表現優於競爭性基線
## 物體檢測
- 大多數現代物體檢測方法都針對一些初始猜測進行預測:
- 兩階段檢測器[37,5]針對建議預測框
- 單階段方法則針對錨點[23]或可能的物體中心網格[53,46]進行預測
- 最近的研究[52]表明,這些系統的最終性能在初始猜測的確定方式上有很大的依賴性
- 循環檢測器。與我們的方法最接近的是用於物體檢測[43]和實例分割[41,30,36,42]的端到端集合預測。與我們類似,它們使用了基於CNN激活的編碼器-解碼器架構,並使用二部匹配損失來直接生成一組邊界框。然而,這些方法僅在小數據集上進行了評估,並且未與現代基線模型進行比較
## The DETR model
- DETR在解碼器的單次通過中推斷一個固定大小的N個預測結果,其中N被設定為明顯大於圖像中典型物體數量的值
- 這篇論文的損失函數產生了預測物體和地實物體之間的最優二部匹配,然後優化物體特定的(邊界框)損失
- 為了在這兩個集合之間找到一個二部匹配,我們尋找具有最低成本的N個元素的排列σ ∈ SN:

- 其中Lmatch(yi,yˆσ(i))是地實物體yi和索引為σ(i)的預測之間的成對匹配成本。這個最優分配是通過匈牙利算法有效地計算的
- 這個二分圖問題的匹配成本考慮了以下
- 類別預測與真實框的相似性
- 預測框與真實框的相似性
- 集合的每個元素i可以看作是一個yi = (ci,bi),其中ci是目標類別標籤(可能為∅),bi ∈ [0, 1](4),是一個向量,定義了地實框中心坐標以及相對於圖像大小的高度和寬度,對於索引為σ(i)的預測,我們將類別ci的概率定義為$\hat{P_{\sigma}(i)}(C_{i})$跟$\hat{b_{\sigma}(i)}$,loss定義如下:

- 這個找到匹配的過程在功能上與現代檢測器中用於將建議[37]或錨點[22]與地實物體匹配的啟發式分配規則相同。主要區別在於,我們需要找到一對一的匹配,以進行無重複的直接集合預測
- 第二步是計算損失函數,即前一步驟中匹配的所有成對的匈牙利損失。我們將損失定義類似於常見物體檢測器的損失,即類別預測的負對數似然和稍後定義的框損失的線性組合

- $\hat{\sigma}$是代表前面匹配算法算出來跟ground truth匹配的那些index
- 在實際操作中,當$ci = ∅$時,我們會將對數概率項下調10倍,以考慮類別不平衡的因素,這類似於Faster R-CNN訓練過程通過子採樣平衡正負建議
- 在匹配成本中,我們使用概率$\hat{P_{\sigma}(i)}(C_{i})$而不是對數概率。這使得類別預測項與Lbox(·, ·)(下面描述)可相互比較,我們觀察到在實際性能上有更好的表現
- 邊界框損失:
- 匹配成本的第二部分和匈牙利損失是Lbox(·),該損失對邊界框進行評分。不同於許多檢測器將框預測作為∆相對於一些初始猜測的w.r.t,我們直接進行框預測
- 雖然這種方法簡化了實現,但存在損失的相對縮放問題。所以這邊使用了L1 loss跟generalized IoU loss進行線性組合來算這個loss,所以最終的bbox loss定義為

- $λ_{iou}, λ_{L1}$是超參數,這兩種損失都通過批次中的物體數量進行歸一化

- 舉例
- 輸入圖片為3 * 800 * 1066
- 過一個cnn提取特徵圖,得到大小2048 * 25 * 34, 25跟34就是前面寬高的1/32
- 因為要進transformer,所以進行1 * 1的捲機操作,進行降維,得到256 * 25 * 34
- 這邊要加入位置編碼,這邊是使用固定的位置編碼,維度大小也是256 * 25 * 34,因為要相加
- 這時候要將寬高拉直,變成850 * 256(850就是序列長度,256就是embedding長度)
- 進了一個transformer encoder(6),一樣得到850 * 256
- 這邊提出了新的概念object query,是可以學習的,大小為100 * 256,100就是輸出的大小
- 最後得到100 * 256的輸出
- 最後要加一個檢測頭,就是加一個FFN,輸出就會變成100 * 95
- 91是分類的頭(過一個linear)
- 4是框的座標中心跟框的寬高(過一個linear)
- 有了這些數據,就可以跟ground truth的框進行匈牙利算法匹配,算得最後的目標函數,然後反向回傳,進行梯度跟新
- decoder每層block都會先進行query的自注意力操作,目的是為了刪除多餘的框,因為query進行互相通信之後,就會之後各自的框是什麼,而不會進行多餘的框
- 在最後算loss的時候,作者發現,為了讓模型收斂得更快,或者訓練得更穩定,所以在decoder每一層的輸出都加上FFN,計算loss function,最後加到最後的loss,這種trick在分割中很常見,意及不光在最後一層算loss,在每層都去算,因為輸出大小都是一樣的,當然這些FFN都是共享參數的
## 伪代碼
```python=
import torch
from torchvision.models import resnet50
class DETR(nn.Module):
def __init__(self, num_classes, hidden_dim, nheads,
num_encoder_layers, num_decoder_layers):
super().__init__()
self.backbone = nn.Sequential(*list(resnet50(pretrained=True).children())[:-2]) # 把backbone抽出來
self.conv = nn.Conv2d(2048, hidden_dim, 1)
self.transformer = nn.Transformer(hidden_dim, nheads,
num_encoder_layers, num_decoder_layers)
self.linear_class = nn.Linear(hidden_dim, num_classes + 1)
self.linear_bbox = nn.Linear(hidden_dim, 4)
self.query_pos = nn.Parameter(torch.rand(100, hidden_dim))
self.row_embed = nn.Parameter(torch.rand(50, hidden_dim // 2))
self.col_embed = nn.Parameter(torch.rand(50, hidden_dim // 2))
def forward(self, inputs):
x = self.backbone(inputs)
h = self.conv(x)
H, W = h.shape[-2:]
pos = torch.cat([
self.col_embed[:W].unsqueeze(0).repeat(H, 1, 1),
self.row_embed[:H].unsqueeze(1).repeat(1, W, 1),
], dim=-1).flatten(0, 1).unsqueeze(1)
h = self.transformer(pos + h.flatten(2).permute(2, 0, 1),
self.query_pos.unsqueeze(1))
return self.linear_class(h), self.linear_bbox(h).sigmoid()
detr = DETR(num_classes=91, hidden_dim=256, nheads=8, num_encoder_layers=6, num_decoder_layers=6)
detr.eval()
inputs = torch.randn(1, 3, 800, 1200)
logits, bboxes = detr(inputs)
```
## 實驗

- 頂部部分顯示了Detectron2 [50]中Faster R-CNN模型的結果,中間部分顯示了具有GIoU [38]、隨機裁剪訓練時間增強和長9x訓練進度的Faster R-CNN模型的結果。DETR模型達到了與經過重大調整的Faster R-CNN基線相當的結果,具有較低的APS但極大改善了AP
- 觀察APL跟APS,就是針對小物體跟大物體的AP,對於小物體,faster-rcnn比detr好很多,但是在大物體,detr反而比faster-rcnn高非常多,可能是因為transformer的全局建模能力,且沒有進行多尺度特徵的建模

- 可視化了訓練模型的最後一個編碼器層的注意力地圖,重點關注圖像中的一些點。編碼器似乎已經分離了實例,這可能使解碼器更容易提取和定位物體。



- 顯示DETR解碼器中N = 100個預測槽中的20個預測槽對COCO 2017驗證集上所有圖像的所有框預測的可視化。每個框預測都表示為一個點,其中心坐標在1x1的方形內,由每個圖像的大小進行了歸一化。這些點以顏色編碼,綠色對應小框,紅色對應大的水平框,藍色對應大的垂直框。我們觀察到每個槽都學會專注於特定區域和框大小,具有多種操作模式。我們注意到,幾乎所有的槽都有一種預測大的全圖像框的模式,這在COCO數據集中很常見
- 觀察到每個槽都有幾種不同的操作模式,專注於不同的區域和框大小。特別是,所有槽都有一種用於預測全圖像框的模式(在圖的中間以紅色點的形式可見)。我們假設這與COCO中物體的分布有關

- 對於看不見的實例數量的泛化。COCO中的一些類別在同一圖像中的相同類別的實例很少。例如,在訓練集中,沒有一張圖像中有超過13只長頸鹿。我們創建了一個合成圖像3來驗證DETR的泛化能力(見圖5)。我們的模型能夠在圖像上找到所有24只長頸鹿,這顯然是超出了分佈範圍。這個實驗確認了每個物體查詢中沒有強烈的類別專業化
## Conclusion
- 我們提出了DETR,這是一種基於Transformer和二分匹配損失的新型物體檢測系統設計,用於直接集合預測。這種方法在具有挑戰性的COCO數據集上取得了與經過優化的Faster R-CNN基線相當的結果。DETR易於實現,具有靈活的架構,可以輕鬆擴展到全景分割,並取得有競爭力的結果。此外,它在處理大物體方面的性能明顯優於Faster R-CNN,這可能歸功於自我注意力執行的全局信息處理。
- 這種新型檢測器設計也帶來了新的挑戰,特別是在訓練、優化和小物體的性能方面。目前的檢測器需要幾年的改進才能應對類似的問題,我們期待未來的工作能夠成功解決DETR的這些挑戰。
