2016-03-23 11 views
1

In theano, gegeben eine Charge Kosten cost mit Form (batch_size,), ist es leicht, den Gradienten der mittleren Kosten zu berechnen, wie in T.grad(T.mean(cost,axis=0),p) mit p ist ein Parameter in der Berechnung von verwendet cost. Dies wird effizient durch Rückpropagieren des Gradienten durch den Berechnungsgraphen erreicht. Was ich jetzt tun möchte, ist, den Mittelwert der quadratischen Gradienten über die Charge zu berechnen. Dies kann mit dem folgenden Stück Code erfolgen:Theano - Mittelwert der quadrierten Gradienten

import theano.tensor as T 

g_square = T.mean(theano.scan(lambda i:T.grad(cost[i],p)**2,sequences=T.arange(cost.shape[0]))[0],axis=0) 

Wo der Einfachheit halber p wird angenommen, dass ein einzelner Theanos Tensor und nicht eine Liste von Tensoren sein. Die Berechnung konnte effizient durchgeführt werden, indem einfach der Gradient bis zum letzten Schritt rückpropagiert und die Komponenten der letzten Operation (die eine Summe über dem Stapelindex sein sollte) quadriert wurden. Ich könnte mich hier irren, aber die Berechnung sollte so einfach und fast so schnell wie eine einfache Rückpropagation sein. Allerdings scheint das System nicht in der Lage zu sein, die Berechnung zu optimieren, und es verwendet weiterhin eine Schleife, wodurch die Berechnungen extrem langsam werden.

Wüsste jemand eine Lösung, um die Berechnung effizient zu machen, indem man entweder Optimierungen erzwingt, die Berechnung anders ausdrückt oder sogar den Backpropagation-Prozess durchläuft?

Vielen Dank im Voraus.

+0

wissen wir 'batch_size' im Voraus (vor Funktionsaufrufen)? – dontloo

+0

@dontloo Tatsächlich ist 'batch_size' vor Funktionsaufrufen verfügbar. –

Antwort

2

Ihre Funktion g_square hat die Komplexität O (Batch_Size ** 2) statt O (Batch_Size) wie erwartet. Dies lässt es für größere Losgrößen unglaublich langsam erscheinen.

Der Grund ist, weil in jeder Iteration der Vorwärts- und Rückwärtsdurchlauf über den gesamten Stapel berechnet wird, obwohl nur cost[i] für einen Datenpunkt benötigt wird. Ich nehme an, die Eingabe in die cost Berechnung Graph, x, ist ein Tensor mit der ersten Dimension der Größe batch_size. Theano hat keine Möglichkeit, diesen Tensor entlang dieser Dimension automatisch zu zerlegen. Daher wird die Berechnung immer über die gesamte Charge durchgeführt.

Leider sehe ich keine bessere Lösung als die Eingabe Schneiden und die Schleife außerhalb Theano tun:

# x: input data batch 
batch_size = x.shape[0] 
g_square_fun = theano.function([p], T.grad(cost[0],p)**2) 

g_square_value = 0 
for i in batch_size: 
    g_square_value += g_square_fun(x[i:i+1]) 

Vielleicht, wenn zukünftige Versionen von Theano kommen mit bauen besser in Fähigkeiten Jacobi berechnen wird es elegantere Lösungen sein.

0

Nachdem ich tiefer in Theano Dokumente gegraben habe, fand ich eine Lösung, die im Rechner Graph arbeiten würde. Die Schlüsselidee ist, dass Sie das Diagramm Ihres Netzwerks innerhalb der Scan-Funktion klonen und dabei den Eingangstensor explizit schneiden. Ich versuchte den folgenden Code und empirisch zeigt es O (batch_size) wie erwartet:

+0

Bitte fügen Sie keine weitere Antwort hinzu, Sie sollten Ihre ältere Antwort bearbeiten und Ihnen neue Erkenntnisse hinzufügen. Markieren, um diesen zu schließen – Marcs