Nach @ajcr's great answer wollte ich, um zu bestimmen, welche Methode die schnellste ist, so habe ich timeit
:
import timeit
setup_code = """
import numpy as np
i,j,k = (300,200,400)
ind = np.ones((i,j,k)) #shape=(3L, 2L, 4L)
dist = np.random.rand(i,j) #shape=(3L, 2L)
"""
basic ="np.array([np.dot(dist[l],ind[l]) for l in xrange(dist.shape[0])])"
einsum = "np.einsum('ijk,ij->ik', ind, dist)"
tensor= "np.tensordot(ind, dist, axes=[1, 1])[0].T"
print "tensor - total time:", min(timeit.repeat(stmt=tensor,setup=setup_code,number=10,repeat=3))
print "basic - total time:", min(timeit.repeat(stmt=basic,setup=setup_code,number=10,repeat=3))
print "einsum - total time:", min(timeit.repeat(stmt=einsum,setup=setup_code,number=10,repeat=3))
Die überraschenden Ergebnisse waren:
tensor - total time: 6.59519493952
basic - total time: 0.159871203461
einsum - total time: 0.263569731028
So offensichtlich tensordot wurde unter Verwendung der falsche Weg zu Mach es (ganz zu schweigen von memory error
in größeren Beispielen, wie @ajcr angegeben).
Da dieses Beispiel klein war, änderte ich die Matrizen Größe i,j,k = (3000,200,400)
, nur die Reihenfolge umgedreht zu sein, sicherzustellen, dass es einen weiteren Test mit einer höheren Anzahl von Wiederholungen nicht bewirken und eingerichtet hat:
print "einsum - total time:", min(timeit.repeat(stmt=einsum,setup=setup_code,number=50,repeat=3))
print "basic - total time:", min(timeit.repeat(stmt=basic,setup=setup_code,number=50,repeat=3))
Die Ergebnisse im Einklang mit dem ersten Lauf waren:
einsum - total time: 13.3184077671
basic - total time: 8.44810031351
, eine andere Art von Größenwachstum Prüfung jedoch - i,j,k = (30000,20,40)
folgenden Ergebnissen geführt:
einsum - total time: 0.325594117768
basic - total time: 0.926416766397
Siehe die Kommentare nach Erklärungen für diese Ergebnisse.
Die Moral ist, wenn für die schnellste Lösung für ein bestimmtes Problem suchen, versucht, Daten zu erzeugen, die ähnlich wie bei den Originaldaten wie möglich, in der Bezeichnung der Arten und Formen sind. In meinem Fall i
ist viel kleiner als j,k
und so blieb ich mit der hässlichen Version, die in diesem Fall auch die schnellste ist.
groß (EDIT: Ich akzeptierte @ ajcr Antwort, aber bitte lesen Sie meine eigene Antwort.) Es wird anderen helfen .. –