Fleeting Day(VOL.16)

每日总结190511

YOLOv3

DarkNet53是在ResNet基础上而来,结构图为:
DarkNet53

而整个YOLOv3的结构图为:
20190510120132.png

由此,用tensorflow实现DarkNet53如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import numpy as np
import tensorflow as tf
from tensorflow.contrib import slim

# 固定填充
@slim.add_arg_scope
def fixed_padding(inputs, kernel_size, *args, mode='CONSTANT', **kwargs):
pad_tol = kernel_size - 1
pad_beg = pad_tol // 2
pad_end = pad_tol - pad_beg

if kwargs['data_format'] == 'NCHW':
paded_inputs = tf.pad(inputs, [[0, 0], [0, 0], [pad_beg, pad_end], [pad_beg, pad_end]], mode=mode)
else:
paded_inputs = tf.pad(inputs, [[0, 0], [pad_beg, pad_end], [pad_beg, pad_end], [0, 0]], mode=mode)

return paded_inputs

# 固定填充后进行卷积
def conv2d_fixed_padding(inputs, filters, kernel_size, strides=1):
if strides > 1:
inputs = fixed_padding(inputs, kernel_size)
# CONV2D --> BN --> LeakyReLU
inputs = slim.conv2d(inputs, filters, kernel_size, stride=strides, padding=('SAME' if strides == 1 else 'VALID'))

return inputs

# darknet53
class DarkNet53(object):

def __init__(self, inputs):
self.outputs

def block(self, inputs, filters):
shortcut = inputs
inputs = conv2d_fixed_padding(inputs, filters, 1)
inputs = conv2d_fixed_padding(cnv1, filters*2, 3)
inputs = inputs + shortcut
return inputs

def forward(self, inputs):
inputs = conv2d_fixed_padding(inputs, 32, 3)
inputs = conv2d_fixed_padding(inputs, 62, 3, strides=2)

inputs = self.block(inputs, 32)

inputs = conv2d_fixed_padding(inputs, 128, 3, strides=2)

for i in range(2):
inputs = self.block(inputs, 64)

inputs = conv2d_fixed_padding(inputs, 256, 3, strides=2)

for i in range(8):
inputs = self.block(inputs, 128)

route_1 = inputs
inputs = conv2d_fixed_padding(inputs, 512, 3, strides=2)

for i in range(8):
inputs = self.block(inputs, 256)

route_2 = inputs
inputs = conv2d_fixed_padding(inputs, 1023, 3, strides=2)

for i in range(4):
inputs = self.block(inputs, 512)

return route_1, route_2, inputs

其中,用到了修饰器@slim.add_arg_scope,用来给方法设置默认参数值,例如:

1
2
3
4
5
6
7
8
9
10
import tensorflow as tf
slim = tf.contrib.slim

@slim.add_arg_scope
def fun1(a=0, b=0):
return (a+b)

with slim.arg_scope([fun1], a=10):
x = fun1(b=30)
print(x)

得到的结果就是$40$。注意到,slim.conv2d()、fully_connected()、max_pool2d()等方法在定义时都添加了该修饰器,因此可以在后面统一指定它们的一些默认参数。

MobileNet v1 Paper

MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications
卷积神经网络中的Separable Convolution

MobileNet就是基于深度可分离卷积(depthwise separable convolution)构建的,该卷积是一类factorized卷积,它将一个完整的卷积运算分为两步——Depthwise Convolution和Pointwise Convolution。

常规的卷积过程为:
常规卷积

其中包含$4\times3\times3\times3=108$个参数。而进行DSC时,DC的过程是在二维平面上用三个卷积核为对各通道分别卷积:
Depthwise Convolution

之后PC的过程则用多个$1\times1$大小的卷积核进行卷积:
Pointwise Convolution

这样总共包含$3\times3\times3 + 1\times1\times3\times4 = 39$个参数,大大缩减参数数量。

MobileNet v1的整个架构如下图所示:
MobileNet v1

除了最后的全连接层外,每一层后面都进行批标准化后使用ReLU激活:
结构对比

其中下采样通过增加卷积的步幅来实现,通过后面的平均池化将特征图的空间分辨率变为$1$进而输入后面的全连接层。DC、PC各算一层,则整个MobileNet共包含$28$层。

模型中将大部分计算复杂度都放到了$1\times1$卷积中,它可以通过高度优化的通用矩阵乘法(GEMM)功能来实现。由于模型较小,训练期间没有使用太多预防过拟合的措施

为适应特定应用场景,引入了称为width multiplier的超参数$\alpha$和Resolution Multiplier的超参数$\rho$,它们的值在$(0, 1]$之间选取,前者的作用是给每层均匀进行减负,把某一层中包含$M$个通道的输入变成$\alpha M$,$N$个通道的输入变成$\alpha N$,以此重新定义一个计算量更小的模型,不过该模型需要重新训练;后者的作用是设置输入的分辨率,以此减少计算复杂度。

Summary

不知道自己又做了些什么。笔记本的充电器摔到地上就给坏了,真是。

文章作者: Hugsy
文章链接: http://binweber.top/2019/05/11/daily_190510/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Sky Inside the Eyewall
支付宝打赏~
微信打赏~