日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

PyTorch框架学习十八——Layer Normalization、Instance Normalization、Group Normalization

發布時間:2024/7/23 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PyTorch框架学习十八——Layer Normalization、Instance Normalization、Group Normalization 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

PyTorch框架學習十八——Layer Normalization、Instance Normalization、Group Normalization

  • 一、為什么要標準化?
  • 二、BN、LN、IN、GN的異同
  • 三、Layer Normalization
  • 四、Instance Normalization
  • 五、Group Normalization

上次筆記介紹了Batch Normalization以及它在PyTorch中的使用:https://blog.csdn.net/qq_40467656/article/details/108375181

這次筆記將介紹由BN引發的其他標準化層,它們各自適用于不同的應用場景,分別是適用于變長網絡的Layer Normalization;適用于圖像生成的Instance Normalization;適用于小mini-batch的Group Normalization。

一、為什么要標準化?

這個在上次BN的筆記中介紹過,本意是為了解決ICS問題,即隨著網絡層數加深,數據分布異常(很小或很大),從而導致訓練困難。詳情回顧:https://blog.csdn.net/qq_40467656/article/details/108375181

二、BN、LN、IN、GN的異同

  • :都做了標準化的工作。
  • :均值和方差的求取方式不一樣,即選擇的計算區域不一樣,這個可以看完下一小節的詳細介紹回過來看,可能會更能理解。

三、Layer Normalization

LN提出的起因是因為BN不適用于變長的網絡,如RNN,這部分的內容還沒有接觸過,但是可以簡單理解為這種網絡的神經元個數是會變化的,不是一樣的,如下圖所示:

ps:注意這里的橫軸不是數據樣本個數,只是代表這層網絡層神經元可能會變為5/3/4個,在每種個數的情況下,樣本數還是一個batchsize的大小。

第一次可能有五個特征,計算得到五個均值和方差,而第二輪計算時,網絡層的神經元變為3個,而BN里計算均值和方差是需要用到之前的結果的,這里之前的五個均值方差就對應不了三個特征,所以BN在這種情況下是不適用的。

那么LN是怎么計算均值和方差的呢?以一維的情況為例:

之所以稱為Layer Norm,就是對該層的數據求均值和方差,不再按照特征那個維度去求,每個樣本都單獨求其均值方差,可以理解為逐樣本的求取方式。

二維三維的情況類似,如下圖所示:

LN需要注意的地方:

  • 不再有running_mean和running_var
  • gamma和beta為逐元素的

LN在PyTorch中的實現:

torch.nn.LayerNorm(normalized_shape: Union[int, List[int], torch.Size], eps: float = 1e-05, elementwise_affine: bool = True)

參數如下所示:

  • normalized_shape:(int/list/torch.Size)該層的特征維度,即要被標準化的維度。
  • eps:分母修正項。
  • elementwise_affine:是否需要affine transform,這里也提醒你是逐元素的仿射變換。
  • 下面看一個PyTorch實現的例子:

    import torch import numpy as np import torch.nn as nn import sys, os hello_pytorch_DIR = os.path.abspath(os.path.dirname(__file__)+os.path.sep+".."+os.path.sep+"..") sys.path.append(hello_pytorch_DIR) from tools.common_tools import set_seedset_seed(1) # 設置隨機種子# ======================================== nn.layer norm flag = 1 # flag = 0 if flag:batch_size = 8num_features = 3features_shape = (3, 4)feature_map = torch.ones(features_shape) # 2Dfeature_maps = torch.stack([feature_map * (i + 1) for i in range(num_features)], dim=0) # 3Dfeature_maps_bs = torch.stack([feature_maps for i in range(batch_size)], dim=0) # 4D# feature_maps_bs shape is [8, 3, 3, 4], B * C * H * Wln = nn.LayerNorm(feature_maps_bs.size()[1:], elementwise_affine=True)# ln = nn.LayerNorm(feature_maps_bs.size()[1:], elementwise_affine=False)# ln = nn.LayerNorm([3, 3, 4])# ln = nn.LayerNorm([3, 3])output = ln(feature_maps_bs)print("Layer Normalization")print(ln.weight.shape)print(feature_maps_bs[0, ...])print(output[0, ...])

    結果如下:

    Layer Normalization torch.Size([3, 3, 4]) tensor([[[1., 1., 1., 1.],[1., 1., 1., 1.],[1., 1., 1., 1.]],[[2., 2., 2., 2.],[2., 2., 2., 2.],[2., 2., 2., 2.]],[[3., 3., 3., 3.],[3., 3., 3., 3.],[3., 3., 3., 3.]]]) tensor([[[-1.2247, -1.2247, -1.2247, -1.2247],[-1.2247, -1.2247, -1.2247, -1.2247],[-1.2247, -1.2247, -1.2247, -1.2247]],[[ 0.0000, 0.0000, 0.0000, 0.0000],[ 0.0000, 0.0000, 0.0000, 0.0000],[ 0.0000, 0.0000, 0.0000, 0.0000]],[[ 1.2247, 1.2247, 1.2247, 1.2247],[ 1.2247, 1.2247, 1.2247, 1.2247],[ 1.2247, 1.2247, 1.2247, 1.2247]]], grad_fn=<SelectBackward>)

    這邊只打印了第一個數據的結果,它的均值是2,所以中間一個3×4的特征標準化之后全為0。

    四、Instance Normalization

    IN層的提出是因為在圖像生成任務中,一個batch里的圖像的風格可能不盡相同,不能通過BN的計算方式去將各個風格的特征混為一談,所以BN在這種情況下會不適用。

    那么,IN層的計算方式的思路是逐Instance(channel)地計算均值和方差,如下圖所示:

    它是每一個樣本每一個特征都去計算均值方差然后標準化。

    IN層在PyTorch中的實現如下所示:(以二維為例)

    torch.nn.InstanceNorm2d(num_features: int, eps: float = 1e-05, momentum: float = 0.1, affine: bool = False, track_running_stats: bool = False)

    參數如下所示:

  • num_features:一個樣本特征的數量。
  • eps:分母修正項。
  • momentum:指數加權平均求均值方差。
  • affine:是否仿射變換,默認False。
  • track_running_stats:是否追蹤batch,使得統計結果更具全局性,一般訓練時是需要追蹤,測試時不追蹤,使用固定的均值方差,默認False(測試)。
  • 看一個IN的例子:

    flag = 1 # flag = 0 if flag:batch_size = 3num_features = 3momentum = 0.3features_shape = (2, 2)feature_map = torch.ones(features_shape) # 2Dfeature_maps = torch.stack([feature_map * (i + 1) for i in range(num_features)], dim=0) # 3Dfeature_maps_bs = torch.stack([feature_maps for i in range(batch_size)], dim=0) # 4Dprint("Instance Normalization")print("input data:\n{} shape is {}".format(feature_maps_bs, feature_maps_bs.shape))instance_n = nn.InstanceNorm2d(num_features=num_features, momentum=momentum, affine=True, track_running_stats=True)for i in range(1):outputs = instance_n(feature_maps_bs)print(outputs)print("\niter:{}, running_mean.shape: {}".format(i, instance_n.running_mean.shape))print("iter:{}, running_var.shape: {}".format(i, instance_n.running_var.shape))print("iter:{}, weight.shape: {}".format(i, instance_n.weight.shape))print("iter:{}, bias.shape: {}".format(i, instance_n.bias.shape))

    結果如下:

    Instance Normalization input data: tensor([[[[1., 1.],[1., 1.]],[[2., 2.],[2., 2.]],[[3., 3.],[3., 3.]]],[[[1., 1.],[1., 1.]],[[2., 2.],[2., 2.]],[[3., 3.],[3., 3.]]],[[[1., 1.],[1., 1.]],[[2., 2.],[2., 2.]],[[3., 3.],[3., 3.]]]]) shape is torch.Size([3, 3, 2, 2]) tensor([[[[0., 0.],[0., 0.]],[[0., 0.],[0., 0.]],[[0., 0.],[0., 0.]]],[[[0., 0.],[0., 0.]],[[0., 0.],[0., 0.]],[[0., 0.],[0., 0.]]],[[[0., 0.],[0., 0.]],[[0., 0.],[0., 0.]],[[0., 0.],[0., 0.]]]], grad_fn=<ViewBackward>)iter:0, running_mean.shape: torch.Size([3]) iter:0, running_var.shape: torch.Size([3]) iter:0, weight.shape: torch.Size([3]) iter:0, bias.shape: torch.Size([3])

    五、Group Normalization

    GN的提出是因為,隨著如今數據樣本變得越來越大,以現有的GPU能力可能只能放置比較小的mini-batch,而一個batch比較少的數據的話,使用BN可能計算得到的均值和方差就有較大的偏差,估計的值不準,所以BN在小mini-batch的場景下不適用。

    那么GN的計算思路就是:數據樣本不夠,通道(特征)數來湊,其如下所示:

    圖中所示是將一個樣本的兩個特征劃分為一個group,這里只是為了說明GN的原理,實際上特征數是很多的,比如256,那么我們分為兩組的話,一組有128個特征通道,數量還是比較可觀的,在這樣的分組下對每一組單獨求取均值方差然后標準化。

    注意:

    • 不再有running_mean和running_var,與LN一致。
    • gamma和beta為逐通道的。

    應用場景:大模型,小batch size的任務。

    GN在PyTorch中的實現如下:

    torch.nn.GroupNorm(num_groups: int, num_channels: int, eps: float = 1e-05, affine: bool = True)

    參數如下所示:

  • num_groups:分組數。
  • num_channels:通道數。
  • eps:同上。
  • affine:是否仿射變換。
  • 下面看一個例子:

    flag = 1 # flag = 0 if flag:batch_size = 2num_features = 4num_groups = 2 # 3 Expected number of channels in input to be divisible by num_groupsfeatures_shape = (2, 2)feature_map = torch.ones(features_shape) # 2Dfeature_maps = torch.stack([feature_map * (i + 1) for i in range(num_features)], dim=0) # 3Dfeature_maps_bs = torch.stack([feature_maps * (i + 1) for i in range(batch_size)], dim=0) # 4Dgn = nn.GroupNorm(num_groups, num_features)outputs = gn(feature_maps_bs)print("Group Normalization")print(gn.weight.shape)print(outputs[0])

    結果如下:

    Group Normalization torch.Size([4]) tensor([[[-1.0000, -1.0000],[-1.0000, -1.0000]],[[ 1.0000, 1.0000],[ 1.0000, 1.0000]],[[-1.0000, -1.0000],[-1.0000, -1.0000]],[[ 1.0000, 1.0000],[ 1.0000, 1.0000]]], grad_fn=<SelectBackward>)

    最后放一張BN、LN、IN和GN的計算方式示例圖,幫助理解:

    總結

    以上是生活随笔為你收集整理的PyTorch框架学习十八——Layer Normalization、Instance Normalization、Group Normalization的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。