Pemanasan Kecepatan Pembelajaran dengan Peluruhan Cosine di Keras/TensorFlow PlatoBlockchain Data Intelligence. Pencarian Vertikal. Ai.

Pemanasan Tingkat Pembelajaran dengan Peluruhan Cosinus di Keras/TensorFlow

Tingkat pembelajaran adalah hyperparameter penting dalam jaringan pembelajaran mendalam – dan secara langsung menentukan gelar di mana pembaruan bobot dilakukan, yang diperkirakan meminimalkan beberapa fungsi kerugian yang diberikan. Dalam SGD:

$$
berat_{t+1} = berat_t – lr * frac{derror}{dweight_t}
$$

Dengan kecepatan belajar 0, bobot yang diperbarui baru saja kembali ke dirinya sendiri – beratt. Tingkat pembelajaran secara efektif merupakan tombol yang dapat kita putar untuk mengaktifkan atau menonaktifkan pembelajaran, dan memiliki pengaruh besar terhadap seberapa banyak pembelajaran yang terjadi, dengan secara langsung mengontrol tingkat pembaruan bobot.

Pengoptimal yang berbeda menggunakan kecepatan pembelajaran secara berbeda – tetapi konsep dasarnya tetap sama. Tak perlu dikatakan, kecepatan belajar telah menjadi objek dari banyak studi, makalah, dan tolok ukur praktisi.

Secara umum, hampir semua orang setuju bahwa kecepatan belajar statis tidak akan menguranginya, dan beberapa jenis pengurangan kecepatan belajar terjadi di sebagian besar teknik yang menyesuaikan kecepatan belajar selama pelatihan – apakah ini jenis monoton, kosinus, segitiga, atau lainnya. pengurangan.

Sebuah teknik yang dalam beberapa tahun terakhir telah mendapatkan pijakan adalah pemanasan tingkat pembelajaran, yang dapat dipasangkan dengan hampir semua teknik reduksi lainnya.

Pemanasan Tingkat Pembelajaran

Gagasan di balik pemanasan tingkat pembelajaran sederhana. Pada tahap awal pelatihan – bobot jauh dari kondisi idealnya. Ini berarti pembaruan besar di seluruh papan, yang dapat dilihat sebagai "koreksi berlebihan" untuk setiap bobot - di mana pembaruan drastis dari yang lain dapat meniadakan pembaruan dari beberapa bobot lainnya, membuat tahap awal pelatihan lebih tidak stabil.

Perubahan ini berhasil, tetapi dapat dihindari dengan memiliki tingkat belajar yang kecil untuk memulai, mencapai keadaan suboptimal yang lebih stabil, dan kemudian menerapkan tingkat belajar yang lebih besar. Anda dapat mengurutkan jaringan ke dalam pembaruan, daripada memukulnya dengan mereka.

Itu pemanasan tingkat pembelajaran! Dimulai dengan tingkat pembelajaran yang rendah (atau 0) dan meningkat ke tingkat pembelajaran awal (apa yang akan Anda mulai). Peningkatan ini benar-benar dapat mengikuti fungsi apa pun, tetapi umumnya linier.

Setelah mencapai laju awal, jadwal lain seperti peluruhan kosinus, reduksi linier, dll. dapat diterapkan untuk menurunkan laju secara progresif hingga akhir pelatihan. Pemanasan laju pembelajaran biasanya merupakan bagian dari jadwal dua jadwal, di mana pemanasan LR adalah yang pertama, sementara jadwal lain mengambil alih setelah laju mencapai titik awal.

Dalam panduan ini, kami akan menerapkan pemanasan kecepatan pembelajaran di Keras/TensorFlow sebagai keras.optimizers.schedules.LearningRateSchedule subkelas dan keras.callbacks.Callback panggilan balik. Tingkat pembelajaran akan meningkat dari 0 untuk target_lr dan menerapkan peluruhan kosinus, karena ini adalah jadwal sekunder yang sangat umum. Seperti biasa, Keras mempermudah penerapan solusi fleksibel dalam berbagai cara dan mengirimkannya dengan jaringan Anda.

Catatan: Implementasinya generik dan terinspirasi oleh Implementasi Keras Tony trik yang diuraikan dalam “Bag of Trik untuk Klasifikasi Gambar dengan Convolutional Neural Networks”.

Tingkat Pembelajaran dengan Keras Callback

Cara paling sederhana untuk menerapkan jadwal kecepatan pembelajaran apa pun adalah dengan membuat fungsi yang mengambil lr parameter (float32), melewatinya melalui beberapa transformasi, dan mengembalikannya. Fungsi ini kemudian diteruskan ke LearningRateScheduler callback, yang menerapkan fungsi ke kecepatan pembelajaran.

Sekarang, tf.keras.callbacks.LearningRateScheduler() meneruskan nomor Epoch ke fungsi yang digunakannya untuk menghitung tingkat pembelajaran, yang cukup kasar. Pemanasan LR harus dilakukan pada masing-masing langkah (batch), bukan epoch, jadi kita harus menurunkan a global_step (di semua zaman) untuk menghitung tingkat pembelajaran sebagai gantinya, dan mensubklasifikasikan Callback class untuk membuat panggilan balik khusus daripada hanya meneruskan fungsi, karena kita harus meneruskan argumen pada setiap panggilan, yang tidak mungkin jika hanya meneruskan fungsi:

def func():
    return ...
    
keras.callbacks.LearningRateScheduler(func)

Pendekatan ini menguntungkan bila Anda tidak menginginkan penyesuaian tingkat tinggi dan Anda tidak ingin mengganggu cara Keras memperlakukan lr, dan terutama jika Anda ingin menggunakan panggilan balik seperti ReduceLROnPlateau() karena itu hanya bisa bekerja dengan berbasis float lr. Mari kita terapkan pemanasan tingkat pembelajaran menggunakan panggilan balik Keras, dimulai dengan fungsi kenyamanan:

def lr_warmup_cosine_decay(global_step,
                           warmup_steps,
                           hold = 0,
                           total_steps=0,
                           start_lr=0.0,
                           target_lr=1e-3):
    
    learning_rate = 0.5 * target_lr * (1 + np.cos(np.pi * (global_step - warmup_steps - hold) / float(total_steps - warmup_steps - hold)))

    
    warmup_lr = target_lr * (global_step / warmup_steps)

    
    
    if hold > 0:
        learning_rate = np.where(global_step > warmup_steps + hold,
                                 learning_rate, target_lr)
    
    learning_rate = np.where(global_step < warmup_steps, warmup_lr, learning_rate)
    return learning_rate

Pada setiap langkah, kami menghitung laju pembelajaran dan laju pembelajaran pemanasan (kedua elemen jadwal), sehubungan dengan start_lr dan target_lr. start_lr biasanya akan dimulai pada 0.0, Sedangkan target_lr tergantung pada jaringan dan pengoptimal Anda – 1e-3 mungkin bukan default yang baik, jadi pastikan untuk menetapkan target Anda memulai LR saat memanggil metode.

Jika global_step dalam pelatihan lebih tinggi dari warmup_steps kami telah mengatur – kami menggunakan jadwal peluruhan kosinus LR. Jika tidak, berarti kita masih melakukan pemanasan, maka digunakan LR pemanasan. jika hold argumen diatur, kami akan menahan target_lr untuk jumlah langkah setelah pemanasan dan sebelum peluruhan kosinus. np.where() menyediakan sintaks yang bagus untuk ini:

np.where(condition, value_if_true, value_if_false)

Anda dapat memvisualisasikan fungsi dengan:

steps = np.arange(0, 1000, 1)
lrs = []

for step in steps:
  lrs.append(lr_warmup_cosine_decay(step, total_steps=len(steps), warmup_steps=100, hold=10))
plt.plot(lrs)

Sekarang, kita ingin menggunakan fungsi ini sebagai bagian dari panggilan balik, dan melewati langkah pengoptimal sebagai global_step daripada elemen array arbitrer - atau Anda dapat melakukan perhitungan di dalam kelas. Ayo subs Callback kelas:

from keras import backend as K

class WarmupCosineDecay(keras.callbacks.Callback):
    def __init__(self, total_steps=0, warmup_steps=0, start_lr=0.0, target_lr=1e-3, hold=0):

        super(WarmupCosineDecay, self).__init__()
        self.start_lr = start_lr
        self.hold = hold
        self.total_steps = total_steps
        self.global_step = 0
        self.target_lr = target_lr
        self.warmup_steps = warmup_steps
        self.lrs = []

    def on_batch_end(self, batch, logs=None):
        self.global_step = self.global_step + 1
        lr = model.optimizer.lr.numpy()
        self.lrs.append(lr)

    def on_batch_begin(self, batch, logs=None):
        lr = lr_warmup_cosine_decay(global_step=self.global_step,
                                    total_steps=self.total_steps,
                                    warmup_steps=self.warmup_steps,
                                    start_lr=self.start_lr,
                                    target_lr=self.target_lr,
                                    hold=self.hold)
        K.set_value(self.model.optimizer.lr, lr)

Lihat panduan praktis dan praktis kami untuk mempelajari Git, dengan praktik terbaik, standar yang diterima industri, dan termasuk lembar contekan. Hentikan perintah Googling Git dan sebenarnya belajar itu!

Pertama, kita mendefinisikan konstruktor untuk kelas dan melacak bidangnya. Pada setiap batch yang berakhir, kami akan meningkatkan langkah global, mencatat LR saat ini dan menambahkannya ke daftar LR sejauh ini. Pada awal setiap batch – kami akan menghitung LR menggunakan lr_warmup_cosine_decay() fungsi dan atur LR itu sebagai LR pengoptimal saat ini. Ini dilakukan dengan backend's set_value().

Setelah itu selesai – cukup hitung langkah total (panjang/batch_size*epoch) dan ambil sebagian dari angka itu untuk Anda warmup_steps:


total_steps = len(train_set)*config['EPOCHS']



warmup_steps = int(0.05*total_steps)

callback = WarmupCosineDecay(total_steps=total_steps, 
                             warmup_steps=warmup_steps,
                             hold=int(warmup_steps/2), 
                             start_lr=0.0, 
                             target_lr=1e-3)

Terakhir, buat model Anda dan berikan panggilan balik di fit() hubungi:

model = keras.applications.EfficientNetV2B0(weights=None, 
                                            classes=n_classes, 
                                            input_shape=[224, 224, 3])
  
model.compile(loss="sparse_categorical_crossentropy",
                  optimizer='adam',
                  jit_compile=True,
                  metrics=['accuracy'])

Di akhir pelatihan, Anda dapat memperoleh dan memvisualisasikan LR yang diubah melalui:

lrs = callback.lrs 
plt.plot(lrs)

Pemanasan Kecepatan Pembelajaran dengan Peluruhan Cosine di Keras/TensorFlow PlatoBlockchain Data Intelligence. Pencarian Vertikal. Ai.

Jika Anda memplot sejarah model yang dilatih dengan dan tanpa pemanasan LR – Anda akan melihat perbedaan nyata dalam stabilitas latihan:

Pemanasan Kecepatan Pembelajaran dengan Peluruhan Cosine di Keras/TensorFlow PlatoBlockchain Data Intelligence. Pencarian Vertikal. Ai.

Tingkat Pembelajaran dengan Subkelas LearningRateSchedule

Alternatif untuk membuat panggilan balik adalah dengan membuat LearningRateSchedule subclass, yang tidak memanipulasi LR – ia menggantikannya. Pendekatan ini memungkinkan Anda untuk mendorong sedikit lebih banyak ke backend Keras/TensorFlow, tetapi ketika digunakan, tidak dapat digabungkan dengan callback terkait LR lainnya, seperti ReduceLROnPlateau(), yang berhubungan dengan LR sebagai angka floating point.

Selain itu, menggunakan subkelas akan mengharuskan Anda untuk membuatnya serial (overload get_config()) karena menjadi bagian dari model, jika Anda ingin menyimpan bobot model. Hal lain yang perlu diperhatikan adalah bahwa kelas akan berharap untuk bekerja secara eksklusif dengan tf.Tensors. Untungnya, satu-satunya perbedaan dalam cara kami bekerja adalah menelepon tf.func() alih-alih np.func() karena TensorFlow dan NumPy API sangat mirip dan kompatibel.

Mari kita tulis ulang kenyamanan lr_warmup_cosine_decay() fungsi untuk menggunakan operasi TensorFlow sebagai gantinya:

def lr_warmup_cosine_decay(global_step,
                           warmup_steps,
                           hold = 0,
                           total_steps=0,
                           start_lr=0.0,
                           target_lr=1e-3):
    
    
    learning_rate = 0.5 * target_lr * (1 + tf.cos(tf.constant(np.pi) * (global_step - warmup_steps - hold) / float(total_steps - warmup_steps - hold)))

    
    warmup_lr = target_lr * (global_step / warmup_steps)

    
    
    if hold > 0:
        learning_rate = tf.where(global_step > warmup_steps + hold,
                                 learning_rate, target_lr)
    
    learning_rate = tf.where(global_step < warmup_steps, warmup_lr, learning_rate)
    return learning_rate

Dengan fungsi kenyamanan, kita dapat mensubklasifikasikan LearningRateSchedule kelas. Pada setiap __call__() (batch), kami akan menghitung LR menggunakan fungsi dan mengembalikannya. Anda secara alami dapat mengemas perhitungan di dalam kelas subkelas juga.

Sintaksnya lebih bersih daripada Callback sublcass, terutama karena kami mendapatkan akses ke step lapangan, daripada melacaknya sendiri, tetapi juga membuatnya agak sulit untuk bekerja dengan properti kelas - khususnya, itu membuat sulit untuk mengekstrak lr dari tf.Tensor() ke dalam jenis lain untuk melacak dalam daftar. Hal ini secara teknis dapat dielakkan dengan menjalankan dalam mode bersemangat, tetapi menghadirkan gangguan untuk melacak LR untuk tujuan debugging dan sebaiknya dihindari:

class WarmUpCosineDecay(keras.optimizers.schedules.LearningRateSchedule):
    def __init__(self, start_lr, target_lr, warmup_steps, total_steps, hold):
        super().__init__()
        self.start_lr = start_lr
        self.target_lr = target_lr
        self.warmup_steps = warmup_steps
        self.total_steps = total_steps
        self.hold = hold

    def __call__(self, step):
        lr = lr_warmup_cosine_decay(global_step=step,
                                    total_steps=self.total_steps,
                                    warmup_steps=self.warmup_steps,
                                    start_lr=self.start_lr,
                                    target_lr=self.target_lr,
                                    hold=self.hold)

        return tf.where(
            step > self.total_steps, 0.0, lr, name="learning_rate"
        )

Parameternya sama, dan dapat dihitung dengan cara yang hampir sama seperti sebelumnya:


total_steps = len(train_set)*config['EPOCHS']



warmup_steps = int(0.05*total_steps)

schedule = WarmUpCosineDecay(start_lr=0.0, target_lr=1e-3, warmup_steps=warmup_steps, total_steps=total_steps, hold=warmup_steps)

Dan jalur pelatihan hanya berbeda karena kami menyetel LR pengoptimal ke schedule:

model = keras.applications.EfficientNetV2B0(weights=None, 
                                            classes=n_classes, 
                                            input_shape=[224, 224, 3])
  
model.compile(loss="sparse_categorical_crossentropy",
                  optimizer=tf.keras.optimizers.Adam(learning_rate=schedule),
                  jit_compile=True,
                  metrics=['accuracy'])

history3 = model.fit(train_set,
                    epochs = config['EPOCHS'],
                    validation_data=valid_set)

Jika Anda ingin menyimpan model, WarmupCosineDecay jadwal harus menimpa get_config() Metode:

    def get_config(self):
        config = {
          'start_lr': self.start_lr,
          'target_lr': self.target_lr,
          'warmup_steps': self.warmup_steps,
          'total_steps': self.total_steps,
          'hold': self.hold
        }
        return config

Akhirnya, saat memuat model, Anda harus melewati a WarmupCosineDecay sebagai objek khusus:

model = keras.models.load_model('weights.h5', 
                                custom_objects={'WarmupCosineDecay', WarmupCosineDecay})

Kesimpulan

Dalam panduan ini, kita telah melihat intuisi di balik Pemanasan Kecepatan Pembelajaran – teknik umum untuk memanipulasi kecepatan pembelajaran saat melatih jaringan saraf.

Kami telah menerapkan pemanasan tingkat pembelajaran dengan peluruhan kosinus, jenis pengurangan LR yang paling umum dipasangkan dengan pemanasan. Anda dapat menerapkan fungsi lain apa pun untuk pengurangan, atau tidak mengurangi kecepatan pembelajaran sama sekali – menyerahkannya ke panggilan balik lain seperti ReduceLROnPlateau(). Kami telah menerapkan pemanasan laju pembelajaran sebagai Panggilan Balik Keras, serta Jadwal Pengoptimal Keras dan memplot laju pembelajaran melalui zaman.

Stempel Waktu:

Lebih dari penyalahgunaan