YOLOv1--從樣本標籤與訓練輸出角度分析

前言

網上有許多YOLOv1的文章,但絕大部分文章將訓練樣本標籤與訓練輸出混爲一談,對初學者的理解造成了很大的困難。本文總結了幾篇優秀的博客,改正了一些用圖與表述錯誤,加上了自己的一些理解和一些實例以助理解

YOLO

YOLO意思是You Only Look Once,創造性的將候選區和對象識別這兩個階段合二爲一,看一眼圖片就能知道有哪些對象以及它們的位置。

實際上,YOLO並沒有真正去掉候選區,而是採用了預定義的候選區(準確點說應該是預測區,因爲並不是Faster RCNN所採用的Anchor)。也就是將圖片劃分爲 7×7=49 個網格(grid),每個網格允許預測出2個邊框(bounding box,包含某個對象的矩形框),總共 492=98 個bounding box。可以理解爲98個候選區,它們很粗略的覆蓋了圖片的整個區域。

RCNN雖然會找到一些候選區,但畢竟只是候選,等真正識別出其中的對象以後,還要對候選區進行微調,使之更接近真實的bounding box。這個過程就是邊框迴歸:將候選區bounding box調整到更接近真實的bounding box。
既然反正最後都是要調整的,幹嘛還要先費勁去尋找候選區呢,大致有個區域範圍就行了,所以YOLO就這麼幹了。

下圖爲YOLO運行過程簡圖:
在這裏插入圖片描述

(1)把圖像縮放到448X448,(2)在圖上運行卷積網絡,(3)根據模型的置信度對檢測結果進行閾值處理

網絡結構

單看網絡結構的話,和普通的CNN對象分類網絡幾乎沒有本質的區別,最大的差異是最後輸出層用線性函數做激活函數,因爲需要預測bounding box的位置(數值型),而不僅僅是對象的概率。

其他層都是使用的激活函數都是leaky rectified activation:

在這裏插入圖片描述

理解YOLO的過程中,最重要的是理解輸入輸出的映射關係,下面將詳細介紹

輸入輸出的結構與映射關係

輸入

輸入就是原始圖像,唯一的要求是縮放到448×448的大小。主要是因爲YOLO的網絡中,卷積層最後接了兩個全連接層,全連接層是要求固定大小的向量作爲輸入,所以倒推回去也就要求原始圖像有固定的尺寸。那麼YOLO設計的尺寸就是448×448

輸出

簡單來說輸出就是一個7×7×30的張量。

爲何是這個尺寸,又包含哪些信息呢?

首先需要知道YOLO的一些規定:

YOLO將圖像分成S×S(S=7)的網格grid cell,並且每個網格單元負責預測B(B=2)個邊界框box。加上每個邊界框box的置信度confidence,每個網格的C個條件類別概率

7*7的網格設計

根據YOLO的設計,輸入圖像被劃分爲7×7的網格(grid cell),輸出張量中的7×7就對應着輸入圖像的7×7網格或者說輸出就是7×7=49個30維張量,正如上圖所示,兩個橙色的gridcell各自對應着輸出中對應位置的兩個30維向量

要注意的是,並不是說僅僅網格內的信息被映射到一個30維向量。經過神經網絡對輸入圖像信息的提取和變換,網格周邊的信息也會被識別和整理,最後編碼到那個30維向量中。

30維向量

(1)20個對象的概率

​ 因爲YOLO支持識別20種不同的對象,(人、鳥、貓、汽車、椅子等),所以這裏有20個值表示該網格位置存在任一種對象的概率。可以記爲

是條件概率,意思是如果網格存在一個對象Object,那麼它是Ci的概率是P(Ci|Object)

(2)兩個bounding box的位置

​ 每個bounding box需要4個數值來表示其位置,(Center_x,Center_y,width,height),即(bounding box的中心點的x座標,y座標,bounding box的寬度,高度),2個bounding box共需要8個數值來表示其位置。

​ 需要強調的是,這裏的x,y,w,h都是歸一化的座標,並且x,y是相對於該bounding box所在的grid cell的左上角的偏移量。

​ 對與w,h的歸一化比較簡單:w=框的寬度/圖片總寬度,h=框的高度/圖片總高度

​ 因爲x,y只是bounding box中心點的相對於所在grid cell左上角的偏移,具體而言如下圖

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-HFGyTQNW-1588516991656)(assets/image-20200503195221736.png)]

如圖,綠色框框的那個grid cell有一個bouding box,這個boundingbox的中心是紅點,這個紅點的座標計算公式如下:
在這裏插入圖片描述

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-gvRNNxmF-1588516991659)(assets/image-20200503195918681.png)]

這個x,y是綠色grid cell 左上角的偏移量,因爲是歸一化後的結果,所以x,y的值在(0,1)範圍

例如這個座標爲(0.4,0.7),如果是在這個網格座標系(即橫縱軸範圍0~7),那麼紅點在網格座標系實際的座標爲(1.4,4.7),同樣也可以將xywh放縮到image實際的大小,也就可以在image中畫出這個紅框了。

(3)兩個bounding box的置信度

​ 這裏很容易產生混淆,需要區分 預測(或稱測試inference)時圖片進入網絡的輸出 中的bounding box的置信度和訓練集產生的標籤裏的置信度

​ 此處只需簡單知道置信度的概念:一個bounding box的置信度Confidence意味着它 是否包含對象且位置準確的程度。置信度高表示這裏存在一個對象且位置比較準確,置信度低表示可能沒有對象 或者 即便有對象也存在較大的位置偏差。

至此我們明確了輸出其實就是 S * S * ( B * 5 + C) }的Tensor(張量)。

訓練樣本的標籤

有了神經網絡,自然要用訓練集去訓練參數,以得到我們想要的模型。

如我們可以用labelImg軟件標註,下面我們用一張用於訓練的圖片舉例,在這張圖片中框出所有我們想要識別對象(Object),並且分別設定類別(class)。這樣我們就完成了一張圖片的標註。

訓練的過程簡單來說,就是這張圖片輸入網絡得到一個預測的7×7×30 的輸出,那我們根據這張圖片的標註,也應該生成一個7×7×30的樣本標籤與預測的輸出計算Loss,再前向傳播調整參數 這麼一個過程

以這張圖爲例:圖中藍色,黃色,粉色的框框就是我們標註時候的框框,對應的類別分別爲 dog,bicycle,car

在這裏插入圖片描述

下面就介紹標註完這張圖片後,對應的7×7×30的樣本標籤如何生成

(1)20個對象分類概率

​ 對此,論文中有個關鍵詞“responsible”,給出了僅由中心點所在的網格對預測該對象負責的這樣一個規定。

​ 意思是說,每個對象(Object)都有一個框框,計算框框的中心點,中心點所在的網格(grid cell)對這個對象負責。例如,狗被標註了一個藍色的框框,藍色的框框中心是那個藍色的圓點,圓點所在的網格(圖中藍色陰影的grid cell)對狗這個Object負責。

​ 每個Object找到負責的grid cell後 這個grid cell對應的30維張量中那20個對象分類概率中就把這個Object的類別設爲1,其他類別爲0。繼續上面的例子:藍色陰影的grid cell對應的30維張量中的20個分類概率中,dog設爲1,其他19個類設爲0。同樣的黃色陰影grid cell類別概率中bicycle設爲1,其餘19個位0,粉色grid cell類別概率中car設爲1,其餘19個位0。

​ 這樣49個30維張量中,3個30維張量的對象分類概率得到了確定,那剩下45個呢?注意"僅由中心點所在的網格對預測該對象負責"這句話中的僅由二字,也就是說及時一個對象橫跨了衆多grid cell,我們也只關係這個對象中心點所在的grid cell,僅由這個grid cell負責。那剩下的45個30維張量的20個對象分類概率都爲0!!

(2)bounding box的位置

​ 依舊在僅由中心點所在的網格對預測該對象負責的前提下

​ 每個對象的框框已經由我們標註獲得,即知道了訓練樣本中對象的真實位置,自然要把真實的位置信息填入負責的grid cell對應的30維張量中。但因爲B=2,即一個grid cell對應了兩個bounding box信息,我們該填入哪一個呢?

需要明確的是這是在訓練過程中在線計算出才填入樣本標籤的!這也牽扯到了置信度問題,故見下面第三點置信度

(3)bounding box的置信度

​ 對於置信度由這樣一個公式確定:

在這裏插入圖片描述

是 bounding box 與 對象真實bounding box 的IOU(Intersection over Union,交併比)。在此已經可以發現 體現了預測的bounding box與真實bounding box的接近程度且這裏不僅用到了我們通過標註就知道的真實bounding box,還牽扯到了預測的bounding box,既然要用到預測信息就不難理解爲何要在訓練時候在線生成。

簡單介紹一下IOU的計算,IOU=交集部分面積/並集部分面積,2個box完全重合時IOU=1,不相交時IOU=0在這裏插入圖片描述

訓練時通過網絡的輸出,每個grid cell都有2個預測的bounding box。對於對 對象 負責的grid cell而言,將這兩個預測的bounding box分別與真實的bounding box計算IOU,然後最重要的一步!比較兩個IOU哪個大,由大的IOU對應的bounding box 負責預測這個對象 (這又是一個負責的重要規定),那麼這個負責的bounding box的 ,另一個不負責的bounding box(IOU小的這個) 。總的來說就是,與對象實際bounding box最接近的那個bounding box,即IOU大的這個 ,不負責的bounding box,

在這裏插入圖片描述
以樣例圖中的黃色grid cell 對應的30維輸出爲例,如上圖,這裏已經假設在線計算時候時候bounding box1的IOU更大。 至於這個座標2因爲不計入Loss的計算,所有顯得沒那麼重要,當然爲了方便在設計代碼時候可以也設爲自行車邊框座標,總之這個值不會產生影響

總結一下,標籤中只有對對象負責的那個grid cell的 負責的那一個bounding box(計算出IOU最大的那個) 對應的置信度纔是計算出的IOU的值,其餘所有的置信度因爲Pr(Object)=0所以都是0

還是拿那個樣例圖來說,7×7個grid cell,每個grid cell 有兩個bounding box ,共計7×7×2=98個bounding box,每個bounding box 都有一個 置信度confidence信息,那麼98箇中只有3個是計算出的IOU值,其餘95個都是0

至此,訓練樣本標籤如何設定就介紹完了,而經過網絡輸出的7×7×30的張量內的值最初都是隨意的,拿出一個30維張量爲例,

在這裏插入圖片描述
就長這個樣子,接下來就是計算Loss,再去迴歸的過程

損失函數

損失就是網絡實際輸出值與樣本標籤值之間的偏差

如:

在這裏插入圖片描述

在這裏插入圖片描述

YOLO給出的損失函數如下:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

函數的設計目標就是讓座標(x,y,w,h),confidence,classification 這個三個方面達到很好的平衡。簡單的全部採用了sum-squared error loss來做這件事會有以下不足: a) 8維的localization error和20維的classification error同等重要顯然是不合理的; b) 如果一個網格中沒有object(一幅圖中這種網格很多),那麼就會將這些網格中的box的confidence push到0,相比於較少的有object的網格,這種做法是overpowering的,這會導致網絡不穩定甚至發散。 解決方案如下:

①更重視8維的座標預測,給這些損失前面賦予更大的loss weight, 上面已經提到了引入了,作者在pascal VOC訓練中取了5

②對沒有object的bbox的confidence loss,賦予小的loss weight,上面也已經提到了引入了,在pascal VOC訓練中取0.5

③有object的bounding box的confidence loss (上圖第三行) 和類別的loss (上圖第五行)的loss weight正常取1

④對不同大小的bounding box預測中,相比於大bounding box預測偏一點,小bounding box預測偏一點更不能忍受。而sum-square error loss中對同樣的偏移loss是一樣。 爲了緩和這個問題,作者用了一個比較取巧的辦法,就是將box的width和height取平方根代替原本的height和width。 如下圖:small bbox的橫軸值較小,發生偏移時,反應到y軸上的loss(下圖綠色)比big box(下圖紅色)要大。
在這裏插入圖片描述

對於負責,再補充一些作者給出的說法

一個網格預測多個bounding box,在訓練時我們希望每個object(ground true box)只有一個bounding box專門負責(一個object 一個bounding box)。具體做法是與ground true box(object)的IOU最大的bounding box 負責該ground true box(object)的預測。這種做法稱作bounding box predictor的specialization(專職化)。每個預測器會對特定(sizes,aspect ratio or classed of object)的ground true box預測的越來越好

預測(inference)與NMS(非極大值抑制)

訓練好的YOLO網絡,輸入一張圖片,將輸出一個 7730 的張量(tensor)來表示圖片中所有網格包含的對象(概率)以及該對象可能的2個位置(bounding box)和置信度。注意在inference過程中就沒有了訓練時標註所知的對象真實位置,也就沒有那些IOU的計算了。

NMS(非極大值抑制)

在inference時,引入一個score公式:score爲在這裏插入圖片描述反映了每個bounding box 特定類別的置信度分數。

可前面提到在inference時候並沒有IOU啊,公式只是爲了反應其意義,對應到inference時候,就是每個bounding box的20個類別概率去乘bounding box 的置信度。

在這裏插入圖片描述

如上圖,就反應了一個bounding box的和類別概率相乘的過程,獲得了一個20×1的張量

一共有98個bounding box 也就有98個20×1的張量,如下圖

在這裏插入圖片描述

接下來以Dog類爲例,Dog類對應位置如下

在這裏插入圖片描述

設置一個閾值小於閾值的score直接設爲0,如下圖:

在這裏插入圖片描述

之後降序排列(這只是dog類) 如下:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-LrJP03tn-1588516991677)(assets/20200430111910248.png)]

降序排列後,由於一些大的物體可能會佔用好幾個grid cell,但是由於一個物體只能由一個grid cell中的一個預測邊界框負責,所以需要選出score值最高的那個邊界框來負責該物體,就像例圖中的狗就佔用了好多grid cell;此時就需要進行NMS處理(非極大值抑制): 抑制的過程是一個迭代-遍歷-消除的過程:

1.將所有框的得分排序,選中最高分及其對應的框。
2.遍歷其餘的框,如果和當前最高分框的重疊面積(IOU)大於一定閾值,我們就將框刪除。
3.從未處理的框中繼續選一個得分最高的,重複上述過程。

在這裏插入圖片描述

通過選出一個類中score值最高的框,添加到輸出列表,然後使用同一類中未選擇過的最高score值進行比較,若是兩個框的IOU大於閾值則表明兩個框重疊太多,屬於共同負責一個物體,此時需要將框中該類的score置爲0,依次將所有框都與其進行比較。如果剩下的(已經去除掉輸出的)還有非0的,那再選出剩下(已經去除掉輸出的)中最大的,重複上述過程。

最後所有的bounding box 要麼輸出,要麼score爲0。

其他的所有類也是如此,都需要進行NMS處理過程。

總結一下這樣一個inference過程就是:

①Resize成448*448,圖片分割得到7×7網格(grid cell)

②CNN提取特徵和預測:卷積層負責提特徵。全鏈接層負責預測:a) 7×7×2=98個bounding box的座標和confidence置信度 b)7×7=49個grid cell中所屬20個物體的概率

③NMS過濾,輸出

如下圖:

在這裏插入圖片描述

cfg配置文件參數簡要解析

[net]
# Testing
#batch=1
#subdivisions=1
Training  
batch=64                                  #一批訓練樣本的樣本數量,每batch個樣本更新一次參數
# subdivisions=8                    #batch/subdivisions作爲一次性送入訓練器的樣本數量,如果內存不夠大,將batch分割爲subdivisions個子batch
		              #上面這兩個參數如果電腦內存小,則把batch改小一點,batch越大,訓練效果越好subdivisions越大,可以減輕顯卡壓力
height=448
width=448
channels=3                           # height,width,channels圖像屬性
momentum=0.9                    #DeepLearning1中最優化方法中的動量參數,這個值影響着梯度下降到最優值得速度  
decay=0.0005                        #權重衰減正則項,防止過擬合
saturation=1.5                      # 通過調整飽和度來生成更多訓練樣本
exposure=1.5                       # 通過調整曝光量來生成更多訓練樣本
hue=.1                                    #通過調整色調來生成更多訓練樣本

learning_rate=0.0005              #學習率決定着權值更新的速度,設置得太大會使結果超過最優值,太小會使下降速度過慢。
			#如果僅靠人爲干預調整參數,需要不斷修改學習率。剛開始訓練時可以將學習率設置的高一點,
			#而一定輪數之後,將其減小
			#在訓練過程中,一般根據訓練輪數設置動態變化的學習率。
			#剛開始訓練時:學習率以 0.01 ~ 0.001 爲宜。
			#一定輪數過後:逐漸減緩。
			#接近訓練結束:學習速率的衰減應該在100倍以上。
 
policy=steps                            #這個是學習率調整的策略,有policy:constant, steps, exp, poly, step, sig, RANDOM,constant等方式
steps=200,400,600,20000,30000       #下面這兩個參數steps和scale是設置學習率的變化,比如迭代到20000次時,學習率衰減十倍。
                                                              #30000次迭代時,學習率又會在前一個學習率的基礎上衰減十倍
scales=2.5,2,2,.1,.1
max_batches = 40000

[convolutional]                #卷積層
batch_normalize=1
filters=64                           # 特徵圖數量
size=7                                 #卷積核大小
stride=2                             # 步長
pad=1                                 #邊緣拓展。輸出尺寸通用公式:(輸入尺寸-卷積核尺寸+2pad)/步長 )+1,理論認爲卷積向下取整,池化向上取整,不同框架規則可能有差異
activation=leaky

[maxpool]                        #池化層
size=2
stride=2

[convolutional]
batch_normalize=1
filters=192
size=3
stride=1
pad=1
activation=leaky

[maxpool]
size=2
stride=2

[convolutional]
batch_normalize=1
filters=128
size=1
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=256
size=3
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=256
size=1
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky

[maxpool]
size=2
stride=2

[convolutional]
batch_normalize=1
filters=256
size=1
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=256
size=1
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=256
size=1
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=256
size=1
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=512
size=1
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=1024
size=3
stride=1
pad=1
activation=leaky

[maxpool]
size=2
stride=2

[convolutional]
batch_normalize=1
filters=512
size=1
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=1024
size=3
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=512
size=1
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=1024
size=3
stride=1
pad=1
activation=leaky

#######

[convolutional]
batch_normalize=1
size=3
stride=1
pad=1
filters=1024
activation=leaky

[convolutional]
batch_normalize=1
size=3
stride=2
pad=1
filters=1024
activation=leaky

[convolutional]
batch_normalize=1
size=3
stride=1
pad=1
filters=1024
activation=leaky

[convolutional]
batch_normalize=1
size=3
stride=1
pad=1
filters=1024
activation=leaky

[local]              #local層與convolution層很類似,只是convolution層共享卷積核參數,而local層每次滑動卷積窗口時,都會使用新的卷積核參數
size=3
stride=1
pad=1
filters=256
activation=leaky

[dropout]
probability=.5           #dropout層依一定概率將輸入值重置爲0並輸出,然後作爲下一層的輸入,這個概率值爲probability

[connected]               #全連接層
output= 1715
activation=linear


#detection層得代碼解析https://cloud.tencent.com/developer/article/1588094
[detection]
classes=20                    #網絡需要識別的物體種類數
coords=4        	     #每個box的4個座標tx,ty,tw,th
rescore=1                      #暫理解爲一個開關,非0時通過重打分來調整l.delta(預測值與真實的差)
side=7                            #gridcell尺寸
num=3                           # gidcell預測幾個box
softmax=0                     #激活函數
sqrt=1		      #yolo v1直接回歸的sqrt(w), 所以與GT bbox 計算IOU前,需要pow一下
jitter=.2                          #通過抖動增加噪聲來抑制過擬合

object_scale=1               #以下爲計算損失值的權重
noobject_scale=.5 
class_scale=1
coord_scale=5


參考與引用資料:
yolov1深入理解
yolov1解讀
中文論文
英文論文

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章