Berechnung effizienter gestalten mittels Vectorizing

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
hukd321
User
Beiträge: 12
Registriert: Dienstag 31. Juli 2012, 16:07

Hi,

ich definiere die Einträge in einer Matrix H und einem Vektor h über die folgenden for-schleifen:

Code: Alles auswählen

    for l in xrange(0, laenge):
        for ls in xrange(0, laenge):
            H[l][ls] = 1.0/tr * numpy.sum([numpy.exp(-(((x_tr[i]-c[l])**2 + (x_tr[i]-c[ls])**2)/(2*s**2))) for i in range(0, tr)])
    for l in range(0, laenge):
        h[l] = 1.0/te * numpy.sum([numpy.exp(-(((x_te[j]-c[l])**2)/(2*s**2))) for j in range(0, te)])
Mal davon abgesehen, dass ich mir die dritte for-schleife (die für den Vektor) eigentlich schenken kann (sehe ich jetzt erst), so habe ich gehört, dass man mittels "Vectorizing" diese Belegung der Matrix und des Vektors deutlich effizienter gestalten kann... diese beiden for-Schleifen sind ja sehr zeitintensiv...

Leider hilft mir google auch nicht weiter bzw. ich kann die Beispiele nicht wirklich auf mein Problem beziehen!

Könntet ihr mir bitte helfen?

gruß
hukd
BlackJack

@hukd321: Du musst halt schauen dass Du das mit Operationen auf Arrays ausdrückst statt mit Schleifen und Operationen auf einzelnen Elementen.

Nehmen wir zum Beispiel den Vektor:

Code: Alles auswählen

    for l in xrange(0, laenge):
        h[l] = (
            1.0 / te * numpy.sum(
                [
                    numpy.exp(-(((x_te[j] - c[l])**2) / (2 * s**2)))
                    for j in xrange(0, te)
                ]
            )
        )
Da hast Du ”innen” eine Python-Schleife über die Elemente von `x_te` über einen Index und erstellst eine Python-Liste. An der Stelle müsste man, unter der Annahme das `x_te` und die Elemente von `c` `numpy`-Arrays sind, doch auch einfach mit `x_te` als Wert arbeiten können und bekommt ohne eine externe Schleife ein Array heraus, welches der Python-Liste entspricht, die durch die „list comprehension” erstellt wird. Auf dem Array kann man dann die `sum()`-Methode aufrufen. Ungetestet:

Code: Alles auswählen

    for l in xrange(0, laenge):
        h[l] = 1.0 / te * numpy.exp(-((x_te - c[l])**2 / (2 * s**2))).sum()
Bei der verbleibenden Python-Schleife wird von immer dem selben Wert `x_te` ein anderer Wert von `c` abgezogen. Hier könnte man also überlegen durch ”wiederholen” von `x_te` ein Array zu erzeugen, dass von der Form zu einer Subtraktion von zwei Arrays passt. Dann bekommt man eine Dimension mehr, die man dann durch aufsummieren über die entsprechende Achse wieder auf das gewünschte Ergebnis reduziert. Auch wieder vollkommen ungetestet:

Code: Alles auswählen

    h = 1.0 / te * numpy.exp(
        -((np.tile(x_te, (laenge, 1)) - c)**2 / (2 * s**2))
    ).sum(1)
Wenn das so funktioniert hat man keine Python-Schleife mehr und alles intern in die `numpy`-Typen verlagert. Wichtiger Unterschied: es wird nicht mehr `h` verändert. Diese Indexzuweisungen an `H` und `h` erscheinen mir sowieso unpythonisch. Das ist eher idiomatisch für C oder Fortran. Oder Cython, denn da könnte diese Art der Programmierung vorteilhafter sein als das „pythonischere” neu erstellen von Objekten.
Antworten