Pytorch-ResNet(残差网络)-下

2019-12-04 11:48:10 浏览数 (2)

ResNet具有诸多优异性能,如下所示

在左图(准确率)的比较中,从AlexNet到GoogleNet再到ResNet,准确率逐渐提高。20层结构是很多网络结构性能提升的分水岭,在20层之前,模型性能提升较容易。但在20层之后,继续添加层数对性能的提升不是很明显。但ResNet很好地解决了高层数带来的误差叠加问题,因此性能也随着层数的增加而提升。

而在右图计算量对比图中,性能最完美的是ResNet-101、Inception-v4等,计算量不大且性能很好。而VGG的运算量较大、AlexNet虽然计算量较小,但性能不佳。

那么在具体代码中,卷积层是如何实现的?

如图我们想构建一个如下图所示得神经网络

首先要明确ResNet本质上是由多个基本单元堆叠实现的,写法与之前所讲的类似。

代码语言:javascript复制
import torch
import torch.nn as nn
import torch.nn.functional as F

# 先明确ResNet是由conv1 bn ReLU conv2 bn ReLU构成

class ResBlk(nn.Module):
    def __init__(self, ch_in, ch_out):
        self.conv1 = nn.Conv2d(ch_in, ch_out, kernel_size=3, stride=1, padding=1)
        self.bn1 = nn.BatchNorm2d(ch_out)
        # 依次对kernel_size、stride、padding进行定义
        self.conv2 = nn.Conv2d(ch_out, ch_out, kernel_size=3, stride=1, padding=1)
        self.bn2 = nn.BatchNorm2d(ch_out)

        self.extra = nn.Sequential()

        if ch_out != ch_in:
            # 该处即为short cut结构,若input_channel与该单元输出channel不一致
            # 即将ch_in作为输入、ch_out作为输出
            self.extra = nn.Sequential(
                nn.Conv2d(ch_in, ch_out, kernel_size=1, stride=1),
                nn.BatchNorm2d(ch_out)
        )

    def forward(self, x):
        out = F.relu(self.bn1(self.conv1(x)))
        out = self.bn2(self.conv2(out))
        out = self.extra(x)   out
        return out

由此我们看出ResNet本质上是在每一层结构上都加了一个short cut。

若将该思路扩展,在中间的每一层均让其可能与之前层接触。这样就成了连接很密集的DenseNet。

如下所示

Densenet是各个channel上的累加,有时会使后面的计算量contact的很大。因此在DenseNet上的channel选择必须要非常的精妙。

0 人点赞