首页 > 解决方案 > 将 2D 数组乘以另一个 2D 数组中正确索引的缩放器

问题描述

当试图将数组相乘时

v = [ ['x1','y1','z1'], ['x2','y2','z2'] ]

通过缩放器数组的正确索引

 b = [ ['t1','c1'], ['t2','c2'] ] 

我希望得到输出:

```
[
[ [x1 * t1, y1 * t1, z1 * t1], [x2 * c1, y2 * c1, z2 * c1] ],
[ [x1 * t2, y1 * t2, z1 * t2], [x2 * c2, y2 * c2, z2 * c2] ]
]
```

我可以通过执行以下循环来实现这一点:

out = []
for i in b:
   for h in range(len(v):
       out.append(v[h] * i[h])

我将如何在 numpy 中正确地乘以矩阵?

标签: pythonnumpy

解决方案


你想要的是一个外部产品。

只是为了它的乐趣,我会坚持你的字符串,但创建objectdtype 数组:

In [677]: v = np.array([ ['x1','y1','z1'], ['x2','y2','z2'] ],object)           
In [678]: v                                                                     
Out[678]: 
array([['x1', 'y1', 'z1'],
       ['x2', 'y2', 'z2']], dtype=object)
In [679]: b = np.array([ ['t1','c1'], ['t2','c2'] ] ,object)                    
In [680]: v.shape                                                               
Out[680]: (2, 3)
In [681]: b.shape                                                               
Out[681]: (2, 2)

然后,如果我使用broadcastingand plus(对于字符串来说是 a join),我会得到:

In [683]: v[None,:,:]+b[:,:,None]                                               
Out[683]: 
array([[['x1t1', 'y1t1', 'z1t1'],
        ['x2c1', 'y2c1', 'z2c1']],

       [['x1t2', 'y1t2', 'z1t2'],
        ['x2c2', 'y2c2', 'z2c2']]], dtype=object)

这将 (2,3) 数组与 (2,2) 相乘,方法是将它们扩展为 (1,2,3) 和 (2,2,1) => (2,2,3)

同样的事情,但使用数字数组,允许我使用 + 或 *:

In [684]: V = np.arange(10,70,10).reshape(2,3)                                  
In [685]: B = np.arange(1,5).reshape(2,2)                                       
In [686]: V[None,:,:]+B[:,:,None]                                               
Out[686]: 
array([[[11, 21, 31],
        [42, 52, 62]],

       [[13, 23, 33],
        [44, 54, 64]]])
In [687]: V[None,:,:]*B[:,:,None]                                               
Out[687]: 
array([[[ 10,  20,  30],
        [ 80, 100, 120]],

       [[ 30,  60,  90],
        [160, 200, 240]]])

您的循环代码不完全相同(组合相同,但形状不同)

In [697]: out = [] 
     ...: for i in b: 
     ...:     for h in range(2): 
     ...:         out.append(v[h] + i[h]) 
     ...: np.array(out)                                                         
Out[697]: 
array([['x1t1', 'y1t1', 'z1t1'],
       ['x2c1', 'y2c1', 'z2c1'],
       ['x1t2', 'y1t2', 'z1t2'],
       ['x2c2', 'y2c2', 'z2c2']], dtype=object)

In [699]: out = [] 
     ...: for i in B: 
     ...:     for h in range(2): 
     ...:         out.append(V[h] * i[h]) 
     ...: np.array(out)                                                         
Out[699]: 
array([[ 10,  20,  30],
       [ 80, 100, 120],
       [ 30,  60,  90],
       [160, 200, 240]])

einsum是表达这些组合的另一种方式:

In [708]: np.einsum('ij,jk->ijk',B,V)                                           
Out[708]: 
array([[[ 10,  20,  30],
        [ 80, 100, 120]],

       [[ 30,  60,  90],
        [160, 200, 240]]])

如果我告诉它对j维度求和,我得到矩阵乘积np.dot(B,V)

In [709]: np.einsum('ij,jk->ik',B,V)                                            
Out[709]: 
array([[ 90, 120, 150],
       [190, 260, 330]])

推荐阅读