DenseNet
DenseNet
还是想主要解决梯度消失的问题,虽然这个问题在之前的模型中,例如resnet给出了解决办法。之前的模型都有一个共同的特点:都在新层和旧层之间创造了捷径。Densenet沿用了这种方法,选择将所有的层都链接在一起,保证最大信息在层与层之间进行流动。
与ResNet不同的是,densenet 并没有将特征进行相加得到新的特征,而是将每一层传进来的特征进行拼接操作。
所以第L层将会有L个inputs,包含着前面所有卷积块的特征图。
- 需要更少的参数,不用去学习冗余的特征图 feature-map
- 每一层都和最初的input有通道连接,又和最终的loss函数直接连接,这会有助于模型的训练。
- 还有一定的规范化的作用,能够克制在小型数据集上的过拟合。
- 说起拼接这一点,和inception,goodlenet有点像,但是比他们更加的高效。
Composite function:复合函数
, 第l层的输出就是将前l-1层的输出拼接起来再经过一个符合函数H得到的,这个函数包括:
- BN:batch normalization
- ReLU
- 3×3的Conv
Dense Block-transition layers
这个就是Densenet的关键核心所在,之前所说的东西基本上都是说的这个,每两个Dense Block之间夹着一个trastion layers
主要用来做卷积和池化操作,在他们的实验中使用的是1×1的Conv 接上一个2×2的pooling。
Growth rate
这个参数感觉就是来限定每一层,使用多少个filter差不多。如果每一层都产生一个通道数为K的输出,那么到了第L层输出的总通道数就是 个通道数。是开始时输入的图像的通道数。k=12的时候的结果就很好了。k其实决定了每一层贡献出多少的信息给全局的状态。
Architecture for ImageNet
bottle neck layer
再dense block 内部的3×3卷积之前,加入一个1×1的卷积bottle neck 从而去减少featuremap的数量,能够有效的提高计算的效率。所以,block内部的的情况就是 BN-RELU-CONV1×1-BN-RELU-CONV3×3.
Compression
上面已经讲过了,在 Dense Block 之间加入的是Transition Layer,为了改善网络的运行效率,从一个Dense Block 出来之后,通过Transition Layer 对feature-map进行压缩,如果前一个block出来的有m个featuremap,经过transition后,它只会有取整个featuremap 流出。当时,是保持不变的。在本文的实验中,他们设置为0.5
Implementation Details
Except ImageNet,在其他数据集上都是用的三个block,在进入第一个block之前,图像会被16个通道数卷积所处理。
对于3×3的kernel,都使用一个0填充去保证大小的一致
训练集50000,测试集10000,验证集50000.
data augmentation scheme:shif,mirror
preprocess: channel mean and standard deviation , normalize
框架简单代码-pytorch
class DenseBlock(nn.Module):
def __init__(self, num_convs, in_channels, out_channels):
super(DenseBlock, self).__init__()
net = []
for i in range(num_convs):
in_c = in_channels + i * out_channels
net.append(conv_block(in_c, out_channels))
self.net = nn.ModuleList(net)
self.out_channels = in_channels + num_convs * out_channels # 计算输出通道数
def forward(self, X):
for blk in self.net:
Y = blk(X)
X = torch.cat((X, Y), dim=1) # 在通道维上将输入和输出连结
return X
def transition_block(in_channels, out_channels):
blk = nn.Sequential(
nn.BatchNorm2d(in_channels),
nn.ReLU(),
nn.Conv2d(in_channels, out_channels, kernel_size=1),
nn.AvgPool2d(kernel_size=2, stride=2))
return blk
num_channels, growth_rate = 64, 32 # num_channels为当前的通道数
num_convs_in_dense_blocks = [4, 4, 4, 4]
for i, num_convs in enumerate(num_convs_in_dense_blocks):
DB = DenseBlock(num_convs, num_channels, growth_rate)
net.add_module("DenseBlosk_%d" % i, DB)
# 上一个稠密块的输出通道数
num_channels = DB.out_channels
# 在稠密块之间加入通道数减半的过渡层
if i != len(num_convs_in_dense_blocks) - 1:
net.add_module("transition_block_%d" % i, transition_block(num_channels, num_channels // 2))
num_channels = num_channels // 2
net.add_module("BN", nn.BatchNorm2d(num_channels))
net.add_module("relu", nn.ReLU())
net.add_module("global_avg_pool", d2l.GlobalAvgPool2d()) # GlobalAvgPool2d的输出: (Batch, num_channels, 1, 1)
net.add_module("fc", nn.Sequential(d2l.FlattenLayer(), nn.Linear(num_channels, 10)))
m_channels, 1, 1)
net.add_module(“fc”, nn.Sequential(d2l.FlattenLayer(), nn.Linear(num_channels, 10)))
上一篇: DenseNet
推荐阅读
-
DenseNet
-
DenseNet
-
【Densenet】Densenet网络结构的代码实现及解析
-
Mxnet (18): 密集连接的网络(DenseNet)
-
AI实战pytorch版DenseNet迁移学习
-
Tensorflow复现DenseNet cifar-10(正确率91%)
-
Tensorflow复现DenseNet cifar-10(正确率91%)
-
AI实战pytorch版DenseNet迁移学习
-
常用神经网络_2_ 残差网络 —> ResNet —> DenseNet
-
caffe跑densenet的错误:Message type "caffe.PoolingParameter" has no field named "ceil_mode".