2016-02-15 14 views
7

kod aşağıda:Döngü için bu döngüyü nasıl vektör edebilirim?

import numpy as np 
X = np.array(range(15)).reshape(5,3) # X's element value is meaningless 
flag = np.random.randn(5,4) 
y = np.array([0, 1, 2, 3, 0]) # Y's element value in range(flag.shape[1]) and Y.shape[0] equals X.shape[0] 
dW = np.zeros((3, 4)) # dW.shape equals (X.shape[1], flag.shape[1]) 
for i in xrange(5): 
    for j in xrange(4): 
     if flag[i,j] > 0: 
      dW[:,j] += X[i,:].T 
      dW[:,y[i]] -= X[i,:].T 

daha verimli, döngü için bu vektörize nasıl dW hesaplamak için? İşte

cevap

5

yapardım nasıl:

# has shape (x.shape[1],) + flag.shape 
masked = np.where(flag > 0, X.T[...,np.newaxis], 0) 

# sum over the i index 
dW = masked.sum(axis=1) 

# sum over the j index 
np.subtract.at(dW, np.s_[:,y], masked.sum(axis=2)) 

# dW[:,y] -= masked.sum(axis=2) does not work here 

+1

'y' endeksi,' - = 'tamponlama problemleri olabilir. Bu 'ufunc' .at 'yardımcı olabilir. – hpaulj

+0

@hpaulj Anladım, teşekkürler – Eric

+0

İlk satırın 'maskelenmiş olduğu = np.where (bayrak> 0, X.T [..., np.newaxis], 0) 'yayını kullan, parlak! Yani vektörleştirmenin bir yolu boyutlarını arttırıyor mu? –

-1

Sen bunu yapabilir son yorumun bir açıklama ufunc.at belgelerine bakın bu:

ff = (flag > 0) * 1 
ff = ff.reshape((5, 4, 1, 1)) 
XX = ff * X 
[ii, jj] = np.meshgrid(np.arange(5), np.arange(4)) 
dW[:, jj] += XX[ii, jj, ii, :].transpose((2, 0, 1)) 
dW[:, y[ii]] -= XX[ii, jj, ii, :].transpose((2, 0, 1)) 

Sen başka can Bir tek liner almak için bu ifadeleri birleştirin ve katlayın, ancak daha fazla performans eklemez.

Güncelleme # 1: Bu doğru sonuçlar vermediğinin üzgün Evet, benim kontrol altında bir yazım hatası vardı

+0

X, sadece [[x, y, x, z] 'de hiç indekslendiğinden, 3 boyutlu hale getirilemez mi? – Eric

+0

İlk üç satırın daha iyi yazıldığını düşünüyorum. XX = np.where (bayrak [..., np.newaxis, np.newaxis], X, 0) ' – Eric

+0

Bu benim için doğru sonucu vermiyor – Eric

1

İşte np.add.reduceat dayalı bir vektörleşen yaklaşım - tekrarlanan değerleriyle

# --------------------- Setup output array ---------------------------------- 
dWOut = np.zeros((X.shape[1], flag.shape[1])) 

# ------ STAGE #1 : Vectorize calculations for "dW[:,j] += X[i,:].T" -------- 
# Get indices where flag's transposed version has > 0 
idx1 = np.argwhere(flag.T > 0) 

# Row-extended version of X using idx1's col2 that corresponds to i-iterator 
X_ext1 = X[idx1[:,1]] 

# Get the indices at which we need to columns change 
shift_idx1 = np.append(0,np.where(np.diff(idx1[:,0])>0)[0]+1) 

# Use the changing indices as boundaries for add.reduceat to add 
# groups of rows from extended version of X 
dWOut[:,np.unique(idx1[:,0])] += np.add.reduceat(X_ext1,shift_idx1,axis=0).T 

# ------ STAGE #2 : Vectorize calculations for "dW[:,y[i]] -= X[i,:].T" ------- 
# Repeat same philsophy for this second stage, except we need to index into y. 
# So, that would involve sorting and also the iterator involved is just "i". 
idx2 = idx1[idx1[:,1].argsort()] 
cols_idx1 = y[idx2[:,1]] 
X_ext2 = X[idx2[:,1]] 
sort_idx = (y[idx2[:,1]]).argsort() 
X_ext2 = X_ext2[sort_idx] 
shift_idx2 = np.append(0,np.where(np.diff(cols_idx1[sort_idx])>0)[0]+1) 
dWOut[:,np.unique(cols_idx1)] -= np.add.reduceat(X_ext2,shift_idx2,axis=0).T 
+0

Teşekkürler. Alt satır kod satırlarına sahip, anlamak daha kolay. –

İlgili konular