2016-03-27 15 views
7

Buduję prosty perceptron wielowarstwowy z TensorFlow, a także muszę uzyskać gradienty (lub sygnał błędu) utraty na wejściach sieci neuronowej.TensorFlow: niska wydajność podczas uzyskiwania gradientów na wejściach

Oto mój kod, który działa:

cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(self.network, self.y)) 
optimizer = tf.train.AdagradOptimizer(learning_rate=nn_learning_rate).minimize(cost) 
... 
for i in range(epochs): 
    .... 
    for batch in batches: 
     ... 
     sess.run(optimizer, feed_dict=feed_dict) 
     grads_wrt_input = sess.run(tf.gradients(cost, self.x), feed_dict=feed_dict)[0] 

(edycja zawierać pętlę szkolenia)

bez ostatniej linii (grads_wrt_input...), to działa bardzo szybko na maszynie CUDA. Jednak tf.gradients() znacznie zmniejsza wydajność o dziesięciokrotność lub więcej.

Przypominam, że sygnały o błędach w węzłach są obliczane jako wartości pośrednie w algorytmie wstecznej propagacji i pomyślnie to zrobiłem przy użyciu biblioteki Java DeepLearning4j. Miałem również wrażenie, że będzie to niewielka modyfikacja wykresu obliczeniowego, który został już zbudowany przez optimizer.

Jak można to zrobić szybciej, czy istnieje inny sposób obliczania gradientów straty w.r.t. dane wejściowe?

+0

Dosłownie nazywasz 'tf.gradients()' w pętli treningowej? Jeśli tak, to podejrzewam, że obciążenie wynika z budowania wykresu mapy za każdym razem, gdy go wywołasz? – mrry

+0

Dołączyłem kod pętli treningowej dla jasności; tak nazywam 'tf.gradients()' w pętli treningowej. Program spowalnia stopniowo. Co powinienem zrobić, aby nie dopuścić do powstania tego budynku? –

+0

Wywołuje tf.gradients poza pętlą, aby raz zbudować wykres obliczeniowy dla gradientów. Możesz także ponownie użyć wykresu gradientu utworzonego dla optymalizatora, używając compute_gradients –

Odpowiedz

10

Funkcjabuduje nowy wykres stratpropagacji za każdym razem, gdy jest wywoływany, więc przyczyną spowolnienia jest to, że TensorFlow musi przeanalizować nowy wykres dla każdej iteracji pętli. (Może to być zaskakująco drogie: Aktualna wersja TensorFlow jest zoptymalizowany do wykonywania wykres sam wiele razy).

jednak rozwiązanie jest proste: obliczania gradientu raz, na zewnątrz pętli. można zrestrukturyzować swój kod w następujący sposób:

cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(self.network, self.y)) 
optimizer = tf.train.AdagradOptimizer(learning_rate=nn_learning_rate).minimize(cost) 
grads_wrt_input_tensor = tf.gradients(cost, self.x)[0] 
# ... 
for i in range(epochs): 
    # ... 
    for batch in batches: 
     # ... 
     _, grads_wrt_input = sess.run([optimizer, grads_wrt_input_tensor], 
             feed_dict=feed_dict) 

uwadze fakt, że wydajność, ja również połączyć dwie sess.run() połączeń. Zapewnia to ponowne wykorzystanie propagacji w przód i znacznej części wstecznej propagacji.


Jak na bok, jedna wskazówka, aby znaleźć błędy wydajności jak to nazwać tf.get_default_graph().finalize() przed rozpoczęciem pętli treningowy. Spowoduje to zgłoszenie wyjątku, jeśli nieodwracalnie dodasz jakiekolwiek węzły do ​​wykresu, co ułatwia prześledzenie przyczyny tych błędów.

+0

To zadziałało, dziękuję! Mój program jest teraz szybki. BTW, myślę, że 'grads_wrt_input' na liście w wywołaniu' sess.run() 'powinno być' grads_wrt_input_tensor'. –

+0

Dobra uwaga: po prostu edytowane z poprawką! – mrry

Powiązane problemy