7-bo‘lim
Pozitsion kodlash
E'tibor tartibni sezmasligining isboti, sinusoidal kodlash, o'rgatiladigan pozitsiya embeddingi va ikkalasining farqi.
Ushbu bo‘lim mundarijasi
Blok tayyor, lekin unda jiddiy kamchilik bor. Uni isbotlab ko'rsatamiz.
E'tibor tartibni sezmaydi #
import torch
import torch.nn as nn
import torch.nn.functional as F
torch.manual_seed(42)
d = 16
Wq, Wk, Wv = (nn.Linear(d, d, bias=False) for _ in range(3))
def attn(x):
Q, K, V = Wq(x), Wk(x), Wv(x)
w = F.softmax(Q @ K.transpose(-2, -1) / d**0.5, dim=-1)
return w @ V
x = torch.randn(1, 4, d)
out1 = attn(x)
perm = torch.tensor([2, 0, 3, 1]) # so'zlarni aralashtiramiz
out2 = attn(x[:, perm, :])
print(" asl tartib, 1-pozitsiya chiqishi:", [round(v, 4) for v in out1[0, 0, :3].tolist()])
print(" aralashtirilgan, o'sha so'z qayerda:", [round(v, 4) for v in out2[0, 1, :3].tolist()])
print(" bir xilmi:", torch.allclose(out1[0, 0], out2[0, 1], atol=1e-5))
asl tartib, 1-pozitsiya chiqishi: [0.223, -0.01, 0.0787]
aralashtirilgan, o'sha so'z qayerda: [0.223, -0.01, 0.0787]
bir xilmi: True
So'zlarni aralashtirdik, lekin har bir so'zning chiqishi aynan o'zgarishsiz qoldi - faqat joyi ko'chdi.
Demak e'tibor uchun «men seni sevaman» va «sevaman seni men» butunlay bir xil. Model so'zlar to'plamini ko'radi, ketma-ketlikni emas.
RNN da tartib bepul kelardi - model matnni ketma-ket o'qirdi. Lekin aynan o'sha ketma-ketlik parallellashtirishga to'sqinlik qilardi (1-bo'lim).
Transformer tartibni tashlab yuborib parallellikni qo'lga kiritdi. Endi tartibni orqaga qaytarish kerak - lekin hisobni ketma-ket qilmasdan.
Sinusoidal kodlash #
2017-yilgi maqolaning yechimi: har pozitsiya uchun turli chastotali sinus va kosinusdan imzo yasash.
import math
def pos_kod(max_len, d_model):
pe = torch.zeros(max_len, d_model)
pos = torch.arange(max_len).unsqueeze(1).float()
bul = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))
pe[:, 0::2] = torch.sin(pos * bul)
pe[:, 1::2] = torch.cos(pos * bul)
return pe
pe = pos_kod(8, 8)
for i in range(4):
print(f" pozitsiya {i}: ", " ".join(f"{v:6.3f}" for v in pe[i].tolist()))
pozitsiya 0: 0.000 1.000 0.000 1.000 0.000 1.000 0.000 1.000
pozitsiya 1: 0.841 0.540 0.100 0.995 0.010 1.000 0.001 1.000
pozitsiya 2: 0.909 -0.416 0.199 0.980 0.020 1.000 0.002 1.000
pozitsiya 3: 0.141 -0.990 0.296 0.955 0.030 1.000 0.003 1.000
Har qator - bitta pozitsiyaning imzosi. Chap ustunlar tez o'zgaradi, o'ng ustunlar sekin.
Soatda uchta strelka bor: soniya tez, daqiqa sekinroq, soat eng sekin. Uchalasining holati birgalikda kunning aniq lahzasini beradi.
Pozitsion kodlash ham shunday: tez chastotalar qo'shni so'zlarni ajratadi, sekinlari esa matnning qaysi qismida ekanini bildiradi.
Har pozitsiya betakror #
pe50 = pos_kod(50, 32)
print(" 0 va 1 orasidagi masofa:", round(torch.dist(pe50[0], pe50[1]).item(), 3))
print(" 0 va 10 orasidagi masofa:", round(torch.dist(pe50[0], pe50[10]).item(), 3))
print(" 0 va 40 orasidagi masofa:", round(torch.dist(pe50[0], pe50[40]).item(), 3))
uniq = len(set(tuple(round(v, 4) for v in r) for r in pe50.tolist()))
print(f" 50 pozitsiyadan nechtasi betakror: {uniq}")
0 va 1 orasidagi masofa: 1.172
0 va 10 orasidagi masofa: 3.447
0 va 40 orasidagi masofa: 4.052
50 pozitsiyadan nechtasi betakror: 50
Ikki xossa ko'rinadi:
- Barchasi betakror - 50 pozitsiya, 50 xil imzo.
- Yaqin pozitsiyalar yaqin - 0 va 1 orasidagi masofa (1.172) 0 va 10 orasidagidan (3.447) kichik.
Ikkinchisi muhim: model «yaqin» va «uzoq» tushunchasini shundan oladi.
Qanday qo'llanadi #
emb = torch.randn(1, 8, 8)
birga = emb + pe.unsqueeze(0)
print(" natija:", tuple(birga.shape), " <- qo'shiladi, ulanmaydi")
embedding: (1, 8, 8) + pozitsiya: (8, 8)
natija: (1, 8, 8) <- qo'shiladi, ulanmaydi
Diqqat: pozitsiya so'z vektoriga qo'shiladi (+), yoniga
ulanmaydi (concat). Shuning uchun o'lcham o'zgarmaydi.
Agar pozitsion kodlashni qo'shmasangiz, model hamon o'qiydi va yo'qotish ham tushadi - lekin u so'z tartibini hech qachon o'rganmaydi.
Natijada «it odamni tishladi» va «odam itni tishladi» bir xil bashorat beradi. Xato xabari chiqmaydi; buni faqat natijaning sifatidan sezasiz.
O'rgatiladigan pozitsiya #
GPT va BERT boshqa yo'ldan boradi - pozitsiyani oddiy nn.Embedding ga
topshiradi:
pos_emb = nn.Embedding(512, 64)
poz = torch.arange(6)
print(" nn.Embedding(512, 64) ->", tuple(pos_emb(poz).shape))
print(" parametrlar:", f"{sum(p.numel() for p in pos_emb.parameters()):,}")
nn.Embedding(512, 64) -> (6, 64)
parametrlar: 32,768
Formula yo'q - model har pozitsiya uchun vektorni o'zi o'rganadi.
| Sinusoidal | O'rgatiladigan | |
|---|---|---|
| Parametrlar | 0 | max_len x d_model |
| Uzunroq matnga | Ishlaydi | Ishlamaydi |
| Sifat | Yaxshi | Odatda biroz yaxshiroq |
| Kim ishlatadi | Asl transformer | GPT-2, BERT |
Ikkinchi qator eng muhimi. Sinusoidal kodlash formula bo'lgani uchun
istalgan uzunlik uchun hisoblanadi. O'rgatiladigan variantda esa
512 dan uzun matn berilsa, jadvalda o'sha qator yo'q - va dastur
xato beradi.
Hozirgi katta modellar uchinchi yo'lni tanlaydi - RoPE (Rotary Position Embedding). U pozitsiyani qo'shmaydi, balki Q va K vektorlarini burchakka buradi.
Foydasi: uzunlikka yaxshi moslashadi va nisbiy masofani tabiiy ifodalaydi. Llama va shunga o'xshash modellar shuni ishlatadi.
Asosiy g'oya esa o'zgarmaydi: modelga pozitsiya haqida ma'lumot yetkazish kerak.
- So'zlarni aralashtirib, e'tibor chiqishi o'zgarmasligini isbotlang.
- Bu nega kamchilik ekanini o'zbek tilidan misol bilan tushuntiring.
pos_kodfunksiyasini yozib, dastlabki 4 pozitsiyani chop eting.- Chap va o'ng ustunlar chastotasi farqini kuzating.
- 50 pozitsiya uchun barcha imzolar betakror ekanini tekshiring.
- 0-1, 0-10 va 0-40 orasidagi masofalarni solishtiring.
- Yaqin pozitsiyalarning yaqin bo'lishi nega muhimligini yozing.
- Pozitsiyani embeddingga qo'shib, shakl o'zgarmasligini ko'rsating.
nn.Embeddingbilan o'rgatiladigan pozitsiya yarating.max_lendan uzun matn berib, xatoni ko'ring va ikki usulni solishtiring.
Xulosa #
- E'tibor so'z tartibini umuman sezmaydi - buni aralashtirish bilan isbotladik.
- Shuning uchun modelga pozitsiya haqida alohida ma'lumot berish kerak.
- Sinusoidal kodlash turli chastotali sinus va kosinusdan imzo yasaydi.
- Tez chastotalar qo'shni so'zlarni, sekinlari uzoq masofani ajratadi.
- Har pozitsiya betakror, yaqin pozitsiyalar esa bir-biriga yaqin turadi.
- Pozitsiya so'z vektoriga qo'shiladi, yoniga ulanmaydi.
- Uni unutish jimgina xato: model o'qiydi, lekin tartibni hech qachon bilmaydi.
- O'rgatiladigan pozitsiya
nn.Embeddingbilan yasaladi - GPT va BERT shuni ishlatadi. - Uning kamchiligi:
max_lendan uzun matnda ishlamaydi. - Zamonaviy modellar RoPE ga o'tdi, lekin g'oya o'sha - pozitsiyani yetkazish.
Keyingi bo'limda barcha qismlarni yig'ib, ishlaydigan kichik GPT quramiz.
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.