2016-03-22 7 views
3

Ich habe zwei numpy Arrays:Effiziente Produkt von 1D-Array und 3D-Array entlang einer Dimension - NumPy

  • Ein 1D-Array t Form (70L,) genannt mit dem Element genannt lassen s sagen ti
  • A 3D-Array namens I mit Form (70L, 1024L, 1024L), mit jedem Element namens Ii. II sind somit die Dimension (1024L, 1024L)

Ich mag ein Produkt aus dem zwei-Array entlang der ersten Dimension machen, das heißt:

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

wie wieder zu erhalten, ein neues Array von Dimension (70L, 1024L, 1024L) und dann die Summe in der ersten Dimension, um eine Reihe von Dimension (1024L, 1024L) zu erhalten:

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

Für den Moment mit dem tun des ich bin folgend zufrieden:

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

Aber es wird ein bisschen langsam sein, wenn die Dimensionen meines Arrays zunehmen. Ich frage mich, ob es eine numpige oder scipy Funktion gibt, mehr für diese spezielle Aufgabe optimiert?

Vielen Dank im Voraus für einen Link oder Informationen.

Greg

Antwort

3

können Sie verwenden np.tensordot -

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

Sie auch np.einsum verwenden -

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

Runtime-Test und Ausgangsprüfung -

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

Für mich ist 'Tensordot' tatsächlich schneller. – egpbos

+0

@egpbos Haben Sie es mit den gleichen Datenmengen versucht? Ich denke, es könnte die Art sein, wie NumPy während der Installation kompiliert wurde. Für verschiedene Hardware kann es anders funktionieren, meistens eine Schätzung. – Divakar

+0

Ja, ich habe Ihren Testcode kopiert. 'Tensordot' ist für mich durchweg um 35% schneller als'Einsum'. 'In [65]:% Zeiteinheit n.Einsum ('i, ijk-> jk', t, I) 10 Schleifen, das Beste aus 3: 106 ms pro Schleife In [66]:% timeit np. Tensordot (t, I, Achsen = ([0], [0])) 10 Schleifen, best of 3: 65,9 ms pro Schleife " – egpbos

2

Divakar gibt die besten (effizientesten) Antworten. Der Vollständigkeit halber ist eine andere Art und Weise tun, indem Numpy's broadcasting capabilities mit:

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

Durch die Zugabe von zwei Achsen t, Rundfunk möglich wird und eine regelmäßige Numpy Operationen verwenden können, die für einige vielleicht mehr lesbar sein.

+0

Und das 'Broadcasting' ist auch ein tolles Feature mit NumPy! Liebe diesen einen. – Divakar

Verwandte Themen