【问题标题】:How to make Hadamard product along axis with numpy?如何用numpy沿轴制作Hadamard产品?
【发布时间】:2018-12-23 23:52:07
【问题描述】:

我正在尝试用 2-D 阵列制作 3-D 的 Hadamard 产品。 2-D 数组共享 3-D 数组的前两个轴的形状,并且应该沿着 2 轴(因此,第 3 轴)移动以进行乘法运算,这意味着:用切片 0 制作 Hadamard 积,然后切片 1,等等(参见图像、示意图)。

原始 3-D 数组是opencv 图像,因此具有 f.e. 的形状。 (1080, 1920, 3)。二维数组是该图像的一个切片,因此形状为(1080, 1920)

有没有办法在没有循环或单独指定每个切片的情况下做到这一点?或者是循环到这里的方式吗?

有效的是:

    img_new = np.zeros(shape=img.shape[:2])
    img_new[0] = (img[:, :, 1] * img[:, :, 0])[0]
    img_new[1] = (img[:, :, 2] * img[:, :, 0])[1]

但是,我不希望在代码中进行两次这种计算。

我试过了:

    img_new = np.multiply(img_cvt[:, :, 1:3], img[:, :, 0])

虽然这在使用二维和一维数组时有效

>>> a = np.array(((1,2),(3,4)))
>>> b = np.array((5,8))
>>> np.multiply(a,b)
array([[ 5, 16],
       [15, 32]])

在 3-D/2-D 情况下会出现广播错误:

ValueError: operands could not be broadcast together with shapes (1080,1920,2) (1080,1920)

同样适用于np.apply_along_axis:

img_new = np.apply_along_axis(np.multiply, 2, img[:, :, 1:3], img[:, :, 0])

产生以下结果:

ValueError: operands could not be broadcast together with shapes (2,) (1080,1920)

但我猜这行不通,因为它是为一维函数设计的......

【问题讨论】:

    标签: python arrays numpy array-broadcasting numpy-ufunc


    【解决方案1】:

    看看broadcasting 是如何工作的。本质上,您可以附加一个轴来执行元素明智的操作,例如这有效

    import numpy as np
    
    a = np.random.rand(10, 3)
    b = np.random.rand(10, 3, 2)
    
    c = b * a[..., np.newaxis] # make a shape 10 x 3 x 1
    

    【讨论】:

    • 相当简洁,看起来我在这里错过了一些基本功能!谢谢
    • 要使用b的一个切片与b的每个切片相乘,需要np.multiply(b,b[:, :, 1, np.newaxis])?
    • 要多个切片的子集,您可以使用上面链接中列出的索引方法。你的具体例子需要这个; b * b[:, :, [1]],如果切片如图所示,使用乘法函数是等效的。编辑:这里的 * 不是点积,如果这会导致混淆的话。
    • 两者似乎都有效,但括号方法中的括号看起来比拼接定义后的 np.newaxis 更好。
    • 我很抱歉。您是正确的,没有明确提及带括号的方法,而是通过广播要求暗示。我应该更清楚。另一个推荐阅读是 numpy 中的indexing,它显示了不同的方法来做到这一点。
    【解决方案2】:

    您可以为此使用np.expand_dims() 函数。

    使用np.arange() 创建一个缺少维度的元组,然后添加它们。 (我假设你想在最后添加 - 你总是可以使用转置来实现):

    c = np.array([
            [[1, 2, 3, 4],[5, 6, 7, 8]],
            [[.1, .2, .3, .4], [.5, .6, .7, .8]]
        ])
    d = np.array([.5, .6])
    
    cdim = len(c.shape)
    ddim = len(d.shape)
    newdims = tuple(np.arange(start=ddim, stop=cdim))
    dx = np.expand_dims(d, newdims)
    
    c + dx
    c * dx
    

    显然,您可以在一行中完成所有这些 - 变量只是为了清楚起见:

    def match_dim(b, A):
        "Adds dimensions of length 1 to b to make it dimension compliant with A and returns the expanded structure"
        return np.expand_dims(b, tuple(np.arange(start=len(b.shape), stop=len(A.shape))))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-08
      • 1970-01-01
      相关资源
      最近更新 更多