2016-03-22 15 views
3

iki numpy diziler vardır:Etkin ürün numpy

  • 1D bir dizi izin adı elemanı (70L), şekil T adı verilen diyelim ti
  • bir Ii olarak adlandırılan her öğe ile şekil (70L, 1024L, 1024L) ile I denen 3B dizi. II (1024L, 1024L) boyutunun ve böylece olan

ilk boyut boyunca iki dizinin bir ürün, yani yapmak olacaktır: tekrar yeni bir dizi elde etmek üzere

tI = t1*I1,t2*I2,...,tN*IN 

gibi Ben aşağıdakileri yaparak memnunum an için

tsum = t1*I1 + t2*I2 + ... +tN*IN 

: boyut (70L, 1024L, 1024L) ve daha sonra bir boyutun dizisi (1024L, 1024L) elde etmek için birinci boyut boyunca toplamını almak

tI = np.asarray([t[i]*I[i,:,:] for i in range(t.shape[0])]) 
tsum = np.sum(tI,axis=0) 

Ama biraz yavaş olacak, dizimin boyutları artıyor. Bu özel görev için daha iyi optimize edilmiş bir numpy veya scipy işlevi olup olmadığını merak ediyordum?

Herhangi bir bağlantı veya bilgi için şimdiden teşekkür ederiz.

Greg

cevap

3

Sen np.tensordot kullanabilirsiniz -

np.tensordot(t,I, axes=([0],[0])) 

da kullanabilirsiniz np.einsum -

np.einsum('i,ijk->jk',t,I) 

Süre testi ve çıkış doğrulaması -

In [21]: def original_app(t,I): 
    ...:  tI = np.asarray([t[i]*I[i,:,:] for i in range(t.shape[0])]) 
    ...:  tsum = np.sum(tI,axis=0) 
    ...:  return tsum 
    ...: 

In [22]: # Inputs with random elements 
    ...: t = np.random.rand(70,) 
    ...: I = np.random.rand(70,1024,1024) 
    ...: 

In [23]: np.allclose(original_app(t,I),np.tensordot(t,I, axes=([0],[0]))) 
Out[23]: True 

In [24]: np.allclose(original_app(t,I),np.einsum('i,ijk->jk',t,I)) 
Out[24]: True 

In [25]: %timeit np.tensordot(t,I, axes=([0],[0])) 
1 loops, best of 3: 110 ms per loop 

In [26]: %timeit np.einsum('i,ijk->jk',t,I) 
1 loops, best of 3: 201 ms per loop 
+0

Benim için 'tensordot' aslında daha hızlıdır. – egpbos

+0

@egpbos Aynı veri boyutlarıyla denediniz mi? NumPy'nin kurulum sırasında derlenmesinin yolu olabileceğini düşünüyorum. Farklı donanımlar için farklı olsa da, çoğunlukla bir tahminde bulunabilir. – Divakar

+0

Evet, test kodunuzu kopyaladım. 'tensordot' sürekli olarak benim için einsum'dan yaklaşık% 35 daha hızlıdır. 'de [65]:% sürümüyle gelen timeit np.einsum ('i, ijk-> jk', t, J) 10 ilmek 3, en:% sürümüyle gelen timeit np: [66]' de döngü başına 106 ms. tensordot (t, I, eksenler = ([0], [0])) 10 döngü, en iyi 3: 65.9 ms döngü başına – egpbos

2

Divakar en iyi (en verimli) cevapları verir. tamlık aşkına, bunu yapmanın bir başka yolu Numpy's broadcasting capabilities kullanmaktır:

(t[:,np.newaxis,np.newaxis]*I).sum(axis=0) 

t iki ekseni ekleyerek, yayın mümkün olur ve bir bazıları için daha okunabilir olabilir düzenli Numpy işlemlerini kullanabilirsiniz.

+0

'dan daha hızlıydı ve 'broadcasting' de NumPy ile harika bir özellik! Bunu sev. – Divakar