numpy:水平广播矢量

numpy: Broadcasting a vector horizontally

我在 numpy v 中有一个一维数组。我想复制它来制作一个矩阵,每一行都是 v 的副本。这很简单:np.broadcast_to(v, desired_shape).

但是,如果我想将 v 视为一个 向量,并将其复制以制作一个包含每个 列的矩阵 作为 v 的副本,我找不到一个简单的方法来做到这一点。通过反复试验,我能够做到这一点:

 np.broadcast_to(v.reshape(v.shape[0], 1), desired_shape)

虽然它有效,但我不能声称理解它(即使它是我写的!)。

部分问题是 numpy 似乎没有列向量的概念(因此 reshape hack 而不是数学中的 .T)。

但是,问题的更深层次似乎是广播只能垂直播放,不能水平播放。或者更正确的说法是:广播只适用于更高的维度,而不适用于更低的维度。 我什至不确定这是否正确。

简而言之,虽然我总体上理解广播的概念,但当我尝试将它用于特定应用时,例如复制 col 向量来制作矩阵,我迷路了。

你能帮我理解或提高这段代码的可读性吗?

https://en.wikipedia.org/wiki/Transpose - 这篇关于转置的文章只讨论转置矩阵。

https://en.wikipedia.org/wiki/Row_and_column_vectors -

a column vector or column matrix is an m × 1 matrix a row vector or row matrix is a 1 × m matrix

您可以轻松创建行或列向量(矩阵):

In [464]: np.array([[1],[2],[3]])   # column vector
Out[464]: 
array([[1],
       [2],
       [3]])
In [465]: _.shape
Out[465]: (3, 1)

In [466]: np.array([[1,2,3]])  # row vector
Out[466]: array([[1, 2, 3]])
In [467]: _.shape
Out[467]: (1, 3)

但在 numpy 中,基本结构是一个 array,而不是向量或矩阵。

[Array in Computer Science] - Generally, a collection of data items that can be selected by indices computed at run-time

numpy 数组可以有 0 维或更多维。相反,在 MATLAB 中,矩阵具有 2 个或更多维。最初 2d 矩阵是 MATLAB 的全部。

要有意义地谈论转置,您必须至少有 2 个维度。一个可能有一个大小,并映射到一维向量上,但它仍然是一个矩阵,一个二维对象。

因此,向一维数组添加维度,无论是使用 reshape 还是 [:,None] 都不是 hack。这是一个完美有效且正常的 numpy 操作。

基本广播规则是:

  • 可以更改大小为 1 的维度以匹配另一个数组的相应维度

  • 可以在左侧(前面)自动添加尺寸为 1 的尺寸以匹配尺寸数量。

在这个例子中,两个步骤都适用:(5,)=>(1,5)=>(3,5)

In [458]: np.broadcast_to(np.arange(5), (3,5))
Out[458]: 
array([[0, 1, 2, 3, 4],
       [0, 1, 2, 3, 4],
       [0, 1, 2, 3, 4]])

在此,我们要显式地在右侧(末尾)添加尺寸一维:

In [459]: np.broadcast_to(np.arange(5)[:,None], (5,3))
Out[459]: 
array([[0, 0, 0],
       [1, 1, 1],
       [2, 2, 2],
       [3, 3, 3],
       [4, 4, 4]])

np.broadcast_arrays(np.arange(5)[:,None], np.arange(3)) 生成两个 (5,3) 数组。

np.broadcast_arrays(np.arange(5), np.arange(3)[:,None]) 生成 (3,5)。

np.broadcast_arrays(np.arange(5), np.arange(3)) 会产生错误,因为它无法确定您想要 (5,3) 还是 (3,5) 或其他。

广播总是在左侧添加新的维度,因为当您想要在右侧添加新维度时,尝试猜测会产生歧义且容易出错。可以做一个向右广播的函数,通过反转坐标轴,广播,反转回来:

def broadcast_rightward(arr, shape):
    return np.broadcast_to(arr.T, shape[::-1]).T