深度学习之DenseNet

本文假设你已经对DenseNet的网络结构有一定的认识,不需要进行详细的结构介绍,本文重心在与如何利用DenseNet做迁移学习,以及作者是如何训练得到令人惊讶的结果的。卷积网络目前发展分为两类,以inception为典型的并行结构与ResNet为典型的串行结构,作者以一个新颖的思路发明了一种新的网络结构,比其他经典网络参数更少,更容易收敛。

超参数

DenseNet的作者认为ResNet的恒等函数与输出H通过加法联系到一起,可能会阻碍信息的流动。而DenseNet的这个结构正好可以改善这种情况。

class DenseNet:
    def __init__(self, data_provider, growth_rate, depth,
                 total_blocks, keep_prob,
                 weight_decay, nesterov_momentum, model_type, dataset,
                 should_save_logs, should_save_model,
                 renew_logs=False,
                 reduction=1.0,
                 bc_mode=False,
                 **kwargs):

如果把DenseNet当做黑盒子来使用的话,你需要了解一些重要的参数,growth_rate与depth。增长率与深度,增长率的大小决定了当前层的输出维度。而depth很显然代表了你创建的网络深度。如果你了解ResNet的基础知识话,就会知道残差网络是以残差块为一个单位进行组织,DenseNet同样如此,total_blocks参数代表将会有多少block。

这里写图片描述这里写图片描述

通过此图,我们可以看到有3个block,growth_rate为5。DenseNet通过卷积与平均池化,接连两个block。keep_prob是dropout的参数,不仅使用了dropout正则化,而且还使用了BN正则化。记得inception-v3网络中使用的BN代替了dropout,理由是BN已经有正则化效果了,不需要dropout,此外作者还用到了L2正则化。从此点来看,作者明显没有受到前人的约束勇于创新。结构如下,BN+Relu+Conv+Dropout

    def composite_function(self, _input, out_features, kernel_size=3):
        with tf.variable_scope("composite_function"):
            # BN
            output = self.batch_norm(_input)
            # ReLU
            output = tf.nn.relu(output)
            # convolution
            output = self.conv2d(
                output, out_features=out_features, kernel_size=kernel_size)
            # dropout(in case of training and in case it is no 1.0)
            output = self.dropout(output)
        return output

weight_decay是BN中的权重衰减系数,一般设置为0.9、0.95。nesterov_momentum参数是动量梯度下降的参数,但是我查看论文作者使用的还是SGD,这让我想起了之前有个争论,Adam到底好不好?有的科研人员验证出Adam是最好的梯度下降方法,也有另外一派,找出了Adam失效的特殊情况。果然还是SGD最靠谱。model_type参数是使用DenseNet还是使用DenseNet-BC,这两个网络的区别还是要从原文中来看,作者为了使得模型更加的紧凑,如果denseblock有k个特征映射,也就是维度数,把连接两个block的层我们称为transition层,通过这个层进行特征降维,输出Qk 维,Q<1。那么就把这个网络称为DenseNet-C,此外还有一个bottleneck层,这是DenseNet-BC才有的层,这个层里面也有一个系数来控制是降维度还是提高维度,如果transition与transition的系数都小于1的话,也就是降低维度则称位DenseNet-BC。

训练细节

除了 ImageNet数据集,作者训练其他的数据集使用3个dense blocks,并且每个block中层数相同,在第一个dense block之前的第一层卷积网络输出16个channel(或者两倍的增长率,使用DenseNet-BC网络),核的大小为33,使用11卷积后接22的平均池化作为连接两个block 的transition层。对于L(深度)与k(增长率),作者使用的有(40,12)、(100,12)、(100、24)。对于DenseNet-BC参数设置为(100,12),(250,24),(190,40)。对于ImageNet数据集,作者训练的方式如下:使用4个dense block ,input大小为224224,初始化第一层卷积是由输出维度为2k,卷积核大小为7*7,步长为2,剩下的featrue-maps(特征映射大小设置为k)

这里写图片描述这里写图片描述,此外还有一处区别,就是红框画出的部分,并不是每个block层数都相同。这个可能需要你自己设置。我翻阅了基于tensorflow DenseNet 论文源码实现,写的最好的还是 这篇,这篇将DenseNet-BC考虑进去了,所有的tensorflow实现中所有的block的层数都相同,所以如果你发现了不要困惑,因为非ImageNet数据集都使用这种方式,这也许给了我们一些启示,如果你做迁移学习的时候,类别并不是很多,图像也不是很复杂,那就完全没有必要使用上面的复杂结构。我测试了MINST数据集,2个block,效果能达到98%,还真是令人吃惊不是吗?点击下载 论文

总结

觉得很有必要一起研读网络实现源码,从中体会到更特别的感触,总的来说DenseNet的网络实现,还是比较简单的,与Inception不同,inception不仅要考虑分支,还要考虑辅助节点,确实很复杂,与ResNet搭建一样简单,封装好block之后就可以happy的搬砖了,遗憾的是我并没有找到DenseNet已经训练好的模型参数,如果有模型参数的话可能几次epoch就能收敛到不错的效果。下面是整个网络的构建过程,逻辑比较清晰没有复杂的结构,点击我查看DenseNet源码。如果还比较困惑可以对照着论文,一目了然,本人能力有限,如果有瑕疵请指出,欢迎与我讨论学习

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值