源碼解析目標檢測的跨界之星DETR(五)倔矾、loss函數(shù)與匈牙利匹配算法

Date: 2020/07/17

Coder: CW

Foreword:

本文將對 loss函數(shù)的實現(xiàn)進行解析丰包,由于 DETR 是預測結(jié)果是集合的形式烫沙,因此在計算loss的時候有個關(guān)鍵的前置步驟就是將預測結(jié)果和GT進行匹配锌蓄,這里的GT類別是不包括背景的瘸爽,未被匹配的預測結(jié)果就自動被歸類為背景。匹配使用的是匈牙利算法柑潦,該算法主要用于解決與二分圖匹配相關(guān)的問題,對這部分感興趣的朋友們可以參考下這篇文:匈牙利算法


Outline

I. Loss Function

????i). 分類loss

????ii). 回歸loss

II. Hungarian algorithm(匈牙利算法)


Loss Function

先來看看與loss函數(shù)相關(guān)的一些參數(shù):matcher就是將預測結(jié)果與GT進行匹配的匈牙利算法峻凫,這部分的實現(xiàn)會在下一節(jié)解析渗鬼。weight_dict是為各部分loss設(shè)置的權(quán)重,主要包括分類與回歸損失荧琼,分類使用的是交叉熵損失譬胎,而回歸損失包括bbox的 L1 Loss(計算x、y命锄、w堰乔、h的絕對值誤差)與 GIoU Loss。若設(shè)置了masks參數(shù)镐侯,則代表分割任務袜瞬,那么還需加入對應的loss類型贴谎。另外仲翎,若設(shè)置了aux_loss,即代表需要計算解碼器中間層預測結(jié)果對應的loss炕吸,那么也要設(shè)置對應的loss權(quán)重嘴瓤。

與loss函數(shù)實現(xiàn)相關(guān)的初始化參數(shù)

loss函數(shù)是通過實例化SetCriterion對象來構(gòu)建。

構(gòu)建loss函數(shù)

losses變量指示需要計算哪些類型的loss谓晌,其中cardinality僅用作log柏肪,并不涉及反向傳播梯度谬俄。

loss_cardinality

可以先來看下SetCriterion這個類的doc string,了解下各部分參數(shù)的意義乎婿。

SetCriterion(i)

CW 也作了對應的注釋:

SetCriterion(ii)

接下來看下其前向過程褒侧,從而知悉loss的計算。

這里一定要先搞清楚模型的輸出(outputs)和GT(targets)的形式鬼贱,對于outputs可參考CW在下圖中的注釋嵌溢;而targets是一個包含多個dict的list,長度與batch size相等,其中每個dict的形式如COCO數(shù)據(jù)集的標注坟冲,具體可參考該系列的第二篇文章:?源碼解析目標檢測的跨界之星DETR(二)沸移、模型訓練過程與數(shù)據(jù)處理?中的數(shù)據(jù)處理部分攒射。

SetCriterion(iii)

如CW在前言部分所述捣鲸,計算loss的一個關(guān)鍵的前置步驟就是將模型輸出的預測結(jié)果與GT進行匹配,對應下圖中self.matcher()的部分啊片,返回的indices的形式已在注釋中說明。

SetCriterion(iv)

接下來是計算各種類型的loss壳炎,并將對應結(jié)果存到一個dict中(如下圖losses變量),self.get_loss()方法返回loss計算結(jié)果晨仑。

SetCriterion(v)
SetCriterion(vi)

get_loss方法中并不涉及具體loss的計算拱镐,其僅僅是將不同類型的loss計算映射到對應的方法,最后將計算結(jié)果返回。

get_loss

接下來娱颊,我們就對分類和回歸損失的計算過程分別進行解析惠昔。

i). 分類loss

首先說明下考传,doc string里寫的是NLL Loss,但實際調(diào)用的是CE Loss证鸥,這是因為在Pytorch實現(xiàn)中僚楞,CE Loss實質(zhì)上就是將Log-Softmax操作和NLL Loss封裝在了一起,如果直接使用NLL Loss枉层,那么需要先對預測結(jié)果作Log-Softmax操作泉褐,而使用CELoss則直接免去了這一步。

loss_labels(i)

其次鸟蜡,要理解紅框部分的_get_src_permutation_idx()在做什么膜赃。輸入?yún)?shù)indices是匹配的預測(query)索引與GT的索引,其形式在上述SetCriterion(iv)圖中注釋已有說明揉忘。該方法返回一個tuple跳座,代表所有匹配的預測結(jié)果的batch index(在當前batch中屬于第幾張圖像)和 query index(圖像中的第幾個query對象)。

_get_src_permutation_idx

類似地泣矛,我們可以獲得當前batch中所有匹配的GT所屬的類別(target_classes_o)疲眷,然后通過src_logitstarget_classes_o就可以設(shè)置預測結(jié)果對應的GT了您朽,這就是下圖中的target_classes狂丝。target_classes的shape和src_logits一致,代表每個query objects對應的GT,首先將它們?nèi)砍跏蓟癁楸尘凹秆眨缓蟾鶕?jù)匹配的索引(idx)設(shè)置匹配的GT(target_classes_p)類別倍试。

loss_labels(ii)?

“熱身活動”做完后,終于可以開始計算loss了菠剩,注意在使用Pytorch的交叉熵損失時易猫,需要將預測類別的那個維度轉(zhuǎn)換到通道這個維度上(dim1)。

loss_labels(iii)?

另外具壮,class_error計算的是Top-1精度(百分數(shù))准颓,即預測概率最大的那個類別與對應被分配的GT類別是否一致,這部分僅用于log棺妓,并不參與模型訓練攘已。

accuracy

ii). 回歸loss

回歸loss的計算包括預測框與GT的中心點和寬高的L1 loss以及GIoU loss

注意在下圖注釋中怜跑,num_matched_queries1+num_matched_queries2+..., 和 num_matched_objs1+num_matched_objs2+... 是相等的样勃,在前面 SetCriterion(iv) 圖中matcher的返回結(jié)果注釋中有說明。

loss_boxes(i)

以下就是loss的計算性芬。注意下 reduction 參數(shù)峡眶,若不顯式進行設(shè)置,在Pytorch的實現(xiàn)中默認是'mean'植锉,即返回所有涉及誤差計算的元素的均值辫樱。

loss_boxes(ii)

另外,在計算GIoU loss時俊庇,使用了torch.diag()獲取對角線元素狮暑,這是因為generalized_box_iou()方法返回的是所有預測框與所有GT的GIoU,比如預測框有N個辉饱,GT有M個搬男,那么返回結(jié)果就是NxM個GIoU。而如?loss_boxes(i) 圖中所示彭沼,我們預先對匹配的預測框和GT進行了排列缔逛,即N個預測框中的第1個匹配M個GT中的第1個,N中第2個匹配M中第2個姓惑,..褐奴,N中第i個匹配M中第i個,于是我們要取相互匹配的那一項來計算loss挺益。

generalized_box_iou(i)
generalized_box_iou(ii)

Hungarian algorithm(匈牙利算法)

build_matcher()方法返回HungarianMatcher對象歉糜,其實現(xiàn)了匈牙利算法,在這里用于預測集(prediction set)和GT的匹配,最終匹配方案是選取“l(fā)oss總和”最小的分配方式。注意CW對loss總和這幾個字用了引號唬血,其與loss函數(shù)中計算的loss并不完全一致红柱,在這里是作為度量cost/metric)的角色氮墨,度量的值決定了匹配的結(jié)果强岸,接下來我們看代碼實現(xiàn)就會一清二楚漩仙。

build_matcher

如doc string所述扰她,GT是不包含背景類的踊兜,通常預測集中的物體數(shù)量(默認為100)會比圖像中實際存在的目標數(shù)量多竿滨,匈牙利算法按1對1的方式進行匹配,沒有被匹配到的預測物體就自動被歸類為背景(non-objects)捏境。

HungarianMatcher(i)

以下cost_xx代表各類型loss的相對權(quán)重于游,在匈牙利算法中,描述為各種度量的相對權(quán)重會更合適垫言,因此贰剥,這里命名使用的是'cost'。

HungarianMatcher(ii)

現(xiàn)在來看看前向過程筷频,注意這里是不需要梯度的蚌成。

HungarianMatcher(iii)

首先將預測結(jié)果和GT進行reshape,并對應起來凛捏,方便進行計算担忧。

HungarianMatcher(iv)

注:以上tgt_bbox等式右邊的torch.cat()方法中應加上參數(shù)dim=0

然后就可以對各種度量(各類型loss)進行計算。

如代碼所示坯癣,這里的cost與上一節(jié)解析的loss并不完全一樣瓶盛,比如對于分類來說,loss計算使用的是交叉熵坡锡,而這里為了更加簡便蓬网,直接采用1減去預測概率的形式窒所,同時由于1是常數(shù)鹉勒,于是作者甚至連1都省去了,有夠機智(懶)的...

HungarianMatcher(v)

另外吵取,在計算bbox的L1誤差時禽额,使用了torch.cdist(),其中設(shè)置參數(shù)p=1代表L1范式(默認是p=2皮官,即L2范式)脯倒,這個方法會對每對預測框與GT都進行誤差計算:比如預測框有N個,GT有M個捺氢,結(jié)果就會有NxM個值藻丢。

接著對各部分度量加權(quán)求和,得到一個總度量摄乒。然后悠反,統(tǒng)計當前batch中每張圖像的GT數(shù)量残黑,這個操作是為什么呢?接著看斋否,你會發(fā)現(xiàn)這招很妙梨水!

C.split()在最后一維按各張圖像的目標數(shù)量進行分割,這樣就可以在各圖像中將預測結(jié)果與GT進行匹配了茵臭。

HungarianMatcher(vi)

匹配方法使用的是scipy優(yōu)化模塊中的linear_sum_assignment()疫诽,其輸入是二分圖的度量矩陣,該方法是計算這個二分圖度量矩陣的最小權(quán)重分配方式旦委,返回的是匹配方案對應的矩陣行索引和列索引奇徒。

linear_sum_assignment

結(jié)尾日常吹水

吾以為,loss函數(shù)的設(shè)計是DL項目中最重要的部分之一缨硝。CW每次看項目的源碼時逼龟,最打起精神的就是這一part了。

從數(shù)學的角度來看追葡,DL本質(zhì)上是一個優(yōu)化問題腺律,loss是模型學習目標在數(shù)學上的表達形式,我們期望模型朝著loss最小的方向發(fā)展宜肉,因此匀钧,loss函數(shù)的設(shè)計關(guān)系到優(yōu)化的可行性及難易程度,可謂成敗之關(guān)鍵谬返。因此之斯,這部分其實很考驗煉丹師的功力,也最能體現(xiàn)一個人考慮和解決問題的思想遣铝。

如今佑刷,我們是站在前人(一堆大佬,不酿炸,是巨佬L毙酢)的肩膀上,日常無腦地來來去去都用那幾種loss填硕,真是幸福的新生兒吶麦萤!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者扁眯。
  • 序言:七十年代末壮莹,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子姻檀,更是在濱河造成了極大的恐慌命满,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绣版,死亡現(xiàn)場離奇詭異胶台,居然都是意外死亡狭莱,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進店門概作,熙熙樓的掌柜王于貴愁眉苦臉地迎上來腋妙,“玉大人,你說我怎么就攤上這事讯榕≈杷兀” “怎么了?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵愚屁,是天一觀的道長济竹。 經(jīng)常有香客問我,道長霎槐,這世上最難降的妖魔是什么送浊? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮丘跌,結(jié)果婚禮上袭景,老公的妹妹穿的比我還像新娘。我一直安慰自己闭树,他們只是感情好耸棒,可當我...
    茶點故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著报辱,像睡著了一般与殃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上碍现,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天幅疼,我揣著相機與錄音,去河邊找鬼昼接。 笑死爽篷,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的辩棒。 我是一名探鬼主播狼忱,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼膨疏,長吁一口氣:“原來是場噩夢啊……” “哼一睁!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起佃却,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤者吁,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后饲帅,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體复凳,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡瘤泪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了育八。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片对途。...
    茶點故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖髓棋,靈堂內(nèi)的尸體忽然破棺而出实檀,到底是詐尸還是另有隱情,我是刑警寧澤按声,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布膳犹,位于F島的核電站,受9級特大地震影響签则,放射性物質(zhì)發(fā)生泄漏须床。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一渐裂、第九天 我趴在偏房一處隱蔽的房頂上張望豺旬。 院中可真熱鬧,春花似錦柒凉、人聲如沸哈垢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽耘分。三九已至,卻和暖如春绑警,著一層夾襖步出監(jiān)牢的瞬間求泰,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工计盒, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留渴频,地道東北人。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓北启,卻偏偏與公主長得像卜朗,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子咕村,可洞房花燭夜當晚...
    茶點故事閱讀 44,947評論 2 355