【问题标题】:Numpy broadcasting on multiple arrays多个阵列上的 Numpy 广播
【发布时间】:2018-09-17 12:26:52
【问题描述】:

我有一个平面的 3 个维度的基础:(u, v)。

我想获得这个基础的所有线性组合,以基本遍历我的整个平面:

对于 [0, 512[ 中的 i 和 [0, 512[ 中的 j,获取所有 (i * u + j * v)。

我需要这个速度很快,所以 for 循环并不是一个真正的选择。如何使用 numpy 广播做到这一点?

看了https://docs.scipy.org/doc/numpy-1.13.0/user/basics.broadcasting.html,我的印象是不可能做到...

试过了:

# This is an orthonormal basis but there is no guarantee it is
u = np.array([1, 0, 0])
v = np.array([0, 1, 0])
tmp = np.arange(512)
factors = itertools.combinations(tmp, 2)
pixels = factors[0] * u + factors[1] + v

但显然它不起作用。

这个问题有解决办法吗?如果是,那怎么办?

【问题讨论】:

    标签: python arrays numpy


    【解决方案1】:

    将 (u, v) 与 2D 索引网格相乘:

    ind = np.indices((512, 512))
    pixels = ind[0, ..., np.newaxis] * u + ind[1, ..., np.newaxis] * v
    
    >>> %timeit ind = np.indices((512, 512)); pixels = ind[0, ..., np.newaxis] * u + ind[1, ..., np.newaxis] * v
    8.06 ms ± 69.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
    

    将 u 乘以 1D 索引范围,将 v 乘以 1D 索引范围,广播并合并为 2D:

    i512 = np.arange(512)[:, np.newaxis]
    pixels = (i512 * u)[:, np.newaxis, :] + (i512 * v)[np.newaxis, :, :]
    
    >>> %timeit i512 = np.arange(512)[:, np.newaxis]; pixels = (i512 * u)[:, np.newaxis, :] + (i512 * v)[np.newaxis, :, :]
    4.06 ms ± 58.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
    

    【讨论】:

    • 我不确定我是否理解您的示例,但似乎这在我的示例的特定情况下有效。如果基是 ([1, 1, 1], [1, -1, 1]) 怎么办?
    • 第一个示例是您尝试仅使用 numpy 的 np.indices 的 itertools 组合代码的直接翻译。第二个示例使用i * u + j * v 的第一项和第二项的线性独立性来加快计算速度。它应该适用于uv 的任何值。您究竟在哪里难以理解解决方案?
    • 事实上,您在 u 的 x 轴上使用“newaxis”,在 v 的 y 轴上使用“newaxis”。我对 numpy 还比较陌生,所以我需要查看这些概念。
    • docs.scipy.org/doc/numpy-1.13.0/reference/arrays.indexing.html 是一个很好的资源,值得学习以及您提到的广播页面。
    • 您的解决方案有效。为了完全回答问题,就像@blue_note 的回答一样,您只需要在最后添加一个 pixel.reshape((512*512), 3) 。您的解决方案是最成功的。
    【解决方案2】:

    对您的代码进行一些修改

    factors = itertools.product(tmp, tmp)
    factors = list(zip(*factors))
    factors = np.array(factors)
    pixels = factors[0][:, None] * u + factors[1][:, None] + v
    

    首先,一个数学错误:您想要笛卡尔积,而不是组合。

    现在,实际的语法错误:itertools 生成 [(i1, j1), (i2, j2)..] 列表,而不是 numpy 数组。所以,为了让你的最后一行起作用,你必须

    1. zip(*) 将列表转换为(i1, i2), (j1, j2) 格式
    2. 使它成为一个 numpy 数组
    3. 1Dfactors[0], factors[1]向量中,添加[:, None]以将其转换为列,以便广播工作。

    【讨论】:

    • 您的解决方案有效且易于理解。不幸的是,它比@w-m 解决方案慢得多。
    • @LukeSkywalker:我知道,就效率而言,我没有把它写成提议的方法。只是想解释一下为什么会出错。
    猜你喜欢
    • 2015-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多