2013-02-22 71 views
2

我有一个3xNxM的numpy数组a,我想遍历最后两个轴:a [:,x,y]。不雅的做法是:在多维的numpy数组中迭代向量

import numpy as np 
a = np.arange(60).reshape((3,4,5)) 
M = np. array([[1,0,0], 
       [0,0,0], 
       [0,0,-1]]) 

for x in arange(a.shape[1]): 
    for y in arange(a.shape[2]): 
     a[:,x,y] = M.dot(a[:,x,y]) 

这可以用nditer完成吗?这样做的目标是对每个条目执行矩阵乘法,例如, a [:,x,y] = M [:,:,x,y] .dot(a [:,x,y])。另一种方法是用MATLAB的方法重塑一个(3,N * M)和M(3,3 * N * M)并且取一个点积,但这往往会消耗大量的内存。

回答

5

虽然与形状鬼混可能使你所要完成更清楚,处理这类问题没有想得太多了最简单的方法是用np.einsum

In [5]: np.einsum('ij, jkl', M, a) 
Out[5]: 
array([[[ 0, 1, 2, 3, 4], 
     [ 5, 6, 7, 8, 9], 
     [ 10, 11, 12, 13, 14], 
     [ 15, 16, 17, 18, 19]], 

     [[ 0, 0, 0, 0, 0], 
     [ 0, 0, 0, 0, 0], 
     [ 0, 0, 0, 0, 0], 
     [ 0, 0, 0, 0, 0]], 

     [[-40, -41, -42, -43, -44], 
     [-45, -46, -47, -48, -49], 
     [-50, -51, -52, -53, -54], 
     [-55, -56, -57, -58, -59]]]) 

加上它常来与业绩奖金:

In [17]: a = np.random.randint(256, size=(3, 1000, 2000)) 

In [18]: %timeit np.dot(M, a.swapaxes(0,1)) 
10 loops, best of 3: 116 ms per loop 

In [19]: %timeit np.einsum('ij, jkl', M, a) 
10 loops, best of 3: 60.7 ms per loop 

编辑einsum为v强大的巫术力量。您还可以按照以下注释做OP:

>>> a = np.arange(60).reshape((3,4,5)) 
>>> M = np.array([[1,0,0], [0,0,0], [0,0,-1]]) 
>>> M = M.reshape((3,3,1,1)).repeat(4,axis=2).repeat(5,axis=3) 
>>> np.einsum('ijkl,jkl->ikl', M, b) 
array([[[ 0, 1, 2, 3, 4], 
     [ 5, 6, 7, 8, 9], 
     [ 10, 11, 12, 13, 14], 
     [ 15, 16, 17, 18, 19]], 

     [[ 0, 0, 0, 0, 0], 
     [ 0, 0, 0, 0, 0], 
     [ 0, 0, 0, 0, 0], 
     [ 0, 0, 0, 0, 0]], 

     [[-40, -41, -42, -43, -44], 
     [-45, -46, -47, -48, -49], 
     [-50, -51, -52, -53, -54], 
     [-55, -56, -57, -58, -59]]]) 
+0

谢谢!有没有一种方法可以将元素乘法包含在Einsum中?例如,我有一个大小为3xMxN的矢量阵列(如上所示),我想对每个矢量执行矩阵旋转,大小为3x3xMxN的张量M. ((3,4,5)) M =数组([[1,0,0], [0,0,0], [0,0,-1 ](a.shape [1])) M = M.reshape((3,3,1,1))。repeat(4,axis = 2).repeat(5,axis = 3) ): for arange(a.shape [2]): a [:,x,y] = M [:,:,x,y] .dot(a [:,x,y]) 什么是正确的消解方法?我得到了: b = einsum('ijkl,jxy',M,a) c = b [:,0,0,:,] – emarti 2013-02-22 08:09:08

+0

@emarti我编辑了我的答案来掩盖您的问题评论。 – Jaime 2013-02-22 16:23:39

+1

+1在答案中使用伏都教 – evan54 2014-11-15 04:51:06

2
for x in np.arange(a.shape[1]): 
    for y in np.arange(a.shape[2]): 
     a[:,x,y] = M.dot(a[:,x,y]) 

相当于

a = np.dot(M,a.swapaxes(0,1)) 

In [73]: np.dot(M,a.swapaxes(0,1)) 
Out[73]: 
array([[[ 0, 1, 2, 3, 4], 
     [ 5, 6, 7, 8, 9], 
     [ 10, 11, 12, 13, 14], 
     [ 15, 16, 17, 18, 19]], 

     [[ 0, 0, 0, 0, 0], 
     [ 0, 0, 0, 0, 0], 
     [ 0, 0, 0, 0, 0], 
     [ 0, 0, 0, 0, 0]], 

     [[-40, -41, -42, -43, -44], 
     [-45, -46, -47, -48, -49], 
     [-50, -51, -52, -53, -54], 
     [-55, -56, -57, -58, -59]]]) 

说明:

对于多维阵列,np.dot(M,a)performs a sum product over the last axis of M and the second-to-last axis of a.

a具有形状(3,4,5),但我们希望对形状3的轴进行求和。由于倒数第二个轴将被求和,因此我们需要a.swapaxis(0,1) - 它具有形状( 4,3,5) - 将3移动到倒数第二个轴。

M已成形(3,3),a.swapaxis(0,1)已成形(4,3,5)。删除M的最后一个轴和a.swapaxis(0,1)的倒数第二轴会使(3,)和(4,5)离开,所以np.dot返回的结果是一个形状数组(3,4,5) - 正是我们想要的。