Bagaimana cara menyetel kecepatan pembelajaran adaptif untuk GradientDescentOptimizer?

104

Saya menggunakan TensorFlow untuk melatih jaringan neural. Ini adalah bagaimana saya menginisialisasi 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)

Masalahnya di sini adalah saya tidak tahu cara menyetel aturan pembaruan untuk kecepatan pemelajaran atau nilai peluruhan untuk itu.

Bagaimana cara menggunakan kecepatan pemelajaran adaptif di sini?

nama tampilan
sumber
3
Ini adalah kebiasaan yang baik untuk menginisialisasi semua variabel setelah Anda menentukan pengoptimal karena beberapa pengoptimal seperti AdamOptimizer menggunakan variabelnya sendiri yang juga perlu diinisialisasi. Jika tidak, Anda mungkin mendapatkan error yang terlihat seperti ini:FailedPreconditionError (see above for traceback): Attempting to use uninitialized value beta2_power
JYun
Saya mendapatkan kesalahan yang disebutkan di atas, ketika saya mencoba menyetel kecepatan pembelajaran baru di Tensorflow oleh tf.train.GradientDescentOptimizer(new_lr).minimize(loss). Tampaknya, menyetel kecepatan pemelajaran baru memerlukan inisialisasi model dengan variabel yang sudah dilatih. Tetapi tidak tahu bagaimana melakukan itu.
Siladittya

Jawaban:

193

Pertama-tama, tf.train.GradientDescentOptimizerdirancang untuk menggunakan kecepatan pembelajaran konstan untuk semua variabel di semua langkah. TensorFlow juga menyediakan pengoptimal adaptif out-of-the-box termasuk the tf.train.AdagradOptimizerdan the tf.train.AdamOptimizer, dan ini dapat digunakan sebagai pengganti drop-in.

Namun, jika Anda ingin mengontrol kecepatan pemelajaran dengan sebaliknya-penurunan gradien vanilla, Anda dapat memanfaatkan fakta bahwa learning_rateargumen ke tf.train.GradientDescentOptimizerkonstruktor dapat berupa Tensorobjek. Ini memungkinkan Anda menghitung nilai yang berbeda untuk kecepatan pembelajaran di setiap langkah, misalnya:

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

Atau, Anda dapat membuat skalar tf.Variableyang menahan kecepatan pembelajaran, dan menetapkannya setiap kali Anda ingin mengubah kecepatan pembelajaran.

mrry
sumber
Jawaban yang bagus. Dapatkah teknik yang sama digunakan untuk pemotongan gradien? tf.clip_by_normtidak menerima tensor untuk norma klip, jadi bagaimana dengan melakukan [(tf.minimum(gv[0], ct), gv[1]) for gv in optimizer.compute_gradients(cost, vars)], di manact = tf.placeholder('float32', shape=[])
richizy
Seharusnya itu berhasil, ya. (Meskipun melihat tf.clip_by_norm, satu-satunya hal yang mencegahnya menerima tensor sebagai input adalah constant_op.constant(1.0 / clip_norm). Mengganti ekspresi itu dengan math_ops.inv(clip_norm)akan membuatnya berfungsi dengan input placeholder (atau tensor lainnya).)
mrry
@mrry Saya melakukan apa yang Anda katakan dan beberapa bagaimana kecepatan pelatihan jauh lebih lambat. Apakah itu diharapkan?
tnq177
89

Tensorflow memberikan op untuk secara otomatis menerapkan peluruhan eksponensial ke tensor tingkat belajar: tf.train.exponential_decay. Untuk contoh yang digunakan, lihat baris ini dalam contoh model konvolusional MNIST . Kemudian gunakan saran @ mrry di atas untuk menyediakan variabel ini sebagai parameter learning_rate ke pengoptimal pilihan Anda.

Kutipan utama untuk dilihat adalah:

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

Perhatikan global_step=batchparameter yang akan diminimalkan. Itu memberi tahu pengoptimal untuk secara membantu menaikkan parameter 'batch' untuk Anda setiap kali berlatih.

dga
sumber
3
Biasanya, variabel yang Anda panggil batchdipanggil global_stepdan ada beberapa fungsi kemudahan, satu untuk membuatnya tf.train.create_global_step()(yang hanya membuat integer tf.Variabledan menambahkannya ke tf.GraphKeys.GLOBAL_STEPkoleksi) dan tf.train.get_global_step().
Lenar Hoyt
86

Algoritme penurunan gradien menggunakan kecepatan pemelajaran konstan yang dapat Anda berikan selama inisialisasi . Anda bisa lulus berbagai learning rate dengan cara yang ditunjukkan oleh Mrry.

Namun selain itu Anda juga dapat menggunakan pengoptimalan yang lebih canggih yang memiliki tingkat konvergensi lebih cepat dan menyesuaikan dengan situasi.

Berikut penjelasan singkat berdasarkan pemahaman saya:

  • momentum membantu SGD untuk menavigasi di sepanjang arah yang relevan dan memperhalus osilasi yang tidak relevan. Ini hanya menambahkan sebagian kecil dari arah langkah sebelumnya ke langkah saat ini. Ini mencapai amplifikasi kecepatan di arah yang benar dan melembutkan osilasi ke arah yang salah. Pecahan ini biasanya berada dalam kisaran (0, 1). Masuk akal juga untuk menggunakan momentum adaptif. Pada awal belajar, momentum besar hanya akan menghalangi kemajuan Anda, jadi masuk akal untuk menggunakan sesuatu seperti 0,01 dan setelah semua gradien tinggi menghilang, Anda dapat menggunakan momentum yang lebih besar. Ada satu masalah dengan momentum: ketika kita sangat dekat dengan tujuan, momentum kita dalam banyak kasus sangat tinggi dan tidak tahu bahwa momentum itu harus melambat. Hal ini dapat menyebabkannya meleset atau bergetar di sekitar minimum
  • Gradien dipercepat nesterov mengatasi masalah ini dengan mulai melambat lebih awal. Dalam momentum, pertama kita menghitung gradien dan kemudian membuat lompatan ke arah itu diperkuat oleh momentum apa pun yang kita miliki sebelumnya. NAG melakukan hal yang sama tetapi dalam urutan lain: pertama-tama kami membuat lompatan besar berdasarkan informasi yang kami simpan, lalu kami menghitung gradien dan membuat koreksi kecil. Perubahan yang tampaknya tidak relevan ini memberikan percepatan praktis yang signifikan.
  • AdaGrad atau gradien adaptif memungkinkan kecepatan pemelajaran beradaptasi berdasarkan parameter. Itu melakukan pembaruan yang lebih besar untuk parameter yang jarang dan pembaruan yang lebih kecil untuk yang sering. Karena itu, ini cocok untuk data renggang (NLP atau pengenalan gambar). Keuntungan lainnya adalah pada dasarnya hal ini menghilangkan kebutuhan untuk menyesuaikan kecepatan pembelajaran. Setiap parameter memiliki kecepatan pemelajaran sendiri dan karena kekhasan algoritme, kecepatan pemelajaran menurun secara monoton. Hal ini menyebabkan masalah terbesar: pada titik waktu kecepatan pemelajaran sangat kecil sehingga sistem berhenti belajar
  • AdaDelta mengatasi masalah penurunan kecepatan pembelajaran secara monoton di AdaGrad. Di AdaGrad, kecepatan pemelajaran dihitung kira-kira sebagai satu dibagi dengan jumlah akar kuadrat. Pada setiap tahap Anda menambahkan akar kuadrat lainnya ke penjumlahan, yang menyebabkan penyebut terus berkurang. Di AdaDelta alih-alih menjumlahkan semua akar kuadrat lampau, ia menggunakan jendela geser yang memungkinkan jumlahnya berkurang. RMSprop sangat mirip dengan AdaDelta
  • Adam atau momentum adaptif adalah algoritma yang mirip dengan AdaDelta. Namun selain menyimpan kecepatan pembelajaran untuk masing-masing parameter, juga menyimpan perubahan momentum untuk masing-masing parameter secara terpisah

    Sebuah beberapa visualisasi : masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini

Salvador Dali
sumber
2
Untuk perbandingan pengoptimal yang berbeda di TensorFlow, lihat notebook ipython berikut: github.com/vsmolyakov/experiments_with_python/blob/master/chp03/… untuk
Vadim Smolyakov
Pengoptimal yang lebih canggih tidak boleh diambil "sebagai gantinya" tetapi sebagai tambahan, lihat stats.stackexchange.com/questions/200063/…
Dima Lituiev
@DimaLituiev dapatkah Anda menggunakan dua pengoptimal secara bersamaan? Jika tidak, maka Anda menggunakan pengoptimal1 daripada pengoptimal2.
Salvador Dali
1
bukan itu yang saya katakan, dan bukan itu pertanyaannya di sini. Anda menyarankan untuk menggunakan pengoptimal lanjutan daripada kecepatan pembelajaran adaptif. Saya mengatakan Anda lebih suka menggunakan pengoptimal lanjutan selain kecepatan pembelajaran adaptif
Dima Lituiev
7

Dari dokumen resmi tensorflow

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))
Prakash Vanapalli
sumber
0

Jika Anda ingin menetapkan kecepatan pembelajaran khusus untuk interval zaman seperti 0 < a < b < c < .... Kemudian Anda dapat menentukan kecepatan pemelajaran Anda sebagai tensor bersyarat, bersyarat pada langkah global, dan memasukkannya seperti biasa ke pengoptimal.

Anda bisa mencapai ini dengan sekumpulan tf.condpernyataan bertingkat , tetapi lebih mudah untuk membangun tensor secara rekursif:

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

Kemudian untuk menggunakannya, Anda perlu mengetahui berapa banyak langkah pelatihan yang ada dalam satu epoch, sehingga kita dapat menggunakan langkah global untuk beralih pada waktu yang tepat, dan terakhir menentukan epoch dan kecepatan pembelajaran yang Anda inginkan. Jadi jika saya ingin kecepatan pembelajaran masing [0.1, 0.01, 0.001, 0.0001]- [0, 19], [20, 59], [60, 99], [100, \infty]masing selama interval periode , saya akan melakukan:

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)
Ben
sumber