7-bo‘lim

Pozitsion kodlash

E'tibor tartibni sezmasligining isboti, sinusoidal kodlash, o'rgatiladigan pozitsiya embeddingi va ikkalasining farqi.

🕑 8 daqiqa o‘qish 📄 617 so‘z 👁 2 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. E'tibor tartibni sezmaydi
  2. Sinusoidal kodlash
  3. Har pozitsiya betakror
  4. Qanday qo'llanadi
  5. O'rgatiladigan pozitsiya
  6. Xulosa

Blok tayyor, lekin unda jiddiy kamchilik bor. Uni isbotlab ko'rsatamiz.

E'tibor tartibni sezmaydi #

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

Bu kamchilik emas, tanlov

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.

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

Soat strelkalari kabi

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 #

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

Har ustun o'z chastotasida tebranadi 0-ustun tez 2-ustun o'rta 4-ustun sekin pozitsiya 2 pozitsiya 10 Uchala to'lqinning bir nuqtadagi qiymati birgalikda betakror imzo beradi
Tez chastotalar qo'shnilarni, sekinlari uzoq masofani ajratadi

Qanday qo'llanadi #

Python
emb = torch.randn(1, 8, 8)
birga = emb + pe.unsqueeze(0)
print("  natija:", tuple(birga.shape), " <- qo'shiladi, ulanmaydi")
Natija
  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.

Pozitsiyani qo'shishni unutish - jimgina xato

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:

Python
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()):,}")
Natija
  nn.Embedding(512, 64) -> (6, 64)
  parametrlar: 32,768

Formula yo'q - model har pozitsiya uchun vektorni o'zi o'rganadi.

SinusoidalO'rgatiladigan
Parametrlar0max_len x d_model
Uzunroq matngaIshlaydiIshlamaydi
SifatYaxshiOdatda biroz yaxshiroq
Kim ishlatadiAsl transformerGPT-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.

Bugungi holat

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.

Amaliy topshiriq
  1. So'zlarni aralashtirib, e'tibor chiqishi o'zgarmasligini isbotlang.
  2. Bu nega kamchilik ekanini o'zbek tilidan misol bilan tushuntiring.
  3. pos_kod funksiyasini yozib, dastlabki 4 pozitsiyani chop eting.
  4. Chap va o'ng ustunlar chastotasi farqini kuzating.
  5. 50 pozitsiya uchun barcha imzolar betakror ekanini tekshiring.
  6. 0-1, 0-10 va 0-40 orasidagi masofalarni solishtiring.
  7. Yaqin pozitsiyalarning yaqin bo'lishi nega muhimligini yozing.
  8. Pozitsiyani embeddingga qo'shib, shakl o'zgarmasligini ko'rsating.
  9. nn.Embedding bilan o'rgatiladigan pozitsiya yarating.
  10. max_len dan 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.Embedding bilan yasaladi - GPT va BERT shuni ishlatadi.
  • Uning kamchiligi: max_len dan 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.

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.