yoloV3網絡
下面爲yoloV3網絡圖:
爲了方便理解,放了來自木盞的yoloV3的網絡結構圖
DBL: 即代碼中的Darknetconv2d_BN_Leaky,是yolo_v3的基本組件。就是卷積+BN+Leaky relu。
resn:n代表數字,有res1,res2, … ,res8等等,表示這個res_block裏含有多少個res_unit。
1.DBL
實現DBL:
@wraps(Conv2D)
# 設置DBL中卷積核參數
def DarknetConv2D(*args, **kwargs):
"""Wrapper to set Darknet parameters for Convolution2D."""
darknet_conv_kwargs = {'kernel_regularizer': l2(5e-4)}
darknet_conv_kwargs['padding'] = 'valid' if kwargs.get('strides')==(2,2) else 'same'
darknet_conv_kwargs.update(kwargs)
return Conv2D(*args, **darknet_conv_kwargs)
# 定義DBL函數
def DarknetConv2D_BN_Leaky(*args, **kwargs):
"""Darknet Convolution2D followed by BatchNormalization and LeakyReLU."""
no_bias_kwargs = {'use_bias': False}
no_bias_kwargs.update(kwargs)
return compose(
DarknetConv2D(*args, **no_bias_kwargs),
BatchNormalization(),
LeakyReLU(alpha=0.1))
2. resblock_body
實現resblock_body:
resblock_body中包含Res_unit:
def resblock_body(x, num_filters, num_blocks):
'''A series of resblocks starting with a downsampling Convolution2D'''
# Darknet uses left and top padding instead of 'same' mode
x = ZeroPadding2D(((1,0),(1,0)))(x)
x = DarknetConv2D_BN_Leaky(num_filters, (3,3), strides=(2,2))(x)
# res_unit
for i in range(num_blocks):
y = compose(
DarknetConv2D_BN_Leaky(num_filters//2, (1,1)),
DarknetConv2D_BN_Leaky(num_filters, (3,3)))(x)
x = Add()([x,y])
return x
3. Darknent-53
實現Darknent-53(不含全連接層):
下圖爲yoloV3論文中的Darknent-53網絡圖(含全連接層),包含了每一層的詳細的通道數,圖中的:
相當於resblock_body。
def darknet_body(x):
'''Darknent body having 53 Convolution2D layers'''
x = DarknetConv2D_BN_Leaky(32, (3,3))(x)
# 3 Convolution2D layers
x = resblock_body(x, 64, 1)
# 5 Convolution2D layers
x = resblock_body(x, 128, 2)
# 17 Convolution2D layers
x = resblock_body(x, 256, 8)
# 17 Convolution2D layers
x = resblock_body(x, 512, 8)
# 9 Convolution2D layers
x = resblock_body(x, 1024, 4)
return x
4. y1、y2和y3
def make_last_layers(x, num_filters, out_filters):
'''6 Conv2D_BN_Leaky layers followed by a Conv2D_linear layer'''
# 5 DBL Layers
x = compose(
DarknetConv2D_BN_Leaky(num_filters, (1,1)),
DarknetConv2D_BN_Leaky(num_filters*2, (3,3)),
DarknetConv2D_BN_Leaky(num_filters, (1,1)),
DarknetConv2D_BN_Leaky(num_filters*2, (3,3)),
DarknetConv2D_BN_Leaky(num_filters, (1,1)))(x)
y = compose(
DarknetConv2D_BN_Leaky(num_filters*2, (3,3)),
DarknetConv2D(out_filters, (1,1)))(x)
return x, y
def yolo_body(inputs, num_anchors, num_classes):
"""Create YOLO_V3 model CNN body in Keras."""
# darknent-53 結構
darknet = Model(inputs, darknet_body(inputs))
# 求 y1
x, y1 = make_last_layers(darknet.output, 512, num_anchors*(num_classes+5))
# 求 y2
x = compose(
DarknetConv2D_BN_Leaky(256, (1,1)),
UpSampling2D(2))(x)
x = Concatenate()([x,darknet.layers[152].output])
x, y2 = make_last_layers(x, 256, num_anchors*(num_classes+5))
# 求 y3
x = compose(
DarknetConv2D_BN_Leaky(128, (1,1)),
UpSampling2D(2))(x)
x = Concatenate()([x,darknet.layers[92].output])
x, y3 = make_last_layers(x, 128, num_anchors*(num_classes+5))
return Model(inputs, [y1,y2,y3])