day7-批量歸一化和殘差網(wǎng)絡(luò)

BN層:

全連接層的BN

位置:仿射變換和激活函數(shù)之間
pytorch:nn.BatchNorm1d

卷積層的BN

位置:卷積計(jì)算和激活函數(shù)之間
pytorch:nn.BatchNorm2d

步驟:


image.png

每次的\mu\sigma都是每個(gè)batch的每個(gè)特征的均值和標(biāo)準(zhǔn)差,這樣可以將每個(gè)特征限制到(0, 1)的正態(tài)分布,但是這樣雖然可以讓分布盡可能保持不變,但是也改變了數(shù)據(jù)的表達(dá)能力,因此引入\gamma\beta兩個(gè)可訓(xùn)練參數(shù),使得數(shù)據(jù)表達(dá)能力增強(qiáng),其中在訓(xùn)練階段的\mu\sigma是利用batch獲得的,但是測(cè)試階段不一定有batch,因此對(duì)測(cè)試集進(jìn)行BN時(shí)采用的是

image.png

ResNet

image.png

ResNet中公式為
H(l) = H(l-1) + x(l-1)

class Residual(nn.Module):  # 本類已保存在d2lzh_pytorch包中方便以后使用
    #可以設(shè)定輸出通道數(shù)、是否使用額外的1x1卷積層來(lái)修改通道數(shù)以及卷積層的步幅。
    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)

從代碼可以看出每次向前傳播的不只是普通的H(l-1)還有$x(l-1),因?yàn)镃NN深度達(dá)到一定深度以后再增加層數(shù)分類性能也不會(huì)一味提高甚至變差,因?yàn)閭鞑ミ^(guò)程中網(wǎng)絡(luò)收斂很慢并且準(zhǔn)確率也不能保證

DenseNet

ResNet通過(guò)前一層的輸入和輸出相加,而DenseNet是在一個(gè)block中將輸入和每一個(gè)conv的輸出在inchannel進(jìn)行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 # 計(jì)算輸出通道數(shù)

    def forward(self, X):
        for blk in self.net:
            Y = blk(X)
            X = torch.cat((X, Y), dim=1)  # 在通道維上將輸入和輸出連結(jié)
        return X
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容