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.

🕑 10 daqiqa o‘qish 📄 773 so‘z 👁 3 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. Masala: keyingi belgini topish
  2. Ma'lumotni tayyorlash
  3. Model
  4. Matn yozish
  5. O'qitamiz
  6. Natija
  7. Xulosa

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.

Python
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)
Natija
matn uzunligi: 89846
lug'at (belgilar): 34
belgilar:  ',.BEKSTabcdefghijklmnopqrstuvxyz

34 ta belgi - butun lug'at shu.

Matn qayerdan

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 #

Python
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
Natija
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.

Bitta paketda 64 ta masala bor

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 #

Python
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))
Natija
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:

QismNima qiladiQaysi bo'limdan
tokBelgi id sini vektorga aylantiradi3-bo'lim
posPozitsiya ma'lumotini qo'shadi7-bo'lim
attnSo'zlar orasida ma'lumot almashadi4, 5-bo'limlar
ffnHar pozitsiyani alohida qayta ishlaydi6-bo'lim
ln1, ln2, lnfQiymatlarni barqarorlashtiradi6-bo'lim
boshVektorni 34 ta belgi ustidagi ballga aylantiradishu bo'lim

Butun darslikning birinchi yarmi shu jadvalga sig'di.

Matn yozish #

Python
@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:

Natija
o'qitishdan oldin: " ffgbzymsso ,ud oysfpzfdorhjj'jttmBcnelk'ymxexrhtkolfbpblrz''hcBv..',ojcdl,, y'xa"

Kutilganidek - shovqin.

O'qitamiz #

Python
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()
Natija
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.

Yo'qotish: tasodifiydan 0.20 gacha 4.0 3.0 2.0 1.0 0 ln(34) = 3.53 tasodifiy taxmin darajasi 3.78 0.20 0 500 1000 1500 qadam O'quv 0.2048 va validatsiya 0.2076 - deyarli teng, ortiqcha moslashish yo'q
Yo'qotish tasodifiy darajadan 250 qadamda tushdi, keyin barqarorlashdi

Natija #

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.

Bu «til modeli», lekin tilni bilmaydi

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.

Nima qo'shilsa, nima o'zgaradi
  • 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.

Amaliy topshiriq
  1. O'z o'zbekcha matningizdan belgi lug'ati tuzing va hajmini chop eting.
  2. Kirish va nishon bir belgiga surilganini tekshiring.
  3. ln(V) ni hisoblab, o'qitishdan oldingi yo'qotish bilan solishtiring.
  4. Modelni qurib, parametrlar sonini sanang.
  5. O'qitishdan oldin matn yozdirib, natijani ko'ring.
  6. 1500 qadam o'qitib, yo'qotish egri chizig'ini yozing.
  7. O'quv va validatsiya yo'qotishini solishtirib, xulosa chiqaring.
  8. temperatura ni 0.2 va 1.5 qilib, natijalarni taqqoslang.
  9. Qatlamlar sonini 3 dan 6 ga oshirib, farqni o'lchang.
  10. BLOK ni 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 BLOK ta masala bir vaqtda o'rgatiladi.
  • Model tok + pos embedding, bir nechta blok va oxirgi Linear dan 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.

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.