一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

源碼解析目標(biāo)檢測的跨界之星DETR(四)、Detection with Transformer

 李xinle 2021-08-03

Date: 2020/07/25

Coder: CW

Foreword:

本文是該系列的重點之一,通過對DETR中Transformer部分的代碼解析,你就會知道Transformer是如何在目標(biāo)檢測領(lǐng)域work的了,并且你還可以自己動手實踐一番,是不是很誘人?哈哈哈!Transformer在這里與NLP的流程類似,主要包括 Embedding、Encoder 和 Decoder,如果對Transformer基本原理不了解的朋友們,可以閱讀下Transformer系列的這幾篇文章:

Transformer 修煉之道(一)、Input Embedding

Transformer 修煉之道(二)、Encoder

Transformer 修煉之道(三)、Decoder

之前寫以上這幾篇文章正是為該系列作鋪墊,以便不熟悉Transformer原理的朋友們快速了解下相關(guān)知識點。


Outline

I. Encoder

II. Query Embedding

III. Decoder

IV. Transformer (Combine Encoder with Decoder)


Encoder

Encoder通常有6層,每層結(jié)構(gòu)相同,這里使用_get_clones()方法將結(jié)構(gòu)相同的層復(fù)制(注意是deepcopy)多次,返回一個nn.ModuleList實例。

Encoder(i)

_get_clones()方法一行代碼就能KO掉。

_get_clones

Encoder的前向過程即循環(huán)調(diào)用每層的前向過程,前一層的輸出作為后一層的輸入。最后,若指定了需要歸一化,那么就對最后一層的輸出作歸一化。

這里注意下幾個輸入?yún)?shù)的意義,CW 已為大家在下圖中作了注釋。

Encoder(ii)

Encoder的每層是下圖這個TransformerEncoderLayer的一個實例,其主要由 多頭自注意力層(Multi-Head Self-Attention) 和 前向反饋層(FFN)構(gòu)成,另外還包含了層歸一化、激活層、Dropout層以及殘差連接。

EncoderLayer(i)

_get_activation_fn()方法根據(jù)輸入?yún)?shù)指定的激活方式返回對應(yīng)的激活層,默認(rèn)是ReLU。

EncoderLayer(ii)

這里歸一化使用了nn.LayerNorm,即層歸一化。與BatchNorm(批歸一化)不同,后者是在通道這個維度上進(jìn)行歸一化,而前者可以指定對最后的哪幾個維度進(jìn)行歸一化。另外,其可學(xué)習(xí)參數(shù)\gamma 和\beta 是對應(yīng)做歸一化的那些維度上的每個元素的,而非批歸一化那種一個通道共享一對\gamma 和\beta 標(biāo)量。還有一點與批歸一化不同,就是其在測試過程中也會計算統(tǒng)計量。

官方給出的說明如下:

Unlike Batch Normalization and Instance Normalization, which applies scalar scale and bias for each entire channel/plane with the :attr:`affine` option, Layer Normalization applies per-element scale and bias with :attr:`elementwise_affine`.

This layer uses statistics computed from input data in both training and evaluation modes.

EncoderLayer的前向過程分為兩種情況,一種是在輸入多頭自注意力層和前向反饋層前先進(jìn)行歸一化,另一種則是在這兩個層輸出后再進(jìn)行歸一化操作。

EncoderLayer(iii)

先進(jìn)行歸一化的前向過程如下圖。

self.self_attnnn.MultiheadAttention的實例,其前向過程返回兩部分,第一個是自注意力層的輸出,第二個是自注意力權(quán)重,因此這里取了輸出索引為0的部分即代表自注意力層的輸出。

另外,這里的key_padding_mask對應(yīng)上述Encoder的src_key_padding_mask,是backbone最后一層輸出特征圖對應(yīng)的mask,值為True的那些位置代表原始圖像padding的部分,在生成注意力的過程中會被填充為-inf,這樣最終生成注意力經(jīng)過softmax時輸出就趨向于0,相當(dāng)于忽略不計,官方對該參數(shù)的解釋如下:

key_padding_mask – if provided, specified padding elements in the key will be ignored by the attention. This is an binary mask. When the value is True, the corresponding value on the attention layer will be filled with -inf.

EncoderLayer(iv)

src_mask是在Transformer中用來“防作弊”的,即遮住當(dāng)前預(yù)測位置之后的位置,忽略這些位置,不計算與其相關(guān)的注意力權(quán)重。而這里的序列是圖像特征(反而就是要計算圖像各位置的全局關(guān)系),不同于NLP,因此沒有這個需求,在這里也就沒有使用。

還有一點,在輸入多頭自注意力層時需要先進(jìn)行位置嵌入,即結(jié)合位置編碼。注意僅對query和key實施,而value不需要。query和key是在圖像特征中各個位置之間計算相關(guān)性,而value作為原圖像特征,使用計算出來的相關(guān)性加權(quán)上去,得到各位置結(jié)合了全局相關(guān)性(增強(qiáng)/削弱)后的特征表示。

position embedding

(不過好奇的童鞋也可以試著對value也進(jìn)行position embedding,實驗對比下效果,然后再想想怎么講故事..)

后進(jìn)行歸一化的前向過程與上類似。

EncoderLayer(v)

Query Embedding

在解析Decoder前,有必要先簡要地談?wù)剄uery embedding,因為它是Decoder的主要輸入之一。

query embedding 有點anchor的味道,而且是自學(xué)習(xí)的anchor,作者使用了nn.Embedding實現(xiàn):

query embedding(i)

其中num_queries代表圖像中有多少個目標(biāo)(位置),默認(rèn)是100個,對這些目標(biāo)(位置)全部進(jìn)行嵌入,維度映射到hidden_dim,將query_embedding的權(quán)重作為參數(shù)輸入到Transformer的前向過程,使用時與position encoding的方式相同:直接相加。

query embedding(ii)

而這個query embedding應(yīng)該加在哪呢?當(dāng)然是我們需要預(yù)測的目標(biāo)(query object)咯!可是網(wǎng)絡(luò)一開始還沒有輸出,我們都不知道預(yù)測目標(biāo)在哪里呀,如何將它實體化?作者也不知道,于是就簡單粗暴地直接將它初始化為全0,shape和query embedding 的權(quán)重一致(從而可以element-wise add)。

Transformer的前向反饋(部分)

Decoder

Decoder的結(jié)構(gòu)和Encoder十分類似。

Decoder(i)

其前向過程如下。具體操作和Encoder的也類似,只不過需要先將以下紅框部分的參數(shù)梳理清楚,明白各自代表的意義,之后整個代碼看起來就十分好理解了。

Decoder(ii)

提一句,這里tgt_maskmemory_mask都是用于“防作弊”的,這里均未使用。

在下圖中,需要注意的是intermediate中記錄的是每層輸出后的歸一化結(jié)果,而每一層的輸入是前一層輸出(沒有歸一化)的結(jié)果。

Decoder(iii)

感覺下圖紅框部分是“多此一舉”,因為上圖中本身intermediate記錄的就是每層輸出的歸一化結(jié)果了。

另外,不知道你們發(fā)現(xiàn)了不,這里的實現(xiàn)有點“令人不舒服”。self.norm是通過初始化時傳進(jìn)來的參數(shù)norm(默認(rèn)為None)設(shè)置的,那么self.norm就有可能是None,因此下圖第一句代碼也對此作了判斷。但是在上圖中,卻在沒有作判斷的情況下直接碼出了self.norm(output)這句,所以有可能會引發(fā)異常。

Decoder(iv)

在整體項目代碼中,作者在構(gòu)建Decoder使始終傳了norm參數(shù),使得其不為None,因此不會引發(fā)異常。但就單獨看Decoder的這部分實現(xiàn)來說,確實是有問題的,如果朋友們直接拿這部分去用,需要注意下這點(沒想到FAIR寫的代碼居然也有這種level的水平,被我抓到了..)。

Decoder構(gòu)建

DecoderLayer與Encoder的實現(xiàn)類似,只不過多了一層 Encoder-Decoder Layer,其實質(zhì)也是多頭自注意力層,但是key和value來自于Encoder的輸出。

DecoderLayer(i)
DecoderLayer(ii)

DecoderLayer的前向過程也如同EncoderLayer一樣分為兩種情況,這里就對“后進(jìn)行歸一化”的情況作解析。

在第一個多頭自注意層中,輸入均和Encoder無關(guān)。

DecoderLayer(iii)

注意,和Encoder中一樣,會對query和key進(jìn)行position embedding(而value則不需要)。

到了第二個多頭自注意力層,即 Encoder-Decoder Layer,key和value均來自Encoder的輸出。同樣地,query和key要進(jìn)行位置嵌入(而value不用)。

DecoderLayer(iv)

這里自注意力層計算的相關(guān)性是目標(biāo)物體與圖像特征各位置的相關(guān)性,然后再把這個相關(guān)性系數(shù)加權(quán)到Encoder編碼后的圖像特征(value)上,相當(dāng)于獲得了object features的意思,更好地表征了圖像中的各個物體。

通過Decoder和Encoder的實現(xiàn)可以發(fā)現(xiàn),作者極力強(qiáng)調(diào)位置嵌入的作用,每次在self-attention操作時都伴隨著position embedding,這是因為繼承了Transformer的permute invariant特性,即對排列和位置是不care的,而我們很清楚,在detection任務(wù)中,位置信息有著舉足輕重的地位!

另外,看完DecoderLayer的實現(xiàn),會發(fā)現(xiàn)可能存在“重復(fù)歸一化”的問題。當(dāng)使用后歸一化的前向方式時(如以上兩幅圖所示),每個DecoderLayer的輸出是歸一化后的結(jié)果,但是在Decoder的前向過程中會使用self.norm對其再進(jìn)行一次歸一化!


Transformer (Combine Encoder with Decoder)

將Encoder和Decoder封裝在一起構(gòu)成Transformer。

Transformer(i)
Transformer(ii)

Transformer的前向過程如下,首先是將輸入(圖像特征)flatten成序列,這里的src是已經(jīng)將CNN提取的特征維度映射到hidden_dim的結(jié)果。

Transformer(iii)

然后就是將以上輸入?yún)?shù)依次送進(jìn)Encoder和Decoder,最后再reshape到需要的結(jié)果。

注意,tgt是與query embedding形狀一直且設(shè)置為全0的結(jié)果,意為初始化需要預(yù)測的目標(biāo)。因為一開始并不清楚這些目標(biāo),所以初始化為全0。其會在Decoder的各層不斷被refine,相當(dāng)于一個coarse-to-fine的過程,但是真正要學(xué)習(xí)的是query embedding,學(xué)習(xí)到的是整個數(shù)據(jù)集中目標(biāo)物體的統(tǒng)計特征,而tgt在每次迭代訓(xùn)練(一個batch數(shù)據(jù)剛到來)時會被重新初始化為0。

(那么這里就可以思考下了,這種學(xué)習(xí)方式會不會使得模型的泛化能力受限?在遇到另一個分布差異巨大的數(shù)據(jù)集時模型的表現(xiàn)想必會很尷尬?不過當(dāng)前深度學(xué)習(xí)中基于特定數(shù)據(jù)集訓(xùn)練而來的模型貌似都有這個通病,畢竟你在A分布上訓(xùn)練,卻要在B分布(與A分布差異巨大)上測試,是不是太不善良了..)

Transformer(iv)

以上有一處需要注意下,就是作者在項目代碼中構(gòu)建Transformer時設(shè)置了return_intermediate為True,因此Decoder會返回6層的輸出結(jié)果,于是hs的第一個維度是6。

build_transformer

@最后

本文解析了Transformer在DETR中的實現(xiàn),這部分是DETR的核心部分之一。但是還沒完,經(jīng)過Transformer后只能說DETR的主要工作基本做完了,其輸出結(jié)果并不是最終的預(yù)測結(jié)果,還需要進(jìn)行轉(zhuǎn)換,后續(xù)部分的內(nèi)容會在該系列后續(xù)的文章中給出,還請諸位客官稍候不知道多少刻..

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    国产美女网红精品演绎| 九九热视频经典在线观看| 亚洲最新的黄色录像在线| 免费精品一区二区三区| 国产不卡免费高清视频| 亚洲一区二区三区熟女少妇| 日本高清视频在线观看不卡| 麻豆最新出品国产精品| 东京热男人的天堂社区| 日本乱论一区二区三区| 美日韩一区二区精品系列 | 欧洲偷拍视频中文字幕| 午夜国产精品国自产拍av| 免费播放一区二区三区四区| 日韩精品成区中文字幕| 99久久精品久久免费| 成人午夜爽爽爽免费视频| 欧美中文日韩一区久久| 十八禁日本一区二区三区| 国产视频福利一区二区| 亚洲视频一区自拍偷拍另类| 少妇特黄av一区二区三区| 国产精品欧美激情在线| 91超频在线视频中文字幕| 国产午夜福利在线免费观看| 精品推荐久久久国产av| 欧美人妻盗摄日韩偷拍| 色丁香之五月婷婷开心| 午夜精品久久久免费视频| 亚洲美女国产精品久久| 欧美整片精品日韩综合| 亚洲一区二区精品免费| 初尝人妻少妇中文字幕在线| 丰满少妇高潮一区二区| 91老熟妇嗷嗷叫太91| 日韩亚洲精品国产第二页| 日韩一区二区三区18| 亚洲中文在线男人的天堂| 久久热在线视频免费观看| 欧美黑人巨大一区二区三区| 亚洲国产精品久久网午夜|