轴上的小数乘法

时间:2019-07-04 15:45:35

标签: python numpy

我有2个numpy数组,一个数组的形状为(2, 5, 10),另一个数组的形状为(2, 5, 10, 10)。 我想要的乘法是[[x1[i][j] * x2[i][j] for j in range(5)] for i in range(2)] 它按预期工作,但速度很慢,我想直接乘以x1 * x2,但是numpy不喜欢这样。 是否有一个numpy方法可以在给定的轴上相乘?

我尝试了numpy.multiply,因为它说'axis'是ufunc'multiply'的无效关键字

x1 = np.arange(100).reshape((2, 5, 10))
x2 = np.arange(1000).reshape((2, 5, 10, 10))
x = [[x1[i][j] * x2[i][j] for j in range(5)] for i in range(2)] # slow method that works
x = np.multiply(x1, x2, axis=2) # What I'm looking for but doesn't work.

3 个答案:

答案 0 :(得分:1)

一种方法是,假设您对x类型为np.array感到满意,那就是更好地利用NumPy broadcasting(请参阅@hpaulj的答案):

import numpy as np

x1 = np.arange((2 * 3 * 4)).reshape((2, 3, 4))
x2 = np.arange((2 * 3 * 4 * 4)).reshape((2, 3, 4, 4))
x = [[x1[i][j] * x2[i][j] for j in range(3)] for i in range(2)]) # slow method that works

# : using NumPy broadcasting
y = x1[:, :, None, :] * x2

np.all(np.array(x) == y)
# True

时间方向的加速度约为10倍:

%timeit np.array([[x1[i][j] * x2[i][j] for j in range(3)] for i in range(2)])
# 13.6 µs ± 388 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
%timeit x1[:, :, None, :] * x2
# 1.4 µs ± 10.4 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

答案 1 :(得分:1)

[[x1[i][j] * x2[i][j] for j in range(5)] for i in range(2)]

也使用广播。

x1[i,j].shape    # (10,)
x2[i,j].shape    # (10,10)

要相乘,广播规则会添加一个维度:

(10,), (10,10) => (1,10), (10,10) => (10,10)

但是,如果您使用过x1[i,j,:,None],广播将会进行

(10,1), (10,10) => (10,10)

产生不同的数字。

@ norok2格式的区别在于:

x1[:, :, None, :] * x2
x1[:, :, :, None] * x2

如果x2的形状为(2,5,8,10)或(2,5,10,8),则差异会更加明显。

答案 2 :(得分:0)

使用您的输入信息

x1.shape (2, 5, 10) x2.shape (2, 5, 10, 10)

您可以使用np.tensordot沿任意轴相乘-只要它们的尺寸匹配即可。

x3 = np.tensordot(x1, x2, (1,1)) x3.shape (2, 10, 2, 10, 10)

tensordot还允许您在多个轴上相乘和相加。例如,在这种情况下。

x4 = np.tensordot(x1,x2, ((0,1), (0,1))) x4.shape (10, 10, 10)

这里的参数((0,1),(0,1))分别指向x1和x2的轴。