Öğ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 lr
ve ö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.0
Iken 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)
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:
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.Tensor
S. 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.