CNN史上的一个里程碑事件是ResNet模型的出现,ResNet可以训练出更深的CNN模型,从而实现更高的准确度。ResNet模型的核心是通过建立前面层与后面层之间的“短路连接”(shortcuts,skip connection),这有助于训练过程中梯度的反向传播,从而能训练出更深的CNN网络。今天我们要介绍的是DenseNet模型,它的基本思路与ResNet一致。ResNet是每个层与前面的某层(一般是2~3层)短路连接在一起,连接方式是通过元素级相加。而在DenseNet中,每个层都会与前面所有层在channel维度上连接在一起,并作为下一层的输入。
CNN网络一般要经过Pooling或者stride>1的Conv来降低特征图的大小,而DenseNet的密集连接方式需要特征图大小保持一致。为了解决这个问题,DenseNet网络中使用DenseBlock+Transition的结构,其中DenseBlock是包含很多层的模块,每个层的特征图大小相同,层与层之间采用密集连接方式。而Transition模块是连接两个相邻的DenseBlock,并且通过Pooling使特征图大小降低。
在DenseBlock中,各个层的特征图大小一致,可以在channel维度上连接。
DenseBlock中的非线性组合函数采用的是BN+ReLU+3x3 Conv的结构。
所有DenseBlock中各个层卷积之后均输出 k个特征图,即得到的特征图的channel数为k,或者说采用 k 个卷积核。 k 在DenseNet称为growth rate,这是一个超参数。一般情况下使用较小的 k (比如12),就可以得到较佳的性能。假定输入层的特征图的channel数为 k0 ,那么l 层输入的channel数为 k0+k(l-1) ,因此随着层数增加,尽管 k 设定得较小,DenseBlock的输入会非常多。
由于后面层的输入会非常大,DenseBlock内部可以采用bottleneck层来减少计算量,主要是原有的结构中增加1x1 Conv,如图7所示,即BN+ReLU+1x1 Conv+BN+ReLU+3x3 Conv,称为DenseNet-B结构。
def bn_rl_conv(x, filters, kernel_size):
x = BatchNormalization()(x)
x = ReLU(