PyTorch中的层范数

92dk7w1h  于 2023-03-08  发布在  其他
关注(0)|答案(1)|浏览(131)

请看下面的例子:

batch, sentence_length, embedding_dim = 2, 3, 4
    embedding = torch.randn(batch, sentence_length, embedding_dim)
    print(embedding)
    
# Output:
    tensor([[[-2.1918,  1.2574, -0.3838,  1.3870],
             [-0.4043,  1.2972, -1.7326,  0.4047],
             [ 0.4560,  0.6482,  1.0858,  2.2086]],
    
            [[-1.4964,  0.3722, -0.7766,  0.3062],
             [ 0.9812,  0.1709, -0.9177, -1.2558],
             [-1.1560, -0.0367,  0.5496, -1.1142]]])

应用在嵌入维数上归一化的层范数,我得到:

layer_norm = torch.nn.LayerNorm(embedding_dim)
layer_norm(embedding)

# Output:
tensor([[[-1.5194,  0.8530, -0.2758,  0.9422],
         [-0.2653,  1.2620, -1.4576,  0.4609],
         [-0.9470, -0.6641, -0.0204,  1.6315]],

        [[-1.4058,  0.9872, -0.4840,  0.9026],
         [ 1.3933,  0.4803, -0.7463, -1.1273],
         [-0.9869,  0.5545,  1.3619, -0.9294]]],
       grad_fn=<NativeLayerNormBackward0>)

现在,当我用一个简单的python实现对上述嵌入Tensor的第一个向量进行归一化时,我得到:

a = [-2.1918,  1.2574, -0.3838,  1.3870]
    mean_a = statistics.mean(a)
    var_a = statistics.stdev(a)
    eps = 1e-5
    d = [ ((i-mean_a)/math.sqrt(var_a + eps)) for i in a]
    print(d)
    
    #Output:
[-1.7048934056508998,0.9571791768620398,-0.3094894774404756,1.0572037062293356]

标准化的值和我从PyTorch的Layernorm得到的不一样。我计算Layernorm的方法有什么问题吗?

iq3niunx

iq3niunx1#

我们需要的是方差而不是标准差(标准差是方差的平方,在d的计算中得到的是平方)。另外,这里使用的是有偏方差(statistics.pvariance)。要使用statistics模块重现预期结果,我们将用途:

a = [-2.1918,  1.2574, -0.3838,  1.3870]
mean_a = statistics.mean(a)
var_a = statistics.pvariance(a)
eps = 1e-5
d = [ ((i-mean_a)/math.sqrt(var_a + eps)) for i in a]
print(d)
[-1.519391435327454, 0.8530327107709863, -0.2758152854532861, 0.942174010009754]

另一种验证正确结果的方法是:

[[torch.mean(i).item(), torch.var(i, unbiased=False).item()] for i in layer_norm(embedding)]

[[1.9868215517249155e-08, 0.9999885559082031],
[-1.9868215517249155e-08, 0.9999839663505554]]

这表明归一化嵌入的均值和方差是(非常接近)0和1,如预期的那样。
相关doc:标准差通过有偏估计量计算,相当于torch.var(输入,无偏=False)。

相关问题