【特征提取网络】|ResNeXt

思想来源

现代的网络设计中通常会次堆叠类似结构,如VGG,Inception,Resnet等,从而减少网络中超参数的数量,简化网络设计。

Inception使用了split-transform-merge策略,即先将输入分成几部分,然后分别做不同的运算,最后再合并到一起。这样可以在保持模型表达能力的情况下降低运算代价。

但是Inception的结构还是过于复杂了,人工设计的痕迹太重了。

然后,站得更高,分析了神经网络的标准范式就符合这样的split-transform-merge模式。以一个最简单的普通神经元为例(比如FC中的每个神经元):
在这里插入图片描述就是先对输入的m个元素,分配到m个分支,进行权重加权,然后merge求和,最后经过一个激活。

由此归纳出神经网络的一个通用的单元可以用如下公式表示:

在这里插入图片描述

Ti代表任意一种变换,C是要聚合的一组转换的大小。我们称C为基数,并且指出,基数C对于结果的影响比宽度和深度更加重要。

在卷积分组也可以应用。

作者想,我直接暴力均分输入,卷积层结构都是一样的,然后再merge。这样的话我只需要告诉网络分成几组就可以了,不就不需要再设计那么精巧的Inception了吗?

在这里插入图片描述

图3中的三种结构实际上是等价的。a是ResNeXt基本单元,如果把输出那里的1x1合并到一起,得到等价网络b拥有和Inception-ResNet相似的结构,而进一步把输入的1x1也合并到一起,得到等价网络c则和通道分组卷积的网络有相似的结构。

到这里,可以看到本文的野心很大,相当于在说,Inception-ResNet和通道分组卷积网络,都只是ResNeXt这一范式的特殊形式而已,进一步说明了split-transform-merge的普遍性和有效性,以及抽象程度更高,更本质一点。

因此现在几乎所有的神经网络框架的conv层都有group这个参数,但在作者之前就是没人把这个group作为超参数调一下(这是个很有意思的问题,明明框架里有,为啥大家不试试呢)。作者后来提到之前做网络压缩的人提出过group的方法,但是却极少有人研究其精度,这篇文章是从模型表达和精度的方向上写的。

ResNeXt

具体结构

如表一中显示的,两边的网络具有相同的参数和计算量,但是右侧会有更好的精度。

请添加图片描述

分组卷积参数量计算

对输入的通道分为g组,卷积核的通道和个数都分为g组来分别对输入做卷积,最后的结果就是g组的输出,通道合并(concatenate)否就是总通道的输出。卷积核的通道分组是为了对应输入,卷积核的个数分组是为了让输出的通道分组。如图
每组,输入数据为H1×W1×C1/g,卷积核大小为h1×w1×C1/g,一共有C2/g个,输出数据为H2×W2×C2/g。

分组的方式能够增加卷积核之间的对角相关性,而且能够减少训练参数(不需要分别做33卷积了,整体做一次33,再通道切分即可),不容易过拟合,这类似于正则的效果。

举例:分组卷积极大减少了参数,比如当输入通道为256,输出通道也为256,kernel size为3×3,不做Group conv参数为256×3×3×256。实施分组卷积时,若group为8,每个group的input channel和output channel均为32,参数为8×32×3×3×32,是原来的八分之一。其实是卷积核对输入做卷积时少做了7/8的通道,局部通道。

原文翻译
https://www.cnblogs.com/wanghui-garcia/p/14007182.html

code

nn.Conv2d中包含group参数

 nn.Conv2d(in_channels, in_channels, kernel_size=3, stride=stride, padding=1, groups=C, bias=False)

ref
https://blog.csdn.net/cp1314971/article/details/104396169

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用TensorFlow实现的ResNeXt特征提取网络的代码示例: ```python import tensorflow as tf from tensorflow.contrib import slim def bottleneck_block(inputs, filters, strides, cardinality, is_training, projection=False): shortcut = inputs if projection: shortcut = slim.conv2d(shortcut, filters * 4, [1, 1], stride=strides, activation_fn=None) x = slim.conv2d(inputs, filters, [1, 1], stride=1, activation_fn=None) x = slim.batch_norm(x, is_training=is_training) x = tf.nn.relu(x) x = tf.split(x, cardinality, axis=3) x = tf.concat([slim.conv2d(elem, filters // cardinality, [3, 3], stride=strides, activation_fn=None) for elem in x], axis=3) x = slim.batch_norm(x, is_training=is_training) x = tf.nn.relu(x) x = slim.conv2d(x, filters * 4, [1, 1], stride=1, activation_fn=None) x = slim.batch_norm(x, is_training=is_training) output = tf.nn.relu(shortcut + x) return output def resnext(inputs, is_training): with slim.arg_scope([slim.conv2d], activation_fn=None, biases_initializer=None): with slim.arg_scope([slim.batch_norm], scale=True, center=True): net = slim.conv2d(inputs, 64, [7, 7], stride=2, padding='SAME') net = slim.batch_norm(net, is_training=is_training) net = tf.nn.relu(net) net = slim.max_pool2d(net, [3, 3], stride=2, padding='SAME') net = bottleneck_block(net, 128, 1, 32, is_training, projection=True) for i in range(3): net = bottleneck_block(net, 128, 1, 32, is_training) net = bottleneck_block(net, 256, 2, 32, is_training, projection=True) for i in range(4): net = bottleneck_block(net, 256, 1, 32, is_training) net = bottleneck_block(net, 512, 2, 32, is_training, projection=True) for i in range(6): net = bottleneck_block(net, 512, 1, 32, is_training) net = bottleneck_block(net, 1024, 2, 32, is_training, projection=True) for i in range(3): net = bottleneck_block(net, 1024, 1, 32, is_training) return net ``` 以上是使用TensorFlow实现的ResNeXt特征提取网络的代码示例,你可以参考这些代码来实现自己的ResNeXt网络。在代码中,我们使用了bottleneck_block函数来实现ResNeXt的残差块,以及resnext函数来构建整个网络。注意,这里的代码仅仅是ResNeXt的一个简化版本,如果你需要更深入的了解,建议参考相关论文和其他代码实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值