公司制作网站价格,网站建设费用什么意思,jquery网站模板下载,怎么申请网址公众号关注 “ML-CVer”设为 “星标”#xff0c;DLCV消息即可送达#xff01;作者丨刘昕宸知乎来源丨https://zhuanlan.zhihu.com/p/268308900编辑丨极市平台导读 通过堆叠神经网络层数(增加深度)可以非常有效地增强表征#xff0c;提升特征学习效果#xff0c;但是会出现… 公众号关注 “ML-CVer”设为 “星标”DLCV消息即可送达作者丨刘昕宸知乎来源丨https://zhuanlan.zhihu.com/p/268308900编辑丨极市平台导读 通过堆叠神经网络层数(增加深度)可以非常有效地增强表征提升特征学习效果但是会出现深层网络的性能退化问题ResNet的出现能够解决这个问题。本文用论文解读的方式展现了ResNet的实现方式、分类、目标检测等任务上相比SOTA更好的效果。论文标题Deep Residual Learning for Image Recognition1 motivation通过总结前人的经验我们常会得出这样的结论通过堆叠神经网络层数(增加深度)可以非常有效地增强表征提升特征学习效果。为什么深度的网络表征效果会好深度学习很不好解释大概的解释可以是网络的不同层可以提取不同抽象层次的特征越深的层提取的特征越抽象。因此深度网络可以整合low-medium-high各种层次的特征增强网络表征能力。那好我们就直接增加网络深度吧但是事情好像并没有那么简单梯度优化问题我们不禁发问Is learning better networks as easy as stacking more layers?首先深度网络优化是比较困难的比如会出现梯度爆炸/梯度消失等问题。不过这个问题已经被normalized initialization和batch normalization等措施解决得差不多了。退化问题好那就直接上deeper network吧但是新问题又来了deeper network收敛是收敛了却出现了效果上的degradationdeeper network准确率饱和后很快就退化了为什么会这样呢网络更深了参数更多了应该拟合能力更强了才对啊噢一定是过拟合了。但似乎也不是过拟合的问题因为56-layer网络(红线)的training error(左图)也比20-layer网络(黄线)要高这就应该不是过拟合了啊那么究竟是什么原因导致了deeper network degradation问题呢现在我们换一种思路来构建deeper networkthe added layers are identity mapping, and the other layers are copied from the learned shallower model.(在原始的浅层网络基础上增加的层视为是identity mapping)也就是假设浅层网络已经可以得到一个不错的结果了那我接下来新增加的层啥也不干只是拟合一个identity mapping输出就拟合输入这样总可以吧。这样的话我们觉得这样构建的深层网络至少不应该比它对应的浅层training error要高。对吧。但是实验又无情地表明这样却又不能得到(与浅层网络)一样好的结果甚至还会比它差看来深度网络的优化并不容易的总结一下直觉上深度网络应该会有更好的表征能力但是事实却是深度网络结果会变差由此我们认为深度网络的优化部分出了问题深度网络的参数空间变得更复杂提升了优化的难度。那么ResNet来了。我们就想啊与其直接拟合一个desired underlying mapping 不如让网络尝试拟合一个residual mapping 。也就是原先的映射 被转换为了 我们在这里假设优化残差映射(residual mapping) 是比优化原映射 要容易的。比如如果现在恒等映射(identity mapping)是最优的那么似乎通过堆叠一些非线性层的网络将残差映射为0从而拟合这个恒等映射最种做法是更容易的。可以通过如上图所示的短路连接(shortcut connection)结构来实现。shortcut就是设计的可以skip几层的结构在ResNet中就是起到了相当于一个最最简单的identity mapping其输出被加到了stacked layers的输出上。这样做既没有增加新的参数也没有增加计算复杂性。ResNet的具体结构后面会详细介绍。接下来本文在ImageNet和CIFAR-10等数据集上做实验主要是想验证2个问题deep residual nets比它对应版本的plain nets更好优化training error更低。deep residual nets能够从更深的网络中获得更好的表征从而提升分类效果。2 solutionResNet想做什么learning residual functions with reference to the layer inputs, instead of learning unreferenced functions.理解不了没关系接着往下看。2.1 Residual Learning前提如果假设多个非线性层能够渐近一个复杂的函数那么多个非线性层也一定可以渐近这个残差函数。令 表示目标拟合函数。所以与其考虑拟合 不如考虑拟合其对应的残差函数 .这两种拟合难度可能是不同的。回到上面的讨论如果被增加层能够被构建成identity mapping那么深层网络的性能至少不应该比其对应的浅层版本要差。这个表明网络是在使用多层非线性网络趋近identity mapping做优化这里出了问题。残差学习的这种方式使得“如果identity mapping是最优的网络的优化器直接将残差学习为0”就可以了这样做是比较简单的。但其实在真实情况下identity mapping不一定是最优的映射啊原文说这种设计仍有意义这种设计help to precondition the problem.也就是如果optimal function更接近identity mapping的话优化器应该能够比较容易找到残差而不是重新学习一个新的。后面实验也表明了残差网络各层输出的标准差是比较低的(如上图后面会解释)这也验证了在identity mapping的基础上学习残差确实是会更容易(identity mappings provide reasonable preconditioning.).这里解释得还是比较含糊但总结来说就是作者想解释训练学习残差会有效降低学习的难度可能据此来解决深层网络的性能退化问题。2.2 Identity Mapping by Shortcuts再回顾一下这个著名的残差块图片identity mapping实现得非常之简单直接就用了个shortcut形式化就是表示residual mapping比如上图实际上就是2层网络也就是 然后直接将 与 element-wise相加。最后给 套一个激活函数 .这么设计(shortcut)有个巨大的好处就是没有引入任何新的参数也没有增加计算复杂度。下面还有2个小问题问题1关于 因为 是element-wise相加那么如果 和 维度不一样怎么办方案一直接对 补0.方案二增加一个网络层(参数为 )改变 的维度。即事实上每个shortcut我们都可以加一个映射层 (实现起来可以就是个感知机)。不需要做维度转化时 就是个方阵。但是后面实验表明直接shortcut就已经足够好了不需要再加那么多参数浪费计算资源。问题2关于 的结构应该是什么样的呢可以是2层或者3层也可以是更多但是不要是1层效果会不好。最后shortcut设计不仅针对全连接网络卷积网络当然也是没问题的2.3 网络架构受VGGNet(左边)启发设计了34层的plain network(中间)以及其对应的residual network版本(右边)。注意中间plain network和右边residual network层数一致网络参数也可以设计得完全一样(element-wise相加维度不match时直接补0就不会增加任何learnable parameters)。34-layer plain network设计原则(遵循VGGNet)for the same output feature map size, the layers have the same number of filtersif the feature map size is halved, the number of filters is doubled so as to preserve the time complexity per layer3 dataset and experiments3.1 ImageNet on Classification3.1.1 与plain network的对比实验这个实验是核心为了说明residual network能够非常完美地解决“深度增加带来的degradation”问题左边是plain network右边是ResNet细线是train error加粗线是val errorPlain network会出现网络的层数增加train error和val error都会升高什么原因呢首先排除过拟合因为train error也会升高其次排除梯度消失网络中使用了batch normalization并且作者也做实验验证了梯度的存在事实上34-layers plain network也是可以实现比较好的准确率的这说明网络在一定程度上也是work了的。作者猜测We conjecture that the deep plain nets may have exponentially low convergence rates. 层数的提升会在一定程度上指数级别影响收敛速度。下面是Residual Network与plain network的量化对比观察上面两张图我们可以得出结论而ResNet却真正实现了网络层数增加train error和val error都降低了证明了网络深度确实可以帮助提升网络的性能。degradation problem在一定程度上得到了解决。相对于plain 34-layersResNet 34-layers的top-1 error rate也降低了3.5%。resnet实现了在没有增加任何参数的情况下获得了更低error rate网络更加高效。从plain/residual 18-layers的比较来看两者的error rate差不多但是ResNet却能够收敛得更快。总结来说就是ResNet在不增加任何参数的情况下仅使用shortcuts and zero-padding for matching dimensions结构就实现了解决了degradation problem更高的准确率更快的收敛速度简直太强了3.1.2 Identity v.s. Projection shortcuts所谓projection shortcuts就是shortcuts包括了一个可学习参数(可以用来对齐维度使得element-wise相加可以实现)设计了ABC三种实验A单纯使用identity shortcuts维度不能对齐时使用zero padding来提升维度此方案没有增加任何参数B仅仅在维度需要对齐时使用projection shortcuts其余均使用parameter-free的identity shortcutsC全部使用projection shortcuts下面是三种方案的实验结果ABC三种方案均明显好于plain版本C虽然结果稍微优于B、C但是却引入了大量的参数增加了时空计算复杂度。作者认为projection shortcuts are not essential for addressing the degradation problem.因此后面的实验仍然采用A或者B结构。3.1.3 Deeper Bottleneck Architectures.为了探索更深层的网络保证训练时间在可控范围内作者重又设计了bottleneck版本的building block左边是原版本右边是bottleneck版本bottleneck版本是将卷积核换成了1*1,3*3,1*1的size虽然层数增加到了3层但是降低了参数量。作者在这里是想探索深度的真正瓶颈而不是追求很低的error rate因此在这里使用了更加精简的bottleneck building block50-layers将34-layers的每个2-layer block换成了3-layers bottleneck block101-layers/152-layers增加更多的3-layers bottleneck block网络具体参数可参考如下图实验结果如下所示网络越深确实取得了更好的结果。Plain network的degradation problem似乎消失了。3.2 CIFAR-10实验与分析实线是test error虚线是train error左边是plain network中间是ResNet右边是ResNet with 110 layers and 1202 layers.结论基本与之前一致但在1202层时ResNet还是出现了degradation现象(结果比110层差)作者认为是过拟合。另外Analysis of Layer Responses关于responseThe responses are the outputs of each layer, after BN and before other nonlinearity (ReLU/addition).从上图我们可以直接看出ResNet较于plain network一般来说response std更小。并且deeper ResNet has smaller magni- tudes of responses这就说明了residual functions(即 ) might be generally closer to zero than the non-residual functions.When there are more layers, an individual layer of ResNets tends to modify the signal less.(也就是后面逐渐就接近identity mapping要拟合的残差越来越小离目标越来越近)4 code reviewResNet实现非常简单网上各种实现多如牛毛这里仅随意找了个实现版本作为对照代码基于CIFAR-10的2层的BasicBlockclass BasicBlock(nn.Module): expansion 1def __init__(self, in_planes, planes, stride1, optionA):super(BasicBlock, self).__init__()self.conv1 nn.Conv2d(in_planes, planes, kernel_size3, stridestride, padding1, biasFalse)self.bn1 nn.BatchNorm2d(planes)self.conv2 nn.Conv2d(planes, planes, kernel_size3, stride1, padding1, biasFalse)self.bn2 nn.BatchNorm2d(planes)self.shortcut nn.Sequential()if stride ! 1 or in_planes ! planes:if option A: For CIFAR10 ResNet paper uses option A. self.shortcut LambdaLayer(lambda x: F.pad(x[:, :, ::2, ::2], (0, 0, 0, 0, planes//4, planes//4), constant, 0))elif option B:self.shortcut nn.Sequential( nn.Conv2d(in_planes, self.expansion * planes, kernel_size1, stridestride, biasFalse), nn.BatchNorm2d(self.expansion * planes) )def forward(self, x): out F.relu(self.bn1(self.conv1(x))) out self.bn2(self.conv2(out)) out self.shortcut(x) out F.relu(out)return outResNet骨架解释一下forward函数中定义resnet骨架首1层conv身由BasicBlock构成layer1、layer2、layer3个数分别为 因为每个BasicBlock有2层所以总层数是 尾1层fc所以总共有 层layer1, layer2, layer3输出维度分别是163264class ResNet(nn.Module):def __init__(self, block, num_blocks, num_classes10):super(ResNet, self).__init__()self.in_planes 16self.conv1 nn.Conv2d(3, 16, kernel_size3, stride1, padding1, biasFalse)self.bn1 nn.BatchNorm2d(16)self.layer1 self._make_layer(block, 16, num_blocks[0], stride1)self.layer2 self._make_layer(block, 32, num_blocks[1], stride2)self.layer3 self._make_layer(block, 64, num_blocks[2], stride2)self.linear nn.Linear(64, num_classes)self.apply(_weights_init)def _make_layer(self, block, planes, num_blocks, stride): strides [stride] [1]*(num_blocks-1) layers []for stride in strides: layers.append(block(self.in_planes, planes, stride))self.in_planes planes * block.expansionreturn nn.Sequential(*layers)def forward(self, x): out F.relu(self.bn1(self.conv1(x))) out self.layer1(out) out self.layer2(out) out self.layer3(out) out F.avg_pool2d(out, out.size()[3]) out out.view(out.size(0), -1) out self.linear(out)return out最后像堆积木一样通过设置layer1、layer2、layer3的BasicBlock个数来堆出不同层的ResNetdef resnet20():return ResNet(BasicBlock, [3, 3, 3])def resnet32():return ResNet(BasicBlock, [5, 5, 5])def resnet44():return ResNet(BasicBlock, [7, 7, 7])def resnet56():return ResNet(BasicBlock, [9, 9, 9])def resnet110():return ResNet(BasicBlock, [18, 18, 18])def resnet1202():return ResNet(BasicBlock, [200, 200, 200])5 conclusionResNet核心就是residual learning和shortcut identity mapping实现方式极其简单却取得了极其好的效果在分类、目标检测等任务上均是大比分领先SOTA这种非常general的创新是非常不容易的这也是ResNet备受推崇的原因吧另外给我的启示就是不仅仅是talk is cheap, show me the code了而是code is also relatively cheap, show me ur sense and thinking!推荐阅读推荐CV预训练模型全集国内外优秀的计算机视觉团队汇总最新版YOLOv4中的数据增强