輸入的標准化處理是對圖片等輸入信息進行標准化處理,使得所有輸入的均值為0,方差為1
normalize = T.Normalize([0.485, 0.456, 0.406],[0.229, 0.224, 0.225])
而Batch Normalization的目的是使各隱藏層輸入的均值和方差為任意值
Batch Norm經常使用在mini-batch上,這也是其名稱的由來
Batch Normalization是對下面隱藏層進行激活函數操作前的輸入Z[l]進行標准層處理
進行的操作有:
1)對輸入進行歸一化操作
- m是單個mini-batch包含樣本個數
是為了防止分母為零,可取值
此時的輸入Z[i]變為了均值為0,方差為1的Znorm[i]
2)對歸一化的結果進行縮放和平移
但是大部分情況下我們其實並不希望輸入均值為0,方差為1,而是希望其根據訓練的需要而設置為任意值
這個時候就需要進一步處理:
和
是可以學習的參數,類似於W和b一樣,可以通過梯度下降等算法求得
當兩者的值為,那么
,實現恆等映射
為什么需要進行這一步的處理:
從激活函數的角度來說,如果各隱藏層的輸入均值在靠近0的區域即處於激活函數的線性區域,這樣不利於訓練好的非線性神經網絡,得到的模型效果也不會太好
如resnet網絡中的使用:
#這個實現的是兩層的殘差塊,用於resnet18/34 class BasicBlock(nn.Module): expansion = 1 def __init__(self, inplanes, planes, stride=1, downsample=None): super(BasicBlock, self).__init__() self.conv1 = conv3x3(inplanes, planes, stride) self.bn1 = nn.BatchNorm2d(planes) self.relu = nn.ReLU(inplace=True) self.conv2 = conv3x3(planes, planes) self.bn2 = nn.BatchNorm2d(planes) self.downsample = downsample self.stride = stride def forward(self, x): identity = x out = self.conv1(x) out = self.bn1(out) out = self.relu(out) out = self.conv2(out) out = self.bn2(out) if self.downsample is not None: #當連接的維度不同時,使用1*1的卷積核將低維轉成高維,然后才能進行相加 identity = self.downsample(x) out += identity out = self.relu(out) return out