我有一个形状为(8,9)的scipy稀疏矩阵和另一个形状为(9,12,17)的数组。我希望将这些乘以这样我得到一个大小为矩阵/数组(8,12,17),其中(8,9)矩阵实际上只乘以第一维。我是否必须使用Kronecker产品才能做到这一点,或者是否有一种简单的方法?
答案 0 :(得分:2)
如果m1
是2d稀疏矩阵,则m1.A
是其密集数组形式。实际上,dinmensions写了einsum
表达式。
np.einsum('ij,jkl->ikl', m1.A, m2)
例如:
In [506]: M = sparse.random(8, 9, 0.1)
In [507]: A = np.ones((9, 12, 17))
In [508]: np.einsum('ij,jkl->ikl', M.A, A).shape
Out[508]: (8, 12, 17)
答案 1 :(得分:1)
正如hpaulj在评论中所说,最简单的方法是使用密集矩阵np.einsum
:
>>> a = np.random.randn(8, 9)
>>> b = np.random.randn(9, 12, 17)
>>> c = np.einsum('ij,jkl->ikl', a, b)
>>> c.shape
(8, 12, 17)
答案 2 :(得分:1)
@Divakar建议np.tensordot
,@ hpaulj和@Praveen建议np.einsum
。另一种方法是转置轴:
(a @ b.transpose((2, 0, 1))).transpose((1, 2, 0))
对于您引用的小尺寸,np.einsum
和换位似乎更快。但是一旦你开始按比例增加轴的尺寸,np.tensordot
就会胜过另外两个。
import numpy as np
m, n, k, l = 8, 9, 12, 17
a = np.random.random((m, n))
b = np.random.random((n, k, l))
%timeit np.tensordot(a, b, axes=([1], [0]))
# => 10000 loops, best of 3: 22 µs per loop
%timeit np.einsum("ij,jkl->ikl", a, b)
# => 100000 loops, best of 3: 10.1 µs per loop
%timeit (a @ b.transpose((2, 0, 1))).transpose((1, 2, 0))
# => 100000 loops, best of 3: 11.1 µs per loop
m, n, k, l = 8, 900, 12, 17
a = np.random.random((m, n))
b = np.random.random((n, k, l))
%timeit np.tensordot(a, b, axes=([1], [0]))
# => 1000 loops, best of 3: 198 µs per loop
%timeit np.einsum("ij,jkl->ikl", a, b)
# => 1000 loops, best of 3: 868 µs per loop
%timeit (a @ b.transpose((2, 0, 1))).transpose((1, 2, 0))
# => 1000 loops, best of 3: 907 µs per loop
m, n, k, l = 8, 90000, 12, 17
a = np.random.random((m, n))
b = np.random.random((n, k, l))
%timeit np.tensordot(a, b, axes=([1], [0]))
# => 10 loops, best of 3: 21.7 ms per loop
%timeit np.einsum("ij,jkl->ikl", a, b)
# => 10 loops, best of 3: 164 ms per loop
%timeit (a @ b.transpose((2, 0, 1))).transpose((1, 2, 0))
# => 10 loops, best of 3: 166 ms per loop
答案 3 :(得分:0)
以下是我可以使用它的几种方法。第二个似乎更好,我测试时快了大约12倍。
def multiply_3D_dim_zero_slow(matrix, array):
shape = array.shape
final_shape = (matrix.shape[0], array.shape[1], array.shape[2])
result = np.zeros(final_shape)
for i in xrange(shape[1]):
for j in xrange(shape[2]):
result[:, i, j] = matrix * array[:, i, j]
return result.reshape(final_shape)
这是一个更快的版本,它使用reshape将多维数组转换为2D数组。
def multiply_3D_dim_zero(matrix, array):
shape = array.shape
final_shape = (matrix.shape[0], array.shape[1], array.shape[2])
array_reshaped = array.reshape(shape[0], shape[1] * shape[2])
return (matrix * array_reshaped).reshape(final_shape)ode here
这只适用于第一个维度,这是我需要的,但可以概括。