一、文章介紹
detr是Facebook AI Research在2020年所提出的一種新型視覺物體檢測方法,通過在全卷積神經網路中使用transformer編碼器-解碼器結構,將物體檢測任務從先前的兩階段目標檢測方法轉變為一階段的end-to-end方法,可以在保持預測準確性的同時提高檢測效率。本文將介紹detr的核心思想、模型結構及其訓練方法,以及與常見的目標檢測方法的比較。
二、一階段end-to-end物體檢測
我們知道,傳統目標檢測方法一般都是兩階段的。首先,使用區域提取演算法生成包含物體的候選窗口,然後將這些窗口送入分類器和回歸器中進行分類和位置估計。這種方法一般效果很好,但是速度慢且複雜。而detr使用了一階段的end-to-end方法,直接在圖像上預測物體的位置和類別。這樣一來,第一階段的計算可以被跳過,檢測速度大大提高。
三、Transformer結構的應用
detr中的核心思想是使用transformer打包特徵圖,然後使用一個解碼器輸出檢測結果。利用transformer的自注意力機制,detr能自動提取特徵圖中的重要特徵,使空間信息得到了更好的利用。同時,transformer使得編碼器-解碼器框架可以應用於物體檢測任務。
四、模型結構
detr的模型結構是一個全卷積神經網路,由一個編碼器和一個解碼器組成。輸入是一張圖像,經過卷積神經網路進行特徵提取,然後傳入transformer編碼器中進行特徵圖打包,最終由解碼器輸出檢測結果,即每個目標包含類別和邊界框。detr使用5個編碼器層和6個解碼器層,每個解碼器層都將encoder輸出和自己的前一個輸出輸入transformer中。
class DETR(nn.Module):
def __init__(self, backbone, num_classes, num_queries):
super().__init__()
self.num_queries = num_queries
self.query_embed = nn.Embedding(num_queries, self.hidden_dim)
self.transformer = nn.Transformer(
d_model=self.hidden_dim,
nhead=self.nhead,
num_encoder_layers=self.num_encoder_layers,
num_decoder_layers=self.num_decoder_layers,
dim_feedforward=self.dim_feedforward,
dropout=self.transformer_dropout,
activation=self.activation,
normalize_before=self.normalize_before,
)
self.input_proj = nn.Conv2d(backbone.num_channels, self.hidden_dim, kernel_size=1)
self.backbone = backbone
self.class_embed = nn.Linear(self.hidden_dim, num_classes + 1)
self.bbox_embed = MLP(hidden_dim, hidden_dim, 4, 3)
五、訓練方法
detr的訓練是一個端到端的過程,梯度由所有步驟共同計算。Cityscapes和COCO數據集是在訓練過程中使用的常見數據集,在COCO數據集上可以達到較好的表現。為了提高模型的準確性,detr使用了多任務學習,並使用了一個匈牙利演算法為每個預測框匹配真實目標或背景類別。為了提高訓練效率,作者使用了分散式訓練並使用了warmup策略逐漸增加學習率。
六、實驗結果與對比
實驗結果表明,detr在COCO數據集上的表現相當出色。mAP@50增加了4.2%(從42.0%到46.2%),並且在只有一個物體的圖像中的表現也特別好。同時,與Faster R-CNN等目標檢測方法相比,detr有著更好的檢測速度。另外,detr也被證明在其他形式的目標檢測中具有靈活性。
七、總結
detr等一階段end-to-end物體檢測方法的出現將徹底改變目標檢測的方式。detr不僅提高了檢測速度,還在準確率方面達到了很好的性能。但是,detr也存在一些限制,例如對小物體的檢測效果不佳等。但是,這個方向仍然具有很大的潛力和研究價值。
完整代碼
# 定義模型
class DETR(nn.Module):
def __init__(self, backbone, num_classes, num_queries):
super().__init__()
self.num_queries = num_queries
self.query_embed = nn.Embedding(num_queries, self.hidden_dim)
self.transformer = nn.Transformer(
d_model=self.hidden_dim,
nhead=self.nhead,
num_encoder_layers=self.num_encoder_layers,
num_decoder_layers=self.num_decoder_layers,
dim_feedforward=self.dim_feedforward,
dropout=self.transformer_dropout,
activation=self.activation,
normalize_before=self.normalize_before,
)
self.input_proj = nn.Conv2d(backbone.num_channels, self.hidden_dim, kernel_size=1)
self.backbone = backbone
self.class_embed = nn.Linear(self.hidden_dim, num_classes + 1)
self.bbox_embed = MLP(hidden_dim, hidden_dim, 4, 3)
def forward(self, x):
hs = self.backbone(x)
hs = self.input_proj(hs)
bs, c, h, w = hs.shape
hs = hs.flatten(2).permute(2, 0, 1)
query_embed = self.query_embed.weight.unsqueeze(1).repeat(1, bs, 1)
memory = self.transformer_encoder(hs)
hs = self.transformer_decoder(query_embed, memory)
return hs.transpose(0, 1), self.class_embed(hs), self.bbox_embed(hs).sigmoid
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/309150.html