如何使用 numpy 沿轴制作 Hadamard 产品?
How to make Hadamard product along axis with numpy?
我正在尝试用 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)
但我猜这行不通,因为它是为一维函数设计的...
看看 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
您可以为此使用 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))))
我正在尝试用 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)
但我猜这行不通,因为它是为一维函数设计的...
看看 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
您可以为此使用 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))))