مواد پر جائیں
8/30باب 8 از 30

Next-token prediction: embeddings، اور perplexity کا مطلب

32,033 ناموں پر character model train کریں؛ gradient descent counts کی table دوبارہ پاتا ہے، پھر perplexity کیوں نہیں ملتی۔

اس صفحے پر

یہ دس نام ایک ایسے program نے بنائے ہیں جس نے کبھی کوئی لفظ نہیں دیکھا:

TEXT
cexze   momakurailezitynn   konimittain   llayn   ka
da      moliellavo          emia          sade    ftlsp

ان میں سے کوئی بھی نام نہیں ہے۔ تقریباً سب کوشش کر رہے ہیں۔ یہ بولنے کے قابل ہیں، وہیں ختم ہوتے ہیں جہاں نام ختم ہوتے ہیں، اور ان میں سے ایک — emia — ایک حقیقی نام سے صرف ایک حرف دور ہے۔ جس program نے انہیں بنایا اس کے پاس 729 numbers ہیں، اسے لفظ، syllable یا شخص کا کوئی تصور نہیں، اور اسے حروف کے adjacent pairs گننے کے ایک ہی pass سے fit کیا گیا تھا۔

اس chapter کے آخر تک ایک neural network اسی measurement پر اس program کا score ایک تہائی کم کر چکا ہوگا۔ جس حصے کے لیے رکنا بنتا ہے وہ یہ ہے کہ network سب سے پہلے کیا کرتا ہے: یہ ہر اچھی طرح populated row پر count table کو تین decimal places تک reproduce کرتا ہے، بغیر کسی prompt کے، کیونکہ دونوں objects ایک ہی سوال کے جواب ہیں۔ اس کے بعد سب کچھ وہ ہے جو counting کبھی نہیں کر سکتی تھی۔

Objective ایک identity ہے، design choice نہیں

اس حصے کا لنک: Objective ایک identity ہے، design choice نہیں

باب 7 نے آپ کو integers کی ایک sequence کے ساتھ چھوڑا تھا، اور یہ بتانے کی کوئی وجہ نہیں دی تھی کہ ایک کے بعد دوسرا کیوں آتا ہے۔ وجہ یہ ہے، اور یہ باب 2 کی ایک line ہے۔

Language model ایک function ہے جو اب تک کے tokens لیتا ہے اور یہ distribution واپس کرتا ہے کہ اگلا token کون سا آئے گا: vocabulary کی ہر entry کے لیے ایک number، non-negative، اور سب کا sum ایک۔ بس۔ وہاں سے پورے document کی probability تک جانے کے لیے probability کا chain rule لگائیں:

P(x1,x2,,xT)=t=1TP(xtx1,,xt1)P(x_1, x_2, \ldots, x_T) = \prod_{t=1}^{T} P(x_t \mid x_1, \ldots, x_{t-1})

یہ ایک identity ہے، کسی بھی چیز کی کسی بھی sequence کے لیے درست، بغیر کسی اضافی assumption کے۔ لہٰذا جو model چھوٹا کام کرتا ہے — پچھلے tokens کے مطابق next token — وہ پہلے ہی ہر ممکن document کو probability assign کرنے کا بڑا کام کر چکا ہے، بالکل اور مفت۔ اسے cheap trick کے طور پر پیش کرنے کا عام انداز، کہ «یہ صرف اگلا word predict کرتا ہے»، logic کو الٹا کر دیتا ہے: next token predict کرنا joint distribution کو model کرنا ہی ہے۔ کرنے کے لیے کبھی کوئی دوسری چیز تھی ہی نہیں۔

Loss بھی اتنی ہی mechanical طرح آتا ہے۔ ہر position پر model ایک distribution qq بناتا ہے اور truth ایک known token ہے، اس لیے باب 4 کی cross-entropy ویسی ہی apply ہوتی ہے:

L=1Tt=1Tlogqθ(xtx<t)L = -\frac{1}{T}\sum_{t=1}^{T} \log q_\theta(x_t \mid x_{<t})

یہ average negative log-likelihood ہے — باب 2 کی recipe، بس اس جگہ categorical distribution ہے جہاں Gaussian بیٹھا تھا۔ اور چونکہ true distribution one-hot ہے، اس کی entropy zero ہے، اس لیے باب 4 کی identity کے مطابق cross-entropy KL divergence کے برابر ہے: اس number کو کم کرنا اور model کے beliefs کو data کی طرف کھینچنا ایک ہی عمل ہے۔

ایک نتیجہ اپنی الگ sentence کا حق دار ہے، کیونکہ یہ پوری field کے نیچے موجود economic fact ہے۔ Labels دراصل data ہیں، ایک position shift کیے ہوئے۔ کوئی کچھ annotate نہیں کرتا۔ text کے ایک trillion tokens دراصل ایک trillion پہلے سے labelled examples ہیں، اسی لیے modern model کا training corpus «انٹرنیٹ» ہوتا ہے، نہ کہ «کسی کے بنائے ہوئے dataset»۔

کسی بھی network سے پہلے baseline: 32,033 نام، ہر line میں ایک، اور کام یہ کہ ایک ایک letter کر کے مزید ایسے نام بنائے جائیں۔1

Vocabulary میں 26 letters کے علاوہ ایک boundary symbol . ہے جو نام کے start اور end دونوں کو mark کرتا ہے، اس لیے model کو یہ سیکھنا ہے کہ نام کہاں شروع ہوتے ہیں اور کہاں رک جاتے ہیں۔ یہ 27 symbols ہیں، اور سب سے چھوٹا ممکن model ایک table ہے کہ ہر symbol کے بعد ہر دوسرا symbol کتنی بار آیا۔

bigram.pyPYTHON
N = torch.zeros((27, 27), dtype=torch.int32)
for w in words:
    cs = ["."] + list(w) + ["."]
    for a, b in zip(cs, cs[1:]):
        N[stoi[a], stoi[b]] += 1

P = N.float()
P = P / P.sum(1, keepdim=True)            # one distribution per row   

Arithmetic کی دو lines اور model fit ہو جاتا ہے — اور یہ heuristic نہیں: counts کو row totals سے divide کرنا categorical distribution کے لیے maximum-likelihood estimate ہے، یعنی باب 2 کی recipe جس کا calculus پہلے ہی ہو چکا ہے۔

TEXT
names: 32033        train/val/test: 25626 / 3203 / 3204
training bigrams: 182583

the six most likely letters after 'a':
    a -> '.'  0.1944   a -> 'n'  0.1600   a -> 'r'  0.0967
    a -> 'l'  0.0749   a -> 'h'  0.0690   a -> 'y'  0.0606

اس سے sample لیں — current letter کی row سے ایک letter pick کریں، اس row پر move کریں، boundary symbol آنے تک repeat کریں — اور آپ کو اس chapter کے شروع والے نام ملتے ہیں۔ وہ ایک specific اور informative طریقے سے fail ہوتے ہیں: locally plausible، globally nonsense۔ momakurailezitynn میں letters کا ہر adjacent pair وہ pair ہے جو حقیقی ناموں میں آتا ہے؛ بس ایسے سترہ ایک ہی row میں آ گئے ہیں۔ Model کے پاس memory کا صرف ایک letter ہے، اس لیے اسے نہیں معلوم ہو سکتا کہ وہ بہت دیر سے چل رہا ہے۔

Held-out names پر loss 2.4546 nats ہے۔ یہ number اپنے آپ میں کچھ نہیں بتاتا، اسی لیے perplexity موجود ہے:

PPL=exp ⁣(1Ttlogq(xtx<t))=eL\mathrm{PPL} = \exp\!\left(-\frac{1}{T}\sum_t \log q(x_t \mid x_{<t})\right) = e^{L}

بغیر کسی library کے اسے لکھیں تو:

perplexity.pyPYTHON
@torch.no_grad()
def perplexity(logits, Y):
    logp = F.log_softmax(logits, dim=1)          # log q for every symbol
    chosen = logp[torch.arange(len(Y)), Y]       # log q of the one that came next   
    return torch.exp(-chosen.mean())             

Exponentiating logarithm کو undo کرتا ہے اور number کو چیزیں گننے کی units میں واپس لے آتا ہے۔ یہ کیا گنتا ہے، اسے دیکھنے کا صاف طریقہ یہ ہے کہ ایک ایسے model کو measure کریں جو کچھ بھی نہیں جانتا — جو context سے قطع نظر ہر symbol کو probability 1/271/27 دیتا ہے:

TEXT
uniform over 27 symbols            loss 3.2958 nats   ppl  27.000
bigram counts, add-one smoothed    loss 2.4546 nats   ppl  11.642

بالکل 27.000، کیونکہ elog27=27e^{\log 27} = 27۔ Perplexity ان equally likely options کی effective تعداد ہے جن کے درمیان model choose کر رہا ہے۔ 27 کی perplexity کا مطلب ہے «کوئی idea نہیں، کچھ بھی ہو سکتا ہے»۔ Count model کا 11.642 مطلب ہے کہ ایک letter کا context اسے اتنا uncertain چھوڑتا ہے جتنا کوئی شخص ستائیس کے بجائے تقریباً بارہ options میں سے blindly pick کر رہا ہو — اسی لیے perplexity quote ہوتی ہے اور raw loss نہیں۔

اس کے ساتھ دو چیزیں غلط ہوتی ہیں، اور دوسری published papers میں غلط ہوتی ہے۔

Zero probabilities fatal ہیں۔ Table کے 729 cells میں سے 113 training میں کبھی نہیں آتے — اس کا 15.5 % empty ہے۔ یہ تب تک ٹھیک ہے جب تک held-out set ان میں نہ جا گرے، اور validation میں سات bigrams ایسا کرتے ہیں، جن میں dq، zj اور qo دو بار شامل ہیں۔ Probability zero کا مطلب log -\infty ہے، جس کا مطلب infinite loss اور infinite perplexity ہے: تین ہزار میں ایک نام metric کو destroy کر دیتا ہے۔ عام patch یہ ہے کہ normalise کرنے سے پہلے ہر count میں 1 add کر دیں، جس کی یہاں تقریباً کوئی cost نہیں (2.4524 کے بجائے 2.4546)۔ مگر patch ایک confession ہے۔ Count model بالکل generalise نہیں کر سکتا۔ اس کے پاس یہ suspect کرنے کا کوئی طریقہ نہیں کہ qo plausible ہے کیونکہ qu common ہے اور o دوسری جگہوں پر u کی طرح behave کرتا ہے، کیونکہ اسے یہ notion ہی نہیں کہ دو symbols ایک دوسرے سے resemble کر سکتے ہیں۔ ہر cell اکیلا learned ہوتا ہے، اور اسی کو fix کرنے کے لیے اس chapter کا باقی حصہ ہے۔

Perplexity فی token قیمت ہے، اور token ایک free parameter ہے۔ یہی mistake مسلسل نظر آتی ہے جب models compare کیے جاتے ہیں، اور دیکھنے کے بعد اسے سمجھنا آسان ہے۔ باب 7 کے English prose کے اسی corpus کو لیں، وہی interpolated bigram model، اور صرف یہ بدل دیں کہ text کیسے cut up ہوتا ہے:

unitvocabularytest میں tokenscross-entropyperplexitybits per character
characters7614,4692.521712.453.6378
BPE، 512 merges3296,8713.854747.212.6407
BPE، 2,048 merges1,8204,2335.7468313.202.4254
words2,9916,2843.562735.262.2322

Perplexity ان rows میں 25 کے factor سے vary کرتی ہے۔ Model کے بارے میں کچھ نہیں بدلا؛ صرف predicted چیز کا size بدلا۔ پورا word predict کرنا letter predict کرنے سے مشکل ہے، اس لیے فی prediction زیادہ cost آتی ہے — اور predictions کم کرنی پڑتی ہیں۔

اب آخری column پڑھیں، جو total cost کو characters کی تعداد سے divide کرتا ہے اور اسے bits میں convert کرتا ہے۔ یہ table کی ترتیب بدل دیتا ہے۔ Perplexity کے حساب سے ranking characters، words، BPE-512، BPE-2048 ہے؛ bits per character کے حساب سے words، BPE-2048، BPE-512، characters ہے۔ Character model first place سے last place پر چلا جاتا ہے۔ 2,048-merge model، جو perplexity کے حساب سے 512-merge والے سے 6.6 times بدتر لگتا ہے، حقیقت میں دونوں میں بہتر ہے: 2.6407 کے مقابلے میں 2.4254 bits۔

لہٰذا perplexity صرف ان دو models کے درمیان comparable ہے جو ایک tokenizer share کرتے ہوں، اور different tokenizers والے models صرف bits per character میں compare کیے جا سکتے ہیں — وہ quantity جسے Shannon نے 1951 میں human subjects سے English text کا next letter guess کرا کے measure کیا، اور تقریباً one bit per character پر bound کیا۔2 ہمارا best bigram 2.23 bits پر بیٹھتا ہے، جو اس chapter کو ابھی جتنا آگے جانا ہے اس کا مناسب خلاصہ ہے۔

اب اسی model کو network کے طور پر بنائیں۔ یہ اسی جگہ پہنچنے کے لیے orders of magnitude زیادہ arithmetic لے گا، اور اسی جگہ پہنچنا ہی point ہے۔

Table کو shape 27×2727 \times 27 کی ایک weight matrix WW سے replace کریں۔ Current letter کو one-hot vector میں بدلیں، multiply کریں، اور result کو logits کہیں — باب 4 کے unnormalised scores۔ پھر softmax، پھر cross-entropy، پھر gradient descent۔

neural_bigram.pyPYTHON
W = torch.randn((27, 27), requires_grad=True)

for step in range(3000):
    logits = W[xs]                            
    loss = F.cross_entropy(logits, ys)
    W.grad = None
    loss.backward()
    W.data -= 50.0 * W.grad

Highlighted line میں ایک definition ہے جسے یاد رکھنا چاہیے۔ One-hot vector کو matrix سے multiply کرنا اس کی ایک row select کرتا ہے، اس لیے multiply ایک lookup ہے — اور ہر implementation arithmetic skip کر کے lookup directly کرتی ہے، یہی W[xs] ہے۔

یہ embedding table ہے۔ ایک matrix جس میں vocabulary کی ہر entry کے لیے ایک row ہے، token id سے indexed۔ کوئی geometry نہیں، کوئی semantics نہیں، کوئی الگ algorithm نہیں: ایک lookup table جس کے contents باقی سب کے ساتھ gradient descent سے learned ہوتے ہیں۔ «embedding space» کے بارے میں ہر mystical claim یہاں آ کر ختم ہوتی ہے۔

اسے train کریں اور دیکھیں یہ کہاں جاتا ہے:

TEXT
  step     1   train 3.7550   val 3.3882   max gap to the count table 0.757269
  step   100   train 2.4732   val 2.4726   max gap to the count table 0.388354
  step  1000   train 2.4557   val 2.4549   max gap to the count table 0.041862
  step  3000   train 2.4547   val 2.4544   max gap to the count table 0.004048

آخری column softmax(W) کے کسی بھی cell اور count table کے matching cell کے درمیان largest absolute difference ہے، اور یہ zero کی طرف جاتا ہے۔ 3,000 steps کے بعد 729 cells میں کہیں بھی سب سے بڑا disagreement 0.004048 ہے اور mean 0.000224۔ Worst cell qi ہے، جو پوری training set میں بارہ بار دیکھا گیا؛ 22 rows میں جن میں ایک ہزار سے زیادہ occurrences ہیں، worst disagreement 0.000562 ہے۔

TEXT
                 count table   network
    a -> '.'        0.1945     0.1945
    a -> 'n'        0.1601     0.1601
    a -> 'r'        0.0967     0.0967

Gradient descent نے random numbers سے شروع کر کے، اور صرف یہ بتایا گیا کہ «next letter کی log-probability بڑی بناؤ»، counts کی table دوبارہ دریافت کر لی۔ اور اسے کرنا ہی تھا: counts maximum-likelihood estimate ہیں، cross-entropy negative log-likelihood ہے، لہٰذا دونوں procedures ایک ہی objective optimise کرتے ہیں اور اس objective کا ایک optimum ہے۔ Network نے counting جیسی کوئی چیز نہیں سیکھی۔ یہ آہستہ آہستہ counting پر converge ہوا۔

جس سے fair سوال اٹھتا ہے کہ کوئی bother کیوں کرے۔ کیونکہ count table یہاں سے کہیں نہیں جا سکتی، اور network جا سکتا ہے۔

Model کو ایک سے زیادہ previous character دیکھنے تک extend کریں۔ یہ Bengio کا 2003 architecture ہے، اس course کے باقی ہر model کا direct ancestor:4 last three characters لیں، ہر ایک کو embedding table کے ذریعے 10-dimensional row میں map کریں، rows کو concatenate کر کے 30 numbers بنائیں، انہیں باب 5 کی hidden layer سے گزاریں، اور output layer پر ختم کریں جو vocabulary کی ہر entry کے لیے ایک logit بناتی ہے۔

mlp.pyPYTHON
C  = torch.randn((27, 10))          # the embedding table
W1 = torch.randn((3 * 10, 200))     # the hidden layer from Chapter 5
W2 = torch.randn((200, 27))         # one output per vocabulary entry

emb = C[X].view(-1, 30)             # three lookups, concatenated   
h = torch.tanh(emb @ W1 + b1)
logits = h @ W2 + b2                
loss = F.cross_entropy(logits, Y)

نوٹ کریں کیا نیا ہے اور کیا نہیں۔ Hidden layer باب 5 والی ہے، unchanged؛ loss باب 4 والا ہے، unchanged۔ نئی چیزیں front پر embedding table اور ایک output layer ہیں جو باب 7 کی vocabulary جتنی wide ہے — اور یہ دوسری چیز ہر language model کا expensive part ہے جو کبھی بنایا گیا، کیونکہ real vocabulary میں 100,000 entries ہوتی ہیں اور یہ matrix multiply ہر position پر چلتا ہے۔

وہی code، identically trained، صرف context window کا size بدلا گیا:

contextparametersvalidation lossvalidation perplexity
counting، 1 character7292.454611.642
neural، 1 character7,8972.457711.678
neural، 3 characters11,8972.11458.285
neural، 8 characters21,8972.05067.773

دوسری row دلچسپ ہے۔ 200-unit hidden layer اور count table سے گیارہ گنا زیادہ parameters والا network count table جتنا ہی perform کرتا ہے، اس سے بہتر نہیں۔ Capacity کبھی limitation تھی ہی نہیں۔ ایک character کا context ایک خاص loss permit کرتا ہے اور آپ جو بھی bolt on کر دیں، اس سے نیچے نہیں جا سکتے، کیونکہ information وہاں ہے ہی نہیں۔

اسے تین characters دیں اور perplexity 11.68 سے 8.29 تک گر جاتی ہے — 29 % cut، 4,000 extra parameters کے بدلے۔ یہ یہاں counting کو اسی وجہ سے beat کرتا ہے جس کی diagnosis پہلے ہوئی: three-character contexts پر count model کو 273=19,68327^3 = 19{,}683 rows چاہئیں، جن میں سے زیادہ تر empty یا single observation والی ہوں گی، اور وہ ہر ایک کو اکیلا learn کرتا ہے۔ Network share کرتا ہے۔ اگر a، e اور i کی embedding rows similar ہو جائیں، تو bra کے بعد یہ جو سیکھتا ہے وہ bre پر transfer ہو جاتا ہے، بغیر اس کے کہ اس نے کبھی bre دیکھا ہو۔ یہی transfer embedding table کی پوری value ہے، اور یہی rows two اور three کے درمیان gap ہے۔

Samples بھی اسی حساب سے improve ہوتے ہیں:

TEXT
deliah   nellara   joce     kael      quintis
salayson  reety    khyrmin  mahnen    madiaryxia

اب بھی real names کی list نہیں۔ مگر deliah، nellara اور kael کسی list میں out of place نہیں لگیں گے، اور run-on monsters غائب ہیں: count model کے twenty samples میں longest انیس letters کا ہے، اس one کے twenty samples میں longest تیرہ کا۔

Embedding table کے اندر اصل میں کیا ہے

اس حصے کا لنک: Embedding table کے اندر اصل میں کیا ہے

Table 27×1027 \times 10 ہے: ہر character کے لیے ten numbers کی ایک row، سب randomly initialised، اور صرف next-character loss کے gradient سے moved۔ کسی نے وہاں کچھ نہیں رکھا۔ تو اس میں آخر آیا کیا؟

پوچھنے کا tool cosine similarity ہے، جو باب 1 کے dot product سے lengths کو divide out کر دیتا ہے:

cos(a,b)=abab\cos(\mathbf{a}, \mathbf{b}) = \frac{\mathbf{a} \cdot \mathbf{b}}{\lVert \mathbf{a} \rVert \, \lVert \mathbf{b} \rVert}

یہ دو vectors کے درمیان angle measure کرتا ہے اور ان کی lengths ignore کرتا ہے، جو آپ چاہتے ہیں جب row کی length یہ reflect کرے کہ اس کا token کتنی بار آیا، نہ کہ اس کا مطلب کیا ہے۔ پہلے ہر vector کو length 1 پر normalise کریں — جیسے real systems indexing time پر ایک بار کرتے ہیں — اور cosine similarity بس dot product رہ جاتی ہے۔

Trained table میں چند characters کے nearest neighbours یہ ہیں:

TEXT
  'c' -> 'k':+0.598      'j' -> 'z':+0.650      'i' -> 'y':+0.541
  'u' -> 'e':+0.482      'a' -> 'h':+0.367      '.' -> 'q':+0.077

اس میں سے کچھ وہی ہے جس کا folklore وعدہ کرتا ہے۔ c اور k names میں interchangeable ہیں، اور i اور y بھی؛ j اور z دونوں rare، mostly-initial consonants ہیں جو alike behave کرتے ہیں۔ Boundary symbol . تقریباً کسی چیز کے near نہیں — اپنے closest letter تک 0.077 — کیونکہ یہ واحد symbol ہے جو sound کے بجائے position mark کرتا ہے۔

اور کچھ ایسا نہیں۔ a کا nearest neighbour h ہے، کوئی دوسرا vowel نہیں۔ تمام pairs پر average کریں:

TEXT
mean cosine, vowel to vowel         : +0.1889
mean cosine, consonant to consonant : +0.0765
mean cosine, vowel to consonant     : -0.0042

Vowels ایک دوسرے سے consonants کے مقابلے میں زیادہ alike ہیں، اور effect real ہے مگر small۔ پانچ letters کے 2,000 randomly chosen groups کے against test کیا گیا تو ان groups میں سے 58 کم از کم اتنی ہی cleanly separate ہوتے ہیں — تقریباً p=0.03p = 0.03 پر significant gap۔ یعنی real ہے، مگر embeddings کے popular accounts جس crisp geometric island کا imply کرتے ہیں ویسا بالکل نہیں۔

Embedding table کی honest description یہی ہے، اور باقی course کے لیے اسے تھامے رکھنا useful ہے۔ یہ meaning کا map نہیں۔ یہ coordinates کی تبدیلی ہے، designed کے بجائے learned، جس کا واحد کام next layer کا کام آسان بنانا ہے — وہی sentence جو باب 5 نے hidden layer کے لیے use کیا تھا جس نے XOR solve کرنے کے لیے plane کو fold کیا۔ آپ کو اس میں جو structure ملتا ہے، وہ اس لیے ہے کہ اس نے loss کم کیا؛ اور جو structure loss کم نہیں کرتا وہ simply وہاں نہیں ہے۔

word2vec، GloVe، اور وہ arithmetic جسے سب quote کرتے ہیں

اس حصے کا لنک: word2vec، GloVe، اور وہ arithmetic جسے سب quote کرتے ہیں

اگر useful part table ہے، تو آپ اس کے پیچھے directly جا سکتے ہیں۔ یہی word2vec ہے: embedding lookup رکھیں، language model پھینک دیں۔5

Skip-gram with negative sampling objective ایک line ہے۔ Corpus سے drawn ایک real (centre, context) pair کے لیے ان کا dot product اوپر push کریں؛ noise distribution سے drawn kk fake pairs کے لیے اسے نیچے push کریں:6

logσ(vcvo)+i=1klogσ(vcvni)\log \sigma(\mathbf{v}_c \cdot \mathbf{v}_o) + \sum_{i=1}^{k} \log \sigma(-\mathbf{v}_c \cdot \mathbf{v}_{n_i})

یہ binary classification ہے — «کیا یہ دو words واقعی ساتھ آئے تھے؟» — اور یہ cheap اسی لیے ہے کہ یہ full vocabulary کو کبھی touch نہیں کرتا، یہی وجہ تھی کہ 2013 میں billions of words پر training practical ہوئی۔ GloVe دوسری direction سے similar vectors تک پہنچتا ہے، examples میں stream کرنے کے بجائے global co-occurrence counts کی matrix factorise کر کے۔7 دونوں exactly اسی statistic پر fitted ہیں جس سے count table بنی تھی۔ یہ counting ہے، compressed۔

text8 پر trained — English Wikipedia کے 17,005,207 words، جن میں سے 71,290 کم از کم پانچ بار آئے، 100 dimensions، تین passes — vectors اس property کے ساتھ نکلتے ہیں جس نے انہیں famous کیا:

TEXT
king     -> charles 0.700, son 0.693, queen 0.686, henry 0.669, throne 0.667
physics  -> chemistry 0.672, electromagnetism 0.661, quantum 0.654, theoretical 0.624
guitar   -> bass 0.733, vocals 0.732, acoustic 0.728, guitars 0.703, drums 0.685
three    -> seven 0.892, two 0.877, one 0.875, five 0.871, four 0.870

کسی نے instruments یا numerals کے لیے category supply نہیں کی۔ اب famous part: king لیں، man subtract کریں، woman add کریں، اور result کے nearest vector کو find کریں۔

TEXT
king - man + woman
   nothing excluded : king 0.693, elizabeth 0.657, wife 0.629, woman 0.607
   a, b, c excluded : elizabeth 0.657, wife 0.629, mary 0.607   (queen is 4th, 0.604)

king - man + woman کا nearest vector king ہے۔ یہ ایک example کی quirk نہیں۔ Mikolov کا evaluation set a : b :: c : ? کی form کے questions پوچھتا ہے — 8,869 semantic ones (paris : france :: rome : italy) اور 10,675 syntactic ones (walking : walked :: swimming : swam) — اور اس vocabulary کے answer کر سکنے والے 4,103 semantic questions میں، winner 99.8 % of the time تین input words میں سے ایک ہوتا ہے۔ Published demonstrations اسے mention نہیں کرتیں، کیونکہ standard scoring rule دیکھنے سے پہلے a، b اور c delete کر دیتا ہے۔ یہ legitimate rule ہے، اور arithmetic سے زیادہ کام یہی کر رہا ہے:

answer کیسے choose کیا گیاsemanticsyntactic
offset، inputs excluded (standard)17.0 %11.9 %
offset، کچھ excluded نہیں0.1 %0.4 %
صرف c کا nearest neighbour، inputs excluded13.1 %9.3 %
صرف b کا nearest neighbour، inputs excluded2.3 %0.4 %

تیسری row وہ ہے جس کے ساتھ بیٹھنا چاہیے۔ a اور b پھینک دیں، کوئی arithmetic نہ کریں، جو بھی c کے nearest ہو return کریں — اور آپ semantic score کا 77 % رکھ لیتے ہیں۔ جو چیز analogical reasoning لگتی ہے اس کا زیادہ حصہ proximity plus ایک rule ہے جو obvious answers کو forbid کرتا ہے، یہی Linzen نے properly trained vectors پر measure کیا اور اوپر کے baselines replicate کرتے ہیں۔8 یہ particular vectors small ہیں — 17 million words، published models کے پیچھے موجود billions کے مقابلے میں — اس لیے percentages کو shape کے طور پر پڑھیں، state of the art کے طور پر نہیں۔ Shape ہر scale پر survive کرتی ہے: arithmetic real ہے، اور اس ایک demonstration سے کہیں weak ہے جسے سب quote کرتے ہیں۔

Static اور contextual: ہر word کے لیے ایک vector، یا ہر occurrence کے لیے ایک

اس حصے کا لنک: Static اور contextual: ہر word کے لیے ایک vector، یا ہر occurrence کے لیے ایک

اب تک ہر چیز میں data structure کے اندر ایک hard limit built in ہے۔ Table میں ہر token کے لیے ایک row ہوتی ہے۔ Word bank کو ایک vector ملتا ہے، river کے بارے میں sentence میں بھی وہی، mortgage کے بارے میں sentence میں بھی وہی — necessarily، کیونکہ id سے lookup کسی اور چیز پر depend نہیں کر سکتا۔

Fix یہ ہے کہ vector کو table سے read کرنا چھوڑیں اور اسے sentence سے compute کرنا شروع کریں۔ یہ contextual embedding ہے، جسے 2018 میں ELMo نے introduce کیا اور اسی سال BERT نے standard بنا دیا۔910 Real model پر measured، numbers explanation سے زیادہ sharp ہیں:

TEXT
sentence A: "He sat on the bank of the river and watched the water go by."
sentence B: "She deposited the cheque at the bank on the corner of the street."

static vector for 'bank' (a row of the input embedding table)
    cosine A vs B ........................ 1.000000

contextual vector for 'bank', layer by layer
    layer  |  A vs B  |  A vs another river sentence  |  B vs another money sentence
        0  |  0.9512  |            0.9512             |            0.9359
        4  |  0.5647  |            0.8987             |            0.7716
        9  |  0.4284  |            0.8699             |            0.7568
       12  |  0.5278  |            0.8702             |            0.7335

پہلی row exact ہے، approximate نہیں: bank کا static vector دونوں sentences میں وہی 768 numbers ہے، اس لیے cosine construction کے لحاظ سے 1 ہے۔ نو layers بعد دونوں occurrences 0.43 پر بیٹھتے ہیں، جبکہ دو different river sentences میں bank 0.87 پر رہتا ہے۔ اس process میں کہیں کوئی sense label نہیں کیا گیا؛ senses اس لیے separate ہوئے کہ ان کو separate کرنا training objective — neighbours سے hidden token guess کرنا — satisfy کرنا آسان بناتا ہے۔

دو details attention کے قابل ہیں۔ Layer 0 پہلے ہی 1.0 کے بجائے 0.9512 ہے، کیونکہ position embeddings add ہو چکی ہیں اور word ہر sentence میں different place پر بیٹھا ہے۔ اور layers 11 اور 12 پر similarity دوبارہ بڑھتی ہے: pretrained model کی final layers اس کے training objective کے لیے specialised ہوتی ہیں، اور representation لینے کے لیے اکثر best جگہ نہیں ہوتیں۔

تفصیلات دکھائیں

Optional: weight tying۔

bert-base-uncased میں embedding table 30,522×76830{,}522 \times 768 ہے — 23,440,896 numbers، model کے 109,482,240 parameters کا 21.4 %۔ Small language model میں fraction اس سے بھی بڑا ہوتا ہے، اسی لیے ایک trick تقریباً universal ہے: input table اور logits produce کرنے والی output layer وہی matrix ہیں، ایک بار row lookup سے used، اور ایک بار transposed۔ Output layer پہلے ہی ہر vocabulary entry کو vector assign کرتی ہے — یہ ہر ایک کے against dot product لیتی ہے — اور tying کہتا ہے کہ token کو read کرنے کے لیے استعمال ہونے والا vector اور اسے write کرنے کے لیے استعمال ہونے والا vector ایک ہی object ہونا چاہیے۔ یہ parameters کم کرتا ہے اور perplexity بھی improve کرتا ہے، جو notice کرنے کے لیے کافی rare ہے۔

Corpus کو meaning کے لحاظ سے search کرنے کے لیے آپ کو ہر sentence کے لیے ایک vector چاہیے۔ وہ مل جائیں تو search trivial ہے — semantic retrieval کا کل یہی ہے، اور باب 19 اس کے around ہر چیز کے بارے میں ہے:

search.pyPYTHON
E = normalise(embed(sentences))       # (200, d), every row of length 1
q = normalise(embed([query]))         # (1, d)
scores = q @ E.T                      # one matrix multiply   
top5 = scores[0].argsort()[::-1][:5]

تو اصل سوال صرف یہ ہے کہ embed کہاں سے آتا ہے۔ Obvious move یہ ہے کہ pretrained language model لیں، ہر sentence کو اس سے گزاریں اور token vectors کا average لے لیں۔ یہاں وہ method چار alternatives کے against ہے، دو ways سے scored: STS benchmark کے 1,379 pairs پر cosine اور human similarity judgements کے درمیان rank correlation، اور ان pairs میں سے 200 most strongly paraphrased pairs سے بنے index پر top-1 retrieval — ہر pair کی ایک side indexed، دوسری query کے طور پر used۔

sentence کیسے embedded ہےrank correlation200-sentence index پر top-1
binary word overlap (کوئی model نہیں)0.550089.0 %
اوپر trained static vectors کا mean0.526385.5 %
BERT، [CLS] token0.203067.0 %
BERT، token vectors کا mean0.472984.0 %
MiniLM، contrastively trained0.820392.0 %

Middle three rows کو first two کے against پڑھیں۔ 109-million-parameter pretrained transformer، obvious way میں used، sentence similarity judge کرنے میں دو sentences کے shared words count کرنے سے بھی بدتر ہے — اور کچھ دیر پہلے trained 100-dimensional text8 vectors کو average کرنے سے بھی بدتر۔ [CLS] token، جسے tutorials اب بھی recommend کرتے ہیں کیونکہ BERT ایک sentence-level objective کے ساتھ pretrained تھا، اس کے آدھے سے بھی worse ہے۔

یہ BERT کا defect نہیں۔ یہ objective ہے۔ Language model اس طرح trained ہوتا ہے کہ اس کی hidden states token predict کریں؛ وہاں کچھ نہیں کہتا کہ دو paraphrases ایک دوسرے کے near end up ہوں، اور ایسی geometry کو کوئی reward نہیں ملتا جس میں cosine کا مطلب «same meaning» ہو۔ آخری row ایک ایسا model ہے جو size کا پانچواں حصہ ہے (22,713,216 parameters) اور بالکل different loss پر trained ہے: contrastive learning، جہاں examples pairs ہوتے ہیں — question اور اس کا answer، sentence اور اس کا paraphrase — اور objective true pairs کو together pull کرتا ہے جبکہ sampled negatives کو apart push کرتا ہے۔ یہی Sentence-BERT کی contribution ہے اور پوری embedding-model industry کی origin۔11 Dense Passage Retrieval یہی recipe direct search پر apply کرتا ہے، queries کے لیے ایک encoder اور passages کے لیے ایک encoder کے ساتھ۔12

لہٰذا practical rule:

Embedding model ایسا language model نہیں جس کی last layer removed ہو۔ یہ different objective پر different model ہے، عموماً بہت smaller، جس کا cosine وہی meaning رکھتا ہے جو آپ چاہتے ہیں کیونکہ یہ ایسے pairs پر trained تھا جہاں target یہی تھا۔ اوپر کی table ایک کو دوسرے کی جگہ استعمال کرنے کی cost ہے۔

اور یہ family word order پر fail ہوتی ہے۔ «The dog bit the man» اور «the man bit the dog» کے bags of words identical ہیں، اس لیے word overlap اور static-vector average انہیں cosine exactly 1.000000 دیتے ہیں، اور mean-pooled BERT، جو position دیکھتا ہے، پھر بھی تقریباً وہیں land کرتا ہے — اور contrastively trained MiniLM بھی انہیں 0.979 پر رکھتا ہے۔ اگر آپ کا retrieval task اس بات پر turn کرتا ہے کہ کس نے کس کے ساتھ کیا کیا، تو کوئی cosine threshold آپ کو نہیں بچائے گا۔

باب 19 اسی footing پر production retrieval system بناتا ہے اور ایک concrete cosine cut-off تک پہنچتا ہے۔ اس chapter کی آخری measurement ہی ایسے number کو magic کے بجائے defensible بناتی ہے۔

Real embeddings میں hundreds یا thousands of components ہوتے ہیں، اور وہاں distances عجیب behave کرتے ہیں۔ dd dimensions کے unit cube میں 1,000 random points لیں اور ان میں کسی بھی دو points کے درمیان largest اور smallest distance کا ratio دیکھیں:

dimensionsnearest pairfarthest pairratio
20.00071.36121921.66
100.23612.33979.91
1003.00475.17521.72
1,00011.780914.03061.19
10,00039.615242.01251.06

دس ہزار dimensions میں points کا farthest pair closest pair سے صرف 6 % زیادہ دور ہے۔ ہر چیز تقریباً ہر دوسری چیز سے equidistant ہے، «nearest neighbour» زیادہ information carry کرنا چھوڑ دیتا ہے، اور یہی curse of dimensionality ہے — ساتھ ہی یہ بھی ایک وجہ ہے کہ large vector databases exact nearest-neighbour search نہیں کرتے۔ اسی coin کی دوسری side وہ ہے جو cosine thresholds کو workable بناتی ہے: random unit vectors کے ایک ہزار pairs پر measured، mean cosine 100 dimensions میں 0.0052-0.0052 اور 768 میں +0.0003+0.0003 پر بیٹھتا ہے، standard deviations 0.0968 اور 0.0357 کے ساتھ — اور 768 dimensions میں random pairs میں سے صرف 0.2 % absolute value میں 0.1 سے exceed کرتے ہیں۔ اس لیے 0.4 کی measured similarity «40 % alike» نہیں؛ یہ chance سے پیدا ہونے والی کسی بھی چیز سے بہت باہر ہے، اسی لیے 0.3 اور 0.7 کے درمیان thresholds signal کو noise سے separate کرتے ہیں، اس کے بیچ میں نہیں بیٹھتے۔

اس chapter کا model previous characters کی fixed تعداد پڑھتا ہے، ہر ایک کو look up کرتا ہے اور results کو order میں glue کر دیتا ہے۔ اس design کے دو problems ہیں، اور وہ ایک ہی problem ہیں۔

Context table کو دوبارہ دیکھیں: three characters سے eight تک جانا parameters کو تقریباً double کر گیا اور 0.06 nats خریدے۔ Cost context کے ساتھ linearly grow کرتی ہے — ہر extra position کو first weight matrix کا اپنا slab چاہیے — اور benefit نہیں۔ اسے thousand tokens تک push کریں تو first layer اکیلی باقی model سے heavier ہو جاتی ہے، اس کا زیادہ حصہ ان positions پر خرچ ہوتا ہے جو کسی given prediction کے لیے matter نہیں کرتیں۔

یہی second problem ہے: model کے پاس یہ decide کرنے کا کوئی طریقہ نہیں کہ previous tokens میں سے کون سے matter کرتے ہیں۔ Position two کو اپنے weights ملتے ہیں اور position seven کو اپنے، permanently، چاہے ان میں کچھ بھی ہو۔ جب model nell spell کر رہا ہو، decisive character وہ ہے جو immediately before ہے۔ جب sentence میں pronoun ہو، تو اس کا referent fix کرنے والا word چالیس tokens پیچھے ہو سکتا ہے — اور کوئی fixed slot «forty back» کو assign نہیں کیا جا سکتا، کیونکہ اگلی بار وہ six ہوگا۔

ہمیں ایسا model چاہیے جو ہر prediction کے لیے compute کرے کہ ہر earlier token کو کتنا count کرنا چاہیے — context پر weights جو layout سے fixed ہونے کے بجائے content سے produced ہوں۔ اسے carefully لکھیں تو یہ بالکل mundane چیز کے طور پر شروع ہوتا ہے: previous tokens کا average۔ پھر اس average کے weights learned ہونے دیں، اور انہیں اس token پر depend کرنے دیں جو ask کر رہا ہے۔

یہ attention ہے، اور یہی باب 9 ہے۔


ساتھ پڑھنے کے لیے یہ بھی valuable ہے: Jurafsky اور Martin کی Speech and Language Processing کا chapter 3، جو n-gram models، smoothing اور perplexity کو یہاں دستیاب space سے کہیں زیادہ carefully treat کرتا ہے، including یہ کہ interpolation اور back-off adding one سے کیوں بہتر ہیں؛ probabilistic side سے language modelling کے لیے Stanford CS229 notes §17.1–17.2؛ اور اوپر Linzen کا paper، جو short ہے اور پورا پڑھنے کے قابل ہے۔

  1. Name-generation example، dataset، اور count table سے Bengio-style network تک progression Andrej Karpathy کی building makemore series کو follow کرتے ہیں، جس کے first two parts اس chapter کے best companion ہیں۔

  2. Shannon, C. E. Prediction and Entropy of Printed English. Bell System Technical Journal 30(1), pp. 50–64 (1951). Human subjects کا English کا next letter guess کرنا، اور اصل bits-per-character measurement۔

  3. Shannon, C. E. A Mathematical Theory of Communication. Bell System Technical Journal 27 (1948). Source coding theorem، اور prediction کی compression کے ساتھ identification۔

  4. Bengio, Y., Ducharme, R., Vincent, P. and Jauvin, C. A Neural Probabilistic Language Model. Journal of Machine Learning Research 3, pp. 1137–1155 (2003). اوپر use کیا گیا architecture: ہر word کے لیے ایک embedding، fixed window پر concatenated، hidden layer سے گزر کر vocabulary پر softmax تک۔

  5. Mikolov, T., Chen, K., Corrado, G. and Dean, J. Efficient Estimation of Word Representations in Vector Space. arXiv:1301.3781 (2013). CBOW اور skip-gram، اور اوپر use کیا گیا analogy set۔

  6. Mikolov, T., Sutskever, I., Chen, K., Corrado, G. and Dean, J. Distributed Representations of Words and Phrases and their Compositionality. arXiv:1310.4546 (2013). Negative sampling، frequent words کی subsampling، اور اوپر used noise distribution کو 3/4 power تک raise کرنا۔

  7. Pennington, J., Socher, R. and Manning, C. GloVe: Global Vectors for Word Representation. EMNLP 2014. Streamed local windows کے بجائے global co-occurrence matrix کی factorisation سے word vectors۔

  8. Linzen, T. Issues in evaluating semantic spaces using word analogies. RepEval 2016، arXiv:1606.07736. اوپر replicate کیے گئے offset-free baselines کا source۔

  9. Peters, M. et al. Deep contextualized word representations. arXiv:1802.05365 (2018). ELMo: ہر occurrence کے لیے ایک vector، bidirectional language model سے computed۔

  10. Devlin, J., Chang, M.-W., Lee, K. and Toutanova, K. BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding. arXiv:1810.04805 (2018). bank experiment میں measured model۔

  11. Reimers, N. and Gurevych, I. Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks. arXiv:1908.10084 (2019). اس کی opening measurement — sentence similarity پر mean-pooled BERT کا averaged static vectors سے underperform کرنا — وہی ہے جسے اوپر کی table reproduce کرتی ہے۔

  12. Karpukhin, V. et al. Dense Passage Retrieval for Open-Domain Question Answering. arXiv:2004.04906 (2020). Two-encoder retriever کی contrastive training؛ باب 19 کے retrieval stack کا direct ancestor۔


تیار کردہ

David Vicente Campos

NeuraLIA Labs کے بانی اور MyRealFood کے شریک بانی

میں یونیورسٹی آف لیون سے کمپیوٹر انجینئر ہوں۔ میں نے MyRealFood کی مشترکہ بنیاد رکھی، جہاں بطور CTO میں نے وہ ایپ بنائی جسے لاکھوں لوگ بہتر غذا کے لیے استعمال کر چکے ہیں، اور میں نے NeuraLIA Labs قائم کیا، جہاں میں AI مصنوعات بناتا ہوں۔ یہاں میں ان باتوں کے بارے میں لکھتا ہوں جو اس سفر میں مجھے سمجھنی پڑیں، اس طرح جس طرح کاش کسی نے مجھے سمجھائی ہوتیں۔

مصنف کے بارے میں مزید

NeuraLIA Labs کی جانب سے شائع کردہ۔

نئی پوسٹس اپنے ان باکس میں پائیں

AI کی خبریں، گائیڈز اور پروڈکٹ اپ ڈیٹس — جب ہم آپ کے وقت کے قابل کچھ شائع کریں تو ایک مختصر ای میل۔

کورس انڈیکس

Abstract software decision engine with branching paths, probability nodes, and glowing gates.
jev14 منٹ مطالعہ

Jev AI ماڈل فیصلوں کے لیے بنایا گیا ہے، نثر کے لیے نہیں

TypeSafe AI کا Jev اس لیے توجہ کھینچ رہا ہے کہ یہ software intelligence کو احتمال کے مسئلے کے طور پر دیکھتا ہے: درست branch چنیں، confidence منسلک کریں، اور جب code کو فیصلہ چاہیے ہو تو text لکھوانے کے لیے LLM کو ادائیگی سے بچیں۔

Abstract agent runtime sorting documents, memory blocks and pointer nodes inside a bounded context frame.
context-engineering14 منٹ مطالعہ

طویل مدتی AI ایجنٹس کے لیے کانٹیکسٹ انجینئرنگ

طویل عرصے تک چلنے والے ایجنٹس صرف اس لیے ناکام نہیں ہوتے کہ ونڈو چھوٹی ہے۔ وہ اس وقت ناکام ہوتے ہیں جب فائلیں، ٹول آؤٹ پٹس اور پرانی ہسٹری اس کام کو باہر دھکیل دیتی ہیں جسے ایجنٹ نے مکمل کرنا تھا۔

ماڈل چننے کا کام LIA کے سپرد کرنے کے لیے تیار ہیں؟

ہر AI ماڈل ایک ہی جگہ — آج ہی مفت شروع کریں۔