【yolo目标检测】(1) yolov3,网络结构Darknet53,特征提取
各位同學(xué)好,今天和大家分享一下使用Tensorflow2.0進(jìn)行yolov3目標(biāo)檢測,如何構(gòu)建Darknet53整體網(wǎng)絡(luò)結(jié)構(gòu),如何使用特征金字塔強(qiáng)化特征提取。
1. 網(wǎng)絡(luò)簡介
yolov3借鑒了resnet的殘差單元,在加深網(wǎng)絡(luò)層數(shù)提高精度的同時大大降低了計(jì)算量。在yolov3中沒有池化層和全連接層。張量的尺度變換是通過改變卷積核的步長來實(shí)現(xiàn)的(也就是通過卷積實(shí)現(xiàn)下采樣)。例如stride=(2,2),相當(dāng)于將圖像邊長縮小一般,整個特征圖縮小2^2倍。詳細(xì)見:目標(biāo)檢測之YOLO v3(附代碼詳細(xì)解析) - 知乎,下圖為yolov3的網(wǎng)絡(luò)結(jié)構(gòu)。
2.?卷積模塊
卷積模塊一般是指卷積層+批歸一化+激活函數(shù),在卷積層函數(shù)中,為了方便處理參數(shù),設(shè)置*args用于接收卷積核個數(shù)和卷積核大小,**kwargs存放用于設(shè)置的權(quán)重正則化方法,在這里使用 keras.regularizers.l2正則化方法;當(dāng)卷積層后面接批標(biāo)準(zhǔn)化BN層,就不需要使用偏置,會導(dǎo)致占用內(nèi)存。
# 卷積
def Conv(x, *args, **kwargs):# 列表一個*號: *args代表卷積核數(shù)量filter和尺寸kernel_size,# 字典兩個**號: **kwargs代表卷積部分其他參數(shù),new_kwargs = {'kernel_regularizer': l2(5e-4), 'use_bias':False} #l2正則化,有BN層不需要偏置# new_kwargs是原來的字典參數(shù),傳進(jìn)來新的參數(shù),比如步長,需要更新字典參數(shù)# 如果步長為2,填充方式需要變成'valid',步長為1填充方式為'same'new_kwargs['padding'] = 'valid' if kwargs.get('strides') == (2,2) else 'same' #字典添加元素# .get()返回指定key的值# .update()把字典kwargs的鍵和值更新到new_kwargs中去new_kwargs.update(kwargs) # 把步長更新進(jìn)去,確定填充方式# 卷積,使用更新后的參數(shù)x = layers.Conv2D(*args, **new_kwargs)(x)return x# 卷積+BN+激活
def CBL(x, *args, **kwargs):# 卷積x = Conv(x, *args, **kwargs)# 批歸一化x = layers.BatchNormalization()(x)# 激活函數(shù)x = LeakyReLU(alpha=0.1)(x)return x
3. 殘差模塊
殘差模塊最顯著的特點(diǎn)是使用了 short cut 機(jī)制(有點(diǎn)類似于電路中的短路機(jī)制)來緩解在神經(jīng)網(wǎng)絡(luò)中增加深度帶來的梯度消失問題,從而使得神經(jīng)網(wǎng)絡(luò)變得更容易優(yōu)化。它通過恒等映射(identity mapping)的方法使得輸入和輸出之間建立了一條直接的關(guān)聯(lián)通道,從而使得網(wǎng)絡(luò)集中學(xué)習(xí)輸入和輸出之間的殘差。
使用layers.ZeroPadding2D()方法用0填充圖像,size為偶數(shù)的圖像在使用步長為(2,2)的卷積可以得到偶數(shù)size的圖像。例如,[416,416,3]的圖像0填充后變成[417,417,3],經(jīng)過卷積核size=(3,3),步長strides=(2,2)的卷積,圖像size變化為(417-3+1)/2 = 208
# 0填充+卷積+BN+激活
def PCBL(x, num_filter):# 補(bǔ)0,將圖片size補(bǔ)成奇數(shù)再降維得到偶數(shù)sizex = layers.ZeroPadding2D(((1,0),(1,0)))(x)# 卷積層,下采樣,步長為2# 傳入的*args有卷積核個數(shù)和大小,*kwargs有步長x = CBL(x, num_filter, (3,3), strides=(2,2))return x# 2次(卷積+BN+激活) + 殘差結(jié)構(gòu),需要把最后的輸出與輸入相加
def CBLR(x, num_filter):# 卷積層y = CBL(x, num_filter, (1,1)) # 步長默認(rèn)為1# 卷積層y = CBL(y, num_filter*2, (3,3))# 殘差,add()相應(yīng)元素相加,h,w,c都不變x = layers.Add()([x,y]) #殘差塊,將輸入和輸出相加return x
4. 網(wǎng)絡(luò)組件
CBL5用于處理各尺度輸出后的特征圖,如最后一層大尺度目標(biāo)檢測的輸出結(jié)果為[13,13,1024],經(jīng)過五次卷積層進(jìn)一步提取特征,從[13,13,1024]==>[13,13,512]==>[13,13,1024]==>[13,13,512]==>[13,13,1024]==>[13,13,512]
特征提取后的結(jié)果,一是用于大尺度目標(biāo)檢測;二是用于上采樣函數(shù)CBLU,從[13,13,512]==>[26,26,256],長寬都變?yōu)樵瓉淼?倍,和中尺度輸出的特征圖像[26,26,512]疊加,即特征融合layers.Concatenate(),圖像size不變,只增加通道數(shù),得到疊加后的特征圖的shape為[26,26,768],也是分別用于中尺度目標(biāo)檢測,和上采樣后與小尺度圖像疊加。
# 處理輸出結(jié)果的各尺度圖像
def CBL5(x, num_filter):# 卷積+BN+激活x = CBL(x, num_filter, (1,1))x = CBL(x, num_filter*2, (3,3))x = CBL(x, num_filter, (1,1))x = CBL(x, num_filter*2, (3,3))x = CBL(x, num_filter, (1,1))return x# 規(guī)整通道數(shù)得輸出
def CBLC(x, num_filter, out_filter):# 上升通道數(shù),提特征x = CBL(x, num_filter*2, (3,3))# 卷積降維,規(guī)整通道數(shù),得輸出結(jié)果的通道數(shù),根據(jù)需求設(shè)置x = Conv(x, out_filter, (1,1))return x# 上采樣用于下一個尺度--圖像的size變大
def CBLU(x, num_filter):# 1*1卷積傳遞圖像信息x = CBL(x, num_filter, (1,1))# 上采樣,寬高size各變成原來的2倍x = layers.UpSampling2D(2)(x)return x
5. 網(wǎng)絡(luò)主體
darknet53網(wǎng)絡(luò)結(jié)構(gòu)如下:
使用特征金字塔FPN的思想,采用多尺度來對不同size的目標(biāo)進(jìn)行檢測,這也對應(yīng)了網(wǎng)絡(luò)結(jié)構(gòu)圖的三個預(yù)測分支(輸出)y1,y2,y3(每一個特征圖會分配3個先驗(yàn)框,一共9個先驗(yàn)框)。y1,y2和y3的深度都是255,邊長的規(guī)律是13:26:52,越小的特征圖代表下采樣的倍數(shù)高,而感受野也大,所以13×13的y1特征圖對應(yīng)檢測大物體,26×26的y2特征圖對應(yīng)檢測中物體,52×52的y3特征圖對應(yīng)檢測小物體。
def body(inputs, num_anchors, num_classes): # 預(yù)選框數(shù)目、類別數(shù)目# 存放最后三尺度的輸出結(jié)果out = []# CBL層,卷積+BN+激活,給定卷積核32個,size(3,3)x = CBL(inputs, 32, (3,3)) # CBLR在兩兩循環(huán)下的自身的循環(huán)次數(shù)n = [1, 2, 8, 8, 4]#(1)網(wǎng)絡(luò)構(gòu)建# PCBL+CBLR出現(xiàn)連著出現(xiàn)五次for i in range(5):# PCBL==> zeropadding + conv + BN + 激活x = PCBL(x, 2**(6+i)) #卷積核個數(shù)為2^(6+i)# CBLR自身也有一個循環(huán)for _ in range(n[i]):# 殘差結(jié)構(gòu)x = CBLR(x, 2**(5+i))# darknet53構(gòu)建完成#(2)輸出最后三尺度的圖像if i in [2,3,4]:out.append(x)#(3)處理每個尺度的圖像# ==1== 大尺度13*13*1024x1 = CBL5(out[2], 512) #[13,13,512]# 普通卷積得輸出結(jié)果,將通道數(shù)變成輸出結(jié)果的分類個數(shù)y1 = CBLC(x1, 512, num_anchors*(num_classes + 5)) # 輸出結(jié)果,和預(yù)選框的數(shù)目和識別物體的種類有關(guān)# 5代表box的坐標(biāo)(x,y), 寬w, 高h(yuǎn), 置信度c# 上采樣用于中尺度目標(biāo)檢測x = CBLU(x1, 256) #[26,26,256]# 大尺度上采樣的返回結(jié)果與中尺度圖像拼接# Concatenate()拼接,h,w不變,通道數(shù)增加x = layers.Concatenate()([x, out[1]]) #out[1]代表中尺度的圖像# [26,26,256] + [26,26,512] = [26,26,768]# ==2== 中尺度26*26*768x2 = CBL5(x, 256) #[26,26,256]# 卷積得輸出結(jié)果y2 = CBLC(x2, 256, num_anchors*(num_classes + 5)) #[26,26,N]# 中尺度上采樣x = CBLU(x2, 128) #[52,52,128]# 與小尺度拼接x = layers.Concatenate()([x, out[0]])# [52,52,128] + [52,52,256] = [52,52,384]# ==3== 小尺度52*52*384x3 = CBL5(x, 128) # [52,52,128]y3 = CBLC(x3, 128, num_anchors*(num_classes + 5)) #[52,52,N]# 返回三個尺度信息return [y1, y2, y3]
6. 查看網(wǎng)絡(luò)結(jié)構(gòu)
num_anchors = 3 # 預(yù)選框數(shù)目
num_classes = 5 # 識別種類,可改# 輸入層
input_tensor = keras.Input(shape=(416,416,3))
# 輸出層,預(yù)選框數(shù)目和,分類數(shù)目
output_tensor = body(input_tensor, num_anchors, num_classes)
# 構(gòu)建網(wǎng)絡(luò)
model = Model(input_tensor, output_tensor)
# input_tensor是416*416*3的圖片,output_tensor是大中小三個尺度的數(shù)組# 查看網(wǎng)絡(luò)結(jié)構(gòu)
model.summary()
---------------------------------------------------------------
省略 N 層
--------------------------------------------------------------- Normalization) batch_normalization_143 (Batch (None, 52, 52, 256) 1024 ['conv2d_148[0][0]'] Normalization) leaky_re_lu_129 (LeakyReLU) (None, 13, 13, 1024 0 ['batch_normalization_129[0][0]']) leaky_re_lu_136 (LeakyReLU) (None, 26, 26, 512) 0 ['batch_normalization_136[0][0]']leaky_re_lu_143 (LeakyReLU) (None, 52, 52, 256) 0 ['batch_normalization_143[0][0]']conv2d_133 (Conv2D) (None, 13, 13, 30) 30720 ['leaky_re_lu_129[0][0]'] conv2d_141 (Conv2D) (None, 26, 26, 30) 15360 ['leaky_re_lu_136[0][0]'] conv2d_149 (Conv2D) (None, 52, 52, 30) 7680 ['leaky_re_lu_143[0][0]'] ==================================================================================================
Total params: 61,597,792
Trainable params: 61,545,184
Non-trainable params: 52,608
__________________________________________________________________________________________________
總結(jié)
以上是生活随笔為你收集整理的【yolo目标检测】(1) yolov3,网络结构Darknet53,特征提取的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【神经网络】(8) 卷积神经网络(Mob
- 下一篇: 【MediaPipe】(1) AI视觉,