GradientDescentOptimizer için uyarlanabilir öğrenme oranı nasıl ayarlanır?


104

Bir sinir ağını eğitmek için TensorFlow kullanıyorum. Ben şu şekilde başlatıyorum 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)

Buradaki şey, öğrenme oranı için bir güncelleme kuralı veya bunun için bir bozulma değerini nasıl belirleyeceğimi bilmediğimdir.

Burada uyarlanabilir bir öğrenme oranını nasıl kullanabilirim?


3
Optimize edicinizi belirledikten sonra tüm değişkenleri başlatmak iyi bir alışkanlıktır çünkü AdamOptimizer gibi bazı optimize ediciler, başlatılması gereken kendi değişkenlerini kullanır. Aksi takdirde şuna benzer bir hata alabilirsiniz:FailedPreconditionError (see above for traceback): Attempting to use uninitialized value beta2_power
JYun

Tensorflow'da yeni bir öğrenme oranı belirlemeye çalışırken yukarıda bahsedilen hatayı alıyorum tf.train.GradientDescentOptimizer(new_lr).minimize(loss). Görünüşe göre, yeni bir öğrenme oranı belirlemek, modeli zaten eğitilmiş değişkenlerle başlatmayı gerektirir. Ama bunu nasıl yapacağımı çözemiyorum.
Siladittya

Yanıtlar:


193

Her şeyden önce, tf.train.GradientDescentOptimizertüm adımlarda tüm değişkenler için sabit bir öğrenme oranı kullanmak üzere tasarlanmıştır. TensorFlow ayrıca tf.train.AdagradOptimizerve dahil olmak üzere kullanıma hazır uyarlanabilir optimize ediciler sağlar tf.train.AdamOptimizerve bunlar drop-in değiştirmeleri olarak kullanılabilir.

Eğer aksi-vanilya gradyan inişi ile öğrenme hızını kontrol etmek istiyorsanız Ancak, aslında yararlanabilirsiniz learning_rateargüman tf.train.GradientDescentOptimizeryapıcı bir olabilir Tensornesnesi. Bu, her adımda öğrenme oranı için farklı bir değer hesaplamanıza olanak tanır, örneğin:

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})

Alternatif olarak, tf.Variableöğrenme oranını tutan bir skaler oluşturabilir ve öğrenme oranını her değiştirmek istediğinizde bunu atayabilirsiniz.


Mükemmel cevap. Gradyan kırpma için aynı teknik kullanılabilir mi? tf.clip_by_normklip normu için bir tensör kabul etmiyor, peki ya yapmaya ne dersin [(tf.minimum(gv[0], ct), gv[1]) for gv in optimizer.compute_gradients(cost, vars)], neredect = tf.placeholder('float32', shape=[])
richizy

Bu işe yaramalı, evet. (Bakmasına rağmen tf.clip_by_norm, bir tensörü girdi olarak kabul etmesini engelleyen tek şey, constant_op.constant(1.0 / clip_norm)bu ifadenin yerine math_ops.inv(clip_norm)bir yer tutucu (veya başka bir tensör) girdisi ile çalışmasını sağlar.)
mrry

@mrry Dediğin gibi yaptım ve bazı antrenman hızı çok daha yavaş. Bu bekleniyor mu lütfen?
tnq177

89

Tensorflow otomatik bir öğrenme hızı tensörü için üstel çürüme uygulamak için bir op sağlamaktadır: tf.train.exponential_decay. Kullanımdaki bir örneği için, MNIST evrişimli model örneğindeki bu satıra bakın . Sonra bu değişkeni, tercih ettiğiniz optimize ediciye öğrenme_ hızı parametresi olarak sağlamak için @ mrry'nin yukarıdaki önerisini kullanın.

Bakılması gereken en önemli alıntı:

# 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)

En global_step=batchaza indirilecek parametreyi not edin . Bu, optimize edene, her eğitildiğinde sizin için "toplu" parametresini yararlı bir şekilde artırmasını söyler.


3
Genellikle, çağırdığınız değişken batchçağrılır global_stepve birkaç kolaylık işlevi vardır, biri onu oluşturmak için tf.train.create_global_step()(sadece bir tam sayı oluşturur tf.Variableve onu tf.GraphKeys.GLOBAL_STEPkoleksiyona ekler ) ve tf.train.get_global_step().
Lenar Hoyt

86

Gradyan iniş algoritması , başlatma sırasında sağlayabileceğiniz sabit öğrenme oranını kullanır . Mrry'nin gösterdiği şekilde çeşitli öğrenme oranlarını geçebilirsiniz.

Ancak bunun yerine daha hızlı yakınsama oranına sahip ve duruma uyum sağlayan daha gelişmiş optimize ediciler de kullanabilirsiniz .

İşte benim anlayışıma dayalı kısa bir açıklama:

  • momentum, SGD'nin ilgili yönlerde gezinmesine yardımcı olur ve ilgisizdeki salınımları yumuşatır. Sadece bir önceki adımın yönünün bir kısmını mevcut adıma ekler. Bu, doğru yönde hız artışı sağlar ve salınımı yanlış yönlerde yumuşatır. Bu kesir genellikle (0, 1) aralığındadır. Ayrıca uyarlanabilir momentum kullanmak mantıklıdır. Öğrenmenin başlangıcında, büyük bir ivme sadece ilerlemenizi engelleyecektir, bu nedenle 0.01 gibi bir şey kullanmak mantıklıdır ve tüm yüksek gradyanlar ortadan kalktığında daha büyük bir anı kullanabilirsiniz. Momentumla ilgili bir sorun var: Hedefe çok yaklaştığımızda, çoğu durumda momentumumuz çok yüksektir ve yavaşlaması gerektiğini bilmez. Bu, minimumları kaçırmasına veya salınmasına neden olabilir.
  • nesterov hızlandırılmış gradyan, erken yavaşlamaya başlayarak bu sorunun üstesinden gelir. Momentumda önce gradyanı hesaplıyoruz ve sonra daha önce sahip olduğumuz momentumla güçlendirilmiş o yönde bir sıçrama yapıyoruz. NAG aynı şeyi yapar ama başka bir sırayla: İlk önce sakladığımız bilgilere göre büyük bir sıçrama yaparız ve sonra gradyanı hesaplar ve küçük bir düzeltme yaparız. Görünüşte alakasız olan bu değişiklik, önemli pratik hızlanmalar sağlar.
  • AdaGrad veya uyarlanabilir gradyan, öğrenme hızının parametrelere göre uyarlanmasını sağlar. Sık olmayan parametreler için daha büyük güncellemeler ve sık olan için daha küçük güncellemeler gerçekleştirir. Bu nedenle, seyrek veriler (NLP veya görüntü tanıma) için çok uygundur. Diğer bir avantaj, temelde öğrenme oranını ayarlama ihtiyacını ortadan kaldırmasıdır. Her parametrenin kendi öğrenme oranı vardır ve algoritmanın özelliklerinden dolayı öğrenme hızı monoton olarak azalmaktadır. Bu, en büyük soruna neden olur: bir noktada öğrenme oranı o kadar küçüktür ki sistem öğrenmeyi durdurur
  • AdaDelta , AdaGrad'da monoton olarak azalan öğrenme oranını çözer. AdaGrad'da öğrenme oranı yaklaşık olarak bir bölü karekökler toplamı olarak hesaplandı. Her aşamada, toplama başka bir karekök eklersiniz, bu da paydanın sürekli olarak azalmasına neden olur. AdaDelta'da tüm geçmiş karekökleri toplamak yerine, toplamın azalmasını sağlayan kayan pencere kullanır. RMSprop , AdaDelta'ya çok benzer
  • Adam veya uyarlanabilir momentum, AdaDelta'ya benzer bir algoritmadır. Ancak, parametrelerin her biri için öğrenme oranlarını depolamanın yanı sıra, her biri için ayrı ayrı momentum değişikliklerini de kaydeder.

    Bir kaç görselleştirme : görüntü açıklamasını buraya girin görüntü açıklamasını buraya girin


2
TensorFlow'daki farklı optimize edicilerin karşılaştırması için aşağıdaki ipython not defterine bakın: github.com/vsmolyakov/experiments_with_python/blob/master/chp03/… için
Vadim Smolyakov

Daha gelişmiş optimize ediciler
Dima Lituiev

@DimaLituiev iki optimize ediciyi aynı anda kullanabilir misiniz? Hayır ise optimizer2 yerine optimizer1 kullanıyorsunuz demektir.
Salvador Dali

1
Söylediğim bu değil ve buradaki soru da bu değildi. Uyarlanabilir öğrenme oranı yerine gelişmiş optimize ediciler kullanmanızı önerirsiniz. Uyarlanabilir öğrenme hızına ek olarak gelişmiş optimize
edicileri

7

Gönderen tensorflow resmi dokümanlar

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

Gibi çağ aralıkları için belirli öğrenme oranları ayarlamak istiyorsanız 0 < a < b < c < .... Daha sonra, öğrenme oranınızı koşullu bir tensör olarak tanımlayabilir, küresel adıma bağlı olarak tanımlayabilir ve bunu normal bir şekilde iyileştiriciye besleyebilirsiniz.

Bunu bir dizi iç içe geçmiş tf.condifadeyle elde edebilirsiniz, ancak tensörü yinelemeli olarak oluşturmak daha kolaydır:

def make_learning_rate_tensor(reduction_steps, learning_rates, global_step):
    assert len(reduction_steps) + 1 == len(learning_rates)
    if len(reduction_steps) == 1:
        return tf.cond(
            global_step < reduction_steps[0],
            lambda: learning_rates[0],
            lambda: learning_rates[1]
        )
    else:
        return tf.cond(
            global_step < reduction_steps[0],
            lambda: learning_rates[0],
            lambda: make_learning_rate_tensor(
                reduction_steps[1:],
                learning_rates[1:],
                global_step,)
            )

Daha sonra bunu kullanmak için tek bir çağda kaç eğitim adımı olduğunu bilmeniz gerekir, böylece doğru zamanda geçiş yapmak için global adımı kullanabilir ve sonunda istediğiniz çağları ve öğrenme oranlarını tanımlayabiliriz. Dolayısıyla [0.1, 0.01, 0.001, 0.0001], [0, 19], [20, 59], [60, 99], [100, \infty]sırasıyla dönem aralıklarındaki öğrenme oranlarını istiyorsam , şunu yapardım:

global_step = tf.train.get_or_create_global_step()
learning_rates = [0.1, 0.01, 0.001, 0.0001]
steps_per_epoch = 225
epochs_to_switch_at = [20, 60, 100]
epochs_to_switch_at = [x*steps_per_epoch for x in epochs_to_switch_at ]
learning_rate = make_learning_rate_tensor(epochs_to_switch_at , learning_rates, global_step)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.