8-bo‘lim
Kichik GPT qurish
Belgi darajasidagi lug'at, keyingi belgini bashorat qilish, to'liq model va uni o'zbekcha matnda noldan o'qitish.
Ushbu bo‘lim mundarijasi
Barcha qismlar tayyor: e'tibor, multi-head, blok va pozitsion kodlash. Endi ulardan ishlaydigan til modeli yig'amiz.
Masala: keyingi belgini topish #
Til modelining butun vazifasi bitta: keyingi belgini bashorat qilish. Boshqa hamma narsa shundan kelib chiqadi.
Bu bo'limda belgi darajasida ishlaymiz - tokenizator o'rniga har harf alohida token bo'ladi. Shunda lug'at kichik qoladi va butun model protsessorda o'qiydi.
import torch
import torch.nn as nn
import torch.nn.functional as F
import math, time
torch.manual_seed(1337)
matn = open("corpus.txt", encoding="utf-8").read()
belgilar = sorted(set(matn))
V = len(belgilar)
stoi = {c: i for i, c in enumerate(belgilar)}
itos = {i: c for c, i in stoi.items()}
kodla = lambda s: [stoi[c] for c in s]
dekodla = lambda l: "".join(itos[i] for i in l)
print("matn uzunligi:", len(matn))
print("lug'at (belgilar):", V)
matn uzunligi: 89846
lug'at (belgilar): 34
belgilar: ',.BEKSTabcdefghijklmnopqrstuvxyz
34 ta belgi - butun lug'at shu.
Bu darslik uchun oddiy o'zbekcha jumlalardan iborat sun'iy matn tayyorlandi: «*Ertalab o'qituvchi ofisda kitob o'qidi, chunki u qiziqardi*» kabi 1400 ta jumla, ularning 1342 tasi betakror.
Nega haqiqiy kitob emas? Chunki 90 ming belgi juda kam. Haqiqiy matnda model faqat bo'g'inlarni o'rganib ulgurardi. Tuzilishi aniq matnda esa u jumla qurilishini o'rganadi va buni natijadan ko'rish mumkin.
Ma'lumotni tayyorlash #
data = torch.tensor(kodla(matn), dtype=torch.long)
n = int(0.9 * len(data))
oquv, valid = data[:n], data[n:]
BLOK, PAKET = 64, 32
def paket_ol(split):
d = oquv if split == "oquv" else valid
i = torch.randint(len(d) - BLOK - 1, (PAKET,))
x = torch.stack([d[j:j + BLOK] for j in i])
y = torch.stack([d[j + 1:j + BLOK + 1] for j in i])
return x, y
o'quv: 80861 | validatsiya: 8985
paket shakli: (32, 64) nishon: (32, 64)
kirish : 'orladi, lekin vaqti yetmadi. Bug'
nishon : 'rladi, lekin vaqti yetmadi. Bugu'
-> nishon kirishdan bitta belgiga surilgan
Butun sir shu ikki qatorda: nishon kirishning bir belgiga surilgani.
Model o ni ko'rib r ni, or ni ko'rib l ni bashorat qilishni
o'rganadi.
BLOK=64 bo'lgani uchun har namuna 64 ta bashorat beradi: 1-belgidan
2-belgini, 1-2 dan 3-ni va hokazo.
Bu niqob tufayli mumkin (4-bo'lim) - har pozitsiya faqat o'zidan oldingilarini ko'radi, shuning uchun 64 ta masalani bir o'tishda o'rgatish mumkin.
Model #
D, H, NL = 128, 4, 3 # o'lcham, boshlar, qatlamlar
class Blok(nn.Module):
def __init__(s):
super().__init__()
s.ln1 = nn.LayerNorm(D); s.ln2 = nn.LayerNorm(D)
s.attn = nn.MultiheadAttention(D, H, batch_first=True)
s.ffn = nn.Sequential(nn.Linear(D, 4*D), nn.GELU(), nn.Linear(4*D, D))
def forward(s, x, m):
h = s.ln1(x)
a, _ = s.attn(h, h, h, attn_mask=m, need_weights=False)
x = x + a
return x + s.ffn(s.ln2(x))
class KichikGPT(nn.Module):
def __init__(s):
super().__init__()
s.tok = nn.Embedding(V, D)
s.pos = nn.Embedding(BLOK, D)
s.bloklar = nn.ModuleList([Blok() for _ in range(NL)])
s.lnf = nn.LayerNorm(D)
s.bosh = nn.Linear(D, V, bias=False)
def forward(s, idx, nishon=None):
B, L = idx.shape
m = torch.triu(torch.ones(L, L, dtype=torch.bool), diagonal=1)
x = s.tok(idx) + s.pos(torch.arange(L))
for b in s.bloklar:
x = b(x, m)
logit = s.bosh(s.lnf(x))
if nishon is None:
return logit, None
return logit, F.cross_entropy(logit.view(-1, V), nishon.view(-1))
parametrlar: 611,968
tasodifiy model yo'qotishi kutilgan qiymati: 3.5264
Oxirgi qatorga e'tibor bering. 34 ta belgidan birini tasodifiy
tanlasak, cross-entropy ln(34) = 3.53 bo'lishi kerak. Bu bizning
tekshiruv nuqtamiz.
Modelning qismlari va ularning manbasi:
| Qism | Nima qiladi | Qaysi bo'limdan |
|---|---|---|
tok | Belgi id sini vektorga aylantiradi | 3-bo'lim |
pos | Pozitsiya ma'lumotini qo'shadi | 7-bo'lim |
attn | So'zlar orasida ma'lumot almashadi | 4, 5-bo'limlar |
ffn | Har pozitsiyani alohida qayta ishlaydi | 6-bo'lim |
ln1, ln2, lnf | Qiymatlarni barqarorlashtiradi | 6-bo'lim |
bosh | Vektorni 34 ta belgi ustidagi ballga aylantiradi | shu bo'lim |
Butun darslikning birinchi yarmi shu jadvalga sig'di.
Matn yozish #
@torch.no_grad()
def yoz(s, idx, n_yangi, temp=1.0):
for _ in range(n_yangi):
logit, _ = s(idx[:, -BLOK:]) # oxirgi BLOK ta belgi
p = F.softmax(logit[:, -1, :] / temp, dim=-1)
idx = torch.cat([idx, torch.multinomial(p, 1)], dim=1)
return idx
Har qadamda: bashorat qil, taqsimotdan tanla, natijani oxiriga qo'sh,
takrorla. idx[:, -BLOK:] kesimi kontekst oynasidan oshib ketmaslik
uchun.
O'qitishdan oldin ko'ramiz:
o'qitishdan oldin: " ffgbzymsso ,ud oysfpzfdorhjj'jttmBcnelk'ymxexrhtkolfbpblrz''hcBv..',ojcdl,, y'xa"
Kutilganidek - shovqin.
O'qitamiz #
opt = torch.optim.AdamW(model.parameters(), lr=3e-3)
for qadam in range(1501):
X, Y = paket_ol("oquv")
_, loss = model(X, Y)
opt.zero_grad(set_to_none=True)
loss.backward()
opt.step()
Qadam | O'quv | Valid | Vaqt
0 | 3.7756 | 3.7730 | 1s
250 | 0.2148 | 0.2197 | 19s
500 | 0.2078 | 0.2109 | 36s
750 | 0.2066 | 0.2066 | 54s
1000 | 0.2049 | 0.2065 | 72s
1250 | 0.2027 | 0.2072 | 90s
1500 | 0.2048 | 0.2076 | 109s
Ikki narsani tekshiramiz.
Boshlang'ich qiymat. 3.7756 - bu bizning ln(34) = 3.53 bashoratimizga
yaqin. Model haqiqatan ham tasodifiy holatdan boshladi.
Yakuniy qiymat. O'quv 0.2048, validatsiya 0.2076 - deyarli teng. PyTorch darsligining 11-bo'limidagi mezon bo'yicha bu sog'lom o'qish: ortiqcha moslashish yo'q.
Natija #
temperatura 0.5:
"Kecha dasturchi kutubxonada tajriba o'tkazdi, va natijadan mamnun bo'ldi. Kecha opam bog'da masala yechdi, shuning uchun charchadi. Bug"
temperatura 1.0:
"Kecha dasturchi laboratoriyada kod yozdi, va natijadan mamnun bo'ldi. Kechqurun do'stim maktabda tajriba o'tkazdi, va natijadan mamnun "
Model to'g'ri o'zbekcha jumlalar yozdi. Muhimi - bular matnda yo'q, yangi birikmalar: «dasturchi kutubxonada tajriba o'tkazdi», «opam bog'da masala yechdi».
U yodlab olmadi - jumla tuzilishini o'rgandi: vaqt, ega, joy, ish, bog'lovchi, nuqta.
Hammasi 611 ming parametr va protsessorda 110 soniya bilan.
Model grammatik to'g'ri jumla yozadi. Lekin u «kutubxona» nima ekanini bilmaydi va tajriba kutubxonada o'tkazilishi g'alati ekanini sezmaydi.
U faqat bitta narsani o'rgandi: qaysi belgidan keyin qaysi belgi kelishi ehtimoli katta. Ma'no emas - statistika.
Katta modellarda ham mexanizm aynan shu. Farq shundaki, ular yuz milliardlab so'zda o'qiydi va o'sha statistika ichida ma'noga o'xshash narsa paydo bo'ladi. Lekin asos o'zgarmaydi - shuni yodda tuting.
- Qatlam va o'lcham oshsa - murakkabroq naqshlarni o'rganadi.
- Ma'lumot ko'paysa - yaxshiroq umumlashtiradi.
- BLOK (kontekst) uzaysa - uzoqroq bog'liqlikni ko'radi.
- Tokenizator qo'shilsa (2-bo'lim) - belgi emas, so'z bo'lagi darajasida ishlaydi.
Shu to'rt yo'nalish bo'yicha kattalashtirish - GPT-2 dan GPT-3 gacha bo'lgan yo'lning mohiyati.
- O'z o'zbekcha matningizdan belgi lug'ati tuzing va hajmini chop eting.
- Kirish va nishon bir belgiga surilganini tekshiring.
ln(V)ni hisoblab, o'qitishdan oldingi yo'qotish bilan solishtiring.- Modelni qurib, parametrlar sonini sanang.
- O'qitishdan oldin matn yozdirib, natijani ko'ring.
- 1500 qadam o'qitib, yo'qotish egri chizig'ini yozing.
- O'quv va validatsiya yo'qotishini solishtirib, xulosa chiqaring.
temperaturani 0.2 va 1.5 qilib, natijalarni taqqoslang.- Qatlamlar sonini 3 dan 6 ga oshirib, farqni o'lchang.
BLOKni 64 dan 128 ga oshirib, natijaga ta'sirini kuzating.
Xulosa #
- Til modelining butun vazifasi - keyingi belgini (yoki tokenni) bashorat qilish.
- Belgi darajasida lug'at kichik bo'ladi: bizda atigi 34 ta belgi.
- Nishon kirishdan bir belgiga surilgan - butun o'qitish shunga tayanadi.
- Niqob tufayli bitta namunada
BLOKta masala bir vaqtda o'rgatiladi. - Model
tok + posembedding, bir nechta blok va oxirgiLineardan iborat. - Tasodifiy model yo'qotishi
ln(V)ga teng - bu kodni tekshirish usuli. - Bizda u 3.53 kutilgan edi, amalda 3.78 chiqdi - model haqiqatan noldan boshladi.
- 1500 qadamdan keyin yo'qotish 0.20 ga tushdi, o'quv va validatsiya deyarli teng.
- Model yodlamadi - yangi, matnda uchramagan jumlalar yozdi.
- 611 ming parametr va 110 soniya protsessor vaqti yetdi.
Keyingi bo'limda matn yozishning o'zini chuqurroq ko'ramiz: temperatura, top-k va top-p.
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.