2016-08-17 25 views
11

W moim problemie potrzebuję uruchomić GD z 1 przykładem z danych na każdym etapie szkolenia. Znany jest problem związany z tym, że session.run() ma narzut i dlatego jest zbyt długi, aby modelować. Próbując uniknąć obciążenia, próbowałem użyć while_loop i modelu pociągu na wszystkich danych za pomocą jednego wywołania run(). Ale to podejście nie działa, a train_op nie wykonuje nawet tych. Poniżej prosty przykład tego, co robię:Tensorflow while_loop for training

data = [k*1. for k in range(10)] 
tf.reset_default_graph() 

i = tf.Variable(0, name='loop_i') 
q_x = tf.FIFOQueue(100000, tf.float32) 
q_y = tf.FIFOQueue(100000, tf.float32) 

x = q_x.dequeue() 
y = q_y.dequeue() 
w = tf.Variable(0.) 
b = tf.Variable(0.) 
loss = (tf.add(tf.mul(x, w), b) - y)**2 

gs = tf.Variable(0) 

train_op = tf.train.GradientDescentOptimizer(0.05).minimize(loss, global_step=gs) 

s = tf.Session() 
s.run(tf.initialize_all_variables()) 

def cond(i): 
    return i < 10 

def body(i): 
    return tf.tuple([tf.add(i, 1)], control_inputs=[train_op]) 


loop = tf.while_loop(cond, body, [i]) 

for _ in range(1): 
    s.run(q_x.enqueue_many((data,))) 
    s.run(q_y.enqueue_many((data,))) 

s.run(loop) 
s.close() 

Co robię źle? Czy istnieje inne rozwiązanie tego problemu ze zbyt wysokim kosztem?

Dzięki!

Odpowiedz

18

Powodem model nie wydaje się, aby szkolić się tak, ponieważ wejście czytanie, obliczanie gradientu, a połączenie minimize() są zdefiniowane poza (a więc w warunkach przepływu danych, przed) korpusu tf.while_loop(). Oznacza to, że wszystkie te części modelu działają tylko raz, przed wykonaniem pętli, a sama pętla nie działa.

Nieznaczne refaktoring — przenieść dequeue() operacje, obliczanie gradientu i minimize() połączenia wewnątrz pętli — rozwiązuje ten problem i umożliwia program do pociągu:

optimizer = tf.train.GradientDescentOptimizer(0.05) 

def cond(i): 
    return i < 10 

def body(i): 
    # Dequeue a new example each iteration. 
    x = q_x.dequeue() 
    y = q_y.dequeue() 

    # Compute the loss and gradient update based on the current example. 
    loss = (tf.add(tf.mul(x, w), b) - y)**2 
    train_op = optimizer.minimize(loss, global_step=gs) 

    # Ensure that the update is applied before continuing. 
    return tf.tuple([tf.add(i, 1)], control_inputs=[train_op]) 

loop = tf.while_loop(cond, body, [i]) 

UPDATE: Oto kompletny program wykonuje pętlę while, w oparciu o kod w pytaniu:

import tensorflow as tf 

# Define a single queue with two components to store the input data. 
q_data = tf.FIFOQueue(100000, [tf.float32, tf.float32]) 

# We will use these placeholders to enqueue input data. 
placeholder_x = tf.placeholder(tf.float32, shape=[None]) 
placeholder_y = tf.placeholder(tf.float32, shape=[None]) 
enqueue_data_op = q_data.enqueue_many([placeholder_x, placeholder_y]) 

gs = tf.Variable(0) 
w = tf.Variable(0.) 
b = tf.Variable(0.) 
optimizer = tf.train.GradientDescentOptimizer(0.05) 

# Construct the while loop. 
def cond(i): 
    return i < 10 

def body(i): 
    # Dequeue a single new example each iteration. 
    x, y = q_data.dequeue() 
    # Compute the loss and gradient update based on the current example. 
    loss = (tf.add(tf.multiply(x, w), b) - y) ** 2 
    train_op = optimizer.minimize(loss, global_step=gs) 
    # Ensure that the update is applied before continuing. 
    with tf.control_dependencies([train_op]): 
     return i + 1 

loop = tf.while_loop(cond, body, [tf.constant(0)]) 

data = [k * 1. for k in range(10)] 

with tf.Session() as sess: 
    sess.run(tf.global_variables_initializer()) 
    for _ in range(1): 
     # NOTE: Constructing the enqueue op ahead of time avoids adding 
     # (potentially many) copies of `data` to the graph. 
     sess.run(enqueue_data_op, 
       feed_dict={placeholder_x: data, placeholder_y: data}) 
    print (sess.run([gs, w, b])) # Prints before-loop values. 
    sess.run(loop) 
    print (sess.run([gs, w, b])) # Prints after-loop values. 
+1

Czy powinienem zdefiniować ** w ** i ** b ** na zewnątrz? Próbuję czegoś takiego (a teraz próbuję dokładnie tego, co oferujesz), ale dostałem błąd * Wszystkie dane wejściowe do węzła podczas/GradientDescent/update_while/w/ApplyGradientDescent muszą pochodzić z tej samej ramki. * –

+0

Dodałem pełny program który uruchomiłem z TensorFlow 0.10rc0. (Być może będziesz musiał dokonać aktualizacji, były różne błędy w implementacji 'tf.while_loop()', które zostały naprawione w ciągu ostatnich kilku wydań – mrry

+0

Tak, uruchomiłem go na 0.9, dziękuję, po aktualizacji działa! jeszcze jedno pytanie dotyczące twojego rozwiązania - wygląda na to, że nowy optymalizator tworzy każdy krok i co jeśli chcę użyć optymalizatora Ftrl (który ma kilka zaktualizowanych gniazd)? Czy będzie działał jak jeden optymalizator podczas procesu szkolenia? –

Powiązane problemy