7-bo‘lim
Hosila va gradient
Hosila - o'zgarish tezligi; gradient - eng tik yo'nalish. Ikkalasini kodda hisoblab ko'ramiz.
Ushbu bo‘lim mundarijasi
Yo'qotishni o'lchashni o'rgandik. Endi savol: uni kamaytirish uchun og'irliklarni qaysi tomonga siljitish kerak? Javob - hosilada.
Hosila - o'zgarish tezligi #
Hosila bitta savolga javob beradi: "x ni juda kichik
miqdorga oshirsam, f(x) qanchaga o'zgaradi?"
import numpy as np
def f(x):
return x ** 2
x = 3.0
h = 1e-6
ozgarish = (f(x + h) - f(x)) / h
print("f(3) =", f(x))
print("f(3.000001) =", f(x + h))
print("o'zgarish tezligi ≈", round(ozgarish, 4))
print("formula 2x =", 2 * x)
f(3) = 9.0
f(3.000001) = 9.000006000001001
o'zgarish tezligi ≈ 6.0
formula 2x = 6.0
x = 3 nuqtada funksiya x dan olti barobar tez
o'sadi.
def f(x):
return x ** 2
def hosila_sonli(fn, x, h=1e-6):
return (fn(x + h) - fn(x - h)) / (2 * h)
for x in [-3.0, -1.0, 0.0, 1.0, 3.0]:
q = hosila_sonli(f, x)
yonalish = "o'sadi" if q > 0 else ("kamayadi" if q < 0 else "tekis")
print(f"x = {x:>5.1f} hosila = {q:>6.2f} o'ngga yursak {yonalish}")
x = -3.0 hosila = -6.00 o'ngga yursak kamayadi
x = -1.0 hosila = -2.00 o'ngga yursak kamayadi
x = 0.0 hosila = 0.00 o'ngga yursak tekis
x = 1.0 hosila = 2.00 o'ngga yursak o'sadi
x = 3.0 hosila = 6.00 o'ngga yursak o'sadi
Bu gradient tushishning butun g'oyasi:
| Hosila | Nima qilish kerak |
|---|---|
Musbat (+6) | x ni kamaytirish |
Manfiy (-6) | x ni oshirish |
| Nol | Allaqachon eng past nuqtada |
Ikkala holatni bitta formula qamrab oladi:
x_yangi = x - tezlik · hosila
Musbat hosilada x kamayadi, manfiyda esa oshadi - chunki
manfiy sondan ayirish qo'shishga teng.
8-bo'limda aynan shu bitta satrni tarmoqning barcha og'irliklariga qo'llaymiz.
Zanjir qoidasi #
Funksiyalar ichma-ich bo'lganda hosilalar ko'paytiriladi.
y = f(g(x)) => dy/dx = f'(g(x)) · g'(x)
def ichki(x):
return 3 * x + 1
def tashqi(u):
return u ** 2
def togri_funksiya(x):
return tashqi(ichki(x))
def hosila_sonli(fn, x, h=1e-6):
return (fn(x + h) - fn(x - h)) / (2 * h)
x = 2.0
sonli = hosila_sonli(togri_funksiya, x)
zanjir = 2 * ichki(x) * 3 # f'(g) · g'
print("f(g(2)) =", togri_funksiya(x))
print("sonli hosila:", round(sonli, 6))
print("zanjir qoidasi:", zanjir)
print("mos keladi:", bool(np.isclose(sonli, zanjir, atol=1e-4)))
f(g(2)) = 49.0
sonli hosila: 42.0
zanjir qoidasi: 42.0
mos keladi: True
Neyron tarmoq - bu juda uzun ichma-ich funksiya:
L( sigmoid( W2 @ relu( W1 @ X + b1 ) + b2 ), y )
W1 ning yo'qotishga ta'sirini topish uchun zanjir bo'ylab
orqaga yurish kerak:
dL/dW1 = dL/dA2 · dA2/dZ2 · dZ2/dA1 · dA1/dZ1 · dZ1/dW1
Beshta hosila ko'paytiriladi - va aynan shu orqaga tarqalish (backpropagation) deb ataladi.
Bu 4-bo'limdagi yo'qolayotgan gradient muammosining ham
sababi: agar har ko'paytuvchi 1 dan kichik bo'lsa,
ko'paytma tez nolga intiladi.
9-bo'limda bu zanjirni qadam-baqadam quramiz.
Ko'p o'zgaruvchili funksiya: gradient #
Bir necha o'zgaruvchi bo'lganda har biri bo'yicha alohida hosila olinadi. Ular birgalikda gradient vektorini tashkil qiladi.
def yigindi(v):
x, y = v
return x ** 2 + 3 * y ** 2
def gradient_sonli(fn, v, h=1e-6):
g = np.zeros_like(v)
for i in range(len(v)):
oldinga = v.copy(); oldinga[i] += h
orqaga = v.copy(); orqaga[i] -= h
g[i] = (fn(oldinga) - fn(orqaga)) / (2 * h)
return g
nuqta = np.array([2.0, 1.0])
g = gradient_sonli(yigindi, nuqta)
print("f(2, 1) =", yigindi(nuqta))
print("gradient:", np.round(g, 4))
print("formula [2x, 6y]:", [2 * 2.0, 6 * 1.0])
f(2, 1) = 7.0
gradient: [4. 6.]
formula [2x, 6y]: [4.0, 6.0]
| Komponent | Ma'nosi |
|---|---|
4 | x ni oshirish f ni 4 barobar tez oshiradi |
6 | y ni oshirish f ni 6 barobar tez oshiradi |
| Yo'nalish | [4, 6] - eng tik ko'tarilish tomoni |
| Teskarisi | [-4, -6] - eng tik tushish tomoni |
Gradient f ni eng tez oshiradigan yo'nalishni beradi.
Uning teskarisi - eng tez kamaytiradigan yo'nalish.
Lekin bu "to'g'ridan-to'g'ri eng past nuqtaga" degani emas. Gradient faqat joriy nuqtadagi mahalliy ma'lumot.
Vodiy shaklidagi funksiyada gradient tushish zigzag bilan yuradi: har qadamda u eng tik tomonga qaraydi, lekin eng tik tomon vodiyning tubiga emas, uning devoriga qarab turadi.
Bu 15-bo'limdagi momentum va Adam optimizatorlarining mavjud bo'lish sababi - ular shu zigzagni yumshatadi.
Analitik va sonli gradient #
def yoqotish(w):
"""Oddiy misol: bitta og'irlikli chiziqli model."""
X = np.array([1.0, 2.0, 3.0])
y = np.array([2.0, 4.0, 6.0])
bashorat = w * X
return float(np.mean((bashorat - y) ** 2))
def analitik_gradient(w):
X = np.array([1.0, 2.0, 3.0])
y = np.array([2.0, 4.0, 6.0])
return float(np.mean(2 * (w * X - y) * X))
for w in [0.0, 1.0, 2.0, 3.0]:
h = 1e-6
sonli = (yoqotish(w + h) - yoqotish(w - h)) / (2 * h)
print(f"w = {w:.1f} yo'qotish = {yoqotish(w):>7.3f} "
f"sonli = {sonli:>8.4f} analitik = {analitik_gradient(w):>8.4f}")
w = 0.0 yo'qotish = 18.667 sonli = -18.6667 analitik = -18.6667
w = 1.0 yo'qotish = 4.667 sonli = -9.3333 analitik = -9.3333
w = 2.0 yo'qotish = 0.000 sonli = 0.0000 analitik = 0.0000
w = 3.0 yo'qotish = 4.667 sonli = 9.3333 analitik = 9.3333
w = 2 da yo'qotish nol va gradient ham nol - bu eng
past nuqta. Ma'lumot aynan y = 2x bo'lgani uchun bu
kutilgan natija.
Sonli gradient formulani tekshirish uchun ajoyib, lekin o'qitishda ishlatib bo'lmaydi.
Sabab - narx:
| Usul | Har qadamda nechta hisob |
|---|---|
| Sonli | Har parametr uchun ikkita to'liq oldinga tarqalish |
| Analitik (backprop) | Bitta oldinga + bitta orqaga |
Million parametrli tarmoqda sonli gradient bir qadam uchun ikki million oldinga tarqalish talab qiladi. Bu amalda imkonsiz.
Backpropagation ning butun qiymati shunda: u barcha gradientlarni bitta o'tishda hisoblaydi.
Shuning uchun tartib shunday: backprop ni yozing, sonli gradient bilan bir marta tekshiring, keyin tekshiruvni o'chiring.
import time
def yoqotish_kop(w):
"""50 ta og'irlikning o'rtachasi bilan bashorat qiladigan model."""
X = np.arange(1.0, 51.0)
y = 2.0 * X
return float(np.mean((np.mean(w) * X - y) ** 2))
w = np.full(50, 1.0)
h = 1e-6
boshlandi = time.perf_counter()
sonli = np.zeros(50)
for i in range(50):
ol = w.copy(); ol[i] += h
or_ = w.copy(); or_[i] -= h
sonli[i] = (yoqotish_kop(ol) - yoqotish_kop(or_)) / (2 * h)
sonli_vaqt = time.perf_counter() - boshlandi
print("50 parametr uchun sonli gradient:", 2 * 50, "ta funksiya chaqiruvi")
print("gradient birinchi 3 element:", np.round(sonli[:3], 4))
print("hammasi bir xilmi:", bool(np.allclose(sonli, sonli[0])))
50 parametr uchun sonli gradient: 100 ta funksiya chaqiruvi
gradient birinchi 3 element: [-34.34 -34.34 -34.34]
hammasi bir xilmi: True
Gradient tekshiruvi funksiyasi #
def gradient_tekshir(yoqotish_fn, gradient_fn, parametr, h=1e-6, chegara=1e-5):
analitik = gradient_fn(parametr)
sonli = np.zeros_like(parametr, dtype=np.float64)
tekis = parametr.ravel()
sonli_tekis = sonli.ravel()
for i in range(tekis.size):
eski = tekis[i]
tekis[i] = eski + h
yuqori = yoqotish_fn(parametr)
tekis[i] = eski - h
past = yoqotish_fn(parametr)
tekis[i] = eski
sonli_tekis[i] = (yuqori - past) / (2 * h)
ayirma = np.abs(analitik - sonli).max()
return ayirma < chegara, ayirma
def yoqotish_v(w):
X = np.array([[1.0, 2.0], [3.0, 1.0], [0.5, 2.0]])
y = np.array([5.0, 5.0, 4.5])
return float(np.mean((X @ w - y) ** 2))
def gradient_v(w):
X = np.array([[1.0, 2.0], [3.0, 1.0], [0.5, 2.0]])
y = np.array([5.0, 5.0, 4.5])
return 2.0 / len(y) * X.T @ (X @ w - y)
w = np.array([0.7, 1.3])
mos, ayirma = gradient_tekshir(yoqotish_v, gradient_v, w)
print("analitik gradient:", np.round(gradient_v(w), 6))
print("mos keladimi:", mos)
print("eng katta ayirma:", f"{ayirma:.2e}")
analitik gradient: [-4.85 -5.4 ]
mos keladimi: True
eng katta ayirma: 4.00e-10
1e-5 chegarasiAyirma 3.31e-10 chiqdi - bu juda yaxshi.
Amaliy mo'ljallar:
| Ayirma | Xulosa |
|---|---|
< 1e-7 | Deyarli aniq to'g'ri |
1e-7 dan 1e-5 gacha | Odatda to'g'ri |
1e-5 dan 1e-3 gacha | Shubhali - tekshiring |
> 1e-3 | Formulada xato bor |
Nisbiy ayirmani ishlatish yanada ishonchli:
|analitik - sonli| / (|analitik| + |sonli|)
Chunki gradient kattaligi 1000 bo'lsa, 1e-5 mutlaq
ayirma aslida juda kichik nisbiy xato.
Muhim ogohlantirish: ReLU bilan gradient tekshiruvi z = 0
atrofida yiqilishi mumkin - u yerda hosila sakraydi.
Tekshiruvni tasodifiy nuqtalarda bajaring va bitta-ikkita
mos kelmagan qiymatga e'tibor bermang.
Bir qadam gradient tushish #
def yoqotish(w):
X = np.array([1.0, 2.0, 3.0])
y = np.array([2.0, 4.0, 6.0])
return float(np.mean((w * X - y) ** 2))
def gradient(w):
X = np.array([1.0, 2.0, 3.0])
y = np.array([2.0, 4.0, 6.0])
return float(np.mean(2 * (w * X - y) * X))
w = 0.0
tezlik = 0.05
for qadam in range(6):
g = gradient(w)
print(f"qadam {qadam}: w = {w:>7.4f} yo'qotish = {yoqotish(w):>8.4f} gradient = {g:>9.4f}")
w = w - tezlik * g
qadam 0: w = 0.0000 yo'qotish = 18.6667 gradient = -18.6667
qadam 1: w = 0.9333 yo'qotish = 5.3096 gradient = -9.9556
qadam 2: w = 1.4311 yo'qotish = 1.5103 gradient = -5.3096
qadam 3: w = 1.6966 yo'qotish = 0.4296 gradient = -2.8318
qadam 4: w = 1.8382 yo'qotish = 0.1222 gradient = -1.5103
qadam 5: w = 1.9137 yo'qotish = 0.0348 gradient = -0.8055
w 2.0 ga yaqinlashmoqda, yo'qotish esa har qadamda
taxminan uch-to'rt barobar kamayyapti - lekin qadamlar
ham kichrayib boryapti, chunki gradient nolga yaqinlashadi.
f(x) = x²uchunx = 3da sonli hosilani hisoblang.- Uni
2xformulasi bilan solishtiring. - Beshta nuqtada hosila ishorasini va ma'nosini tushuntiring.
- Zanjir qoidasini
(3x+1)²misolida tekshiring. - Ikki o'zgaruvchili funksiyaning gradientini soniy hisoblang.
- Gradientning ikki komponenti nimani anglatishini ayting.
- Analitik va sonli gradientni to'rtta
wqiymatida solishtiring. - Sonli gradient nima uchun o'qitishga yaramasligini hisoblang.
gradient_tekshirfunksiyasini yozing va ayirmani chop eting.- Olti qadam gradient tushish bajarib,
wning yo'lini kuzating.
Xulosa #
- Hosila - o'zgarish tezligi, ya'ni urinma chiziqning qiyaligi.
- Kamaytirish uchun hosilaga teskari yuring.
x_yangi = x - tezlik · hosila- bitta formula ikkala holatni qamraydi.- Zanjir qoidasi: ichma-ich funksiyalarda hosilalar ko'paytiriladi.
- Tarmoq - uzun ichma-ich funksiya; backprop - zanjir qoidasi.
- Gradient - har parametr bo'yicha hosilalar vektori.
- Gradient eng tik yo'nalish, lekin eng past nuqtaga qaramaydi.
- Sonli gradient - tekshirish uchun, o'qitish uchun emas.
- Ayirma
1e-5dan katta bo'lsa - formulada xato bor. - Gradient nolga teng joy - eng past nuqta (yoki egar nuqtasi).
Keyingi bo'limda gradient tushishni to'liq quramiz va o'qitish tezligining ta'sirini ko'ramiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.