Date: 2020/06/27
Author: CW
前言:
閱讀了 DETR 的論文后蓬痒,近期梳理了相關(guān)代碼憨攒,本系列會(huì)結(jié)合源碼對(duì) DETR 進(jìn)行解析世杀,包含模型效果的簡(jiǎn)單演示、訓(xùn)練的 pipeline肝集、backbone瞻坝、編碼、解碼杏瞻、loss的設(shè)計(jì)與計(jì)算所刀、后處理、評(píng)估驗(yàn)證的 pipeline捞挥。CW認(rèn)為浮创,認(rèn)真閱讀完本系列的每篇文后,將 DETR 的實(shí)現(xiàn)理解透徹是OK的砌函,但要真正地吃透斩披,還需要朋友你親自實(shí)踐并且深入思考。
本文作為系列的開篇之作讹俊,就簡(jiǎn)單一些吧垦沉,一上來就是復(fù)雜的源碼分析難免有將客人拒之門外的趕腳。因此仍劈,CW在本文中會(huì)對(duì)這個(gè)模型做個(gè)簡(jiǎn)單的概述厕倍,然后基于官方給出的 notebook demo對(duì)模型推斷部分的代碼進(jìn)行解析(注意,這個(gè)demo中模型的實(shí)現(xiàn)并不是 DETR 真正的實(shí)現(xiàn)方式贩疙,僅是個(gè)簡(jiǎn)化版)讹弯。
DETR: End-to-end Object Detection with Transformers
Outline
I. 概述
II. 模型推斷
概述
DETR 即 DEtection TRansformer, 是 Facebook AI 研究院提出的 CV 模型这溅,主要用于目標(biāo)檢測(cè)组民,也可以用于分割任務(wù)。該模型使用 Transformer 替代了復(fù)雜的目標(biāo)檢測(cè)傳統(tǒng)套路悲靴,比如 two-stage 或 one-stage臭胜、anchor-based 或 anchor-free、nms 后處理等对竣;也沒有使用一些騷里騷氣的技巧庇楞,比如在使用多尺度特征融合榜配、使用一些特殊類型的卷積(如分組卷積否纬、可變性卷積、動(dòng)態(tài)生成卷積等)來抽取特征蛋褥、對(duì)特征圖作不同類型的映射以將分類與回歸任務(wù)解耦临燃、甚至是數(shù)據(jù)增強(qiáng),整個(gè)過程就是使用CNN提取特征后編碼解碼得到預(yù)測(cè)輸出。
可以說膜廊,整體工作很solid乏沸,雖然效果未至于 SOTA,但將煉丹者們通常認(rèn)為是屬于 NLP 領(lǐng)域的 Transformer 拿來跨界到 CV 領(lǐng)域使用爪瓜,并且能work蹬跃,這是具有重大意義的,其中的思想也值得我們學(xué)習(xí)铆铆。這種突破傳統(tǒng)與開創(chuàng)時(shí)代的工作往往是深得人心的蝶缀,比如 Faster R-CNN 和 YOLO,你可以看到之后的許多工作都是在它們的基礎(chǔ)上做改進(jìn)的薄货。
概括地說翁都,DETR 將目標(biāo)檢測(cè)任務(wù)看作集合預(yù)測(cè)問題,對(duì)于一張圖片谅猾,固定預(yù)測(cè)一定數(shù)量的物體(原作是100個(gè)柄慰,在代碼中可更改),模型根據(jù)這些物體對(duì)象與圖片中全局上下文的關(guān)系直接并行輸出預(yù)測(cè)集税娜,也就是 Transformer 一次性解碼出圖片中所有物體的預(yù)測(cè)結(jié)果坐搔,這種并行特性使得 DETR 非常高效。
模型推斷
這個(gè)demo會(huì)基于預(yù)訓(xùn)練權(quán)重實(shí)現(xiàn)一個(gè)DETR的簡(jiǎn)化版巧涧,然后對(duì)一張圖片作預(yù)測(cè)薯蝎,最后展示出預(yù)測(cè)效果。
首先導(dǎo)入需要的相關(guān)庫(kù):
然后谤绳,實(shí)現(xiàn)一個(gè)簡(jiǎn)化版的模型:
模型主要由 backbone占锯、transformer 以及 最后形成預(yù)測(cè)輸出的線性層構(gòu)成,另外缩筛,還需要一個(gè)卷積層將backbone輸出的特征圖維度映射到transformer輸入所需的維度消略。
了解 Transformer 的朋友們應(yīng)該知道,其本身是不了解輸入序列中各部分的位置關(guān)系的瞎抛,因此通常需要加入位置編碼艺演,此處也一樣:
上圖中,行列編碼的第一個(gè)維度都是50桐臊,代表這里默認(rèn)backbone輸出的特征圖尺寸不超過50x50胎撤。
模型的初始化方法就到此結(jié)束了,是那么得絲滑..額不對(duì)断凶,是那么得簡(jiǎn)潔明了伤提,接下來看看模型的前向過程:
上圖中的部分是將圖片輸入到backbone提取特征,然后對(duì)輸出特征圖維度進(jìn)行轉(zhuǎn)換认烁,并且構(gòu)造位置編碼張量肿男。這里位置編碼張量的實(shí)現(xiàn)是對(duì)特征圖的行介汹、列分別進(jìn)行編碼后拼接起來,同時(shí)進(jìn)行維度轉(zhuǎn)換以適應(yīng)編碼器的輸入舶沛。
下面就是將以上部分輸入到 Transformer 進(jìn)行編碼與解碼嘹承,最后將解碼的結(jié)果輸入到線性層形成最終的預(yù)測(cè)結(jié)果:
注意下,上圖中對(duì) Transformer 的輸出維度順序做了調(diào)整如庭,因此最后得到的h的維度是(batch, 100, hidden_dim)叹卷。
整個(gè)前向過程也就這樣了,是不是感覺讓你擼起代碼來毫無(wú)壓力坪它,嘿嘿豪娜!
下面是對(duì)輸入圖片和輸出bbox的處理:
對(duì)于輸出bbox,先將其由中心點(diǎn)坐標(biāo)和寬高轉(zhuǎn)換為矩形框左上角和右下角坐標(biāo)的形式哟楷,同時(shí)瘤载,由于回歸的是歸一化后的值,因此需要根據(jù)圖像尺寸轉(zhuǎn)換為絕對(duì)坐標(biāo)值卖擅。
現(xiàn)在鸣奔,我們定義一個(gè)方法來封裝整個(gè)推斷過程,從而獲取預(yù)測(cè)結(jié)果:
這里有個(gè)點(diǎn)提一下惩阶,torch1.5版本中挎狸,對(duì)于tensor.max()的返回是torch.return_types.max(values=tensor(xxx), indices=tensor(xxx)),但是torch1.0中断楷,這個(gè)方法的返回是一個(gè)tuple锨匆。
選用COCO數(shù)據(jù)集的類別,總共80類冬筒,但索引是1到90恐锣。
上圖中的COLORS用于畫出bbox的矩形框顏色。
現(xiàn)在我們可以實(shí)例化一個(gè)模型舞痰,由于COCO的類別索引是1到90土榴,因此我們的num_classes參數(shù)需要設(shè)置為91:
OK,一切準(zhǔn)備就緒响牛,我們現(xiàn)在來對(duì)一張圖片進(jìn)行檢測(cè):
可以看到玷禽,模型在這張圖中檢測(cè)到了5個(gè)物體,最后我們對(duì)這個(gè)結(jié)果進(jìn)行可視化:
最終效果如下圖所示:
#最后
CW認(rèn)為呀打,通過本文矢赁,應(yīng)該可以讓大家對(duì) DETR 有個(gè)基本了解,當(dāng)然同時(shí)可能也會(huì)產(chǎn)生出許多不解贬丛,不著急撩银,更多的細(xì)節(jié)實(shí)現(xiàn)與原理會(huì)在后面的篇章中解析,待我醞釀醞釀瘫寝,才香~