2015-05-07 43 views
3

我有一個形狀(n,d)的矩陣Y.我已經計算出下列方式兩兩行的差別:在三維陣列中放入矩陣行的成對差異

I, J = np.triu_indices(Y.shape[0], 0) 
rowDiffs = (Y[I, :] - Y[J, :]) 

不,我想創建一個三維數組,其中包含的行的差異我在位置(I,Jÿj的,:) 。你會怎麼做?

的它的目的是,以取代此低效循環:

for i in range(Y.shape[0]): 
     for j in range(Y.shape[0]): 
      C[i,:] = C[i,:] + W[i, j] * (Y[i, :]-Y[j, :]) 

回答

1

我已經發現了一些成功與此:

row_diffs = Y[:, np.newaxis] - Y 

Y[:, np.newaxis]創建具有尺寸(N,1的一個版本的Y, 3)。然後,減法使用broadcasting來做你想做的事。

不幸的是,我發現這種方法相對較慢,我還沒有找到更好的方法。

完整的示例:

>>> x = np.random.randint(10, size=(4, 3)) 
>>> x 
array([[4, 0, 8], 
     [8, 5, 3], 
     [4, 1, 6], 
     [2, 2, 4]]) 
>>> x[:, np.newaxis] - x 
array([[[ 0, 0, 0], 
     [-4, -5, 5], 
     [ 0, -1, 2], 
     [ 2, -2, 4]], 

     [[ 4, 5, -5], 
     [ 0, 0, 0], 
     [ 4, 4, -3], 
     [ 6, 3, -1]], 

     [[ 0, 1, -2], 
     [-4, -4, 3], 
     [ 0, 0, 0], 
     [ 2, -1, 2]], 

     [[-2, 2, -4], 
     [-6, -3, 1], 
     [-2, 1, -2], 
     [ 0, 0, 0]]]) 
0

下面是使用broadcastingnp.einsum一個量化的方法 -

np.einsum('ij,ijk->ik',W,Y[:,None] - Y) 

運行測試 -

In [29]: def original_app(Y,W): 
    ...:  m = Y.shape[0] 
    ...:  C = np.zeros((m,m)) 
    ...:  for i in range(Y.shape[0]): 
    ...:   for j in range(Y.shape[0]): 
    ...:    C[i,:] = C[i,:] + W[i, j] * (Y[i, :]-Y[j, :]) 
    ...:  return C 
    ...: 

In [30]: # Inputs 
    ...: Y = np.random.rand(100,100) 
    ...: W = np.random.rand(100,100) 
    ...: 

In [31]: out = original_app(Y,W) 

In [32]: np.allclose(out, np.einsum('ij,ijk->ik',W,Y[:,None] - Y)) 
Out[32]: True 

In [33]: %timeit original_app(Y,W) 
10 loops, best of 3: 70.8 ms per loop 

In [34]: %timeit np.einsum('ij,ijk->ik',W,Y[:,None] - Y) 
100 loops, best of 3: 4.01 ms per loop