2015-11-25 8 views
62

Używam TensorFlow do szkolenia sieci neuronowej. To jak ja inicjowania GradientDescentOptimizer:Jak ustawić szybkość uczenia adaptacyjnego dla GradientDescentOptimizer?

init = tf.initialize_all_variables() 
sess = tf.Session() 
sess.run(init) 

mse  = tf.reduce_mean(tf.square(out - out_)) 
train_step = tf.train.GradientDescentOptimizer(0.3).minimize(mse) 

Chodzi o to, że nie wiem jak ustawić regułę aktualizacji dla szybkości uczenia się lub wartości zaniku dla tego.

W jaki sposób mogę wykorzystać współczynnik adaptacyjnego uczenia się?

+0

Jest to dobry zwyczaj, aby zainicjować wszystkie zmienne _after_ określić twój optymalizator, ponieważ niektóre optymalizatory, takie jak AdamOptimizer, używają własnych zmiennych, które również wymagają inicjalizacji. W przeciwnym razie może pojawić się błąd, który wygląda następująco: '' 'FailedPreconditionError (zobacz powyżej dla traceback): Próba użycia niezainicjowanej wartości beta2_power'''' – JYun

Odpowiedz

138

Przede wszystkim, tf.train.GradientDescentOptimizer jest zaprojektowany do używania stałej szybkości uczenia się dla wszystkich zmiennych we wszystkich etapach. TensorFlow oferuje również gotowe optymalizatory adaptacyjne, w tym tf.train.AdagradOptimizer i tf.train.AdamOptimizer, które mogą być używane jako zamienniki.

Jednakże, jeśli chcesz kontrolować szybkość uczenia się, stosując gradienty waniliowe, możesz skorzystać z faktu, że argument learning_rate dla tf.train.GradientDescentOptimizer constructor może być obiektem Tensor. To pozwala obliczyć inną wartość dla nauki stopy w każdym kroku, na przykład:

learning_rate = tf.placeholder(tf.float32, shape=[]) 
# ... 
train_step = tf.train.GradientDescentOptimizer(
    learning_rate=learning_rate).minimize(mse) 

sess = tf.Session() 

# Feed different values for learning rate to each training step. 
sess.run(train_step, feed_dict={learning_rate: 0.1}) 
sess.run(train_step, feed_dict={learning_rate: 0.1}) 
sess.run(train_step, feed_dict={learning_rate: 0.01}) 
sess.run(train_step, feed_dict={learning_rate: 0.01}) 

Alternatywnie, można utworzyć skalarnego tf.Variable która posiada szybkość uczenia się, i przypisać go za każdym razem, gdy chcesz zmienić wskaźnik uczenia się.

+0

Świetna odpowiedź. Czy tę samą technikę można zastosować do obcinania gradientu? 'tf.clip_by_norm' nie akceptuje tensora dla normy clip, więc co powiesz na wykonanie' [(tf.minimum (gv [0], ct), gv [1]) dla gv w optimizer.compute_gradients (cost, vars)] ', gdzie' ct = tf.placeholder ('float32', shape = []) ' – richizy

+0

To powinno zadziałać, tak. (Chociaż patrząc na 'tf.clip_by_norm', jedyną rzeczą uniemożliwiającą przyjęcie tensora jako wejścia jest' constant_op.constant (1.0/clip_norm) '. Zastąpienie tego wyrażenia przez' math_ops.inv (clip_norm) 'sprawiłoby, że działałoby z elementem zastępczym (lub dowolnym innym tensorem).) – mrry

65

Tensorflow umożliwia automatyczne przeliczanie wykładnicze na tensor o współczynniku uczenia: tf.train.exponential_decay. Aby zapoznać się z jego przykładem, zobacz this line in the MNIST convolutional model example. Następnie użyj powyższej sugestii @ mrry, aby podać tę zmienną jako parametr value_rate do wybranego przez siebie optymalizatora.

Kluczowym fragmentem patrzeć na to:

# Optimizer: set up a variable that's incremented once per batch and 
# controls the learning rate decay. 
batch = tf.Variable(0) 

learning_rate = tf.train.exponential_decay(
    0.01,    # Base learning rate. 
    batch * BATCH_SIZE, # Current index into the dataset. 
    train_size,   # Decay step. 
    0.95,    # Decay rate. 
    staircase=True) 
# Use simple momentum for the optimization. 
optimizer = tf.train.MomentumOptimizer(learning_rate, 
            0.9).minimize(loss, 
                global_step=batch) 

Uwaga parametr global_step=batch aby zminimalizować. To mówi optymalizatorowi, że przy każdym treningu pomaga zwiększyć parametr "partia".

+0

Zazwyczaj zmienna, którą nazywasz 'batch' nazywa się' global_step' i jest kilka funkcji wygodnych, jedna do jej utworzenia 'tf.train.create_global_step()' (która po prostu tworzy liczbę całkowitą 'tf.Variable' i dodaje ją do kolekcji' tf.GraphKeys.GLOBAL_STEP' oraz 'tf.train.get_global_step()'. –

0

Od tensorflow oficjalne docs

global_step = tf.Variable(0, trainable=False) 
starter_learning_rate = 0.1 
learning_rate = tf.train.exponential_decay(starter_learning_rate, global_step, 
             100000, 0.96, staircase=True) 

# Passing global_step to minimize() will increment it at each step. 
learning_step = (
tf.train.GradientDescentOptimizer(learning_rate) 
.minimize(...my loss..., global_step=global_step)) 
+0

Ten link jest już martwy. –

43

Gradient algorytmu zejście wykorzystuje stałą szybkość uczenia się, które można dostarczyć w during the initialization. Możesz przekazać różne wskaźniki uczenia się w sposób pokazany przez Mrry'ego.

Ale zamiast tego można również użyć more advanced optimizers, które mają szybszy współczynnik konwergencji i dostosowują się do sytuacji.

Oto krótkie wyjaśnienie na podstawie mojego zrozumienia:

  • pędhelps SGD poruszać się wzdłuż odpowiednich kierunków i zmiękcza oscylacje w znaczenia. Po prostu dodaje ułamek kierunku z poprzedniego kroku do bieżącego kroku. Pozwala to uzyskać wzmocnienie prędkości we właściwym kierunku i zmiękcza oscylacje w niewłaściwych kierunkach. Ta frakcja zazwyczaj znajduje się w zakresie (0, 1). Sensowne jest także wykorzystanie dynamiki adaptacyjnej. Na początku nauki duży impet będzie tylko przeszkadzał waszemu postępowi, więc rozsądnie jest użyć czegoś podobnego do 0.01 i gdy znikną wszystkie wysokie gradienty, można użyć większej chwili. Jest jeden problem z rozmachem: kiedy jesteśmy bardzo blisko celu, nasz pęd w większości przypadków jest bardzo wysoki i nie wie, że powinien zwolnić.To może spowodować, że będzie chybiał albo oscyluje wokół minima
  • przyspieszony gradient nesterov pokonuje ten problem, zaczynając zwalniać wcześniej. W pędzie najpierw obliczamy gradient, a następnie wykonujemy skok w tym kierunku, wzmocniony jakimkolwiek rozmachem, jaki mieliśmy wcześniej. NAG robi to samo, ale w innej kolejności: najpierw wykonujemy duży skok w oparciu o nasze zapisane informacje, a następnie obliczamy gradient i wprowadzamy niewielką korektę. Ta pozornie nieistotna zmiana daje znaczne przyspieszenia praktyczne.
  • AdaGrad lub gradient adaptacyjny umożliwia dostosowanie szybkości uczenia się w oparciu o parametry. Wykonuje większe aktualizacje dla rzadkich parametrów i mniejszych aktualizacji dla częstych. Z tego powodu dobrze nadaje się do rozrzedzonych danych (NLP lub rozpoznawanie obrazu). Kolejną zaletą jest to, że w zasadzie obniża to potrzebę dostrojenia tempa uczenia się. Każdy parametr ma swoją własną szybkość uczenia się, a ze względu na specyfikę algorytmu szybkość uczenia się maleje monotonicznie. To powoduje największy problem: w pewnym momencie tempo uczenia się jest tak małe, że system przestaje się uczyć:
  • AdaDelta rozwiązuje problem monotonicznego zmniejszania wskaźnika uczenia się w AdaGrad. W AdaGrad wskaźnik uczenia się został obliczony w przybliżeniu jako jeden podzielony przez sumę pierwiastków kwadratowych. Na każdym etapie dodajemy kolejny pierwiastek kwadratowy do sumy, co powoduje, że mianownik stale się zmniejsza. W AdaDelta zamiast sumowania wszystkich przeszłych pierwiastków kwadratowych wykorzystuje okno przesuwne, które pozwala zmniejszyć sumę. RMSprop jest bardzo podobna do AdaDelta
  • Adama lub adaptacyjny algorytm pęd jest podobna do AdaDelta. Ale oprócz przechowywania ceny uczenia się dla każdego z parametrów także przechowuje zmiany tempa dla każdego z nich osobno

    few visualizations: enter image description here enter image description here

+1

fajne animacje! –

+1

Aby porównać różne optymalizatory w TensorFlow, spójrz na następujący notatnik na ipythonie: https://github.com/vsmolyakov/experiments_with_python/blob/master/chp03/tensorflow_optimizers.ipynb for –