广播语义学

许多PyTorch操作支持NumPy的广播语义。看见 https://numpy.org/doc/stable/user/basics.broadcasting.html详情请见。

简而言之,如果PyTorch操作支持广播,那么它的张量参数可以自动扩展为相同的大小(无需复制数据)。

普通语义学

如果下列规则成立,则两个张量是“可广播的”:

  • 每个张量至少有一维。
  • 当迭代维度大小时,从尾部维度开始,维度大小必须相等,其中一个为1,或者其中一个不存在。

例如:


>>> x=torch.empty(5,7,3)
>>> y=torch.empty(5,7,3)
# same shapes are always broadcastable (i.e. the above rules always hold)

>>> x=torch.empty((0,))
>>> y=torch.empty(2,2)
# x and y are not broadcastable, because x does not have at least 1 dimension

# can line up trailing dimensions
>>> x=torch.empty(5,3,4,1)
>>> y=torch.empty(  3,1,1)
# x and y are broadcastable.
# 1st trailing dimension: both have size 1
# 2nd trailing dimension: y has size 1
# 3rd trailing dimension: x size == y size
# 4th trailing dimension: y dimension doesn't exist

# but:
>>> x=torch.empty(5,2,4,1)
>>> y=torch.empty(  3,1,1)
# x and y are not broadcastable, because in the 3rd trailing dimension 2 != 3
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.


如果两个张量xy是“可广播的”,结果张量大小计算如下:

  • 如果的维数xy不相等,则在维数较少的张量的维数前加1,使它们长度相等。
  • 然后,对于每个维度大小,生成的维度大小是xy沿着那个维度。

例如:


# can line up trailing dimensions to make reading easier
>>> x=torch.empty(5,1,4,1)
>>> y=torch.empty(  3,1,1)
>>> (x+y).size()
torch.Size([5, 3, 4, 1])

# but not necessary:
>>> x=torch.empty(1)
>>> y=torch.empty(3,1,7)
>>> (x+y).size()
torch.Size([3, 1, 7])

>>> x=torch.empty(5,2,4,1)
>>> y=torch.empty(3,1,1)
>>> (x+y).size()
RuntimeError: The size of tensor a (2) must match the size of tensor b (3) at non-singleton dimension 1
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.


原地语义

一个复杂的问题是,原位操作不允许原位张量由于广播而改变形状。

例如:


>>> x=torch.empty(5,3,4,1)
>>> y=torch.empty(3,1,1)
>>> (x.add_(y)).size()
torch.Size([5, 3, 4, 1])

# but:
>>> x=torch.empty(1,3,1)
>>> y=torch.empty(3,1,7)
>>> (x.add_(y)).size()
RuntimeError: The expanded size of the tensor (1) must match the existing size (7) at non-singleton dimension 2.
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.


向后兼容性

PyTorch的早期版本允许在不同形状的张量上执行某些逐点函数,只要每个张量中的元素数量相等。逐点运算将通过把每个张量看作一维来进行。PyTorch现在支持广播,并且“一维”逐点行为被认为是不推荐的,并且在张量不可广播但具有相同数量的元素的情况下会生成Python警告。

请注意,在两个张量不具有相同的形状,但可广播并具有相同数量的元素的情况下,广播的引入会导致向后不兼容的变化。例如:


>>> torch.add(torch.ones(4,1), torch.randn(4))
  • 1.


会产生一个大小为torch的张量。Size([4,1]),但现在产生了一个带Size的张量:torch。大小([4,4])。为了帮助识别代码中可能存在由广播引入的向后不兼容的情况,可以将torch . utils . back compat . broadcast _ warning . enabled到真实的,这将在这种情况下生成python警告。

例如:


>>> torch.utils.backcompat.broadcast_warning.enabled=True
>>> torch.add(torch.ones(4,1), torch.ones(4))
__main__:1: UserWarning: self and other do not have the same shape, but are broadcastable, and have the same number of elements.
Changing behavior in a backwards incompatible manner to broadcasting rather than viewing as 1-dimensional.
  • 1.
  • 2.
  • 3.
  • 4.


 然后编辑 编辑以前的