EffNet

EffNet

背景介绍

  EffNet:2018年发表于ICIP,提出一种新颖的卷积块设计,能够显著减轻计算负担,且性能远胜当前的最好的模型(对比MobileNet,ShuffleNet)。

EffNet

EffNet特点

  借鉴了Depthwise Convolution(深度卷积)的思想,并且将Inception中spatial separable convolutions(空间可分离卷积)的思想推广到池化分解。采用深度可分离卷积代替传统的卷积,并且卷积核采用1x3和3x1代替3x3,两次卷积核之间插入一维池化核,可以进一步减少参数量。

Depthwise Convolution

depthwise
  Depthwise Convolution(深度卷积):在每一个通道上单独进行卷积**
  参数depth_multiplier默认为1,代表每个通道数进行一次单独卷积,输出的通道数和输入通道数相等,设置depth_multiplier=n,则代表每个通道数进行n次单独卷积,输出通道数是输入通道数的n倍
  主要作用是大大降低网络的参数量。如果一个8x8x1024的特征图,经过5x5的卷积核后变为8x8x1024的图像,经过普通卷积的参数量为1024x(1024x5x5+1)=26215424,而深度卷积参数量为1024x(1x5x5+1)=26624,参数量缩小了约1024倍。

Spatial Separable Convolution

spatial
  Spatial Separable Convolution(空间可分离卷积):将3x3的卷积分解为3x1的卷积核1x3的卷积,将7x7的卷积分解为7x1的卷积核1x7的卷积.。
  主要作用是
大大降低网络的参数量
。如果一个64x64x256的特征图,经过7x7的卷积核后变为64x64x256的图像,经过普通卷积的参数量为256x(256x7x7+1)=3211520,而空间可分离卷积参数量为2x256x(256x7x1+1)=918016,参数量缩小了约3.5倍。

EffNet图像分析

EffNet

TensorFlow2.0实现

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
from functools import reduce
import tensorflow.keras as keras


def compose(*funcs):
if funcs:
return reduce(lambda f, g: lambda *a, **kw: g(f(*a, **kw)), funcs)
else:
raise ValueError('Composition of empty sequence not supported.')


class Conv_Bn_LeakyRelu(keras.layers.Layer):
def __init__(self, filters, kernel_size, strides, padding, name):
super(Conv_Bn_LeakyRelu, self).__init__()
self._name = name
self.block = keras.Sequential()
if name.find('depthwise') == -1:
self.block.add(keras.layers.Conv2D(filters, kernel_size, strides, padding=padding))
else:
self.block.add(keras.layers.DepthwiseConv2D(kernel_size, strides, padding=padding))
self.block.add(keras.layers.BatchNormalization())
self.block.add(keras.layers.LeakyReLU())

def call(self, inputs, **kwargs):

return self.block(inputs)


def block(inchannel, outchannel, name):

return compose(Conv_Bn_LeakyRelu(inchannel, (1, 1), (1, 1), 'same', name='{}_conv_bn_leakyrelu1'.format(name)),
Conv_Bn_LeakyRelu(None, (1, 3), (1, 1), 'same', name='{}_depthwiseconv_bn_leakyrelu1'.format(name)),
keras.layers.MaxPool2D((1, 2), (1, 2), name='{}_maxpool'.format(name)),
Conv_Bn_LeakyRelu(None, (3, 1), (1, 1), 'same', name='{}_depthwiseconv_bn_leakyrelu2'.format(name)),
Conv_Bn_LeakyRelu(outchannel, (1, 1), (2, 1), 'same', name='{}_conv_bn_leakyrelu2'.format(name)))


def effnet(input_shape):
input_tensor = keras.layers.Input(input_shape, name='input')
x = input_tensor

x = compose(block(32, 64, name='block1'),
block(64, 128, name='block2'),
block(128, 256, name='block3'))(x)

x = compose(keras.layers.Flatten(name='flatten'),
keras.layers.Dense(10, activation='softmax', name='dense'))(x)

model = keras.Model(input_tensor, x, name='EffNet')

return model


if __name__ == '__main__':

model = effnet(input_shape=(32, 32, 3))
model.build(input_shape=(None, 32, 32, 3))
model.summary()

EffNet

EffNet小结

  EffNet给我们提供了一种一维池化的思路,虽然论文中以Cifar10作为数据集,参数量无法和其他模型进行直接的对比,但是模型的使用效果却优于MobileNet和ShuffleNet。

-------------本文结束感谢您的阅读-------------
0%