在 PyTorch 中计算向量的范数、1-范数和 2-范数的正确方法是什么?

问题描述 投票:0回答:3

我有一个矩阵:

t = torch.rand(2,3)
print(t)
>>>tensor([[0.5164, 0.3651, 0.0882],
        [0.4488, 0.9824, 0.4067]])

我正在关注 this 规范介绍,并想在 PyTorch 中尝试一下。

看起来像:

    向量的
  • norm
    是“向量的大小或长度是一个非负数,描述向量在空间中的范围,有时称为向量的大小或范数”
  • 1-Norm
    是“绝对向量值的总和,其中标量的绝对值使用符号 |a1|。实际上,范数是距向量空间原点的曼哈顿距离的计算。”
  • 2-Norm
    是“向量坐标距向量空间原点的距离。L2 范数计算为向量值平方和的平方根。”

我目前只知道这个:

print(torch.linalg.norm(t, dim=1))
>>>tensor([0.6385, 1.1541])

但是我无法从这里计算出这三个(范数,1-范数,2-范数)中的哪一个,以及如何计算其余的

python vector pytorch
3个回答
17
投票

要计算 0-、1-和 2-范数,您可以使用

torch.linalg.norm
,并提供
ord
参数(分别为
0
1
2
)。或者直接在张量上:
Tensor.norm
,带有
p
参数。以下是三种变体:手动计算、使用
torch.linalg.norm
和使用
Tensor.norm

  • 0-范数

    >>> x.norm(dim=1, p=0)
    >>> torch.linalg.norm(x, dim=1, ord=0)
    >>> x.ne(0).sum(dim=1)
    
  • 1-范数

    >>> x.norm(dim=1, p=1)
    >>> torch.linalg.norm(x, dim=1, ord=1)
    >>> x.abs().sum(dim=1)
    
  • 2-范数

    >>> x.norm(dim=1, p=2)
    >>> torch.linalg.norm(x, dim=1, ord=2)
    >>> x.pow(2).sum(dim=1).sqrt()
    

2
投票

要计算不同阶数的范数,您只需传入

ord
参数和您想要的阶数。例如:

  • torch.linalg.norm(t, dim=1, ord = 0)
    应该适用于 norm
  • torch.linalg.norm(t, dim=1,  ord = 1)
    应该适用于 1-Norm
  • torch.linalg.norm(t, dim=1, ord = 2)
    应该适用于 2-Norm
    等等。

0
投票

我想提出一个非常重要的观点。

在 pytorch 中计算 p 范数以进行神经网络训练时,我强烈鼓励您使用 pytorch 内置函数。

我尝试变得聪明,并使用以下方法自己实现了 2-范数:

loss = diff.pow(2).sum(dim=1).sqrt().mean()
# ^ diff is some difference between 2 pytorch tensors

然而,这在数值上是不稳定的,因为随着时间的推移,损失会促使

diff
接近0,但
sqrt(x) = 1/(2 * sqrt(x)
的梯度。正如你所看到的,如果 x 为 0,梯度将是无限的,你的模型将在没有警告的情况下发散(特别是因为损失接近 0,你不会怀疑这是爆炸性损失或梯度问题)。

我的情况的修复方法是修剪

diff
,使其不小于某个 epsilon,例如 1e-8

diff = diff.pow(2).sum(dim=1)
diff = torch.where(diff < eps, torch.tensor(eps, device=diff.device), diff)
loss = diff.sqrt().mean()

这具有更加稳定的数值行为,并且您的模型不应再发散。

我非常确定 pytorch 开发人员已经考虑过这样的问题,并在内置函数中解决了它。

© www.soinside.com 2019 - 2024. All rights reserved.