day7-批量归一化和残差网络

BN层:

全连接层的BN

位置:仿射变换和激活函数之间
pytorch:nn.BatchNorm1d

卷积层的BN

位置:卷积计算和激活函数之间
pytorch:nn.BatchNorm2d

步骤:


image.png

每次的和都是每个batch的每个特征的均值和标准差,这样可以将每个特征限制到(0, 1)的正态分布,但是这样虽然可以让分布尽可能保持不变,但是也改变了数据的表达能力,因此引入和两个可训练参数,使得数据表达能力增强,其中在训练阶段的和是利用batch获得的,但是测试阶段不一定有batch,因此对测试集进行BN时采用的是

image.png

ResNet

image.png

ResNet中公式为

class Residual(nn.Module):  # 本类已保存在d2lzh_pytorch包中方便以后使用
    #可以设定输出通道数、是否使用额外的1x1卷积层来修改通道数以及卷积层的步幅。
    def __init__(self, in_channels, out_channels, use_1x1conv=False, stride=1):
        super(Residual, self).__init__()
        self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1, stride=stride)
        self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1)
        if use_1x1conv:
            self.conv3 = nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=stride)
        else:
            self.conv3 = None
        self.bn1 = nn.BatchNorm2d(out_channels)
        self.bn2 = nn.BatchNorm2d(out_channels)

    def forward(self, X):
        Y = F.relu(self.bn1(self.conv1(X)))
        Y = self.bn2(self.conv2(Y))
        if self.conv3:
            X = self.conv3(X)
        return F.relu(Y + X)

从代码可以看出每次向前传播的不只是普通的还有$x(l-1),因为CNN深度达到一定深度以后再增加层数分类性能也不会一味提高甚至变差,因为传播过程中网络收敛很慢并且准确率也不能保证

DenseNet

ResNet通过前一层的输入和输出相加,而DenseNet是在一个block中将输入和每一个conv的输出在inchannel进行concat

def conv_block(in_channels, out_channels):
    blk = nn.Sequential(nn.BatchNorm2d(in_channels), 
                        nn.ReLU(),
                        nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1))
    return blk

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

你可能感兴趣的:(day7-批量归一化和残差网络)