赞
踩
1. torch中标准normalization函数与自定义函数的对比,以说明标准库函数的使用方法。
同时,代码中对4维数据、3维数据以及2维数据进行了对比。
注意在2维数据的情况下,nn.InstanceNorm1d是不能求解的,不存在1维的Instancenorm.
- #-*- coding:utf-8 -*-
- #Author LJB Create on 2021/8/27
- import torch
- import torch.nn as nn
- import numpy as np
-
-
- #对于4维数据[batchsize,channel,H,W],其中[H,W]表示一个实例的二维特征维度
- #LayerNorm: axis=(1,2,3)
- #InstanceNorm: axis=(2,3)
- #BatchNorm: axis=(0,2,3)
- def MyNorm_4d(x, axis,gamma=1.0, beta=0.0):
-
- # x_shape:[B, C, H, W]
- results = 0.
- eps = 1e-5
- x_mean = np.mean(x, axis=axis, keepdims=True)
- x_var = np.var(x, axis=axis, keepdims=True)
- x_normalized = (x - x_mean) / np.sqrt(x_var + eps)
- results = gamma * x_normalized + beta
- return results
-
- #对于3维数据[batchsize,channel,d_model],d_model表示一个实例的一维特征维度
- #LayerNorm: axis=(1,2)
- #InstanceNorm: axis=(2)
- #BatchNorm: axis=(0,2)
- def MyNorm_3d(x, axis,gamma=1.0, beta=0.0):
-
- # x_shape:[B, C, D], D表示d_model
- results = 0.
- eps = 1e-5
- x_mean = np.mean(x, axis=axis, keepdims=True)
- x_var = np.var(x, axis=axis, keepdims=True)
- x_normalized = (x - x_mean) / np.sqrt(x_var + eps)
- results = gamma * x_normalized + beta
- return results
-
- #对于2维数据[batchsize,d_model],d_model表示一个实例的一维特征维度
- #LayerNorm: axis=(1)
- #InstanceNorm: axis=(1)
- #BatchNorm: axis=(0)
- def MyNorm_2d(x, axis,gamma=1.0, beta=0.0):
-
- # x_shape:[B, D], D表示d_model
- results = 0.
- eps = 1e-5
- x_mean = np.mean(x, axis=axis, keepdims=True)
- x_var = np.var(x, axis=axis, keepdims=True)
- x_normalized = (x - x_mean) / np.sqrt(x_var + eps)
- results = gamma * x_normalized + beta
- # print('x_mean x_std:',x_mean,np.sqrt(x_var + eps))
- return results
-
-
- if __name__=='__main__':
- #模拟数据
- batchsize = 3
- channel = 2
- H = 5
- W = 7
- data = torch.randint(0,9,(batchsize,channel,H,W)).float()
- #标准layernorm
- n1 = nn.LayerNorm(normalized_shape=[channel,H,W])(data) #参数为shape
- n2 = MyNorm_4d(data.numpy(),axis=(1,2,3)) #参数为坐标轴
- # print('+++ Normal Layernorm:',n1)
- # print('+++ My Layernorm:',n2)
-
-
- #当数据为4维时,一个实例是[H,W]形的矩阵,此时nn.LayerNorm也可以当InstanceNorm使用
- n3 = nn.LayerNorm(normalized_shape=[H,W])(data) #参数为shape
- n4 = MyNorm_4d(data.numpy(),axis=(2,3)) #参数为坐标轴
- #标准InstanceNorm
- n5 = nn.InstanceNorm2d(channel)(data) #参数为通道数
- # print('+++ Normal Instance(Layernorm):')
- # print(n3)
- # print('+++ My Instance norm:')
- # print(n4)
- # print('+++ Normal InstanceNorm:')
- # print(n5)
-
- n6 = nn.BatchNorm2d(channel)(data)
- n7 = MyNorm_4d(data.numpy(),axis=(0,2,3)) #参数为坐标轴
- # print('+++ Normal BatchNorm2d:')
- # print(n6)
- # print('+++ My batch norm:')
- # print(n7)
-
- ############################################################
- #对3维数据(形状为[batchsize,seqlen,d_model]时
- batchsize_3d = 5
- seqlen = 4
- d_model = 3
- data_3d = torch.randint(0,9,(batchsize_3d,seqlen,d_model)).float()
- # print('+++ Normal LayerNorm:')
- # print(nn.LayerNorm([seqlen,d_model])(data_3d)) #此时seqlen视为通道维
- # print('+++ My LayerNorm:')
- # print(MyNorm_3d(data_3d.numpy(),axis=(1,2)))
- #
- # print('+++ Normal InstanceNorm1d:')
- # print(nn.InstanceNorm1d(seqlen)(data_3d))
- # print('+++ Normal Instance(LayerNorm):')
- # print(nn.LayerNorm(d_model)(data_3d)) #此时seqlen视为通道维
- # print('+++ My Instance Norm:')
- # print(MyNorm_3d(data_3d.numpy(),axis=(2)))
- #
- # print('+++ Normal BatchNorm1d:')
- # print(nn.BatchNorm1d(seqlen)(data_3d))
- # print('+++ My Batch Norm:')
- # print(MyNorm_3d(data_3d.numpy(),axis=(0,2)))
- print('#'*80)
- batchsize_2d = 5
- d_model = 3
- data_2d = torch.randint(0,9,(batchsize_2d,d_model)).float()
- print('+++ Normal LayerNorm:')
- print(nn.LayerNorm([d_model])(data_2d))
- print('+++ My LayerNorm:')
- print(MyNorm_2d(data_2d.numpy(),axis=(1)))
-
- print('+++ Normal InstanceNorm1d: Error')
- #print(nn.InstanceNorm1d(1)(data_2d) #二维数据时,会报错
- print('+++ Normal Instance(LayerNorm):')
- print(nn.LayerNorm(d_model)(data_2d))
- print('+++ My Instance Norm:')
- print(MyNorm_2d(data_2d.numpy(),axis=(1)))
-
- print('+++ Normal BatchNorm1d:')
- print(nn.BatchNorm1d(d_model)(data_2d)) #二维数据时,用d_model,详看函数定义
- print('+++ My Batch Norm:')
- print(MyNorm_2d(data_2d.numpy(),axis=(0)))
2. 说明了在eval模式下,只有BatchNorm会屏蔽,其他Norm函数不会屏蔽
- import torch
- import torch.nn as nn
- import numpy as np
-
- class NormModel(nn.Module):
- def __init__(self,size):
- super(NormModel,self).__init__()
- self.layer_norm = nn.LayerNorm(size) #不受eval 影响
- self.instance_norm = nn.InstanceNorm2d(3)#不受eval影响
- self.batch_norm = nn.BatchNorm2d(3) #当模型为eval时,会屏蔽batchnorm
-
-
- norm = NormModel((5,7))
- data = torch.randint(0,9,(2,3,5,7)).float()
- # print(list(norm.named_parameters()))
- norm.eval()
- print(data)
- print('*'*50)
- print(norm.layer_norm(data))
- print('*'*50)
- print(norm.instance_norm(data))
- print('*'*50)
- print(norm.batch_norm(data))
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。