Keras/TensorFlow PlatoBlockchain Veri Zekasında Kosinüs Bozulması ile Öğrenme Hızının Isınması. Dikey Arama. Ai.

Keras/TensorFlow'da Kosinüs Azalması ile Öğrenme Hızı Isınması

Öğrenme oranı, derin öğrenme ağlarında önemli bir hiperparametredir ve doğrudan derece verilen bazı kayıp fonksiyonlarını en aza indirdiği tahmin edilen ağırlık güncellemelerinin gerçekleştirildiği. SGD'de:

$$
ağırlık_{t+1} = ağırlık_t – lr * frac{derror}{dweight_t}
$$

öğrenme oranı ile 0, güncellenen ağırlık tekrar kendine geldi – ağırlıkt. Öğrenme hızı, öğrenmeyi etkinleştirmek veya devre dışı bırakmak için çevirebileceğimiz etkili bir düğmedir ve ağırlık güncellemelerinin derecesini doğrudan kontrol ederek, öğrenmenin ne kadar gerçekleştiği üzerinde büyük etkiye sahiptir.

Farklı optimize ediciler, öğrenme oranlarını farklı şekilde kullanır, ancak temel kavram aynı kalır. Söylemeye gerek yok, öğrenme oranları birçok çalışmanın, makalenin ve pratisyenlerin kıyaslamalarının konusu olmuştur.

Genel olarak konuşursak, hemen hemen herkes statik bir öğrenme oranının onu kesmeyeceği konusunda hemfikirdir ve eğitim sırasında öğrenme oranını ayarlayan çoğu teknikte bir tür öğrenme oranı düşüşü gerçekleşir - bu ister monoton, kosinüs, üçgen veya diğer tipte olsun. kesinti.

Son yıllarda yer edinen bir teknik, öğrenme hızı ısınması, pratik olarak diğer herhangi bir azaltma tekniği ile eşleştirilebilir.

Öğrenme Hızı Isınması

Öğrenme hızı ısıtmasının arkasındaki fikir basittir. Antrenmanın ilk aşamalarında ağırlıklar ideal hallerinden çok uzaktır. Bu, her bir ağırlık için "aşırı düzeltmeler" olarak görülebilen, tahtanın her yerinde büyük güncellemeler anlamına gelir - burada bir başkasının sert güncellemesi, başka bir ağırlığın güncellemesini geçersiz kılabilir ve eğitimin ilk aşamalarını daha kararsız hale getirebilir.

Bu değişiklikler ortadan kalkar, ancak başlangıçta küçük bir öğrenme hızına sahip olarak, daha istikrarlı bir optimumun altında duruma ulaşarak ve ardından daha büyük bir öğrenme oranı uygulayarak önlenebilir. Ağı, güncellemelerle vurmak yerine, bir şekilde kolaylaştırabilirsiniz.

Bu, öğrenme hızı ısınmasıdır! Düşük (veya 0) bir öğrenme oranıyla başlayıp, bir başlangıç ​​öğrenme oranına (zaten neyle başlarsanız) doğru artırın. Bu artış gerçekten herhangi bir işlevi takip edebilir, ancak genellikle doğrusaldır.

İlk hıza ulaştıktan sonra, hızı eğitimin sonuna kadar kademeli olarak düşürmek için kosinüs azalması, doğrusal azalma vb. gibi diğer programlar uygulanabilir. Öğrenme hızı ısıtması genellikle iki programlı bir programın parçasıdır; burada LR ısınması ilk, hız bir başlangıç ​​noktasına ulaştıktan sonra başka bir program devralır.

Bu kılavuzda, Keras/TensorFlow'da bir öğrenme hızı ısınması uygulayacağız. keras.optimizers.schedules.LearningRateSchedule alt sınıf ve keras.callbacks.Callback geri çağırmak. Öğrenme oranı artacak 0 için target_lr ve kosinüs bozunmasını uygulayın, çünkü bu çok yaygın bir ikincil programdır. Her zamanki gibi Keras, esnek çözümleri çeşitli şekillerde uygulamayı ve bunları ağınızla birlikte göndermeyi kolaylaştırır.

Not: Uygulama jeneriktir ve şunlardan esinlenmiştir: Tony'nin Keras uygulaması “ bölümünde belirtilen hilelerdenKonvolüsyonel Sinir Ağları ile Görüntü Sınıflandırma için Hileler Çantası”.

Keras Geri Aramalarıyla Öğrenme Oranı

Herhangi bir öğrenme oranı çizelgesini uygulamanın en basit yolu, lr parametre (float32), onu bir dönüşümden geçirir ve döndürür. Bu işlev daha sonra bilgisayara aktarılır. LearningRateScheduler işlevi öğrenme oranına uygulayan geri arama.

Şimdi, tf.keras.callbacks.LearningRateScheduler() oldukça kaba olan öğrenme oranını hesaplamak için kullandığı işleve dönem numarasını iletir. LR Isınma her adım (toplu), çağ değil, bu yüzden bir türetmemiz gerekecek global_step Bunun yerine öğrenme oranını hesaplamak için (tüm çağlarda) ve Callback Her çağrıda bağımsız değişkenleri iletmemiz gerekeceğinden, yalnızca işlevi iletirken imkansız olan, yalnızca işlevi iletmek yerine özel bir geri arama oluşturmak için class'ı kullanın:

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

Bu yaklaşım, yüksek düzeyde bir özelleştirme istemediğinizde ve Keras'ın lrve özellikle aşağıdaki gibi geri aramalar kullanmak istiyorsanız ReduceLROnPlateau() sadece bir float tabanlı ile çalışabildiğinden lr. Bir uygunluk işlevinden başlayarak bir Keras geri araması kullanarak bir öğrenme hızı ısınması uygulayalım:

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

Her adımda, öğrenme oranını ve ısınma öğrenme oranını (programın her iki öğesi) şuna göre hesaplarız: start_lr ve target_lr. start_lr genellikle başlayacak 0.0Iken target_lr ağınıza ve optimize edicinize bağlıdır – 1e-3 iyi bir varsayılan olmayabilir, bu nedenle yöntemi çağırırken LR ile başlayan hedefinizi ayarladığınızdan emin olun.

Eğer global_step eğitimde daha yüksek warmup_steps belirledik – kosinüs bozunma çizelgesi LR'yi kullanıyoruz. Değilse, hala ısınıyoruz demektir, bu nedenle ısınma LR kullanılır. Eğer hold argüman ayarlandı, tutacağız target_lr ısınmadan sonraki ve kosinüs bozulmasından önceki adım sayısı için. np.where() bunun için harika bir sözdizimi sağlar:

np.where(condition, value_if_true, value_if_false)

İşlevi şu şekilde görselleştirebilirsiniz:

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)

Şimdi, bu işlevi geri aramanın bir parçası olarak kullanmak ve optimize edici adımını global_step rastgele bir dizinin bir öğesi yerine - veya hesaplamayı sınıf içinde gerçekleştirebilirsiniz. alt sınıflara ayıralım Callback sınıf:

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)

En iyi uygulamalar, endüstri tarafından kabul edilen standartlar ve dahil edilen hile sayfası ile Git'i öğrenmek için uygulamalı, pratik kılavuzumuza göz atın. Googling Git komutlarını durdurun ve aslında öğrenmek o!

İlk olarak, sınıf için yapıcıyı tanımlar ve alanlarını takip ederiz. Biten her partide global adımı artıracağız, mevcut LR'yi not edeceğiz ve şimdiye kadarki LR listesine ekleyeceğiz. Her grubun başlangıcında – LR'yi aşağıdakini kullanarak hesaplayacağız: lr_warmup_cosine_decay() işlevini seçin ve bu LR'yi optimize edicinin geçerli LR'si olarak ayarlayın. Bu arka uç ile yapılır set_value().

Bunu yaptıktan sonra, yalnızca toplam adımları (uzunluk/batch_size*epochs) hesaplayın ve bu sayının bir kısmını sizin için alın. 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)

Son olarak, modelinizi oluşturun ve geri aramayı fit() telefon etmek:

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'])

Eğitimin sonunda, değiştirilen LR'leri şu yollarla elde edebilir ve görselleştirebilirsiniz:

lrs = callback.lrs 
plt.plot(lrs)

Keras/TensorFlow PlatoBlockchain Veri Zekasında Kosinüs Bozulması ile Öğrenme Hızının Isınması. Dikey Arama. Ai.

LR ısınması olan ve olmayan eğitilmiş bir modelin geçmişini çizerseniz, eğitimin kararlılığında belirgin bir fark görürsünüz:

Keras/TensorFlow PlatoBlockchain Veri Zekasında Kosinüs Bozulması ile Öğrenme Hızının Isınması. Dikey Arama. Ai.

LearningRateSchedule Alt Sınıfı ile Öğrenme Hızı

Geri arama oluşturmanın bir alternatifi, LearningRateSchedule LR'yi manipüle etmeyen alt sınıf - onun yerini alır. Bu yaklaşım, Keras/TensorFlow'un arka ucuna biraz daha girmenizi sağlar, ancak kullanıldığında, LR ile ilgili diğer geri aramalarla birleştirilemez, örneğin ReduceLROnPlateau(), LR'leri kayan noktalı sayılar olarak ele alır.

Ek olarak, alt sınıfı kullanmak, onu serileştirilebilir hale getirmenizi gerektirecektir (aşırı yükleme get_config()) model ağırlıklarını kaydetmek istiyorsanız, modelin bir parçası haline gelir. Unutulmaması gereken başka bir şey de, sınıfın yalnızca şunlarla çalışmayı bekleyeceğidir: tf.TensorS. Neyse ki, çalışma şeklimizdeki tek fark, telefon görüşmesi olacak. tf.func() yerine np.func() çünkü TensorFlow ve NumPy API'leri inanılmaz derecede benzer ve uyumludur.

Kolaylığı yeniden yazalım lr_warmup_cosine_decay() bunun yerine TensorFlow işlemlerini kullanmak için işlev:

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

Convinience fonksiyonu ile, LearningRateSchedule sınıf. Her birinde __call__() (toplu), işlevi kullanarak LR'yi hesaplayacağız ve onu döndüreceğiz. Hesaplamayı doğal olarak alt sınıflanmış sınıf içinde de paketleyebilirsiniz.

Sözdizimi şundan daha temizdir: Callback altküme, öncelikle erişim sağladığımız için step alanını kendi başımıza takip etmek yerine, aynı zamanda sınıf özellikleriyle çalışmayı biraz zorlaştırır - özellikle, ayıklamayı zorlaştırır. lr Bir gelen tf.Tensor() bir listede takip etmek için başka herhangi bir türe. Bu, istekli modda çalıştırılarak teknik olarak aşılabilir, ancak hata ayıklama amacıyla LR'yi takip etmek için bir sıkıntı oluşturur ve en iyi şekilde bundan kaçınılır:

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

Parametreler aynıdır ve öncekiyle hemen hemen aynı şekilde hesaplanabilir:


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)

Ve eğitim boru hattı, yalnızca optimize edicinin LR'sini şu şekilde ayarlamamızla farklılık gösterir: 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)

Modeli kaydetmek isterseniz, WarmupCosineDecay programın geçersiz kılması gerekecek get_config() yöntem:

    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

Son olarak, modeli yüklerken bir WarmupCosineDecay özel bir nesne olarak:

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

Sonuç

Bu kılavuzda, sinir ağlarını eğitirken öğrenme oranını manipüle etmek için yaygın bir teknik olan Learning Rate Warmup'ın arkasındaki sezgiye bir göz attık.

Isınma ile eşleştirilmiş en yaygın LR azaltma türü olan kosinüs bozunumlu bir öğrenme hızı ısınması uyguladık. Azaltma için başka herhangi bir işlevi uygulayabilir veya öğrenme oranını hiç düşürmeyebilirsiniz - bunu aşağıdakiler gibi diğer geri aramalara bırakın: ReduceLROnPlateau(). Öğrenme oranı ısınmasını bir Keras Geri Arama olarak ve ayrıca bir Keras Optimize Edici Takvimi olarak uyguladık ve çağlar boyunca öğrenme oranını çizdik.

Zaman Damgası:

Den fazla Yığın kötüye kullanımı