Layer Norm
參考ConvNeXt中的Layer Normalization(LN) - 海斌的文章 - 知乎
https://zhuanlan.zhihu.com/p/481901798
Layer Norm本來是一個樣本norm自己,如圖所示:
也就是說,在[C,H,W]維進行歸一化
而ConvNeXt中是這樣:
也就是在C的維度歸一化,即單一像素的所有channel做歸一化。
兩者實現方式上有所不同。
可以用F.layer_norm實現,也可以用nn.layer_norm實現,這里選用F.layer_norm
LayerNorm2d繼承的nn.LayerNorm,在初始化時調用了父類的init函數,我們來看看父類是干了啥?
def __init__(self, normalized_shape: _shape_t, eps: float = 1e-5, elementwise_affine: bool = True,device=None, dtype=None) -> None:***self.normalized_shape = tuple(normalized_shape)實際上這里僅僅是把num_channels,通道數,存入了self.normalized_shape,并且用一個tuple保存。
所以說,關鍵是forward里面的F.layer_norm
我們看看傳入的參數
第一個參數是轉置后的x,也就是N,C,H,W轉置為N,H,W,C,把通道數放在最后一個維度,過F.layer_norm,normalized_shape實際上就是前面init函數里傳入的num_channels,就是一個數字。
接下來我們看看F.layer_norm的用法:
其實和nn.layernorm基本是一樣的,只是不用事先實例化,這樣的話參數要一起傳進去。
對于nn.layernorm來說,
上面這段話的意思就是說,這個normalized_shape可以是一個數,也可以是一個list,如果是一個數,則默認在最后一維歸一化,且這個數需要等于最后一維的維度;如果是一個list,則這個list需要匹配從后往前的不同維度的維數
eg.
如果是普通的layer norm,normalized_shape=[96, 8, 8]
如果這個參數是8,則在最后一維進行歸一化
如果希望在所有point的channel歸一化,如ConvNeXt
則先轉置,把channel轉到最后一維,然后normalized_shape=num_channel即可
那么ConvNeXt的layer norm如何改成普通的layer norm呢?
如代碼所示:
實際上只需要改forward里即可,即不轉置,且normalized_shape參數傳入x的最后三3維度
class LayerNorm2d(nn.LayerNorm):def __init__(self, num_channels: int, **kwargs) -> None:super().__init__(num_channels, **kwargs)self.num_channels = self.normalized_shape[0]def forward(self, x):return F.layer_norm(x, x.shape[1:], self.weight,self.bias, self.eps))總結
以上是生活随笔為你收集整理的Layer Norm的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Git 客户端的安装与使用
- 下一篇: 2.2 反相放大器、高输入电阻反相放大器