8-bo‘lim
Gradient tushish
Og'irliklarni qadam-baqadam to'g'rilash - o'qitish tezligi, yaqinlashish va uchraydigan nosozliklar.
Ushbu bo‘lim mundarijasi
Gradient qaysi tomonga yurishni aytadi. Gradient tushish
- shu yo'nalishda kichik qadamlar tashlab, eng past nuqtaga
borish.
Algoritm #
1. Bashorat qil (oldinga tarqalish)
2. Xatoni o'lcha (yo'qotish funksiyasi)
3. Gradientni hisobla (orqaga tarqalish)
4. Og'irliklarni siljit: w = w - tezlik · gradient
5. Takrorla
Bitta parametr #
import numpy as np
def yoqotish(w):
X = np.array([1.0, 2.0, 3.0, 4.0])
y = np.array([2.0, 4.0, 6.0, 8.0])
return float(np.mean((w * X - y) ** 2))
def gradient(w):
X = np.array([1.0, 2.0, 3.0, 4.0])
y = np.array([2.0, 4.0, 6.0, 8.0])
return float(np.mean(2 * (w * X - y) * X))
def tushish(w0, tezlik, qadamlar):
w = w0
tarix = [w]
for _ in range(qadamlar):
w = w - tezlik * gradient(w)
tarix.append(w)
return np.array(tarix)
tarix = tushish(0.0, 0.02, 20)
for i in [0, 1, 2, 5, 10, 20]:
w = tarix[i]
print(f"qadam {i:>2}: w = {w:.6f} yo'qotish = {yoqotish(w):.6f}")
qadam 0: w = 0.000000 yo'qotish = 30.000000
qadam 1: w = 0.600000 yo'qotish = 14.700000
qadam 2: w = 1.020000 yo'qotish = 7.203000
qadam 5: w = 1.663860 yo'qotish = 0.847426
qadam 10: w = 1.943505 yo'qotish = 0.023938
qadam 20: w = 1.998404 yo'qotish = 0.000019
Yigirma qadamda w 2.0 ga deyarli aynan yetdi.
O'qitish tezligining ta'siri #
for tezlik in [0.001, 0.02, 0.06, 0.07]:
tarix = tushish(0.0, tezlik, 30)
oxirgi = tarix[-1]
holat = "yaqinlashdi" if abs(oxirgi - 2.0) < 0.01 else "yaqinlashmadi"
print(f"tezlik = {tezlik:<7} 30 qadamdan keyin w = {oxirgi:>12.6f} {holat}")
tezlik = 0.001 30 qadamdan keyin w = 0.729084 yaqinlashmadi
tezlik = 0.02 30 qadamdan keyin w = 1.999955 yaqinlashdi
tezlik = 0.06 30 qadamdan keyin w = 2.000000 yaqinlashdi
tezlik = 0.07 30 qadamdan keyin w = 2.000000 yaqinlashdi
Yuqoridagi misolda 0.07 hali ham ishladi. Chegarani
oshirib ko'ramiz - va nima bo'lishini kuzatamiz.
Bu masalada gradient w ga chiziqli bog'liq, shuning uchun
aniq chegara mavjud: tezlik 2/λ dan oshsa, jarayon
uzoqlashadi (λ - egrilik).
Amaliy tarmoqda bunday formula yo'q, lekin belgilar bir xil:
| Belgi | Sabab |
|---|---|
| Yo'qotish o'sib boryapti | Tezlik juda katta |
Yo'qotish nan bo'ldi | Tezlik juda katta (portladi) |
| Yo'qotish sakrab-sakrab tushyapti | Tezlik biroz katta |
| Yo'qotish juda sekin tushyapti | Tezlik juda kichik |
| Yo'qotish umuman qimirlamayapti | Tezlik juda kichik yoki gradient nol |
Birinchi ikkitasini ko'rsangiz - tezlikni o'n barobar kamaytiring va qaytadan boshlang.
for tezlik in [0.1, 0.2, 0.3]:
tarix = tushish(0.0, tezlik, 20)
oxirgi = tarix[-1]
yoq = yoqotish(oxirgi)
holat = "portladi" if (not np.isfinite(yoq)) or yoq > 1e6 else "barqaror"
print(f"tezlik = {tezlik:<5} oxirgi w = {oxirgi:>18.4f} {holat}")
tezlik = 0.1 oxirgi w = 2.0000 barqaror
tezlik = 0.2 oxirgi w = -2097150.0000 portladi
tezlik = 0.3 oxirgi w = -152191670029.7612 portladi
0.1 va 0.2 orasida chegara yotibdi. Undan oshgach w
har qadamda kattalashib, yo'qotish cheksizlikka intiladi.
Ko'p parametr - vektor shaklida #
def chiziqli_yoqotish(w, X, y):
return float(np.mean((X @ w - y) ** 2))
def chiziqli_gradient(w, X, y):
n = len(y)
return 2.0 / n * X.T @ (X @ w - y)
gen = np.random.default_rng(42)
X = gen.normal(0, 1, (100, 3))
haqiqiy_w = np.array([2.0, -1.0, 0.5])
y = X @ haqiqiy_w + gen.normal(0, 0.1, 100)
w = np.zeros(3)
tezlik = 0.1
for qadam in range(201):
if qadam % 50 == 0:
print(f"qadam {qadam:>3}: w = {np.round(w, 4)} "
f"yo'qotish = {chiziqli_yoqotish(w, X, y):.6f}")
w = w - tezlik * chiziqli_gradient(w, X, y)
print("haqiqiy w:", haqiqiy_w)
qadam 0: w = [0. 0. 0.] yo'qotish = 4.085068
qadam 50: w = [ 1.9999 -0.9927 0.4791] yo'qotish = 0.009907
qadam 100: w = [ 2.0003 -0.993 0.4794] yo'qotish = 0.009906
qadam 150: w = [ 2.0003 -0.993 0.4794] yo'qotish = 0.009906
qadam 200: w = [ 2.0003 -0.993 0.4794] yo'qotish = 0.009906
haqiqiy w: [ 2. -1. 0.5]
Model haqiqiy og'irliklarni deyarli aniq topdi. Yo'qotish noldan katta qolgani - shovqin sababli.
Ma'lumotga normal(0, 0.1) shovqin qo'shilgan edi. Model
shovqinni bashorat qila olmaydi - va qilmasligi ham
kerak.
Qolgan yo'qotish taxminan shovqin dispersiyasiga teng:
0.1² = 0.01
Kuzatilgan qiymat 0.0099 - kutilganga juda yaqin.
Bu muhim mo'ljal: agar yo'qotish shovqin darajasidan pastga tushsa, model shovqinni yodlab olyapti - ya'ni haddan ortiq moslashuv (16-bo'lim).
Shuning uchun "yo'qotish nolga tushdi" degan natija odatda yaxshi emas, yomon xabar.
print("shovqin dispersiyasi:", 0.1 ** 2)
print("qolgan yo'qotish: ", 0.009906)
print("nisbat:", round(0.009906 / 0.01, 3))
shovqin dispersiyasi: 0.010000000000000002
qolgan yo'qotish: 0.009906
nisbat: 0.991
To'xtash mezoni #
def chiziqli_yoqotish(w, X, y):
return float(np.mean((X @ w - y) ** 2))
def chiziqli_gradient(w, X, y):
return 2.0 / len(y) * X.T @ (X @ w - y)
gen = np.random.default_rng(42)
X = gen.normal(0, 1, (100, 3))
y = X @ np.array([2.0, -1.0, 0.5]) + gen.normal(0, 0.1, 100)
w = np.zeros(3)
oldingi = float("inf")
for qadam in range(1, 501):
w = w - 0.1 * chiziqli_gradient(w, X, y)
joriy = chiziqli_yoqotish(w, X, y)
if abs(oldingi - joriy) < 1e-9:
print(f"{qadam}-qadamda to'xtadi (o'zgarish 1e-9 dan kichik)")
break
oldingi = joriy
print("yakuniy yo'qotish:", round(joriy, 6))
65-qadamda to'xtadi (o'zgarish 1e-9 dan kichik)
yakuniy yo'qotish: 0.009906
| Mezon | Izoh |
|---|---|
| Belgilangan qadamlar soni | Eng oddiy, lekin ko'r-ko'rona |
| Yo'qotish o'zgarmay qolsa | Yuqoridagi usul |
| Gradient normasi kichik bo'lsa | np.linalg.norm(g) < eps |
| Tekshiruv to'plamida yomonlashsa | Early stopping (16-bo'lim) |
Oxirgisi amalda eng muhimi - u haddan ortiq moslashuvni ham to'xtatadi.
Mahalliy minimum #
def qiyin(w):
return float(w ** 4 - 3 * w ** 3 + 2)
def qiyin_gradient(w):
return float(4 * w ** 3 - 9 * w ** 2)
for boshlanish in [-1.0, 0.5, 3.0]:
w = boshlanish
for _ in range(300):
w = w - 0.01 * qiyin_gradient(w)
print(f"boshlanish {boshlanish:>5.1f} -> w = {w:>8.4f} f(w) = {qiyin(w):>10.4f}")
boshlanish -1.0 -> w = -0.0337 f(w) = 2.0001
boshlanish 0.5 -> w = 2.2500 f(w) = -6.5430
boshlanish 3.0 -> w = 2.2500 f(w) = -6.5430
Uchta boshlanish - ikki xil natija. -1.0 dan
boshlangan jarayon w = 0 atrofida qotib qoldi, qolgan
ikkitasi esa haqiqiy minimumga (w = 2.25) yetdi.
Yuqorida faqat -1.0 dan boshlangan jarayon w = 0
atrofida qotib qoldi - u yerda gradient nolga juda
yaqin (w = 0 bu funksiyaning egar nuqtasi).
0.5 dan boshlangan jarayon esa undan chiqib ketdi:
u yerda gradient -1.75, ya'ni yetarlicha katta. Ya'ni
egar nuqtasidan qochish boshlanish nuqtasiga juda nozik
bog'liq.
Neyron tarmoqlarda bu doim shunday: yo'qotish yuzasi ko'p o'lchovli va juda notekis. Har o'qitish boshqa minimumga tushadi.
Amaliy oqibatlari:
| Fakt | Nima qilish kerak |
|---|---|
| Har urug' boshqa natija beradi | Bir necha urug' bilan sinang |
| "Global minimum" topilmaydi | Va bu kerak ham emas |
| Yaxshi mahalliy minimumlar ko'p | Amalda ular yetarli |
Chuqur tarmoqlarda haqiqiy muammo mahalliy minimumlar emas, egar nuqtalari - gradient nolga yaqin, lekin bu minimum ham emas. Momentum (15-bo'lim) aynan shulardan chiqishga yordam beradi.
O'qitish tezligi jadvali #
def yoqotish(w):
X = np.array([1.0, 2.0, 3.0, 4.0])
y = np.array([2.0, 4.0, 6.0, 8.0])
return float(np.mean((w * X - y) ** 2))
def gradient(w):
X = np.array([1.0, 2.0, 3.0, 4.0])
y = np.array([2.0, 4.0, 6.0, 8.0])
return float(np.mean(2 * (w * X - y) * X))
w_qatiy, w_pasayuvchi = 0.0, 0.0
for qadam in range(1, 41):
w_qatiy -= 0.05 * gradient(w_qatiy)
tezlik = 0.05 / (1 + 0.05 * qadam)
w_pasayuvchi -= tezlik * gradient(w_pasayuvchi)
print(f"qat'iy tezlik: w = {w_qatiy:.8f} yo'qotish = {yoqotish(w_qatiy):.3e}")
print(f"pasayuvchi tezlik: w = {w_pasayuvchi:.8f} yo'qotish = {yoqotish(w_pasayuvchi):.3e}")
qat'iy tezlik: w = 2.00000000 yo'qotish = 0.000e+00
pasayuvchi tezlik: w = 2.00000000 yo'qotish = 2.548e-18
Bu misolda qat'iy tezlik yaxshiroq natija berdi - chunki masala oddiy va tezlik allaqachon to'g'ri tanlangan.
Pasayuvchi tezlik (learning rate schedule) boshqa holatda foydali: yo'qotish minimum atrofida sakrab turganda.
| Vaziyat | Jadval kerakmi |
|---|---|
| Oddiy masala, to'g'ri tezlik | Yo'q |
| Minimum atrofida sakrash | Ha |
| Katta tarmoq, uzoq o'qitish | Ha - deyarli har doim |
| Mini-paketli o'qitish | Ha - shovqin tufayli |
Keng tarqalgan jadvallar: har N davrda 0.1 ga ko'paytirish
(step decay), kosinus jadvali, yoki yo'qotish to'xtaganda
kamaytirish (reduce on plateau).
15-bo'limdagi Adam optimizatori tezlikni qisman o'zi moslashtiradi - shuning uchun u bilan jadval kamroq kerak bo'ladi.
- Bitta parametrli gradient tushishni yozing va 20 qadam bajaring.
wva yo'qotish qanday o'zgarganini jadvalda ko'rsating.- To'rtta turli tezlikda natijani solishtiring.
- Tezlikni oshirib, portlash chegarasini toping.
- Uchta parametrli chiziqli modelni o'qiting.
- Qolgan yo'qotishni shovqin dispersiyasi bilan solishtiring.
- Yo'qotish o'zgarmay qolganda to'xtaydigan sikl yozing.
w⁴ - 3w³ + 2uchun turli boshlanishlardan tushing.- Nima uchun natijalar farq qilganini tushuntiring.
- Qat'iy va pasayuvchi tezlikni solishtiring.
Xulosa #
- Gradient tushish: bashorat → xato → gradient → siljish → takror.
w = w - tezlik · gradient- butun algoritm shu satrda.- O'qitish tezligi - eng muhim giperparametr.
- Yo'qotish o'sib ketsa yoki
nanbo'lsa - tezlikni 10 barobar kamaytiring. - Chegaradan oshgan tezlik jarayonni uzoqlashtiradi.
- Yo'qotish shovqin darajasida to'xtashi - normal.
- Yo'qotish nolga tushsa - model shovqinni yodlagan bo'lishi mumkin.
- To'xtash mezoni: o'zgarish kichik bo'lganda yoki tekshiruvda yomonlashganda.
- Boshlanish nuqtasi natijaga ta'sir qiladi - bir necha urug' bilan sinang.
- Chuqur tarmoqda asosiy to'siq - mahalliy minimum emas, egar nuqtalari.
Keyingi bo'limda orqaga tarqalishni quramiz - gradientni tarmoqning barcha og'irliklari uchun hisoblaymiz.
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.