矩阵数组的元素有效乘法

时间:2013-10-26 04:43:59

标签: python arrays numpy matrix matrix-multiplication

假设array_1array_2是两个大小相同的矩阵数组。有没有任何向量化的方法来乘元素,这两个数组的元素(它们的元素的乘法定义得很好)?

虚拟代码:

def mat_multiply(array_1,array_2):
    size=np.shape(array_1)[0]

    result=np.array([])
    for i in range(size):
        result=np.append(result,np.dot(array_1[i],array_2[i]),axis=0)
    return np.reshape(result,(size,2))

示例输入:

a=[[[1,2],[3,4]],[[1,2],[3,4]]]
b=[[1,3],[4,5]]

输出:

[[  7.  15.]
 [ 14.  32.]]

2 个答案:

答案 0 :(得分:4)

与您的第一句相反,ab的大小不同。但是让我们关注你的例子。

所以你想要这个--2点产品,每一行ab

np.array([np.dot(x,y) for x,y in zip(a,b)])

或避免追加

X = np.zeros((2,2))
for i in range(2):
    X[i,...] = np.dot(a[i],b[i])

dot产品可以用einsum(矩阵索引表示法)表示为

[np.einsum('ij,j->i',x,y) for x,y in zip(a,b)]

所以下一步是索引第一个维度:

np.einsum('kij,kj->ki',a,b)

我对einsum非常熟悉,但是仍需要一些试验和错误来弄清楚你想要什么。既然问题很清楚,我可以用其他几种方式来计算它

A, B = np.array(a), np.array(b)    
np.multiply(A,B[:,np.newaxis,:]).sum(axis=2)
(A*B[:,None,:]).sum(2)
np.dot(A,B.T)[0,...]
np.tensordot(b,a,(-1,-1))[:,0,:]

我发现使用不同大小的数组很有帮助。例如,如果A(2,3,4)B (2,4),则点数总和必须位于最后一维上。


另一个numpy迭代工具是np.nditereinsum使用此(在C中)。 http://docs.scipy.org/doc/numpy/reference/arrays.nditer.html

it = np.nditer([A, B, None],flags=['external_loop'],
    op_axes=[[0,1,2], [0,-1,1], None])
for x,y,w in it:
    # x, y are shape (2,)
    w[...] = np.dot(x,y)
it.operands[2][...,0]

避免[...,0]步骤,需要更精细的设置。

C = np.zeros((2,2))
it = np.nditer([A, B, C],flags=['external_loop','reduce_ok'],
    op_axes=[[0,1,2], [0,-1,1], [0,1,-1]],
    op_flags=[['readonly'],['readonly'],['readwrite']])
for x,y,w in it:
    w[...] = np.dot(x,y)
    # w[...] += x*y 
print C
# array([[  7.,  15.],[ 14.,  32.]])

答案 1 :(得分:2)

还有一个选项,@ hpaulj在他广泛而全面的选项列表中遗漏了这些选项:

>>> a = np.array(a)
>>> b = np.array(b)
>>> from numpy.core.umath_tests import matrix_multiply
>>> matrix_multiply.signature
'(m,n),(n,p)->(m,p)'
>>> matrix_multiply(a, b[..., np.newaxis])
array([[[ 7],
        [15]],

       [[14],
        [32]]])
>>> matrix_multiply(a, b[..., np.newaxis]).shape
(2L, 2L, 1L)
>>> np.squeeze(matrix_multiply(a, b[..., np.newaxis]), axis=-1)
array([[ 7, 15],
       [14, 32]])

关于matrix_multiply的好处是,它是一个gufunc,它不仅适用于一维矩阵数组,还适用于可广播数组。例如,如果不是将第一个矩阵与第一个向量相乘,而是将第二个矩阵与第二个向量相乘,而是想要计算所有可能的乘法,您可以这样做:

>>> a = np.arange(8).reshape(2, 2, 2) # to have different matrices
>>> np.squeeze(matrix_multiply(a[...,np.newaxis, :, :],
...                            b[..., np.newaxis]), axis=-1)
array([[[ 3, 11],
        [ 5, 23]],

       [[19, 27],
        [41, 59]]])