11.4. Rasgele Gradyan İnişi¶ Open the notebook in SageMaker Studio Lab
Daha önceki bölümlerde, eğitim prosedürümüzde rasgele gradyan inişi kullanmaya devam ettik, ancak, neden çalıştığını açıklamadık. Üzerine biraz ışık tutmak için, Section 11.3 içinde gradyan inişinin temel prensiplerini tanımladık. Bu bölümde, rasgele gradyan inişini daha ayrıntılı olarak tartışmaya devam ediyoruz.
%matplotlib inline
import math
from d2l import mxnet as d2l
from mxnet import np, npx
npx.set_np()
%matplotlib inline
import math
import torch
from d2l import torch as d2l
%matplotlib inline
import math
import tensorflow as tf
from d2l import tensorflow as d2l
11.4.1. Rasgele Gradyan Güncellemeleri¶
Derin öğrenmede, amaç işlevi genellikle eğitim veri kümelerindeki her örnek için kayıp fonksiyonlarının ortalamasıdır. \(n\) örnekten oluşan bir eğitim veri kümesi verildiğinde, \(f_i(\mathbf{x})\)’in \(i.\) dizindeki eğitim örneğine göre kayıp işlevi olduğunu varsayarız, burada \(\mathbf{x}\) parametre vektörüdür. Sonra şu amaç fonksiyonuna varırız
\(\mathbf{x}\)’teki amaç fonksiyonunun gradyanı böyle hesaplanır:
Gradyan inişi kullanılıyorsa, her bağımsız değişken yineleme için hesaplama maliyeti \(\mathcal{O}(n)\)’dir ve \(n\) ile doğrusal olarak büyür. Bu nedenle, eğitim veri kümesi daha büyük olduğunda, her yineleme için gradyan iniş maliyeti daha yüksek olacaktır.
Rasgele gradyan iniş (SGD), her yinelemede hesaplama maliyetini düşürür. Rasgele gradyan inişin her yinelemesinde, rastgele veri örnekleri için \(i\in\{1,\ldots, n\}\) dizinden eşit olarak örneklemleriz ve \(\mathbf{x}\)’i güncelleştirmek için \(\nabla f_i(\mathbf{x})\) gradyanını hesaplarız:
burada \(\eta\) öğrenme oranıdır. Her yineleme için gradyan inişinin hesaplama maliyetinin \(\mathcal{O}(n)\)’den \(\mathcal{O}(1)\) sabitine düştüğünü görebiliriz. Dahası, rasgele gradyan \(\nabla f_i(\mathbf{x})\)’in \(\nabla f(\mathbf{x})\)’in tam gradyanının tarafsız bir tahmini olduğunu vurgulamak istiyoruz, çünkü
Bu, ortalama olarak rasgele gradyanın, gradyanın iyi bir tahmini olduğu anlamına gelir.
Şimdi, bir rasgele gradyan inişini benzetmek için gradyana ortalaması 0 ve varyansı 1 olan rastgele gürültü ekleyerek gradyan inişiyle karşılaştıracağız.
def f(x1, x2): # Amaç fonksiyonu
return x1 ** 2 + 2 * x2 ** 2
def f_grad(x1, x2): # Amaç fonksiyonun gradyanı
return 2 * x1, 4 * x2
def sgd(x1, x2, s1, s2, f_grad):
g1, g2 = f_grad(x1, x2)
# Gürültülü gradyan benzetimi
g1 += np.random.normal(0.0, 1, (1,))
g2 += np.random.normal(0.0, 1, (1,))
eta_t = eta * lr()
return (x1 - eta_t * g1, x2 - eta_t * g2, 0, 0)
def constant_lr():
return 1
eta = 0.1
lr = constant_lr # Sabit öğrenme oranı
d2l.show_trace_2d(f, d2l.train_2d(sgd, steps=50, f_grad=f_grad))
epoch 50, x1: -0.472513, x2: 0.110780
/home/d2l-worker/miniconda3/envs/d2l-tr-release-0/lib/python3.9/site-packages/numpy/core/shape_base.py:65: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
ary = asanyarray(ary)
def f(x1, x2): # Amaç fonksiyonu
return x1 ** 2 + 2 * x2 ** 2
def f_grad(x1, x2): # Amaç fonksiyonun gradyanı
return 2 * x1, 4 * x2
def sgd(x1, x2, s1, s2, f_grad):
g1, g2 = f_grad(x1, x2)
# Gürültülü gradyan benzetimi
g1 += torch.normal(0.0, 1, (1,))
g2 += torch.normal(0.0, 1, (1,))
eta_t = eta * lr()
return (x1 - eta_t * g1, x2 - eta_t * g2, 0, 0)
def constant_lr():
return 1
eta = 0.1
lr = constant_lr # Sabit öğrenme oranı
d2l.show_trace_2d(f, d2l.train_2d(sgd, steps=50, f_grad=f_grad))
epoch 50, x1: 0.174384, x2: -0.102252
/home/d2l-worker/miniconda3/envs/d2l-tr-release-0/lib/python3.9/site-packages/numpy/core/shape_base.py:65: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
ary = asanyarray(ary)
/home/d2l-worker/miniconda3/envs/d2l-tr-release-0/lib/python3.9/site-packages/torch/functional.py:478: UserWarning: torch.meshgrid: in an upcoming release, it will be required to pass the indexing argument. (Triggered internally at ../aten/src/ATen/native/TensorShape.cpp:2895.)
return _VF.meshgrid(tensors, **kwargs) # type: ignore[attr-defined]
def f(x1, x2): # Amaç fonksiyonu
return x1 ** 2 + 2 * x2 ** 2
def f_grad(x1, x2): # Amaç fonksiyonun gradyanı
return 2 * x1, 4 * x2
def sgd(x1, x2, s1, s2, f_grad):
g1, g2 = f_grad(x1, x2)
# Gürültülü gradyan benzetimi
g1 += tf.random.normal([1], 0.0, 1)
g2 += tf.random.normal([1], 0.0, 1)
eta_t = eta * lr()
return (x1 - eta_t * g1, x2 - eta_t * g2, 0, 0)
def constant_lr():
return 1
eta = 0.1
lr = constant_lr # Sabit öğrenme oranı
d2l.show_trace_2d(f, d2l.train_2d(sgd, steps=50, f_grad=f_grad))
epoch 50, x1: 0.120303, x2: -0.076531
/home/d2l-worker/miniconda3/envs/d2l-tr-release-0/lib/python3.9/site-packages/numpy/core/shape_base.py:65: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
ary = asanyarray(ary)
Gördüğümüz gibi, rasgele gradyan inişindeki değişkenlerin yörüngesi, Section 11.3 içinde gradyan inişinde gözlemlediğimizden çok daha gürültülüdür. Bunun nedeni, gradyanın rasgele doğasından kaynaklanmaktadır. Yani, en düşük seviyeye yaklaştığımızda bile, \(\eta \nabla f_i(\mathbf{x})\) aracılığıyla anlık gradyan tarafından aşılanan belirsizliğe hala tabiyiz. 50 adımdan sonra bile kalite hala o kadar iyi değil. Daha da kötüsü, ek adımlardan sonra iyileşmeyecektir (bunu onaylamak için daha fazla sayıda adım denemenizi öneririz). Bu bize tek alternatif bırakır: Öğrenme oranı \(\eta\)’yı değiştirmek. Ancak, bunu çok küçük seçersek, ilkin bir ilerleme kaydetmeyeceğiz. Öte yandan, eğer çok büyük alırsak, yukarıda görüldüğü gibi iyi bir çözüm elde edemeyiz. Bu çelişkili hedefleri çözmenin tek yolu, optimizasyon ilerledikçe öğrenme oranını dinamik azaltmaktır.
Bu aynı zamanda sgd
adım işlevine lr
öğrenme hızı işlevinin
eklenmesinin de sebebidir. Yukarıdaki örnekte, ilişkili ‘lr’ işlevini
sabit olarak ayarladığımız için öğrenme hızı planlaması için herhangi
bir işlevsellik uykuda kalmaktadır.
11.4.2. Dinamik Öğrenme Oranı¶
\(\eta\)’nın zamana bağlı öğrenme hızı \(\eta(t)\) ile değiştirilmesi, optimizasyon algoritmasının yakınsamasını kontrol etmenin karmaşıklığını arttırır. Özellikle, \(\eta\)’nın ne kadar hızlı sönmesi gerektiğini bulmamız gerekiyor. Çok hızlıysa, eniyilemeyi erken bırakacağız. Eğer çok yavaş azaltırsak, optimizasyon için çok fazla zaman harcarız. Aşağıdakiler, \(\eta\)’nın zamanla ayarlanmasında kullanılan birkaç temel stratejidir (daha sonra daha gelişmiş stratejileri tartışacağız):
İlk parçalı sabit senaryosunda, öğrenme oranını düşürüyoruz, mesela optimizasyondaki ilerleme durduğunda. Bu, derin ağları eğitmek için yaygın bir stratejidir. Alternatif olarak çok daha saldırgan bir üstel sönüm ile azaltabiliriz. Ne yazık ki bu genellikle algoritma yakınsamadan önce erken durmaya yol açar. Popüler bir seçim, \(\alpha = 0.5\) ile polinom sönümdür. Dışbükey optimizasyon durumunda, bu oranın iyi davrandığını gösteren bir dizi kanıt vardır.
Üstel sönmenin pratikte neye benzediğini görelim.
def exponential_lr():
# Bu fonksiyonun dışında tanımlanan ve içinde güncellenen global değişken
global t
t += 1
return math.exp(-0.1 * t)
t = 1
lr = exponential_lr
d2l.show_trace_2d(f, d2l.train_2d(sgd, steps=1000, f_grad=f_grad))
epoch 1000, x1: -0.820458, x2: 0.004701
def exponential_lr():
# Bu fonksiyonun dışında tanımlanan ve içinde güncellenen global değişken
global t
t += 1
return math.exp(-0.1 * t)
t = 1
lr = exponential_lr
d2l.show_trace_2d(f, d2l.train_2d(sgd, steps=1000, f_grad=f_grad))
epoch 1000, x1: -0.895644, x2: -0.085209
def exponential_lr():
# Bu fonksiyonun dışında tanımlanan ve içinde güncellenen global değişken
global t
t += 1
return math.exp(-0.1 * t)
t = 1
lr = exponential_lr
d2l.show_trace_2d(f, d2l.train_2d(sgd, steps=1000, f_grad=f_grad))
epoch 1000, x1: -0.763287, x2: -0.058114
Beklendiği gibi, parametrelerdeki varyans önemli ölçüde azaltılır. Bununla birlikte, bu, \(\mathbf{x} = (0, 0)\) eniyi çözümüne yakınsamama pahasına gelir. Hatta sonra 1000 yineleme adımında sonra bile eniyi çözümden hala çok uzaktayız. Gerçekten de, algoritma yakınsamada tam anlamıyla başarısız. Öte yandan, öğrenme oranının adım sayısının ters karekökü ile söndüğü polinom sönmesi kullanırsak yakınsama sadece 50 adımdan sonra daha iyi olur.
def polynomial_lr():
# Bu fonksiyonun dışında tanımlanan ve içinde güncellenen global değişken
global t
t += 1
return (1 + 0.1 * t) ** (-0.5)
t = 1
lr = polynomial_lr
d2l.show_trace_2d(f, d2l.train_2d(sgd, steps=50, f_grad=f_grad))
epoch 50, x1: 0.025029, x2: 0.115820
def polynomial_lr():
# Bu fonksiyonun dışında tanımlanan ve içinde güncellenen global değişken
global t
t += 1
return (1 + 0.1 * t) ** (-0.5)
t = 1
lr = polynomial_lr
d2l.show_trace_2d(f, d2l.train_2d(sgd, steps=50, f_grad=f_grad))
epoch 50, x1: 0.123653, x2: 0.020916
def polynomial_lr():
# Bu fonksiyonun dışında tanımlanan ve içinde güncellenen global değişken
global t
t += 1
return (1 + 0.1 * t) ** (-0.5)
t = 1
lr = polynomial_lr
d2l.show_trace_2d(f, d2l.train_2d(sgd, steps=50, f_grad=f_grad))
epoch 50, x1: -0.119864, x2: -0.093422
Öğrenme oranının nasıl ayarlanacağı konusunda çok daha fazla seçenek var. Örneğin, küçük bir hızla başlayabilir, sonra hızlıca yükseltebilir ve daha yavaş da olsa tekrar azaltabiliriz. Hatta daha küçük ve daha büyük öğrenme oranları arasında geçiş yapabiliriz. Bu tür ayarlamaların çok çeşidi vardır. Şimdilik kapsamlı bir teorik analizin mümkün olduğu öğrenme oranı ayarlamalarına odaklanalım, yani dışbükey bir ortamda öğrenme oranları üzerine. Genel dışbükey olmayan problemler için anlamlı yakınsama garantileri elde etmek çok zordur, çünkü genel olarak doğrusal olmayan dışbükey problemlerin en aza indirilmesi NP zorludur. Bir araştırma için örneğin, Tibshirani’nin 2015’teki mükemmel ders notlarına bakınız.
11.4.3. Dışbükey Amaç İşlevleri için Yakınsaklık Analizi¶
Dışbükey amaç fonksiyonları için rasgele gradyan inişinin aşağıdaki yakınsama analizi isteğe bağlıdır ve öncelikle problem hakkında daha fazla sezgi iletmek için hizmet vermektedir. Kendimizi en basit kanıtlardan biriyle sınırlıyoruz (Nesterov and Vial, 2000). Önemli ölçüde daha gelişmiş ispat teknikleri mevcuttur, örn. amaç fonksiyonu özellikle iyi-huyluysa.
\(f(\boldsymbol{\xi}, \mathbf{x})\)’in amaç işlevinin \(\boldsymbol{\xi}\)’nin tümü için \(\mathbf{x}\)’de dışbükey olduğunu varsayalım. Daha somut olarak, rasgele gradyan iniş güncellemesini aklımızda bulunduruyoruz:
burada \(f(\boldsymbol{\xi}_t, \mathbf{x})\), bir dağılımdan \(t\) adımında çekilen \(\boldsymbol{\xi}_t\) eğitim örneğine göre amaç fonksiyonudur ve \(\mathbf{x}\) model parametresidir. Aşağıda
beklenen riski ifade eder ve \(R^*\), \(\mathbf{x}\)’e göre en düşük değerdir. Son olarak \(\mathbf{x}^*\) küçültücü (minimizer) olsun (\(\mathbf{x}\)’in tanımlandığı etki alanında var olduğunu varsayıyoruz). Bu durumda \(t\) zamanında \(\mathbf{x}_t\) ve risk küçültücü \(\mathbf{x}^*\) arasındaki mesafeyi izleyebilir ve zamanla iyileşip iyileşmediğini görebiliriz:
Rasgele gradyan \(\partial_\mathbf{x} f(\boldsymbol{\xi}_t, \mathbf{x})\)’in \(L_2\) normunun bir \(L\) sabiti ile sınırlandığını varsayıyoruz, dolayısıyla
Çoğunlukla \(\mathbf{x}_t\) ve \(\mathbf{x}^*\) arasındaki mesafenin beklentide nasıl değiştiğiyle ilgileniyoruz. Aslında, herhangi bir belirli adım dizisi için, karşılaştığımız herhangi \(\boldsymbol{\xi}_t\)’ye bağlı olarak mesafe artabilir. Bu yüzden nokta çarpımını sınırlamamız gerekiyor. Herhangi bir dışbükey fonksiyon \(f\) için \(f(\mathbf{y}) \geq f(\mathbf{x}) + \langle f'(\mathbf{x}), \mathbf{y} - \mathbf{x} \rangle\)’nin tüm \(\mathbf{x}\) ve \(\mathbf{y}\) için, dışbükeylik ile şuna varırız:
(11.4.9) ve (11.4.10) içindeki her iki eşitsizliği (11.4.8) denklemine yerleştirerek parametreler arasındaki mesafeye \(t+1\) zamanında aşağıdaki gibi sınır koyarız:
Bu, mevcut kayıp ile optimal kayıp arasındaki fark \(\eta_t L^2/2\)’ten ağır bastığı sürece ilerleme kaydettiğimiz anlamına gelir. Bu fark sıfıra yakınsamaya bağlı olduğundan, \(\eta_t\) öğrenme oranının da yok olması gerekir.
Sonrasında (11.4.11) üzerinden beklentileri alırız. Şu sonuca varırız:
Son adım \(t \in \{1, \ldots, T\}\) için eşitsizlikler üzerinde toplamayı içerir. Toplam içeriye daralır ve düşük terimi düşürürsek şunu elde ederiz:
\(\mathbf{x}_1\)’in verildiğini ve böylece beklentinin düştüğünü unutmayın. Son tanımımız
Çünkü
Jensen’in eşitsizliği ile (\(i=t\), (11.2.3) içinde \(\alpha_i = \eta_t/\sum_{t=1}^T \eta_t\) ayarlarız) ve \(R\) dışbükeyliği ile \(E[R(\mathbf{x}_t)] \geq E[R(\bar{\mathbf{x}})]\), şuna ulaşırız:
Bunu (11.4.13) eşitsizliğinin içine koymak aşağıdaki sınırı verir:
burada \(r^2 \stackrel{\mathrm{def}}{=} \|\mathbf{x}_1 - \mathbf{x}^*\|^2\), parametrelerin ilk seçimi ile nihai sonuç arasındaki mesafeye bağlıdır. Kısacası, yakınsama hızı, rasgele gradyanın normunun nasıl sınırlandığına (\(L\)) ve ilk parametre (\(r\)) değerinin eniyi değerden ne kadar uzakta olduğuna bağlıdır. Sınırın \(\mathbf{x}_T\) yerine \(\bar{\mathbf{x}}\) cinsinden olduğuna dikkat edin. \(\bar{\mathbf{x}}\)’in optimizasyon yolunun yumuşatılmış bir sürümü olduğu için bu durum böyledir. \(r, L\) ve \(T\) bilindiğinde öğrenme oranını \(\eta = r/(L \sqrt{T})\) alabiliriz. Bu, üst sınırı \(rL/\sqrt{T}\) olarak verir. Yani, \(\mathcal{O}(1/\sqrt{T})\) oranıyla eniyi çözüme yakınsıyoruz.
11.4.4. Rasgele Gradyanlar ve Sonlu Örnekler¶
Şimdiye kadar, rasgele gradyan inişi hakkında konuşurken biraz hızlı ve gevşek hareket ettik. \(x_i\) örneklerini, tipik olarak \(y_i\) etiketleriyle bazı \(p(x, y)\) dağılımlardan çektiğimizi ve bunu model parametrelerini bir şekilde güncellemek için kullandığımızı belirttik. Özellikle, sonlu bir örnek boyutu için \(p(x, y) = \frac{1}{n} \sum_{i=1}^n \delta_{x_i}(x) \delta_{y_i}(y)\) ayrık dağılımın olduğunu savunduk. Bazı \(\delta_{x_i}\) ve \(\delta_{y_i}\) fonksiyonları için üzerinde rasgele gradyan inişini gerçekleştirmemizi sağlar.
Ancak, gerçekten yaptığımız şey bu değildi. Mevcut bölümdeki basit örneklerde, aksi takdirde rasgele olmayan bir gradyana gürültü ekledik, yani \((x_i, y_i)\) çiftleri varmış gibi davrandık. Bunun burada haklı olduğu ortaya çıkıyor (ayrıntılı bir tartışma için alıştırmalara bakın). Daha rahatsız edici olan, önceki tüm tartışmalarda bunu açıkça yapmadığımızdır. Bunun neden tercih edilebilir olduğunu görmek için, tersini düşünün, yani ayrık dağılımdan değiştirmeli \(n\) gözlemleri örnekliyoruz. Rastgele \(i\) elemanını seçme olasılığı \(1/n\)’dır. Böylece onu en azından bir kez seçeriz:
Benzer bir akıl yürütme, bir numunenin (yani eğitim örneği) tam bir kez seçme olasılığının şöyle verildiğini göstermektedir:
Bu, değiştirmesiz örneklemeye göreceli oranla artan bir varyansa ve azalan veri verimliliğine yol açar. Bu nedenle, pratikte ikincisini gerçekleştiriyoruz (ve bu kitap boyunca varsayılan seçimdir). Son olarak eğitim veri kümesindeki tekrarlanan geçişler ondan farklı rastgele sırayla geçer.
11.4.5. Özet¶
Dışbükey problemler için, geniş bir öğrenme oranları seçeneği için rasgele gradyan inişinin eniyi çözüme yakınsayacağını kanıtlayabiliriz.
Derin öğrenme için bu genellikle böyle değildir. Bununla birlikte, dışbükey problemlerin analizi, optimizasyona nasıl yaklaşılacağına dair, yani öğrenme oranını çok hızlı olmasa da aşamalı olarak azaltmak için, bize yararlı bilgiler verir.
Öğrenme oranı çok küçük veya çok büyük olduğunda sorunlar ortaya çıkar. Pratikte uygun bir öğrenme oranı genellikle sadece birden fazla deneyden sonra bulunur.
Eğitim veri kümesinde daha fazla örnek olduğunda, gradyan inişi için her yinelemede hesaplamak daha pahalıya mal olur, bu nedenle bu durumlarda rasgele gradyan inişi tercih edilir.
Rasgele gradyan inişi için optimizasyon garantileri genel olarak dışbükey olmayan durumlarda mevcut değildir, çünkü kontrol gerektiren yerel minimum sayısı da üstel olabilir.
11.4.6. Alıştırmalar¶
Rasgele gradyan inişini farklı sayıda yineleme ile farklı öğrenme oranı düzenleri ile deneyin. Özellikle, yineleme sayısının bir fonksiyonu olarak optimal çözüm \((0, 0)\)’dan uzaklığı çizin.
\(f(x_1, x_2) = x_1^2 + 2 x_2^2\) işlevi için gradyana normal gürültü eklemenin bir kayıp işlevini \(f(\mathbf{x}, \mathbf{w}) = (x_1 - w_1)^2 + 2 (x_2 - w_2)^2\) en aza indirmeye eşdeğer olduğunu kanıtlayın, burada \(\mathbf{x}\) normal dağılımdan çekilmektedir.
\(\{(x_1, y_1), \ldots, (x_n, y_n)\}\)’ten değiştirmeli ve değiştirmesiz örnek aldığınızda rasgele gradyan inişinin yakınsamasını karşılaştırın.
Bir gradyan (veya onunla ilişkili bir koordinat) diğer tüm gradyanlardan tutarlı bir şekilde daha büyükse, rasgele gradyan inişi çözücüsünü nasıl değiştirirsiniz?
Bunu varsayalım: \(f(x) = x^2 (1 + \sin x)\). \(f\)’te kaç tane yerel minimum vardır? \(f\)’, en aza indirgemek için tüm yerel minimumları değerlendirmek zorunda kalacak şekilde değiştirebilir misiniz?