如何让一维数组乘以二维数组得到三维数组(Python)

3

我担心这可能是一个非常愚蠢的问题。然而,我找不到解决方法。 我想在Python中执行以下操作,但不使用循环,因为我正在处理大型数组。 有什么建议吗?

import numpy as np
a = np.array([1,2,3,..., N]) # arbitrary 1d array
b = np.array([[1,2,3],[4,5,6],[7,8,9]]) # arbitrary 2d array
c = np.zeros((N,3,3))
c[0,:,:] = a[0]*b
c[1,:,:] = a[1]*b
c[2,:,:] = a[2]*b
c[3,:,:] = ...
...
...
c[N-1,:,:] = a[N-1]*b

通过魔法......你想做什么?为什么矩阵乘以向量应该是一个三维矩阵...你会使用什么样的数学? - Michele d'Amico
在将一维数组和二维数组相乘后,您不会得到三维数组,如果这种乘法是有效的,它只会给出一个二维转换。 - nishparadox
这不是矩阵乘法。但我想避免使用循环,并且希望有一个简单的数组结构。 - Heungson
4个回答

2

我的答案仅使用了 numpy 原语,特别是对于数组乘法(你想要做的事情有一个名字,叫做外积)。

由于 numpy 的外积函数存在限制,我们必须重新调整结果的形状,但这非常便宜,因为 ndarray 的数据块未涉及。

% python
Python 2.7.8 (default, Oct 18 2014, 12:50:18) 
[GCC 4.9.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> a = np.array((1,2))
>>> b = np.array([[n*m for m in (1,2,3,4,5,6)] for n in (10,100,1000)])
>>> print b
[[  10   20   30   40   50   60]
 [ 100  200  300  400  500  600]
 [1000 2000 3000 4000 5000 6000]]
>>> print np.outer(a,b)
[[   10    20    30    40    50    60   100   200   300   400   500   600
   1000  2000  3000  4000  5000  6000]
 [   20    40    60    80   100   120   200   400   600   800  1000  1200
   2000  4000  6000  8000 10000 12000]]
>>> print "Almost there!"
Almost there!
>>> print np.outer(a,b).reshape(a.shape[0],b.shape[0], b.shape[1])
[[[   10    20    30    40    50    60]
  [  100   200   300   400   500   600]
  [ 1000  2000  3000  4000  5000  6000]]

 [[   20    40    60    80   100   120]
  [  200   400   600   800  1000  1200]
  [ 2000  4000  6000  8000 10000 12000]]]
>>> 

谢谢。这真的很有帮助。 - Heungson

1
为了避免Python级别的循环,你可以使用np.newaxis来扩展a(或者说是None,它们是一样的):
>>> a = np.arange(1,5)
>>> b = np.arange(1,10).reshape((3,3))
>>> a[:,None,None]*b
array([[[ 1,  2,  3],
        [ 4,  5,  6],
        [ 7,  8,  9]],

       [[ 2,  4,  6],
        [ 8, 10, 12],
        [14, 16, 18]],

       [[ 3,  6,  9],
        [12, 15, 18],
        [21, 24, 27]],

       [[ 4,  8, 12],
        [16, 20, 24],
        [28, 32, 36]]])

或者使用 np.einsum,虽然在这里有些过度,但通常很方便,并且可以非常明确地说明你想要坐标发生的情况:
>>> c2 = np.einsum('i,jk->ijk', a, b)
>>> np.allclose(c2, a[:,None,None]*b)
True

看起来非常简单易懂。现在我也理解了“a[:,None,None]”。谢谢。 - Heungson

0

不理解这个乘法.. 但是这里有一种使用numpy在python中进行矩阵乘法的方法:

import numpy as np
a = np.matrix([1, 2])
b = np.matrix([[1, 2], [3, 4]])
result = a*b
print(result)

>>>result
matrix([7, 10])

谢谢。但这不是我想要的。 - Heungson
请参考外积和矩阵乘积的文章。 - mins

0
你正在进行的是一个外积。这个运算符在numpy中可用,名为multiply.outer
import numpy as np
a = np.array([1,2,3,4,5])
b = np.array([[1,2,3],
              [4,5,6],
              [7,8,9]])
c = np.multiply.outer(a, b)
print(c)

[[[ 1  2  3]
  [ 4  5  6]
  [ 7  8  9]]

 [[ 2  4  6]
  [ 8 10 12]
  [14 16 18]]

 [[ 3  6  9]
  [12 15 18]
  [21 24 27]]

 [[ 4  8 12]
  [16 20 24]
  [28 32 36]]

 [[ 5 10 15]
  [20 25 30]
  [35 40 45]]]

multiply是一个ufunc。根据ufunc.outer的文档:"将ufunc op应用于A中的所有元素与B中的所有元素的对(a, b)"(这里指应用乘法运算符)。根据文档,这样做等同于:

r = empty(len(A),len(B))
for i in range(len(A)):
    for j in range(len(B)):
        r[i,j] = op(A[i], B[j])  # op = ufunc in question

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接