【问题标题】:numpy: Broadcasting a vector horizontallynumpy:水平广播矢量
【发布时间】:2017-06-30 03:21:04
【问题描述】:

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

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

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

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

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

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

简而言之,虽然我了解广播的一般概念,但当我尝试将它用于特定应用程序时,例如复制 col 向量以制作矩阵时,我会迷路。

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

【问题讨论】:

  • NumPy 不是面向矩阵的。如果您愿意,您可以将其视为面向张量的。一维数组没有二维来交换转置。

标签: numpy array-broadcasting


【解决方案1】:

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

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

列向量或列矩阵是一个 m × 1 矩阵 行向量或行矩阵是 1 × m 矩阵

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

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,而不是向量或矩阵。

[计算机科学中的数组] - 通常,可以通过运行时计算的索引选择的数据项的集合

numpy 数组可以有 0 个或多个维度。相比之下,MATLAB 矩阵具有 2 维或更多维。最初,二维矩阵是 MATLAB 所拥有的。

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

因此,向一维数组添加维度,无论是使用 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) 或其他东西。

【讨论】:

  • “大小为 1 的维度可以自动添加到右侧” - 在您的示例中,似乎这是在 left 上添加的。右侧需要手动添加。
  • 已更正 - 我并不是真的有阅读障碍;我只需要大量的校对。
【解决方案2】:

广播总是在左侧添加新维度,因为尝试猜测您何时需要在右侧添加新维度会很模棱两可且容易出错。您可以通过反转轴,广播和反转来制作向右广播的功能:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-01
    • 1970-01-01
    • 2020-07-09
    • 1970-01-01
    • 2016-04-04
    • 1970-01-01
    相关资源
    最近更新 更多