DenseNet网络解析
简介
DenseNet: 全称Dense Convolutional Network,稠密卷积网络。
传统的网络L层有L个连接,DenseNet却有L(L+1)/2个连接。
DenseNet使用更少的计算量就可以获得更好的性能。
网络特点
1.有利于特征传播;
2.鼓励特征的重复利用;
3.可以减少参数量;
4.有助于解决梯度消失问题,改善了网络中信息和梯度的传递,让网络更容易训练。
网络结构
Densenet网络主要由稠密块和过渡层构成。
稠密块:稠密块由多个conv_block组成,每块使用相同的输出通道数,然后用循环将每块的输入和输出在通道维上连结。
过渡层:过渡层用来控制模型复杂度。由于每个稠密块连结都会带来通道数的增加,使用过多则会带来过于复杂的模型。它通过1×1卷积层来减小通道数,并使用stride=2的平均池化层降采样,从而进一步降低模型复杂度。
The top-1 and top-5 error rates on the ImageNet validation set.
代码实现
以DenseNet-121网络为例
网络输入
inputs = Input([224, 224, 3])
blocks = [6, 12, 24, 16]
主干结构
def denseNet(inputs, blocks):
x = Conv2D(24, (7, 7), padding='same', strides=2)(inputs)
x = MaxPooling2D(pool_size=(3, 3), strides=2, padding='same')(x)
for i, block in enumerate(blocks):
x = dense_block(x, block)
if i != len(blocks) - 1:
x = transition_block(x, 0.5)
x = GlobalAveragePooling2D()(x)
x = Flatten()(x)
x = Dense(1000, activation='relu')(x)
return x
稠密块 Dense Block
def dense_block(x, blocks):
for i in range(blocks):
x = conv2d_block(x, 32)
return x
def conv2d_block(x, grow_rate):
# axis = 3 表示channel层
bn_axis = 3
x1 = BatchNormalization(axis=bn_axis, epsilon=1.0001e-5)(x)
x1 = Activation('relu')(x1)
x1 = Conv2D(grow_rate * 4, (1, 1), padding='same')(x1)
x1 = BatchNormalization(axis=bn_axis, epsilon=1.0001e-5)(x1)
x1 = Activation('relu')(x1)
x1 = Conv2D(grow_rate, (3, 3), padding='same')(x1)
x = Concatenate()([x, x1])
return x
过渡层 Transition Layer
def transition_block(x, reduction):
bn_axis = 3
x = BatchNormalization(axis=bn_axis, epsilon=1.001e-5)(x)
x = Activation('relu')(x)
x = Conv2D(int(int(x.shape[bn_axis]) * reduction), (1, 1), padding='same')(x)
x = AveragePooling2D(strides=(2, 2))(x)
return x
DenseNet和ResNet
DenseNet网络参数量更少,因为channel比较小。
DenseNet错误率更低,计算消耗更少。