人工智能目标检测总结(五)——深入理解one-stage目标检测模型
本文翻譯自O(shè)ne-shot object detection,原作者保留版權(quán)。
作為計(jì)算機(jī)視覺領(lǐng)域的一項(xiàng)重要任務(wù),目標(biāo)檢測(cè)是要找到一張圖片里的感興趣物體:
這比圖像分類任務(wù)更高級(jí),因?yàn)榉诸愔恍枰嬖V圖像中主要物體是什么,然而目標(biāo)檢測(cè)要找到多個(gè)物體,不僅要分類,而且要定位出它們?cè)趫D像中的位置。目標(biāo)檢測(cè)模型不僅要預(yù)測(cè)出各個(gè)物體的邊界框(bounding boxes),還要給出每個(gè)物體的分類概率。通常情況下目標(biāo)檢測(cè)要預(yù)測(cè)許多邊界框。每個(gè)邊界框還需要一個(gè)置信度(confidence score),代表其包含物體的可能性大小。在后處理中,通過設(shè)定置信度閾值來過濾那些置信度較低的邊界框。目標(biāo)檢測(cè)相比分類任務(wù)更復(fù)雜,其面臨的一個(gè)主要問題在于一張圖片中可能存在許多位置不定的物體,而且模型會(huì)輸出很多預(yù)測(cè)結(jié)果,要計(jì)算損失函數(shù)就需要匹配真實(shí)框(ground-truth bounding box)與預(yù)測(cè)框。
這里我們主要關(guān)注one-stage目標(biāo)檢測(cè)算法(也稱one-shot object detectors),其特點(diǎn)是一步到位,速度相對(duì)較快。另外一類目標(biāo)檢測(cè)算法是two-stage的,如Faster R-CNN算法先生成候選框(region proposals,可能包含物體的區(qū)域),然后再對(duì)每個(gè)候選框進(jìn)行分類(也會(huì)修正位置)。這類算法相對(duì)就慢,因?yàn)樗枰啻芜\(yùn)行檢測(cè)和分類流程。而one-stage檢測(cè)方法,僅僅需要送入網(wǎng)絡(luò)一次就可以預(yù)測(cè)出所有的邊界框,因而速度較快,非常適合移動(dòng)端。最典型的one-stage檢測(cè)算法包括YOLO,SSD,SqueezeDet以及DetectNet。
盡管這些方法都已經(jīng)公布paper和源碼,但是大部分paper對(duì)技術(shù)細(xì)節(jié)并沒有完全給出來。因而,這篇博文將詳細(xì)講述one-shot檢測(cè)算法(以YOLO和SSD作為典例)的原理,以及它是如何訓(xùn)練和預(yù)測(cè)的。
為什么目標(biāo)檢測(cè)問題更難
圖像分類是生成單個(gè)輸出,即類別概率分布。但是這只能給出圖像整體內(nèi)容的摘要,當(dāng)圖像有多個(gè)感興趣的物體時(shí),它就不行了。在下面的圖像中,分類器可能會(huì)識(shí)別出圖像即包含貓,也包含狗,這是它最擅長的。
而目標(biāo)檢測(cè)模型將通過預(yù)測(cè)每個(gè)物體的邊界框來給出各個(gè)物體的位置:
因?yàn)榭梢詫W⒂趯?duì)邊界框內(nèi)的物體進(jìn)行分類并忽略外部背景,因此模型能夠?yàn)楦鱾€(gè)物體提供更加準(zhǔn)確的預(yù)測(cè)。如果數(shù)據(jù)集帶有邊界框標(biāo)注,則可以非常輕松地在模型添加一個(gè)定位預(yù)測(cè):只需預(yù)測(cè)額外4個(gè)數(shù)字,分別用于邊界框的每個(gè)角落。
現(xiàn)在該模型有兩部分輸出:類別概率分布和邊界框回歸。模型的損失函數(shù)只是將邊界框的回歸損失與分類的交叉熵?fù)p失相加,通常使用均方誤差(MSE):
outputs = model.forward_pass(image) class_pred = outputs[0] bbox_pred = outputs[1] class_loss = cross_entropy_loss(class_pred, class_true) bbox_loss = mse_loss(bbox_pred, bbox_true) loss = class_loss + bbox_loss optimize(loss)然后采用SGD方法對(duì)模型優(yōu)化訓(xùn)練,這是一個(gè)預(yù)測(cè)實(shí)例:
模型已正確對(duì)圖像中物體(狗)分類,并給出它在圖像中的位置。紅色框是真實(shí)框,而青色框是預(yù)測(cè)框,雖然有偏差,但非常接近。為了評(píng)估預(yù)測(cè)框與真實(shí)框的匹配程度,我們可以計(jì)算兩個(gè)邊界框之間的IOU(intersection-over-union,也稱為Jaccard index)。IOU在0到1之間,越大越好。理想情況下,預(yù)測(cè)框和真框的IOU為100%,但實(shí)際上任何超過50%的預(yù)測(cè)通常都被認(rèn)為是正確的。對(duì)于上面的示例,IOU為74.9%,因而預(yù)測(cè)框比較精確。
使用回歸方法預(yù)測(cè)單個(gè)邊界框可以獲得較好的結(jié)果。然而,當(dāng)圖像中存在多個(gè)感興趣的物體時(shí),就會(huì)出現(xiàn)問題:
由于模型只能預(yù)測(cè)一個(gè)邊界框,因而它必須要選擇一個(gè)物體,這會(huì)最終落在中間位置。實(shí)際上這很容易理解:圖像里有兩個(gè)物體,但是模型只能給出一個(gè)邊界框,因而選擇了折中,預(yù)測(cè)框位于兩者中間,也許大小也是介于兩個(gè)物體大小之間。
注意:也許你可能認(rèn)為模型應(yīng)該給出一個(gè)包含兩個(gè)物體的邊界框,但是這不太會(huì)發(fā)生,因?yàn)橛?xùn)練不是這樣的,真實(shí)框都是各個(gè)物體分開標(biāo)注的,而不是一組物體進(jìn)行標(biāo)注。
你也許認(rèn)為,上述問題很好解決,對(duì)于模型的回歸部分增加更多的邊界框預(yù)測(cè)不就好了。畢竟,如果模型可以預(yù)測(cè)N個(gè)邊界框,那么就應(yīng)該可以正確定位N個(gè)物體。聽起來不錯(cuò),但是并沒有效。就算模型有多個(gè)檢測(cè)器(這里一個(gè)邊界框回歸稱為一個(gè)檢測(cè)器),我們得到的邊界框依然會(huì)落在圖像中間:
為什么會(huì)這樣?問題是模型不知道應(yīng)該將哪個(gè)邊界框分配給哪個(gè)物體,為了安全起見,它將它們放在中間的某個(gè)位置。該模型無法決定:“我可以在左邊的馬周圍放置邊界框1,并在右邊的馬周圍放置框2。”相反,每檢測(cè)器仍然試圖預(yù)測(cè)所有物體,而不是一個(gè)檢測(cè)器預(yù)測(cè)一個(gè)物體。盡管該模型具有N個(gè)檢測(cè)器,但它們無法協(xié)同工作。具有多個(gè)邊界框檢測(cè)器的模型的效果與僅預(yù)測(cè)一個(gè)邊界框的模型完全相同。
我們需要的是使邊界框檢測(cè)器更專一化的一些方法,以便每個(gè)檢測(cè)器將嘗試僅預(yù)測(cè)單個(gè)物體,并且不同的探測(cè)器將找到不同的物體。在不專一的模型中,每個(gè)檢測(cè)器應(yīng)該能夠處理圖像中任何可能位置的各類物體。這太簡(jiǎn)單了,模型學(xué)會(huì)的是預(yù)測(cè)位于圖像中心的方框,因?yàn)檫@樣整個(gè)訓(xùn)練集實(shí)際上會(huì)最小化損失函數(shù)。從SGD的角度來看,這樣做平均得到了相當(dāng)不錯(cuò)的結(jié)果,但在實(shí)踐中它卻不是真正有用的結(jié)果,所以我們需要更加有效地訓(xùn)練模型。
通過將每個(gè)邊界框檢測(cè)器分配到圖像中的特定位置,one-stage目標(biāo)檢測(cè)算法(例如YOLO,SSD和DetectNet)都是這樣來解決這個(gè)問題。因?yàn)?#xff0c;檢測(cè)器學(xué)會(huì)專注于某些位置的物體。為了獲得更好的效果,我們還可以讓檢測(cè)器專注于物體的形狀和大小。
使用網(wǎng)格
使用固定網(wǎng)格上的檢測(cè)器是one-stage目標(biāo)檢測(cè)算法的主要思想,也是它們與基于候選框的目標(biāo)檢測(cè)方法(如R-CNN)的區(qū)別所在(實(shí)際上Faster R-CNN中RPN網(wǎng)絡(luò)也采用網(wǎng)格檢測(cè))。
讓我們考慮這類模型最簡(jiǎn)單的架構(gòu)。它首先有一個(gè)充當(dāng)特征提取器的基礎(chǔ)網(wǎng)絡(luò)。像大多數(shù)特征提取器一樣,它通常在ImageNet上訓(xùn)練。對(duì)于YOLO,特征提取器以416×416圖像作為輸入。SSD通常使用300×300大小的圖像。它們比用于分類的圖像(如224×224)更大,因?yàn)槲覀儾幌M麃G失細(xì)節(jié)。
作為特征提取器的基礎(chǔ)網(wǎng)絡(luò)可以是任何CNN網(wǎng)絡(luò),如Inception,ResNet以及YOLO中DarkNet,對(duì)于移動(dòng)端可以采用輕量級(jí)的網(wǎng)路,如SqueezeNet以及MobileNet等。在特征提取器的后面是幾個(gè)額外的卷積層。這是模型的目標(biāo)檢測(cè)部分,這些都經(jīng)過訓(xùn)練后學(xué)習(xí)如何預(yù)測(cè)這些邊界框以及框內(nèi)物體的分類概率。
有許多用于訓(xùn)練目標(biāo)檢測(cè)算法的通用數(shù)據(jù)集。這里,我們將使用Pascal VOC數(shù)據(jù)集,該數(shù)據(jù)集有20個(gè)類。因此神經(jīng)網(wǎng)絡(luò)的第一部分在ImageNet上進(jìn)行訓(xùn)練,而檢測(cè)部分是在VOC數(shù)據(jù)集上訓(xùn)練。
YOLO或SSD的實(shí)際架構(gòu)要比這個(gè)簡(jiǎn)單的示例網(wǎng)絡(luò)稍微復(fù)雜一點(diǎn),比如有殘差結(jié)構(gòu),但我們稍后會(huì)介紹。目前,上述模型已經(jīng)可用于構(gòu)建快速且相當(dāng)精確的目標(biāo)檢測(cè)模型。
最后一層的輸出是一個(gè)特征圖(上圖中的綠色圖)。對(duì)于我們的示例模型,這是一個(gè)包含125個(gè)通道的13×13大小的特征圖。
注意:此處的13x13是因?yàn)檩斎雸D片大小為416x416,而此處使用的特定基礎(chǔ)網(wǎng)絡(luò)具有五個(gè)池化層(或具有stride=2的卷積層),這樣按比例縮小32倍:416/32 = 13。如果你想要一個(gè)更精細(xì)的網(wǎng)格,例如19×19,那么輸入圖像應(yīng)該是19×32 =608像素寬和高(或者你可以使用一個(gè)較小步幅的網(wǎng)絡(luò))。
我們將此特征圖解釋為13x13個(gè)單元格的網(wǎng)格。該數(shù)字是奇數(shù),因此中心有一個(gè)單元格。網(wǎng)格中的每個(gè)單元格都有5個(gè)獨(dú)立的物體檢測(cè)器,每個(gè)檢測(cè)器都預(yù)測(cè)一個(gè)邊界框。
這里的關(guān)鍵是檢測(cè)器的位置是固定的:它只能檢測(cè)位于該單元附近的物體(實(shí)際上,物體的中心必須位于網(wǎng)格單元內(nèi))。這可以避免上一部分所說的問題,當(dāng)時(shí)的檢測(cè)器有太多的自由度。使用此網(wǎng)格,圖像左側(cè)的檢測(cè)器將永遠(yuǎn)不會(huì)預(yù)測(cè)位于右側(cè)的物體。
每個(gè)物體檢測(cè)器產(chǎn)生25個(gè)值:
- 表征類別概率的20個(gè)值
- 4個(gè)邊界框坐標(biāo)(中心x,中心y,寬度w,高度h)
- 1個(gè)值表示置信度
由于每個(gè)單元有5個(gè)檢測(cè)器,5×25 = 125,這就是我們有125個(gè)輸出通道的原因。
與常規(guī)分類器一樣,類別概率可以采用softmax獲得。我們可以通過查看最高概率值確定類別。 (雖然通常情況下將其視為多標(biāo)簽分類,但是這里20個(gè)類是獨(dú)立的,我們使用sigmoid而不是softmax)
置信度介于0和1(或100%)之間,用于表征模型認(rèn)為此預(yù)測(cè)邊界框包含真實(shí)物體的可能性。請(qǐng)注意,這個(gè)分?jǐn)?shù)只說明了這是否是一個(gè)物體,但沒有說明這是什么類型的物體,后面需要分類概率才能確定。
該模型總是預(yù)測(cè)固定數(shù)量的邊界框:13×13個(gè)單元乘以5個(gè)檢測(cè)器給出845個(gè)預(yù)測(cè)。顯然,絕大多數(shù)這些預(yù)測(cè)都不會(huì)有用,畢竟大多數(shù)圖像最多只包含少量物體,而不是超過800。置信度告訴我們哪些預(yù)測(cè)框可以忽略。通常情況下,我們最終會(huì)得到模型認(rèn)為很好的十幾個(gè)預(yù)測(cè)。其中一些將重疊,這是因?yàn)橄噜彽膯卧赡芏紝?duì)同一個(gè)物體進(jìn)行預(yù)測(cè),有時(shí)單個(gè)單元會(huì)進(jìn)行多次預(yù)測(cè)(盡管在訓(xùn)練中這是被抑制的)。
具有許多大部分重疊的預(yù)測(cè)框在目標(biāo)檢測(cè)中比較常見。標(biāo)準(zhǔn)后處理方法是應(yīng)用非最大抑制(NMS)來去除重疊框。簡(jiǎn)而言之,NMS保留擁有最高的置信度的預(yù)測(cè)框,并刪除任何與之重疊超過一定閾值的預(yù)測(cè)框(例如60%)。通常我們只保留10個(gè)左右的最佳預(yù)測(cè)并丟棄其他預(yù)測(cè)。理想情況下,我們希望圖像中的每個(gè)物體只有一個(gè)邊界框。
好吧,上面描述了使用網(wǎng)格進(jìn)行物體檢測(cè)的基本思路。但為什么它有效呢?
約束讓模型更容易學(xué)習(xí)
前面已經(jīng)提到將每個(gè)邊界框檢測(cè)器分配到圖像中的固定位置是one-stage目標(biāo)檢測(cè)算法的技巧。我們使用13×13網(wǎng)格作為空間約束,使模型更容易學(xué)習(xí)如何預(yù)測(cè)對(duì)象。使用這種(架構(gòu))約束是神經(jīng)網(wǎng)絡(luò)特別有用的技巧。事實(shí)上,卷積本身也是一個(gè)約束:卷積層實(shí)際上只是一個(gè)全連接(FC)層的更受限制的版本。(這就是為什么你可以使用FC層實(shí)現(xiàn)卷積,反之亦然,它們基本上是相同的)
如果我們只使用普通的FC層,那么神經(jīng)網(wǎng)絡(luò)模型要學(xué)習(xí)圖像要困難得多。對(duì)卷積層施加的約束:它一次只看幾個(gè)像素,并且連接共享相同的權(quán)重。我們使用這些約束來消除自由度并引導(dǎo)模型學(xué)習(xí)我們想要學(xué)習(xí)的內(nèi)容。
同樣,網(wǎng)格結(jié)構(gòu)強(qiáng)制讓模型學(xué)習(xí)專門針對(duì)特定位置的物體檢測(cè)器。左上角單元格中的檢測(cè)器僅預(yù)測(cè)位于左上角單元格附近的物體,而不會(huì)預(yù)測(cè)距離較遠(yuǎn)的物體(對(duì)模型進(jìn)行訓(xùn)練,使得給定網(wǎng)格單元中的檢測(cè)器僅負(fù)責(zé)檢測(cè)其中心落入該網(wǎng)格單元內(nèi)的物體)。
前面所說的模型沒有這樣的約束,因此它的回歸層永遠(yuǎn)不會(huì)限制在特定位置。
先驗(yàn)框(Anchors,錨)
網(wǎng)格是一種有用的約束,它限制了檢測(cè)器可以在圖像中找到物體的位置。我們還可以添加另一個(gè)約束來幫助模型做出更好的預(yù)測(cè),就是物體形狀的約束。
我們的示例模型具有13×13個(gè)網(wǎng)格單元,每個(gè)單元具有5個(gè)檢測(cè)器,因此總共有845個(gè)檢測(cè)器。但為什么每個(gè)網(wǎng)格單元有5個(gè)檢測(cè)器而不是一個(gè)?好吧,就像檢測(cè)器很難學(xué)會(huì)如何預(yù)測(cè)可以位于任何地方的物體一樣,檢測(cè)器也很難學(xué)會(huì)預(yù)測(cè)任何形狀或大小的物體。
我們使用網(wǎng)格來專門限制檢測(cè)器僅查看某個(gè)特定空間位置。相應(yīng)地,為每個(gè)網(wǎng)格單元設(shè)置幾個(gè)不同的檢測(cè)器,我們可以使這些物體檢測(cè)器中的每一個(gè)都專注于某種物體形狀。
我們?cè)?種特定形狀上訓(xùn)練檢測(cè)器:
紅色框是訓(xùn)練集中五個(gè)最典型的物體形狀。青色框分別是訓(xùn)練集中最小和最大的物體。請(qǐng)注意,這些邊界框顯示在輸入為416×416中。 (該圖還以淺灰色顯示網(wǎng)格,因此可以看到這五個(gè)形狀網(wǎng)格單元相關(guān)。每個(gè)網(wǎng)格單元在輸入圖像中覆蓋32×32像素)
這五種形狀稱為先驗(yàn)框或者錨。先驗(yàn)框只是一個(gè)寬度和高度列表:
anchors = [1.19, 1.99, # width, height for anchor 12.79, 4.60, # width, height for anchor 24.54, 8.93, # etc.8.06, 5.29,10.33, 10.65]先驗(yàn)框描述數(shù)據(jù)集中5個(gè)最常見(平均)的物體形狀。這里的“形狀”指的是它們的寬度和高度,因?yàn)樵谀繕?biāo)檢測(cè)種總是使用基本的矩形。有5個(gè)先驗(yàn)框并非偶然。網(wǎng)格單元中的每個(gè)檢測(cè)器都有一個(gè)先驗(yàn)框。就像網(wǎng)格對(duì)檢測(cè)器施加位置約束一樣,先驗(yàn)框迫使檢測(cè)器專門處理特定的物體形狀。
單元中的第一個(gè)檢測(cè)器負(fù)責(zé)檢測(cè)與第一個(gè)先驗(yàn)框相似的物體,第二個(gè)檢測(cè)器負(fù)責(zé)與第二個(gè)先驗(yàn)框相似的物體,依此類推。因?yàn)槲覀兠總€(gè)單元有5個(gè)檢測(cè)器,所以我們也有5個(gè)先驗(yàn)框。因此,檢測(cè)器1將拾取小物體,檢測(cè)器2拾取稍大的物體,檢測(cè)器3拾取長而扁平的物體,檢測(cè)器4拾取高而薄的物體,而檢測(cè)器5拾取大物體。
注意:上面代碼片段中先驗(yàn)框的寬度和高度用網(wǎng)格的13×13坐標(biāo)系表示,因此第一個(gè)先驗(yàn)框略寬于1個(gè)網(wǎng)格單元格,高度接近2個(gè)網(wǎng)格單元格。最后一個(gè)先驗(yàn)框覆蓋了幾乎整個(gè)網(wǎng)格,超過10×10個(gè)單元格。這就是YOLO設(shè)置先驗(yàn)框的方式。然而,SSD具有幾個(gè)不同尺寸的不同網(wǎng)格,因此使用先驗(yàn)框的標(biāo)準(zhǔn)化坐標(biāo)(在0和1之間),它們與網(wǎng)格的大小無關(guān)。任何一種方法都可以。
重要的是要了解這些先驗(yàn)框是事先選擇的。它們是恒定的,在訓(xùn)練期間不會(huì)改變。
由于先驗(yàn)框只是一個(gè)寬度和高度集合,而且它們是事先選擇的,所以YOLO紙也稱它們?yōu)椤癲imension priors”(Darknet,官方的YOLO源代碼,稱它們?yōu)椤癰iases”,也是比較合理 - 檢測(cè)器偏向于預(yù)測(cè)某個(gè)形狀的物體,但是這個(gè)術(shù)語令人困惑)。
YOLO通過在所有訓(xùn)練圖像的所有邊界框上進(jìn)行k-means聚類來選擇先驗(yàn)框(k=5,因此它找到五個(gè)最常見的物體形狀)。因此,YOLO的先驗(yàn)框適合當(dāng)前訓(xùn)練(和測(cè)試)的數(shù)據(jù)集。k-means算法中數(shù)據(jù)點(diǎn)是數(shù)據(jù)集中所有真實(shí)邊界框的寬度和高度值。如果我們?cè)赑ascal VOC數(shù)據(jù)集的框中運(yùn)行k-means,將得到5個(gè)簇:
這些簇表示此數(shù)據(jù)集中存在的不同物體形狀的五個(gè)“平均值”。你可以看到k-means在藍(lán)色簇中將非常小的物體組合在一起,在紅色簇中將較大的物體組合在一起,將非常大的物體分組為綠色。它決定將中間物體分成兩組:一組邊界框(黃色)寬大于高,另一組高于寬(紫色)。
但5個(gè)簇是最佳選擇嗎?我們可以設(shè)定不同的k進(jìn)行k-means,并計(jì)算真實(shí)框與它們最接近的先驗(yàn)框之間的平均IOU。當(dāng)然,使用更多的質(zhì)心(更大的k值)會(huì)產(chǎn)生更高的平均IOU,但這也意味著我們需要在每個(gè)網(wǎng)格單元中使用更多的檢測(cè)器,這會(huì)使模型運(yùn)行得更慢。對(duì)于YOLO v2,他們選擇5個(gè)聚類中心,這是在準(zhǔn)確度和模型復(fù)雜性之間的折衷。
SSD不使用k-means來確定先驗(yàn)框。相反,它使用數(shù)學(xué)公式來計(jì)算先驗(yàn)框尺寸,因此SSD的先驗(yàn)框與數(shù)據(jù)集無關(guān)(SSD稱它們?yōu)椤癲efault boxes”)。SSD和YOLO的先驗(yàn)框設(shè)置,到底哪種方式比較好,并沒有定論。另一個(gè)小差異是:YOLO的先驗(yàn)框只是寬度和高度,但SSD的先驗(yàn)框也有x,y位置。其實(shí),YOLO也包含位置,只是默認(rèn)先驗(yàn)框位置始終位于網(wǎng)格單元格的中心(對(duì)于SSD,先驗(yàn)框也是在網(wǎng)格中心)。
由于先驗(yàn)框,檢測(cè)器僅預(yù)測(cè)相比邊界框的偏移值,這使得訓(xùn)練更容易,因?yàn)轭A(yù)測(cè)值全為零時(shí)等價(jià)于輸出先驗(yàn)框,平均上更接近真實(shí)物體。如果沒有先驗(yàn)框,每個(gè)檢測(cè)器都必須從頭開始學(xué)習(xí)不同的邊界框形狀,這相當(dāng)困難。
注意:本文所說的YOLO是指YOLOv2或v3,這與YOLOv1是非常不同的。YOLOv1具有較小的網(wǎng)格(7×7,每個(gè)單元僅有2個(gè)檢測(cè)器),使用全連接層而不是卷積層來預(yù)測(cè)網(wǎng)格,并且不使用先驗(yàn)框。那個(gè)版本的YOLO現(xiàn)在已經(jīng)過時(shí)了。相比之下,v2和v3之間的差異要小得多。而YOLOv3在很多方面與SSD非常相似。
模型到底預(yù)測(cè)了什么
讓我們更加細(xì)致地看一下模型的輸出是什么,由于模型僅僅是一個(gè)卷積神經(jīng)網(wǎng)絡(luò),所以前向過程是這樣的:
你輸入一個(gè)416x416的RGB圖像,經(jīng)過卷積層之后是一個(gè)13x13x125的特征圖。由于是回歸預(yù)測(cè),最后的層沒有激活函數(shù)。最后的輸出包含21,125個(gè)數(shù),我們要將它們轉(zhuǎn)化為邊界框。
我們采用4個(gè)數(shù)來表示一個(gè)邊界框的坐標(biāo)。通常有兩種方式:或者用xmin, ymin, xmax, ymax表示邊界框左上和右下點(diǎn)坐標(biāo),或者使用center x, center y, width, height。兩個(gè)方式都可以(兩者可以互相轉(zhuǎn)換),但是這里采用后者,因?yàn)橹揽蛑行母尤菀讓⑦吔缈蚺c網(wǎng)格單元進(jìn)行匹配。
模型預(yù)測(cè)的不是邊界框在圖像中的絕對(duì)坐標(biāo),而是4個(gè)偏移值(delta or offset):
- delta_x, delta_y:邊界框中心點(diǎn)在網(wǎng)格單元內(nèi)部的坐標(biāo);
- delta_w, delta_h: 邊界框的寬和高相對(duì)先驗(yàn)框的縮放值。
每個(gè)檢測(cè)器預(yù)測(cè)的邊界框都是相對(duì)一個(gè)先驗(yàn)框,這個(gè)先驗(yàn)框已經(jīng)很好地匹配了物體的實(shí)際大小(這也是為什么要使用先驗(yàn)框),但是它不完全準(zhǔn)確。因而,我們需要預(yù)測(cè)一個(gè)縮放因子來知道預(yù)測(cè)的框是比先驗(yàn)框大還是小,同樣地,也要知道預(yù)測(cè)框的中心相對(duì)于網(wǎng)格中心的偏移量。
要得到邊界框在圖像中的真實(shí)寬與高,需要這樣計(jì)算:
box_w[i, j, b] = anchor_w[b] * exp(delta_w[i, j, b]) * 32 box_h[i, j, b] = anchor_h[b] * exp(delta_h[i, j, b]) * 32這里的i和j是網(wǎng)格(0-12)的行與列,而b是檢測(cè)器(0-4)的索引。預(yù)測(cè)框比原始圖片寬或者高都是正常的,但是寬和高不應(yīng)該會(huì)是負(fù)值,因此這里取預(yù)測(cè)值的指數(shù)。如果delta_w<0,那么exp(delta_w)介于0~1,此時(shí)預(yù)測(cè)框比先驗(yàn)框小。若delta_w>0,那么exp(delta_w)大于1,此時(shí)預(yù)測(cè)框比先驗(yàn)框大。特別地,delta_w=0,那么exp(delta_w)為1,此時(shí)預(yù)測(cè)框與先驗(yàn)框一樣大小。順便說一下,這里之所以要乘以32是因?yàn)橄闰?yàn)框坐標(biāo)是13x13網(wǎng)格上的,網(wǎng)格上各個(gè)像素點(diǎn)等價(jià)于原始416x416圖像上的32個(gè)像素點(diǎn)。
注意:在損失函數(shù)中,我們使用上述公式的逆運(yùn)算:不是將預(yù)測(cè)的偏移值通過exp轉(zhuǎn)換到實(shí)際坐標(biāo),而是將真實(shí)框通過log運(yùn)算轉(zhuǎn)換為偏移值。后面會(huì)詳細(xì)介紹。
利用下面公式可以得到預(yù)測(cè)框中心的像素坐標(biāo):
box_x[i, j, b] = (i + sigmoid(delta_x[i, j, b])) * 32 box_y[i, j, b] = (j + sigmoid(delta_y[i, j, b])) * 32YOLO模型的一個(gè)重要特點(diǎn)是僅當(dāng)某個(gè)物體的中心點(diǎn)落在一個(gè)檢測(cè)器的網(wǎng)格單元中心時(shí),這個(gè)檢測(cè)器才負(fù)責(zé)預(yù)測(cè)它。這樣避免沖突,即相鄰的單元格不會(huì)用來預(yù)測(cè)同一個(gè)物體。這樣,delta_x和delta_y必須限制在0~1之間,代表預(yù)測(cè)框在網(wǎng)格單元的相對(duì)位置,這里用sigmod函數(shù)限制值的范圍。然后我們加上單元格的坐標(biāo)i和j(0~12之間),乘以每個(gè)單元格所包含的像素?cái)?shù)(32)。這樣box_x和box_y就表示預(yù)測(cè)框中心在原始416×416圖像中的坐標(biāo)。
然后,SSD卻有點(diǎn)不同:
box_x[i, j, b] = (anchor_x[b] + delta_x[i, j, b]*anchor_w[b]) * image_w box_y[i, j, b] = (anchor_y[b] + delta_y[i, j, b]*anchor_h[b]) * image_h這里預(yù)測(cè)的delta值實(shí)際上是先驗(yàn)框?qū)捇蚋叩谋稊?shù),所以沒有sigmoid函數(shù)。這也意味著在SSD中物體的中心可落在單元格的外面。需要注意的是SSD預(yù)測(cè)的坐標(biāo)是相對(duì)于先驗(yàn)框中心而不是單元格中心。實(shí)際上一般情況下兩個(gè)中心是重合的,但是SSD和YOLO采用的坐標(biāo)系不一樣。SSD的先驗(yàn)框坐標(biāo)是歸一化到[0,1],這樣它們獨(dú)立于網(wǎng)格大小(SSD之所以這樣是采用了不同大小的網(wǎng)格)。
可以看出,即使YOLO和SSD大致原理是相同的,但是具體的實(shí)現(xiàn)細(xì)節(jié)是有差異的。
除了坐標(biāo)之外,模型每個(gè)邊界框預(yù)測(cè)了一個(gè)置信度,一般采用sigmoid函數(shù)得到0~1的概率值:
confidence[i, j, b] = sigmoid(predicted_confidence[i, j, b])實(shí)際上我們的模型預(yù)測(cè)了845個(gè)邊界框,但是一張圖片中的物體一般是很少的。在訓(xùn)練過程中,由于我們僅讓一個(gè)檢測(cè)器預(yù)測(cè)一個(gè)真實(shí)框,因此只有很少的預(yù)測(cè)框的置信度較高,那些不應(yīng)該找到物體的檢測(cè)器應(yīng)該得到較小的置信度。
最后,我們預(yù)測(cè)分類概率,對(duì)于Pasval VOC數(shù)據(jù)每個(gè)邊界框有20個(gè)值,采用softmax得到概率分布:
classes[i, j, b] = softmax(predicted_classes[i, j, b])除了采用softmax,還可以采用sigmoid,這將變成一個(gè)多標(biāo)簽分類器,每個(gè)預(yù)測(cè)框?qū)嶋H上可以同時(shí)有多個(gè)類別,SSD和YOLOv3是這樣。
但是SSD沒有預(yù)測(cè)置信度,它給分類器增加了一個(gè)特殊的類:背景。如果分類結(jié)果是背景,那么意味著檢測(cè)器沒有找到物體,這實(shí)際上等價(jià)于YOLO給出一個(gè)較低的置信度。
由于很多預(yù)測(cè)是不需要的,所以對(duì)于置信度較低的預(yù)測(cè)我們將舍棄。在YOLO中,結(jié)合置信度和最大類別概率來過濾預(yù)測(cè)值(條件概率):
confidence_in_class[i, j, b] = classes[i, j, b].max() * confidence[i, j, b]置信度低表示模型很不確定預(yù)測(cè)框是否含有物體,而低分類概率表示模型不確定哪種物體在預(yù)測(cè)框內(nèi),只有兩者都高時(shí),我們才采納這個(gè)預(yù)測(cè)值。
由于大部分的框不含物體,我們可以忽略那些置信度低于某個(gè)閾值(比如0.3)的預(yù)測(cè)框,然后對(duì)余下的框執(zhí)行NMS(non-maximum suppression),去除重疊框,這樣處理后一般得到1~10個(gè)預(yù)測(cè)框。
這是卷積預(yù)測(cè)
卷積神經(jīng)網(wǎng)絡(luò)天然適合這樣的網(wǎng)格檢測(cè)器,13×13的網(wǎng)格是卷積層得到的. 卷積實(shí)際上是在整個(gè)輸入圖像上以較小的窗口(卷積核)進(jìn)行滑動(dòng),卷積核在每個(gè)位置是共享的。我們的樣例模型最后的卷積層包含125個(gè)卷積核。
為什么是125?因?yàn)橛?個(gè)檢測(cè)器,每個(gè)檢測(cè)器有25個(gè)卷積核。這25個(gè)卷積核中的每一個(gè)都預(yù)測(cè)邊界框的屬性值:坐標(biāo)x和y,寬度,高度,置信度,20類概率。
注意:一般來說,如果數(shù)據(jù)集有k類,而模型有b個(gè)檢測(cè)器,那么網(wǎng)格需要有b×(4+1+k)個(gè)輸出通道。
這125個(gè)卷積核在13×13特征圖中的每個(gè)位置上滑動(dòng),并在每個(gè)位置上進(jìn)行預(yù)測(cè)。然后,我們將這125個(gè)數(shù)字解釋為5個(gè)預(yù)測(cè)邊界框。最初,在每個(gè)網(wǎng)格位置預(yù)測(cè)到的125個(gè)數(shù)字將是完全隨機(jī)和無意義的,但是隨著訓(xùn)練,損失函數(shù)將引導(dǎo)模型學(xué)習(xí)做出更有意義的預(yù)測(cè)。
盡管每個(gè)網(wǎng)格單元中有5個(gè)檢測(cè)器,但對(duì)于845個(gè)檢測(cè)器來說,這個(gè)模型實(shí)際上只學(xué)習(xí)了總共5個(gè)檢測(cè)器,而不是每個(gè)網(wǎng)格單元都學(xué)習(xí)5個(gè)唯一的檢測(cè)器。這是因?yàn)榫矸e層的權(quán)重在每個(gè)位置都相同,因此在網(wǎng)格單元之間共享。但模型為每個(gè)先驗(yàn)框?qū)W習(xí)一個(gè)檢測(cè)器,它們?cè)趫D像上滑動(dòng),以獲得845個(gè)預(yù)測(cè)值,網(wǎng)格上每個(gè)位置有5個(gè)。因此,盡管我們總共只有5個(gè)獨(dú)特的檢測(cè)器,但由于卷積的緣故,這些檢測(cè)器與它們?cè)趫D像中的位置無關(guān),因此無論它們位于何處,都可以檢測(cè)到物體。每個(gè)位置的輸入像素與檢測(cè)器所學(xué)習(xí)到的權(quán)重,決定了該位置的最終邊界框預(yù)測(cè)。
這也解釋了為什么模型總是預(yù)測(cè)邊界框相對(duì)于網(wǎng)格單元中心的位置。由于該模型具有卷積性質(zhì),無法預(yù)測(cè)絕對(duì)坐標(biāo),而卷積核在圖像上滑動(dòng),因此它們的預(yù)測(cè)總是相對(duì)于在特征圖中的當(dāng)前位置。
YOLO vs SSD
上面關(guān)于one-stage的目標(biāo)檢測(cè)模型的原理的描述幾乎適用于所有的檢測(cè)器。但是在解釋輸出的方式上可能存在細(xì)微的差異(例如,分類概率采用sigmoid而不是softmax),但一般是相同的。
然而,不同版本的YOLO和SSD之間存在一些結(jié)構(gòu)上的差異。以下是YOLOv2&v3和SSD模型的架構(gòu)示意圖:
可以看到,YOLOv3和SSD非常相似,盡管它們是通過不同的方法得到網(wǎng)格(YOLO使用升序采樣,SSD使用降序采樣)。而YOLOv2(我們的示例模型)只有一個(gè)13×13的輸出網(wǎng)格,而SSD有幾個(gè)不同大小的網(wǎng)格。Mobilenet+SSD版本有6個(gè)網(wǎng)格,大小分別為19×19、10×10、5×5、3×3、2×2和1×1。因此,SSD網(wǎng)格的范圍從非常細(xì)到非常粗。這樣做是為了在更廣泛的物體尺度上獲得更精確的預(yù)測(cè)。比較精細(xì)的19×19網(wǎng)格,其網(wǎng)格單元非常靠近,負(fù)責(zé)預(yù)測(cè)最小的物體。而最后一層生成的1×1網(wǎng)格負(fù)責(zé)預(yù)測(cè)基本上占據(jù)整個(gè)圖像的較大物體,其他層的網(wǎng)格適應(yīng)比較寬范圍的物體。YOLOv3更像SSD,因?yàn)樗褂?個(gè)不同大小的網(wǎng)格預(yù)測(cè)邊界框。
和YOLO一樣,每個(gè)SSD網(wǎng)格單元都會(huì)進(jìn)行多個(gè)預(yù)測(cè)。每個(gè)網(wǎng)格單元的檢測(cè)數(shù)量各不相同:在更大、更細(xì)粒度的網(wǎng)格上,SSD每個(gè)網(wǎng)格單元有3或4個(gè)檢測(cè)器,在較小的網(wǎng)格上,每個(gè)網(wǎng)格單元有6個(gè)檢測(cè)器。而YOLOv3的每個(gè)網(wǎng)格單元均使用3個(gè)檢測(cè)器。
坐標(biāo)預(yù)測(cè)是相對(duì)于先驗(yàn)框的,在SSD文件中被稱為“default boxes”,但有一個(gè)區(qū)別是,SSD的預(yù)測(cè)中心坐標(biāo)可以超出其網(wǎng)格單元。先驗(yàn)框位于單元的中心,但SSD不會(huì)對(duì)預(yù)測(cè)的X,Y偏移應(yīng)用sigmoid。所以理論上,模型右下角的一個(gè)檢測(cè)器可以預(yù)測(cè)一個(gè)中心在圖像左上角的邊界框(但這在實(shí)踐中可能不會(huì)發(fā)生)。
與YOLO不同的是,SSD沒有置信度。每個(gè)預(yù)測(cè)只包含4個(gè)邊界框坐標(biāo)和類概率。YOLO使用置信度來表示這個(gè)預(yù)測(cè)包含實(shí)際物體的可能性。SSD通過一個(gè)特殊的“背景”類來解決這個(gè)問題:如果類預(yù)測(cè)是背景類,那么它意味著沒有為這個(gè)檢測(cè)器找到物體。這實(shí)際上和YOLO中置信度較低等同。
SSD在先驗(yàn)框上與YOLO稍有不同。因?yàn)閅OLO必須從單個(gè)網(wǎng)格進(jìn)行所有預(yù)測(cè),所以它使用的先驗(yàn)框的范圍從小(大約單個(gè)網(wǎng)格單元的大小)到大(大約整個(gè)圖像的大小)。SSD更為保守。19×19網(wǎng)格上的先驗(yàn)框比10×10網(wǎng)格上的要小,比5×5網(wǎng)格上的更小,以此類推。與YOLO不同的是,SSD不使用先驗(yàn)框來使檢測(cè)器專注于物體大小,而是使用不同的網(wǎng)格來實(shí)現(xiàn)這一點(diǎn)。SSD的先驗(yàn)框主要用于使檢測(cè)器處理物體形狀(長寬比)的變化,而不是它們的大小。如前所述,SSD的先驗(yàn)框是使用公式計(jì)算的,而YOLO的先驗(yàn)框是通過對(duì)訓(xùn)練數(shù)據(jù)運(yùn)行k-means聚類來找到的。
因?yàn)镾SD使用3到6個(gè)先驗(yàn)框,它有6個(gè)網(wǎng)格而不是1個(gè),所以實(shí)際上它總共使用了32個(gè)獨(dú)特的檢測(cè)器(這與具體網(wǎng)絡(luò)結(jié)構(gòu)有關(guān))。因?yàn)镾SD有更多的網(wǎng)格和檢測(cè)器,它將輸出更多的預(yù)測(cè)。YOLO進(jìn)行了845次預(yù)測(cè),而MobileNet-SSD則包含1917次預(yù)測(cè)。而SSD512甚至輸出24564個(gè)預(yù)測(cè)!其優(yōu)點(diǎn)是可以更容易找到圖像中的所有物體。缺點(diǎn)是,你最終不得不做更多的后處理來找出你想要保留的預(yù)測(cè)。
由于這些差異,將真實(shí)框與檢測(cè)器的匹配方式在SSD和YOLO之間稍有不同,損失函數(shù)也略有不同。后面講解訓(xùn)練過程時(shí)會(huì)討論這個(gè)問題。
現(xiàn)在關(guān)于這些模型如何做出預(yù)測(cè)已經(jīng)講解的非常清楚了。現(xiàn)在讓我們來看看訓(xùn)練目標(biāo)檢測(cè)模型所需的數(shù)據(jù)類型。
數(shù)據(jù)
有很多常用的目標(biāo)檢測(cè)訓(xùn)練數(shù)據(jù)集,如Pascal VOC, COCO, KITTI。這里我們關(guān)注Pascal VOC,因?yàn)樗亲畛S玫?#xff0c;并且YOLO使用了它。
VOC數(shù)據(jù)集包含圖像和不同任務(wù)的標(biāo)注,這里我們僅關(guān)注目標(biāo)檢測(cè)的標(biāo)注,共有20個(gè)類別:
aeroplane bicycle bird boat bottle bus car cat chair cow diningtable dog horse motorbike person pottedplant sheep sofa train tvmonitorVOC數(shù)據(jù)集附帶一個(gè)建議的訓(xùn)練/驗(yàn)證集分割,大約為50/50。由于數(shù)據(jù)集不太大,因此將50%的數(shù)據(jù)用于驗(yàn)證似乎有點(diǎn)浪費(fèi)。因此,通常將訓(xùn)練集和驗(yàn)證集組合成一個(gè)大的訓(xùn)練集“trainval”(總共16551張圖像),然后隨機(jī)選取10%左右的圖像用于驗(yàn)證。可以在2007測(cè)試集上測(cè)試模型,因?yàn)閘abel已經(jīng)給出。還有一個(gè)2012年的測(cè)試集,但label是不公開的(也有習(xí)慣于將2007年測(cè)試集包括在訓(xùn)練數(shù)據(jù)中,數(shù)據(jù)越多越好)。
2007+2012組合訓(xùn)練集有8218個(gè)帶物體框標(biāo)注的圖像,驗(yàn)證集有8333個(gè)圖像,2007測(cè)試集有4952個(gè)圖像。這比ImageNet的130萬張圖片要少得多,所以最好使用遷移學(xué)習(xí),而不是從頭開始訓(xùn)練模型。這就是為什么我們從一個(gè)已經(jīng)在ImageNet上預(yù)訓(xùn)練過的特征提取器開始。
標(biāo)注
標(biāo)注描述了圖像中的內(nèi)容。簡(jiǎn)而言之,標(biāo)注提供了我們訓(xùn)練所需的目標(biāo)。標(biāo)注采用XML格式,每個(gè)訓(xùn)練圖像一個(gè)。標(biāo)注文件包含一個(gè)或多個(gè)帶有類名稱的部分:用xmin、xmax、ymin、ymax描述的邊界框以及每個(gè)object的一些其他屬性。如果一個(gè)物體被標(biāo)為difficult,我們將忽略它,這些通常是非常小的物體,它們也被VOC競(jìng)賽的官方評(píng)估指標(biāo)忽略。以下是標(biāo)注文件示例,voc2007/annotations/003585.xml:
<annotation><folder>VOC2007</folder>
<filename>003585.jpg</filename>
<source>
<database>The VOC2007 Database</database>
<annotation>PASCAL VOC2007</annotation>
<image>flickr</image>
<flickrid>304100796</flickrid>
</source>
<owner>
<flickrid>Huw Lambert</flickrid>
<name>huw lambert</name>
</owner>
<size>
<width>333</width>
<height>500</height>
<depth>3</depth>
</size>
<object>
<name>person</name>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>138</xmin>
<ymin>183</ymin>
<xmax>259</xmax>
<ymax>411</ymax>
</bndbox>
</object>
<object>
<name>motorbike</name>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>89</xmin>
<ymin>244</ymin>
<xmax>291</xmax>
<ymax>425</ymax>
</bndbox>
</object>
</annotation>
這個(gè)圖片大小為333×500,包含兩個(gè)物體:人和摩托車。沒有被標(biāo)注為difficult或者truncated (部分在圖像外).
注意:Pascal VOC數(shù)據(jù)集坐標(biāo)從1開始,而不是0,也許是采用MATLAB的格式。 我們可以畫出這個(gè)圖像的各個(gè)物體的邊界框:
VOC2007和2012共包含如下的圖像:
------------------------------
train 8218 19910
val 8333 20148
test 4952 12032 (2007 only)
約有一半的圖像僅有一個(gè)物體,其它的包含1個(gè)以上,下面是訓(xùn)練集統(tǒng)計(jì)的直方圖:
一張圖片中最大物體數(shù)為39,驗(yàn)證集和測(cè)試集的直方圖大致類似。同樣地,我們給出訓(xùn)練集中所有物體區(qū)域大小的直方圖(長和寬歸一化到[0,1]):
可以看到許多物體相對(duì)較小。峰值為1.0是因?yàn)橛邢喈?dāng)多的物體大于圖像(例如,只有部分可見的人),因此邊界框填充整個(gè)圖像。這里還有另一種方法來查看這些數(shù)據(jù):邊界框?qū)挾扰c高度的關(guān)系圖。圖中的“坡度”顯示框的高寬比。
數(shù)據(jù)擴(kuò)增
由于數(shù)據(jù)集相當(dāng)小,在訓(xùn)練時(shí)經(jīng)常使用大量的數(shù)據(jù)擴(kuò)增,如隨機(jī)翻轉(zhuǎn)、隨機(jī)裁剪、顏色抖動(dòng)等。值得注意的是,對(duì)圖像所做的任何操作都必須對(duì)邊界框同樣執(zhí)行!比如,如果翻轉(zhuǎn)圖像,還必須對(duì)應(yīng)地翻轉(zhuǎn)真值框的坐標(biāo)。
YOLO的數(shù)據(jù)擴(kuò)增流程如下:
- 加載原始圖像;
- 通過隨機(jī)增加/減去原始大小的20%來選擇新的寬度和高度;
- 按照新大小裁剪圖像,如果新圖像在一個(gè)或多個(gè)邊上大于原始圖像,則用零填充
- 將圖像resize到416×416,使其成為正方形
- 隨機(jī)水平翻轉(zhuǎn)圖像(50%的概率)
- 隨機(jī)改變圖像的色調(diào)、飽和度和曝光(亮度)
- 對(duì)應(yīng)地,要通過移動(dòng)和縮放邊界框坐標(biāo)來調(diào)整邊界框,以適應(yīng)前面所做的裁剪和調(diào)整大小,以及水平翻轉(zhuǎn)等操作
旋轉(zhuǎn)也是一種常見的數(shù)據(jù)擴(kuò)增技術(shù),但這會(huì)比較麻煩,因?yàn)槲覀冞€需要同時(shí)旋轉(zhuǎn)邊界框,所以通常不會(huì)這樣做。而SSD采用的數(shù)據(jù)擴(kuò)增方式包括:
- 隨機(jī)裁剪一個(gè)圖像區(qū)域,使該區(qū)域中物體的最小IOU(與原始圖像中物體)為0.1、0.3、0.5、0.7或0.9,IOU越小,模型就越難檢測(cè)到物體
- 使用“縮小”增強(qiáng),將圖像變小,從而構(gòu)建包含小物體的訓(xùn)練數(shù)據(jù),這對(duì)于模型更好地處理小物體很有用。
隨機(jī)裁剪可能會(huì)導(dǎo)致物體的部分(或全部)落在裁剪圖像之外。因此,我們只希望保留中心位于該裁剪區(qū)域某個(gè)位置的邊界框,而不希望保留中心位于裁剪區(qū)域之外的框。
注意高寬比
我們的預(yù)測(cè)是在13x13的正方形網(wǎng)格上,輸入圖像也是正方形的(416x416)。但是訓(xùn)練數(shù)據(jù)集中圖像通常不是正方形的,而且測(cè)試圖像一般也不是。而且,所有的圖像大小可能并不相同。下圖是VOC數(shù)據(jù)集中所有圖像的高寬比的可視化:
紅色框是寬大于高,而青色框恰恰相反。 雖然存在一些奇怪的高寬比,但是大部分是1.333 (4:3), 1.5 (3:2), 0.75 (3:4)。有些圖片甚至很寬,這里是一個(gè)極端例子:
由于網(wǎng)絡(luò)的輸入是416×416大小的正方形圖像,因此我們必須將訓(xùn)練圖像放在該正方形中。下面是幾種方法:
- 直接將圖像resize到416×416,這可能會(huì)擠壓圖像;
- 將最小邊調(diào)整為416,然后從圖像中裁剪出416×416區(qū)域;
- 將最大邊調(diào)整為416,用零填充另外的短邊;
上述方法都是有效的,但每個(gè)方法都有其副作用。我們直接將其高寬比更改為1:1,可能會(huì)擠壓圖像。如果原始圖像寬大于高,則所有物體都比平常窄。如果原來的物體高大于寬,那么所有的物體都會(huì)變平。通過裁剪,雖然高寬比保持不變,但我們可能切掉圖像的重要部分,使模型更難看到真實(shí)的物體,這樣模型可能需要預(yù)測(cè)部分位于圖像外部的邊界框。而對(duì)于方法3,它可能會(huì)使物體太小而無法檢測(cè),尤其是在高寬比極端的情況下。
為什么這很重要?訓(xùn)練前,我們將邊界框的xmin和xmax除以圖像寬度,ymin和ymax除以圖像高度,以歸一化坐標(biāo),使它們介于0和1之間。這樣做是為了使訓(xùn)練獨(dú)立于每個(gè)圖像的實(shí)際像素大小。但是輸入的圖像通常不是正方形的,所以x坐標(biāo)除以一個(gè)與y坐標(biāo)不同的數(shù)字。根據(jù)圖像的尺寸和高寬比,每個(gè)圖像的除數(shù)可能不同,這會(huì)影響我們?nèi)绾翁幚磉吔缈蜃鴺?biāo)和先驗(yàn)框。
方法1是最簡(jiǎn)單粗暴,盡管它會(huì)暫時(shí)破壞圖像的高寬比。如果所有的圖像都有相似的高寬比(在VOC中沒有),或者高寬比不太極端,那么神經(jīng)網(wǎng)絡(luò)仍然可以正常工作。CNN網(wǎng)絡(luò)似乎對(duì)于物體的“厚度”變化相當(dāng)健壯(意思是物體擠壓時(shí)CNN依然有效)。
對(duì)于方法2和3,在歸一化邊界框坐標(biāo)時(shí),我們應(yīng)該記住高寬比。現(xiàn)在有可能邊界框比輸入圖像大,因?yàn)槲覀冎皇菍?duì)裁剪部分進(jìn)行預(yù)測(cè)。而由于物體可能部分落在圖像之外,邊界框也可能部分落在圖像之外。裁剪的缺點(diǎn)是我們可能會(huì)丟失圖像的重要部分,這可能比稍微擠壓物體更糟糕。擠壓還是裁剪也會(huì)影響如何從數(shù)據(jù)集中計(jì)算先驗(yàn)框。使用先驗(yàn)框的重要因素,這些先驗(yàn)框的形狀類似于數(shù)據(jù)集中最常見的物體形狀。這在裁剪時(shí)仍然是正確的。一些先驗(yàn)框現(xiàn)在可能部分落在圖像之外,但至少它們的高寬比真正代表了訓(xùn)練數(shù)據(jù)中的物體。對(duì)于擠壓,計(jì)算出的先驗(yàn)框并不能真正代表真正的框,不同的高寬比會(huì)被忽略,因?yàn)槊總€(gè)訓(xùn)練圖像的擠壓方式略有不同。現(xiàn)在,先驗(yàn)框更像是在不同的扭曲圖像求平均結(jié)果。
數(shù)據(jù)擴(kuò)增也會(huì)有副作用。通過隨機(jī)截取圖像,然后將大小調(diào)整為416×416,這也會(huì)擾亂高寬比(更像故意的)。
總結(jié)來看,直接對(duì)原始圖像進(jìn)行resize,而忽略邊界框的高寬比,這是最簡(jiǎn)單有效的。這也是Yolo和SSD所采用的方式,這種方式可以看成讓模型學(xué)會(huì)自適應(yīng)高寬比。如果我們?cè)谔幚砉潭ù笮〉妮斎雸D像,例如1280×720,那么使用裁剪可能更合適。
模型是如何訓(xùn)練的
前面都是預(yù)備項(xiàng),接下來我們將來介紹這類目標(biāo)檢測(cè)模型是如何訓(xùn)練的。該模型使用卷積神經(jīng)網(wǎng)絡(luò)直接進(jìn)行預(yù)測(cè),然后把這些預(yù)測(cè)數(shù)字轉(zhuǎn)換成邊界框。數(shù)據(jù)集包含真實(shí)框,表示訓(xùn)練圖像中實(shí)際存在哪些物體,因此要訓(xùn)練這種模型,我們需要設(shè)計(jì)一個(gè)損失函數(shù),將預(yù)測(cè)框與真實(shí)框進(jìn)行比較。
問題是,不同圖像之間的真實(shí)框數(shù)量可能會(huì)有所不同,從零到幾十個(gè)不等。這些框可能圖像的不同位置,而且有些會(huì)重疊。在訓(xùn)練期間,我們必須將每個(gè)檢測(cè)器與這些真實(shí)框中的一個(gè)相匹配,以便我們可以計(jì)算每個(gè)預(yù)測(cè)框的回歸損失。
如果我們直接簡(jiǎn)單地進(jìn)行匹配,例如總是將第一個(gè)真實(shí)框分配給第一個(gè)檢測(cè)器,將第二個(gè)物體分配給第二個(gè)檢測(cè)器,以此類推,或者通過將物體隨機(jī)分配給檢測(cè)器,那么每個(gè)檢測(cè)器都將被訓(xùn)練來預(yù)測(cè)各種各樣的物體:一些較大的物體,一些是極小的物體,有的會(huì)在圖像的一角,有的會(huì)在相反的一角,有的會(huì)在中間,等等。這就出現(xiàn)前面所提到的問題:為什么僅僅在模型中添加一組回歸輸出就難有效。解決方案是使用帶有固定大小網(wǎng)格的檢測(cè)器,其中每個(gè)檢測(cè)器只負(fù)責(zé)檢測(cè)位于圖像該部分的物體,并且只負(fù)責(zé)特定大小的物體。
現(xiàn)在,損失函數(shù)需要知道哪個(gè)物體歸屬于哪個(gè)檢測(cè)器,或者說在哪個(gè)網(wǎng)格單元中,相反地,哪些檢測(cè)器沒有與它們相關(guān)聯(lián)的真實(shí)框。這就是我們所說的“匹配”。
將真實(shí)框與檢測(cè)器匹配
匹配的方法是各種各樣的,在YOLO中,圖像中的每個(gè)物體僅由一個(gè)檢測(cè)器負(fù)責(zé)來預(yù)測(cè)。由于我們要找到邊界框中心落在哪個(gè)網(wǎng)格單元中,那個(gè)單元與整個(gè)物體關(guān)聯(lián),而其它的網(wǎng)格單元如果預(yù)測(cè)了這個(gè)物體將被損失函數(shù)所懲罰。
VOC數(shù)據(jù)集給出的邊界框標(biāo)注為xmin, ymin, xmax, ymax。由于我們需要知道邊界框中心,所以需要將邊界框坐標(biāo)轉(zhuǎn)為center x, center y, width, and height。我們一般會(huì)先將邊界框坐標(biāo)歸一化到[0, 1],這樣它們獨(dú)立于輸入圖像的大小(因?yàn)橛?xùn)練圖像的大小并不一致)。
由于需要匹配,我們?cè)诓捎靡恍?shù)據(jù)擴(kuò)增如隨機(jī)翻轉(zhuǎn),要同時(shí)應(yīng)用在圖像和邊界框上。
注意:對(duì)于一些數(shù)據(jù)擴(kuò)增如隨機(jī)裁剪和翻轉(zhuǎn),我們?cè)诿總€(gè)epoch需要重新對(duì)真實(shí)框與檢測(cè)器進(jìn)行匹配。這個(gè)過程無法提前完成,并緩存下來,因?yàn)閿?shù)據(jù)擴(kuò)增是隨機(jī)的,一般會(huì)改變匹配結(jié)果。
僅僅為每個(gè)物體選擇網(wǎng)格單元是不夠的。每個(gè)網(wǎng)格單元都有多個(gè)檢測(cè)器,我們只需要其中一個(gè)檢測(cè)器來查找物體,我們需要選擇其先驗(yàn)框與物體的真實(shí)框最匹配的檢測(cè)器。這通常采用IOU來衡量匹配度。這樣,最小的物體被分配給檢測(cè)器1(有最小的先驗(yàn)框),非常大的物體使用檢測(cè)器5(有最大的先驗(yàn)框),以此類推。所以,只有那個(gè)單元中的特定檢測(cè)器才可以預(yù)測(cè)這個(gè)物體。此規(guī)則使得不同的檢測(cè)器更專注于處理形狀和大小與先驗(yàn)框相似的物體(記住,物體的大小不必與先驗(yàn)框的大小完全相同,因?yàn)槟P皖A(yù)測(cè)會(huì)預(yù)測(cè)相對(duì)于先驗(yàn)框的位置和大小偏移,先驗(yàn)框只是一個(gè)參考)。
因此,對(duì)于一個(gè)給定的訓(xùn)練圖像,一些檢測(cè)器將有一個(gè)與之相關(guān)的物體,而其他檢測(cè)器將不會(huì)。如果訓(xùn)練圖像中有3個(gè)物體,即有3個(gè)真實(shí)框,那么845個(gè)檢測(cè)器中只有3個(gè)應(yīng)該進(jìn)行預(yù)測(cè),而其他842個(gè)檢測(cè)器則應(yīng)該預(yù)測(cè)“無物體”(就我們的模型輸出而言,得到的是置信度很低的邊界框,理想情況下為0)。
從現(xiàn)在開始,我們用正例指代一個(gè)匹配到物體的檢測(cè)器,而對(duì)于一個(gè)沒有關(guān)聯(lián)物體的檢測(cè)器來說,則是負(fù)例,也可以說是“無對(duì)象”或背景。
由于模型的輸出是13×13×125張量,因此損失函數(shù)所使用的目標(biāo)張量也將是13×13×125。這個(gè)數(shù)字125來自:5個(gè)檢測(cè)器,每個(gè)檢測(cè)器預(yù)測(cè)類別的20個(gè)概率值+4個(gè)邊界框坐標(biāo)+1個(gè)置信度得分。在目標(biāo)張量中,對(duì)于正例,我們會(huì)給出物體的邊界框坐標(biāo)和onehot編碼的類別向量,而置信度為1.0(因?yàn)槲覀?00%確定這是一個(gè)真實(shí)的物體)。對(duì)于負(fù)例,目標(biāo)張量的所有值為0,邊界框坐標(biāo)和類向量在這里并不重要,因?yàn)樗鼈儗⒈粨p失函數(shù)所忽略,并且置信度得分為0,因?yàn)槲覀?00%確定這里沒有物體。
因此,訓(xùn)練的每個(gè)迭代過程,需要的是一個(gè)batch×416×416×3的圖像張量和一個(gè)batch×13×13×125的目標(biāo)張量,這個(gè)目標(biāo)張量中元素的大多都是0,因?yàn)榇蠖鄶?shù)檢測(cè)器不負(fù)責(zé)預(yù)測(cè)一個(gè)物體。
匹配時(shí)還需要考慮一些其他細(xì)節(jié)。例如,當(dāng)有多個(gè)物體的中心恰好落在同一個(gè)單元中時(shí),該怎么處理?雖然實(shí)際上這可能不是一個(gè)大問題,特別是如果網(wǎng)格足夠大時(shí),但是我們?nèi)匀恍枰环N方法來處理這種情況。理論上,物體基于最佳IOU來匹配檢測(cè)器,例如,物體A的邊界框與檢測(cè)器2的IOU最大,物體B的邊界框與檢測(cè)器4的IOU最大,那么我們可以將這物體與該單元中的不同檢測(cè)器匹配。然而,這并不能避免有兩個(gè)物體需要相同檢測(cè)器這個(gè)問題。
YOLO的解決方案比較粗暴:每次隨機(jī)打亂真實(shí)框,每個(gè)單元只選擇第一個(gè)進(jìn)入它中心的物體。因此,如果一個(gè)新的真實(shí)框與一個(gè)已經(jīng)負(fù)責(zé)另一個(gè)物體的單元相匹配,那么我們就只能忽略它了。這意味著在YOLO中,每個(gè)單元至多有一個(gè)檢測(cè)器被匹配到物體,而其他檢測(cè)器不應(yīng)該檢測(cè)到任何東西(如果檢測(cè)到了,就會(huì)受到懲罰)。
這只是YOLO的策略,SSD的匹配策略卻不相同。SSD可以將同一個(gè)真實(shí)框與多個(gè)檢測(cè)器匹配:首先選擇具有最佳IOU值的檢測(cè)器,然后選擇那些與之IOU超過0.5的但是未被匹配過的檢測(cè)器(注意檢測(cè)器和先驗(yàn)框是綁定的,一一對(duì)應(yīng),所以說IOU指的是檢測(cè)器的先驗(yàn)框與物體的邊界框之間的重疊)。這應(yīng)該使模型更容易學(xué)習(xí),因?yàn)樗槐卦谀膫€(gè)檢測(cè)器應(yīng)該預(yù)測(cè)這個(gè)對(duì)象之間進(jìn)行唯一選擇,畢竟多個(gè)檢測(cè)器可以預(yù)測(cè)這個(gè)對(duì)象。
注意:兩者設(shè)計(jì)似乎是矛盾的。YOLO將一個(gè)物體只分配給一個(gè)檢測(cè)器(而該單元的其他檢測(cè)器則是無物體),以幫助檢測(cè)器更專注。但是SSD說多個(gè)檢測(cè)器可以預(yù)測(cè)同一個(gè)物體。兩者實(shí)際上都可以。對(duì)于SSD,檢測(cè)器專注于形狀而不是大小。
損失函數(shù)
損失函數(shù)實(shí)際上是告訴模型它應(yīng)該學(xué)習(xí)什么。對(duì)于目標(biāo)檢測(cè),我們需要損失函數(shù)它能夠使模型預(yù)測(cè)出正確的邊界框,并對(duì)這些框正確分類,另一方面,模型不應(yīng)該預(yù)測(cè)不存在的物體。這實(shí)際上是多任務(wù)學(xué)習(xí)。因此,損失函數(shù)由幾個(gè)不同的部分組成,其中一部分是回歸以預(yù)測(cè)邊界框位置,另一部分用于分類。
對(duì)于任何一個(gè)檢測(cè)器,有兩種可能的情況:
- 這個(gè)檢測(cè)器沒有與之相關(guān)的真實(shí)框,這是負(fù)例,它不應(yīng)該檢測(cè)到任何物體(即它應(yīng)該預(yù)測(cè)一個(gè)置信度為0的邊界框)。
- 這個(gè)檢測(cè)器匹配到了一個(gè)真實(shí)框,即正例,它負(fù)責(zé)檢測(cè)到物體。
對(duì)于不應(yīng)該檢測(cè)到物體的檢測(cè)器,當(dāng)它們預(yù)測(cè)出置信度大于0的邊界框時(shí)要懲罰它們。因?yàn)樗鼈兘o出的檢測(cè)是假陽性,圖像中的這個(gè)位置上并沒有真實(shí)物體。過多的誤檢會(huì)降低模型的效果。相反,如果檢測(cè)器是正例,當(dāng)出現(xiàn)下面的情況時(shí),我們希望懲罰它:
- 當(dāng)坐標(biāo)錯(cuò)誤
- 當(dāng)置信度太低時(shí)
- 分類錯(cuò)誤
理想情況下,檢測(cè)器應(yīng)該預(yù)測(cè)一個(gè)與真實(shí)框完全重疊的框,類別也應(yīng)該一致,并且具有較高的置信度。當(dāng)置信度得分過低時(shí),預(yù)測(cè)結(jié)果將被視為假陰性(false negative),這也意味著模型沒有找到真正的物體。但是,如果置信度得分高,但坐標(biāo)不準(zhǔn)確或分類錯(cuò)誤,則預(yù)測(cè)將被視為假陽性(false positive)。盡管模型檢測(cè)出一個(gè)物體,但它是錯(cuò)誤的。
這意味著相同的預(yù)測(cè)可以被判定為假陰性(會(huì)減低模型的召回),也可能是假陽性(降低模型的準(zhǔn)確度)。只有當(dāng)所有三個(gè)方面——坐標(biāo)、置信度、類別都正確時(shí),預(yù)測(cè)才算真陽性(true positive)。因?yàn)槿魏我粋€(gè)方面都可能出錯(cuò),損失函數(shù)由幾個(gè)部分組成,分別來衡量模型給出的預(yù)測(cè)的不同類型“錯(cuò)誤性”,將這些部分相加,得到整體損失函數(shù)。
SSD、YOLO、Squezedet、Detectnet和其他one-stage目標(biāo)檢測(cè)模型的損失函數(shù)可能有差異,但是它們往往由相同的部分組成。
(1)沒有被匹配的檢測(cè)器(負(fù)例)
對(duì)于負(fù)例,損失函數(shù)僅包含置信度部分,因?yàn)闆]有真實(shí)框,所以沒有任何坐標(biāo)或類別標(biāo)簽來計(jì)算損失。如果這樣的檢測(cè)器確實(shí)找到了一個(gè)物體,它應(yīng)該受到懲罰。置信度分?jǐn)?shù)表示檢測(cè)器是否認(rèn)為有一個(gè)物體的中心在這個(gè)網(wǎng)格單元中。對(duì)于這樣的檢測(cè)器,目標(biāo)張量中的真實(shí)置信度得分被設(shè)置為0,因?yàn)檫@里沒有物體。預(yù)測(cè)得分也應(yīng)該是0,或接近它。損失函數(shù)要降低預(yù)測(cè)值與目標(biāo)值之間的誤差。在YOLO中,這樣計(jì)算:
no_object_loss[i, j, b] = no_object_scale * (0 - sigmoid(pred_conf[i, j, b]))**2這里pred_conf[i, j, b]是網(wǎng)格單元 i, j上的檢測(cè)器b預(yù)測(cè)的置信度. 這里使用sigmoid來將置信度的取值限制在[0,1]。可以看到,上面的loss僅僅是計(jì)算預(yù)測(cè)值與目標(biāo)值之差的平方。而no_object_scale是一個(gè)超參數(shù),一般取0.5, 這樣這部分loss占整體比重不大. 由于圖像中只有少量物體,所以845個(gè)檢測(cè)器中的大部分僅計(jì)算這類“no object”損失。由于我們不想讓模型僅僅學(xué)習(xí)到“no objects”,這部分loss不應(yīng)該比那些匹配到物體的檢測(cè)器的loss重要。
上述公式僅是計(jì)算一個(gè)網(wǎng)格單元中一個(gè)檢測(cè)器的loss,實(shí)際上要將所有網(wǎng)格中的負(fù)例檢測(cè)器的loss求和才是最終的loss。對(duì)于那些正例檢測(cè)器,這項(xiàng)loss總是0。SqueezeDet求的是各個(gè)檢測(cè)器loss的平均值(總loss除以負(fù)例檢測(cè)器數(shù)量),而在YOLO中直接取loss和。
實(shí)際上,YOLO還有一個(gè)特別處理之處。如果一個(gè)檢測(cè)器的預(yù)測(cè)框與所有真實(shí)框的IOU最大值大于一個(gè)閾值(比如0.6),那么忽略這個(gè)檢測(cè)器的no_object_loss。換句話說,如果一個(gè)檢測(cè)器被認(rèn)為不應(yīng)該預(yù)測(cè)一個(gè)物體,但是實(shí)際上卻預(yù)測(cè)了一個(gè)不錯(cuò)的結(jié)果,那么最好是忽略它(或者鼓勵(lì)它預(yù)測(cè)物體,也許我們應(yīng)該讓這個(gè)檢測(cè)器與這個(gè)物體匹配)。這個(gè)trick到底會(huì)起多大作用,并無法評(píng)估(深度學(xué)習(xí)很多這樣無法講明白的trick)。
SSD沒有這項(xiàng)loss,因?yàn)樗鼘⒈尘邦惪闯梢粋€(gè)特殊類進(jìn)行處理。如果預(yù)測(cè)的是背景類,那個(gè)檢測(cè)器被認(rèn)為沒有檢測(cè)到物體。
注意:YOLO采用平方和誤差(sum-squared error,SSE),而不是常見的用于回歸的均方差(mean-squared error,MSE),或是用于分類的交叉熵。一個(gè)可能原因是每張圖片物體數(shù)量并不同,如果取平均,那么包含10個(gè)物體的圖片與包含1個(gè)物體的圖片的loss的重要性一樣,而采用求和,前者的重要性約是后者的10倍,這可能更公平。
(2)被匹配的檢測(cè)器(正例)
前面所說的是不負(fù)責(zé)檢測(cè)物體的負(fù)例檢測(cè)器,接下來講另一類檢測(cè)器:它們應(yīng)該檢測(cè)到物體。當(dāng)這類檢測(cè)器沒有檢測(cè)到物體,或者給物體錯(cuò)誤分類時(shí),它們就被判定出錯(cuò),有三部分loss來評(píng)估錯(cuò)誤。
(a)置信度
首先是置信度loss:
object_loss[i, j, b] = object_scale * (1 - sigmoid(pred_conf[i, j, b]))**2這與前面的no_object_loss很類似,只是這里的目標(biāo)值是1,因?yàn)槲覀?00%確定存在一個(gè)物體。 實(shí)際上,YOLO的處理方式更微妙:
object_loss[i, j, b] = object_scale * (IOU(truth_coords, pred_coords) - sigmoid(pred_conf[i, j, b]))**2預(yù)測(cè)的置信度pred_conf[i, j, b]應(yīng)該能夠表示預(yù)測(cè)框和真實(shí)框的IOU值,理想狀態(tài)下這是1。YOLO在計(jì)算loss時(shí)不采用理想值,而是使用兩個(gè)框的實(shí)際IOU值。這也講得通:當(dāng)IOU值低時(shí),置信度會(huì)低,反之IOU值高,置信度也會(huì)高。對(duì)于no-object loss,我們一直希望預(yù)測(cè)的置信度為0,而這里我們并不是想要模型的置信度一直是100%。相反,模型應(yīng)該能夠?qū)W習(xí)評(píng)估預(yù)測(cè)的邊界框的實(shí)際好壞,而IOU恰好可以反映這一點(diǎn)。前面已經(jīng)提到, SSD不預(yù)測(cè)置信度,所以這項(xiàng)loss也不計(jì)算。
(b)類別概率
每個(gè)檢測(cè)器都會(huì)預(yù)測(cè)物體的類別,這與邊界框坐標(biāo)是分開的。本質(zhì)上,我們?yōu)椴煌笮〉奈矬w訓(xùn)練了5個(gè)獨(dú)立的分類器(同一個(gè)網(wǎng)格中的每個(gè)檢測(cè)器的分類器是不同的)。YOLOv1和v2按如下方式計(jì)算分類的loss:
class_loss[i, j, b] = class_scale * (true_class - softmax(pred_class))**2這里true_class是onehot編碼的目標(biāo)向量(對(duì)于VOC數(shù)據(jù)集,大小為20) ,而pred_class是預(yù)測(cè)的logits向量。注意這里我們雖然使用了softmax,但是并沒有計(jì)算交叉熵,反而是誤差平方和loss,或者這是為了與其它loss保持一致。實(shí)際上,甚至可以不應(yīng)用softmax也是可以的。
而YOLOv3和SSD采用不同的方式,它們將這個(gè)問題看成多標(biāo)簽分類問題。所以不采用softmax(它導(dǎo)致各個(gè)類別互斥),反而使用sigmoid,這樣允許預(yù)測(cè)多個(gè)標(biāo)簽。進(jìn)一步,它們采用標(biāo)準(zhǔn)的二元交叉熵計(jì)算loss。
由于SSD不預(yù)測(cè)置信度,所以它增加了一個(gè)背景類。如果檢測(cè)器預(yù)測(cè)是背景,那么此檢測(cè)器沒有檢測(cè)到物體,即忽略這個(gè)預(yù)測(cè)。實(shí)際上SSD的no-object loss就是背景類的分類loss。
(c)邊界框坐標(biāo)
最后一項(xiàng)loss是邊界框坐標(biāo),也稱為定位損失,其實(shí)就是簡(jiǎn)單地計(jì)算邊界框的4個(gè)坐標(biāo)的回歸損失:
coord_loss[i, j, b] = coord_scale * ((true_x[i, j, b] - pred_x[i, j, b])**2+ (true_y[i, j, b] - pred_y[i, j, b])**2+ (true_w[i, j, b] - pred_w[i, j, b])**2+ (true_h[i, j, b] - pred_h[i, j, b])**2)其中縮放因子coord_scale是設(shè)置定位損失的權(quán)重,這個(gè)超參一般設(shè)置為5,這樣該項(xiàng)損失相比其它更重要。這項(xiàng)損失是極其簡(jiǎn)單的,但是有必要知道公式中true_*和pred_*到底指什么。 在之前的部分,我們已經(jīng)給出了如何得到真實(shí)的邊界框坐標(biāo):
box_x[i, j, b] = (i + sigmoid(pred_x[i, j, b])) * 32 box_y[i, j, b] = (j + sigmoid(pred_y[i, j, b])) * 32 box_w[i, j, b] = anchor_w[b] * exp(pred_w[i, j, b]) * 32 box_h[i, j, b] = anchor_h[b] * exp(pred_h[i, j, b]) * 32我們需要進(jìn)行對(duì)模型的預(yù)測(cè)做一定的后處理才能得到有效的坐標(biāo)值。由于模型實(shí)際上不是直接預(yù)測(cè)有效的邊界框坐標(biāo),所以損失函數(shù)中的真實(shí)框也要與之對(duì)應(yīng),即我們要先將真實(shí)框的實(shí)際坐標(biāo)進(jìn)行逆向轉(zhuǎn)換:
true_x[i, j, b] = ground_truth.center_x - grid[i, j].center_x true_y[i, j, b] = ground_truth.center_y - grid[i, j].center_y true_w[i, j, b] = log(ground_truth.width / anchor_w[b]) true_h[i, j, b] = log(ground_truth.height / anchor_h[b])注意true_x和true_y是相對(duì)于網(wǎng)格單元格的,而true_w和true_h是相對(duì)于先驗(yàn)框的縮放因子。因此,在填充目標(biāo)張量時(shí),一定要先進(jìn)行上述的逆向轉(zhuǎn)換,否則損失函數(shù)將計(jì)算的是兩個(gè)不同量的誤差。
在SSD中,計(jì)算定位損失有稍微的不同,它采用的是“Smooth L1”損失:
difference = abs(true_x[i, j, b] - pred_x[i, j, b]) if difference < 1:coord_loss_x[i, j, b] = 0.5 * difference**2 else:coord_loss_x[i, j, b] = difference - 0.5對(duì)于其它項(xiàng)坐標(biāo)也是如此,這項(xiàng)loss對(duì)邊界值更不敏感(曲線更平穩(wěn))。
開始訓(xùn)練
接下來,我們可以給出一個(gè)完整的模型訓(xùn)練過程,首先我們需要:
- 一個(gè)包含圖片以及邊界框標(biāo)注的數(shù)據(jù)集(如Pascal VOC);
- 一個(gè)可以擁有網(wǎng)格檢測(cè)器的模型,并采用一個(gè)匹配策略將真實(shí)框轉(zhuǎn)化為目標(biāo)張量;
- 一個(gè)計(jì)算預(yù)測(cè)值與目標(biāo)值的損失函數(shù)。
然后就可以采用SGD對(duì)模型進(jìn)行訓(xùn)練,由于檢測(cè)器對(duì)正例和負(fù)例的loss計(jì)算方式不同,需要一定的循環(huán)才可以計(jì)算出整個(gè)loss,簡(jiǎn)單的偽代碼如下:
for i in 0 to 12:for j in 0 to 12:for b in 0 to 4:gt = target[i, j, b] # ground-truthpred = grid[i, j, b] # prediction from model# is this detector responsible for an object?if gt.conf == 1:iou = IOU(gt.coords, pred.coords)object_loss[i, j, b] = (iou - sigmoid(pred.conf[i, j, b]))**2coord_loss[i, j, b] = sum((gt.coords - pred.coords)**2)class_loss[i, j, b] = cross_entropy(gt.class, pred.class)else:no_object_loss[i, j, b] = (0 - sigmoid(pred.conf[i, j, b]))**2最終的loss是各項(xiàng)loss的加權(quán)和:
loss = no_object_scale * sum(no_object_loss) + object_scale * sum(object_loss) + coord_scale * sum(coord_loss) + class_scale * sum(class_loss)但是實(shí)際上可以將上述循環(huán)過程向量化以可以在GPU上加速運(yùn)算,主要思路是采用一個(gè)mask屏蔽那些不需要計(jì)算的部分:
# the mask is 1 for detectors that have an object, 0 otherwise mask = (target.conf == 1) # compute IOUs between each detector's predicted box and # the corresponding ground-truth box from the target tensor ious = IOU(target.coords, grid.coords) # compute the loss terms for the entire grid at once: object_loss = sum(mask * (ious - sigmoid(grid.conf))**2) coord_loss = sum(mask * (target.coords - grid.coords)**2) class_loss = sum(mask * (target.class - softmax(grid.class))**2) no_object_loss = sum((1 - mask) * (0 - sigmoid(grid.conf))**2)即使看起來目標(biāo)檢測(cè)的損失函數(shù)比圖像分類更復(fù)雜,但是一旦你理解了每個(gè)部分的含義就比較簡(jiǎn)單了。由于YOLO,SSD以及其它的one-stage目標(biāo)檢測(cè)模型在計(jì)算loss時(shí)有稍微的不同,因而你有很多可選擇的余地進(jìn)行設(shè)計(jì)。
另外有一些值得注意的小技巧來訓(xùn)練模型:
- 多尺度訓(xùn)練。一般情況下,目標(biāo)檢測(cè)模型用于不同大小的圖片,因而也包含不同尺度的物體。一個(gè)可以讓模型可以對(duì)不同大小的輸入泛化的方法是每一定的迭代過程中隨機(jī)選擇不同的輸入尺寸。比如隨機(jī)從320×320到608×608之間選擇的輸入,而不是恒定在416x416。
- 熱身訓(xùn)練(Warm-up training)。 YOLO在早期訓(xùn)練階段為每個(gè)單元中心增加一個(gè)假的真實(shí)框(先驗(yàn)框),采用這個(gè)額外的坐標(biāo)損失來鼓勵(lì)模型的預(yù)測(cè)可以匹配到檢測(cè)器的先驗(yàn)框。
- 難例挖掘(Hard negative mining)。前面已經(jīng)說過大部分檢測(cè)器是不負(fù)責(zé)檢測(cè)任何物體的。這意味著正例數(shù)量要遠(yuǎn)少于負(fù)例。YOLO采用一個(gè)超參數(shù)no_object_scale 來處理這種情況,但是SSD采用難例挖掘:它不是計(jì)算所有負(fù)例的損失,而是只計(jì)算那些預(yù)測(cè)結(jié)果最錯(cuò)的部分損失(即置信度較高的負(fù)例)。
即使一旦訓(xùn)練后模型就能很好地工作,但是你有時(shí)候需要這些技巧讓模型快速學(xué)習(xí)。
如何評(píng)價(jià)模型
為了評(píng)估一個(gè)分類模型,你可以簡(jiǎn)單的計(jì)算在測(cè)試集上預(yù)測(cè)正確的數(shù)量,并除以測(cè)試圖片的總數(shù),從而得到分類準(zhǔn)確度。然而對(duì)于目標(biāo)檢測(cè)模型,你需要評(píng)估以下幾個(gè)部分:
- 每個(gè)檢測(cè)物體的分類準(zhǔn)確度;
- 預(yù)測(cè)框與真實(shí)框的重合度(IOU)
- 模型是否找到圖片中的所有物體(召回,recall)。
僅采用任何一個(gè)指標(biāo)是不夠的。比如,如果設(shè)定IOU的閾值為50%,當(dāng)一個(gè)預(yù)測(cè)框與一個(gè)真實(shí)框的IOU值大于該閾值時(shí),被判定為真陽(TP),反之被判定為假陽(FP)。但是這并不足以評(píng)估模型的好壞,因?yàn)槲覀儫o法知道模型是否漏檢了一些物體,比如存在某些模型沒有預(yù)測(cè)出的真實(shí)框(假陰,FN)。
注意:在目標(biāo)檢測(cè)中沒有真陰(true negatives),一個(gè)真陰是本來物體也不存在,正好模型也沒有給出預(yù)測(cè)。大部分情況下我們更關(guān)心包含物體的地方,而不關(guān)心背景部分,實(shí)際上真陰也無法計(jì)算。
為了將以上幾種不同因素轉(zhuǎn)化為一個(gè)單一指標(biāo),通常我們計(jì)算mAP(mean average precision)。mAP值越高,模型越好。計(jì)算mAP的方法隨數(shù)據(jù)集略有差異。
計(jì)算mAP
對(duì)于Pascal VOC數(shù)據(jù)集,首先我們要單獨(dú)計(jì)算各個(gè)類別的AP(average precision),然后取平均值得到最終的mAP,所以mAP是平均的平均。對(duì)于precision,它是真陽數(shù)除以檢測(cè)的總數(shù):
precision = TP / (TP + FP)在這個(gè)場(chǎng)景中,假陽值是檢測(cè)器預(yù)測(cè)了一個(gè)在圖像中并不存在的物體。這一般發(fā)生在預(yù)測(cè)框與圖像中的真實(shí)框差異很大(IOU值低于閾值),或者預(yù)測(cè)的類別是錯(cuò)誤的。
注意:這里我們并關(guān)心到底是哪個(gè)檢測(cè)器給出的預(yù)測(cè)。在評(píng)估模型時(shí)我們并不會(huì)像訓(xùn)練過程那樣將特定的檢測(cè)器分配給某個(gè)物體,而是僅僅將預(yù)測(cè)框與真實(shí)框進(jìn)行比較,以確定到底檢測(cè)出了多少物體。
另外一個(gè)與 precision一起計(jì)算的指標(biāo)是recall(true positive rate or the sensitivity):
recall = TP / (TP + FN)recall和precision的唯一區(qū)別是分母不同,前者是真陽數(shù)加假陰數(shù),即所有真實(shí)物體的總數(shù)。對(duì)于假陰,就是檢測(cè)器沒有找到一個(gè)真實(shí)的物體,或者給出的置信度較低。
舉例來說,precision衡量的在預(yù)測(cè)為貓的物體中,到底有多少是真的貓,這里FP就是那些預(yù)測(cè)為貓但實(shí)際上卻不是貓的數(shù)量。而recall衡量的是模型找到了圖像中所有真實(shí)貓的多少個(gè),FN是指的遺漏檢測(cè)的貓的數(shù)量。比如,模型預(yù)測(cè)出了3只貓,但是實(shí)際上其中一個(gè)是狗,另外一個(gè)不存在物體,那么precision就等于1/3=0.33(三個(gè)預(yù)測(cè)中僅有一個(gè)是對(duì)的)。如果圖像中存在4只貓,那么recall就是1/4=0.25,因?yàn)閮H檢測(cè)出了一只貓。如果圖像中存在一只狗,那么對(duì)于狗這類,precision和recall都是0,因?yàn)楣返腡P為0。這里是計(jì)算TP和FP的偽代碼:
sort the predictions by confidence score (high to low) for each prediction:true_boxes = get the annotations with same class as the predictionand that are not marked as "difficult"find IOUs between true_boxes and predictionchoose ground-truth box with biggest IOU overlapif biggest IOU > threshold (which is 0.5 for Pascal VOC):if we do not already have a detection for this ground-truth box:TP += 1else:FP += 1else:FP += 1如果某個(gè)預(yù)測(cè)框的分類正確,且與真實(shí)框的IOU值大于50%,那么就認(rèn)為是TP,反之則是FP。如果存在兩個(gè)及以上的預(yù)測(cè)與某個(gè)真實(shí)框的IOU大于50%,那么我們必須選擇其中的一個(gè)認(rèn)為是正確的預(yù)測(cè),其它的將被當(dāng)做FP。我們希望模型僅對(duì)每個(gè)物體預(yù)測(cè)一個(gè)框,這里我們通常會(huì)選擇那個(gè)置信度最高的預(yù)測(cè)框。
由于對(duì)同個(gè)物體進(jìn)行多次預(yù)測(cè)是受到懲罰的,所以最好先進(jìn)行NMS以盡可能地去除重復(fù)的預(yù)測(cè)。最好也要扔掉那些置信度較低的預(yù)測(cè)(如低于0.3),否則它們會(huì)被當(dāng)成FP。YOLO模型給出845個(gè)預(yù)測(cè),而SSD給出1917個(gè)預(yù)測(cè),這遠(yuǎn)遠(yuǎn)多于真實(shí)物體,因?yàn)榇蟛糠謭D像只含有1到3個(gè)物體。
目前為止,我們并沒有計(jì)算FN,實(shí)際上并不需要。因?yàn)橛?jì)算recall公式的分母是TP+FN,這實(shí)際上等于圖像中真實(shí)物體的數(shù)量(我們所關(guān)注的特定類)。
現(xiàn)在我們計(jì)算出了precision和recall,但是單個(gè)precision和recall無法說明模型的效果。所以我們將計(jì)算一系列的precision和recall對(duì),然后畫出precision-recall曲線。對(duì)每個(gè)類,我們都會(huì)做出這樣的曲線。而某個(gè)類的AP值就是曲線下的面積。
precision-recall曲線
如下是狗這個(gè)類的precision-recall曲線:
其中x坐標(biāo)是recall,從0(沒有檢測(cè)到物體)到1(發(fā)現(xiàn)了所有物體),而y坐標(biāo)是precision。這里precision看成是recall的函數(shù),所以曲線的面積實(shí)際上就是這類物體的平均precision,因此叫做 “mean average precision”:我們想知道不同recall下的precision的平均值。
如何解釋這條曲線?precision-recall曲線通常是通過設(shè)定不同的閾值來計(jì)算precision和recall對(duì)。對(duì)于一個(gè)二分類器來說,高于閾值就被判定為正例。在目標(biāo)檢測(cè)領(lǐng)域,我們會(huì)不斷改變閾值(對(duì)應(yīng)預(yù)測(cè)框的置信度)來得到不同的precision和recall。首先,我們計(jì)算第一個(gè)預(yù)測(cè)值(最大閾值)的precision和recall,然后計(jì)算第一個(gè)和第二個(gè)預(yù)測(cè)值(稍微降低閾值)的precision和recall,接著是前三個(gè)預(yù)測(cè)值的precision和recall(閾值更低),直到我們計(jì)算所有預(yù)測(cè)值下(閾值最低)的precision和recall。每對(duì)precision和recall對(duì)應(yīng)就是曲線的一個(gè)點(diǎn),x值為recall而y值是precision。在較大閾值處,recall是較低的,因?yàn)橹话苌兕A(yù)測(cè)結(jié)果,所以會(huì)有非常多的FN。你可以看到在曲線的最左側(cè),precision為100%,因?yàn)槲覀冎话朔浅?隙ǖ念A(yù)測(cè)框。但是recall是極低的,因?yàn)槁┑袅撕芏辔矬w。隨著閾值降低,將包含更多物體,recall增加。但precision上下波動(dòng),但由于FP會(huì)越來越多,它往往會(huì)變得更低。在最低閾值處,recall是最大的,因?yàn)楝F(xiàn)在包含了模型的所有預(yù)測(cè)。
可以看到,模型預(yù)測(cè)值的FP和FN之間始終存在折中。使用precision-recall曲線可以衡量這種折中,并找到一個(gè)較好的置信度閾值。選擇高閾值意味著我們保留較少的預(yù)測(cè),因此將減少FP(減少了錯(cuò)誤),但我們也會(huì)有更多的FN(錯(cuò)過了更多的物體)。閾值越低,包含的預(yù)測(cè)越多,但它們通常質(zhì)量較低。
理想情況下,各個(gè)recall下的precision都很高。計(jì)算出所有recall下的precision的平均值,可以給出模型在檢測(cè)此特定類物體的總體效果。一旦我們獲得了所有不同閾值下的precision和recall,就可以通過計(jì)算該曲線下的面積來得到AP。對(duì)于Pascal VOC數(shù)據(jù)集,實(shí)際上有兩種不同的方法:2007版本使用近似方法; 2012版本更精確(使用積分)但分?jǐn)?shù)一般更低。最終的mAP僅僅是20個(gè)類的AP平均值。當(dāng)然,mAP越高越好。但這并不意味著mAP就是最重要的, YOLO的mAP一般低于其它模型,但速度卻更快,特別是在移動(dòng)設(shè)備上使用時(shí),我們希望使用在速度和準(zhǔn)確度之間具有較好折衷的模型。
總結(jié)
以上是生活随笔為你收集整理的人工智能目标检测总结(五)——深入理解one-stage目标检测模型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 通过python requests第三方
- 下一篇: 鼠标点击添加动态类名active