Faza 05 · lecția 03
Reprezentări vectoriale ale cuvintelor — Word2Vec de la zero
Scopul lecției: Un cuvânt este compania pe care o păstrează. Antrenați o rețea superficială pe această idee și apare geometria.
Versiunea curentă AlexBred.com: primele 100 de lecții ale programului în limba română.
Cuprinsul lecției
- Problema
- Conceptul
- Construiți
- Pasul 1: perechi de antrenare dintr-un corpus
- Pasul 2: tabele de reprezentări vectoriale
- Pasul 3: obiectivul cu eșantionare negativă
- Pasul 4: antrenați pe un corpus-jucărie
- Pasul 5: trucul analogiei
- Folosiți
- Când Word2Vec încă câștigă în 2026
- Unde Word2Vec eșuează
- Livrați
- Exerciții
- Termeni-cheie
- Lecturi suplimentare
Un cuvânt este compania pe care o păstrează. Antrenați o rețea superficială pe această idee și apare geometria.
Tip: Construire Limbaje: Python Cerințe prealabile: Faza 5 · 02 (BoW + TF-IDF), Faza 3 · 03 (retropropagare de la zero) Timp: ~75 de minute
Problema
TF-IDF știe că dog și puppy sunt cuvinte diferite. Nu știe că ele înseamnă aproape același lucru. Un clasificator antrenat pe dog nu poate generaliza la o recenzie despre puppy. Puteți acoperi acest gol cu o listă de sinonime, dar aceasta eșuează pentru termeni rari, jargon de domeniu și fiecare limbă pe care nu ați anticipat-o.
Vă doriți o reprezentare în care dog și puppy ajung apropiate în spațiu. În care king - man + woman ajunge aproape de queen. În care un model antrenat pe dog transferă gratuit o parte din semnal către puppy.
Word2Vec ne-a oferit acest spațiu. O rețea neuronală cu două straturi, rulări de antrenare pe trilioane de tokenuri, publicată în 2013. Arhitectura este aproape jenant de simplă. Rezultatele au remodelat NLP-ul timp de un deceniu.
Notă tehnică a traducerii: Lucrarea Word2Vec din 2013 raportează, pentru experimentele sale, un set de 1,6 miliarde de cuvinte, nu o rulare identificată de „trilioane de tokenuri”. Dimensiunea corpusului, tokenizarea, obiectivul și hardware-ul determină atât calitatea, cât și costul; nu transformați această afirmație istorică într-o specificație generală. Consultați lucrarea originală despre arhitecturile Word2Vec.
Conceptul
Ipoteza distribuțională (Firth, 1957): „Veți cunoaște un cuvânt după compania pe care o păstrează.” Dacă două cuvinte apar în contexte asemănătoare, probabil că au sensuri asemănătoare.
Word2Vec are două variante, ambele exploatând această idee.
- Skip-gram. Dat fiind un cuvânt central, preziceți cuvintele din jur.
cat -> (the, sat, on)cu o fereastră de dimensiune 2. - CBOW (continuous bag of words). Date fiind cuvintele din jur, preziceți cuvântul central.
(the, sat, on) -> cat.
Skip-gram se antrenează mai lent, dar gestionează mai bine cuvintele rare. A devenit varianta implicită.
Rețeaua are un strat ascuns fără neliniaritate. Intrarea este un vector one-hot peste vocabular. Ieșirea este un softmax peste vocabular. După antrenare, eliminați stratul de ieșire. Ponderile stratului ascuns sunt reprezentările vectoriale.
one-hot(cuvânt central) ── W ──▶ strat ascuns (d dim.) ── W' ──▶ softmax(vocabular)
^
aceasta este reprezentarea vectorială
Notă tehnică a traducerii: Avantajul Skip-gram pentru cuvinte rare depinde de corpus, frecvențe, dimensiunea ferestrei, subeșantionare și configurația de antrenare; nu este o regulă universală. După antrenare există două tabele,
WșiW'; alegerea luiW, a luiW'sau a unei combinații este parte din protocolul de evaluare, nu o proprietate obligatorie a tuturor implementărilor.
Trucul este următorul: softmax peste 100k de cuvinte este prohibitiv de costisitor. Word2Vec folosește eșantionarea negativă pentru a o transforma într-o sarcină de clasificare binară. Preziceți „acest cuvânt de context a apărut lângă acest cuvânt central, da sau nu”. Eșantionați câteva cuvinte negative (care nu coapar) pentru fiecare pereche de antrenare, în loc să calculați softmax peste întreg vocabularul.
Notă tehnică a traducerii: În eșantionarea negativă, nu se garantează că un cuvânt de zgomot nu coapare în întreg corpusul; cuvintele sunt extrase dintr-o distribuție de zgomot. Implementarea Word2Vec uzuală modelează acea distribuție după frecvență, de regulă cu exponentul
0.75, nu uniform. Consultați documentația gensim și lucrarea despre negative sampling.
word-vector-arithmetic
Notă tehnică a traducerii: Cheia figurii
word-vector-arithmeticeste mapată explicit la SVG-ul originalword2vec.svg; diagrama este păstrată fără modificări. Relațiaking - man ≈ queen - womaneste o ilustrație geometrică, nu un test reproductibil de calitate sau de „înțelegere”. Astfel de direcții pot reflecta și stereotipuri din corpus; evaluați efectele asupra sarcinii și asupra grupurilor afectate. Consultați Bolukbasi et al..
Construiți
Pasul 1: perechi de antrenare dintr-un corpus
def skipgram_pairs(docs, window=2):
pairs = []
for doc in docs:
for i, center in enumerate(doc):
for j in range(max(0, i - window), min(len(doc), i + window + 1)):
if i == j:
continue
pairs.append((center, doc[j]))
return pairs
>>> skipgram_pairs("the", "cat", "sat", "on", "mat", window=2)
[('the', 'cat'), ('the', 'sat'),
('cat', 'the'), ('cat', 'sat'), ('cat', 'on'),
('sat', 'the'), ('sat', 'cat'), ('sat', 'on'), ('sat', 'mat'),
...]
Fiecare pereche (central, context) dintr-o fereastră este un exemplu pozitiv de antrenare.
Notă tehnică a traducerii: Fragmentul atribuie aceeași pondere tuturor pozițiilor din fereastra fixă. Implementările Word2Vec pot eșantiona dimensiunea efectivă a ferestrei și subeșantiona cuvintele foarte frecvente; tratați această funcție ca generator didactic de perechi, nu ca reproducere completă a antrenării originale.
Pasul 2: tabele de reprezentări vectoriale
Două matrici. W este tabelul reprezentărilor pentru cuvântul central (cel pe care îl păstrați). W' este tabelul pentru cuvântul de context (adesea eliminat, uneori mediat cu W).
import numpy as np
def init_embeddings(vocab_size, dim, seed=0):
rng = np.random.default_rng(seed)
W = rng.normal(0, 0.1, size=(vocab_size, dim))
W_prime = rng.normal(0, 0.1, size=(vocab_size, dim))
return W, W_prime
Inițializare aleatoare mică. Un vocabular de 10k și dimensiunea 100 sunt realiste; pentru predare, 50 de cuvinte în vocabular și dimensiunea 16 sunt suficiente pentru a observa geometria.
Pasul 3: obiectivul cu eșantionare negativă
Pentru fiecare pereche pozitivă (center, context), eșantionați k cuvinte aleatoare din vocabular ca negative. Antrenați modelul astfel încât produsul scalar W[center] · W'[context] să fie mare pentru pozitive și mic pentru negative.
def sigmoid(x):
return 1.0 / (1.0 + np.exp(-np.clip(x, -20, 20)))
def train_pair(W, W_prime, center_idx, context_idx, negative_indices, lr):
v_c = W[center_idx]
u_pos = W_prime[context_idx]
u_negs = W_prime[negative_indices]
pos_score = sigmoid(v_c @ u_pos)
neg_scores = sigmoid(u_negs @ v_c)
grad_center = (pos_score - 1) * u_pos
for i, u in enumerate(u_negs):
grad_center += neg_scores[i] * u
W[context_idx] = W[context_idx]
W_prime[context_idx] -= lr * (pos_score - 1) * v_c
for i, neg_idx in enumerate(negative_indices):
W_prime[neg_idx] -= lr * neg_scores[i] * v_c
W[center_idx] -= lr * grad_center
Formula magică: pierderea logistică pentru perechea pozitivă (doriți sigmoid aproape de 1), plus pierderea logistică pentru perechile negative (doriți sigmoid aproape de 0). Gradienții ajung la ambele tabele. Derivarea completă se află în lucrarea originală; parcurgeți-o o dată cu creionul și hârtia dacă doriți să o rețineți.
Notă tehnică a traducerii: Codul trebuie păstrat exact, însă este o demonstrație, nu o implementare completă. Instrucțiunea
W[context_idx] = W[context_idx]nu modifică nimic. Eșantioanele negative pot conține duplicate și, după filtrarea indicilor, pot fi mai puține decâtk; lipsesc distribuția de frecvență, validările de intrare și monitorizarea pierderii. Limitarea logiturilor la[-20, 20]evită overflow-ul numeric, dar nu înlocuiește o implementare stabilă și verificată a obiectivului.
Pasul 4: antrenați pe un corpus-jucărie
def train(docs, dim=16, window=2, k_neg=5, epochs=100, lr=0.05, seed=0):
vocab = build_vocab(docs)
vocab_size = len(vocab)
rng = np.random.default_rng(seed)
W, W_prime = init_embeddings(vocab_size, dim, seed=seed)
pairs = skipgram_pairs(docs, window=window)
for epoch in range(epochs):
rng.shuffle(pairs)
for center, context in pairs:
c_idx = vocab[center]
ctx_idx = vocab[context]
negs = rng.integers(0, vocab_size, size=k_neg)
negs = [n for n in negs if n != ctx_idx and n != c_idx]
train_pair(W, W_prime, c_idx, ctx_idx, negs, lr)
return vocab, W
După suficiente epoci pe un corpus mare, cuvintele care împart contexte au reprezentări centrale asemănătoare. Pe un corpus-jucărie, observați efectul slab. Pe miliarde de tokenuri, îl observați spectaculos.
Notă tehnică a traducerii: Acest bloc presupune existența lui
build_vocab, dar lecția nu îl definește; folosiți funcția din lecția precedentă sau o implementare echivalentă. Fișierul localcode/main.pynu este identic cu fragmentul: el defineștebuild_vocab, produce mai mulți candidați negativi înainte de filtrare și elimină instrucțiunea fără efect. Nu comparați direct rezultatele lor ca și cum ar proveni din aceeași implementare.
Pasul 5: trucul analogiei
def nearest(vocab, W, target_vec, topk=5, exclude=None):
exclude = exclude or set()
inv_vocab = {i: w for w, i in vocab.items()}
norms = np.linalg.norm(W, axis=1, keepdims=True) + 1e-9
W_norm = W / norms
target = target_vec / (np.linalg.norm(target_vec) + 1e-9)
sims = W_norm @ target
order = np.argsort(-sims)
out = []
for i in order:
if i in exclude:
continue
out.append((inv_vocab[i], float(sims[i])))
if len(out) == topk:
break
return out
def analogy(vocab, W, a, b, c, topk=5):
v = W[vocab[b]] - W[vocab[a]] + W[vocab[c]]
return nearest(vocab, W, v, topk=topk, exclude={vocab[a], vocab[b], vocab[c]})
Pe vectori Google News preantrenați de 300d:
>>> analogy(vocab, W, "man", "king", "woman")
[('queen', 0.71), ('monarch', 0.62), ('princess', 0.59), ...]
king - man + woman = queen. Nu pentru că modelul știe ce este regalitatea. Ci pentru că vectorul (king - man) surprinde ceva asemănător cu „regal”, iar adăugarea lui la woman ajunge aproape de regiunea regală-feminină.
Notă tehnică a traducerii: Rezultatul depinde de vocabularul exact, normalizare și checkpoint; funcția ridică
KeyErrorcând unul dintre cuvinte lipsește. Analogiiile sunt evaluări intrinseci limitate și nu demonstrează înțelegere semantică, robustețe sau performanță downstream. Pentru un vector țintă nul, epsilonul doar evită împărțirea la zero, iar ordinea rezultatelor poate fi neinformativă.
Folosiți
Scrierea Word2Vec de la zero este pentru predare. NLP-ul de producție folosește gensim.
from gensim.models import Word2Vec
sentences = [
["the", "cat", "sat", "on", "the", "mat"],
["the", "dog", "ran", "across", "the", "room"],
]
model = Word2Vec(
sentences,
vector_size=100,
window=5,
min_count=1,
sg=1,
negative=5,
workers=4,
epochs=30,
)
print(model.wv["cat"])
print(model.wv.most_similar("cat", topn=3))
Notă tehnică a traducerii: Aceasta este interfața gensim 4.x:
sg=1selectează Skip-gram, iarnegative=5selectează cinci cuvinte de zgomot. Pentru reproducibilitate nu sunt suficiente aceleași date:workers=4introduce variații de ordonare; documentația recomandăworkers=1, unseedfix și controlulPYTHONHASHSEEDpentru rulări deterministe. În producție, fixați și versiunea gensim, tokenizarea și pragulmin_count.
Pentru lucru real, aproape niciodată nu antrenați Word2Vec personal. Descărcați vectori preantrenați.
- GloVe — abordarea Stanford de factorizare a matricei de coapariții. Checkpointuri de 50d, 100d, 200d, 300d. Acoperire generală bună. Lecția 04 tratează GloVe în mod specific.
- fastText — extensia Facebook a Word2Vec care reprezintă n-grame de caractere. Gestionează cuvinte din afara vocabularului compunând subcuvinte. Lecția 04.
- Word2Vec preantrenat pe Google News — 300d, vocabular de 3M de cuvinte, publicat în 2013. Încă este descărcat zilnic.
Notă tehnică a traducerii: Alegeți un checkpoint după corpus, limbă, dimensiune, licență și versiune, nu doar după nume. fastText produce vectori OOV din modelul binar; un fișier text conține numai vectorii deja listați. Dimensiunile și disponibilitatea checkpointurilor GloVe sau Google News nu sunt garanții permanente. Consultați fastText și GloVe.
Când Word2Vec încă câștigă în 2026
- Regăsire ușoară specifică domeniului. Antrenați pe rezumate medicale într-o oră pe un laptop, obțineți vectori specializați pe care niciun model general nu îi surprinde.
- Inginerie de caracteristici de tip analogie.
gender_vector = mean(man - woman pairs). Scădeți-l din alte cuvinte pentru a obține o axă neutră de gen. Încă este folosit în cercetarea despre echitate. - Interpretabilitate. Dimensiunea 100 este suficient de mică pentru a o reprezenta prin PCA sau t-SNE și pentru a observa efectiv formarea clusterelor.
- Oriunde inferența trebuie să ruleze pe dispozitiv fără GPU. Căutarea Word2Vec este extragerea unui singur rând.
Notă tehnică a traducerii: Acestea sunt recomandări dependente de sarcină, nu avantaje garantate în 2026. Timpul de răspuns include tokenizarea, agregarea vectorilor, accesul la memorie și restul sistemului, nu doar extragerea unui rând. O direcție
gender_vectormăsoară asocieri ale corpusului; simpla scădere a ei nu certifică neutralitate sau echitate și trebuie evaluată separat pentru cazul de utilizare.
Unde Word2Vec eșuează
Zidul polisemiei. bank are un singur vector. river bank și financial bank îl împart. table (foaie de calcul față de mobilă) îl împarte. Un clasificator din aval nu poate distinge sensurile din vector.
Reprezentările contextuale (ELMo, BERT, fiecare Transformer de atunci) au rezolvat această problemă producând un vector diferit pentru fiecare apariție a cuvântului pe baza contextului înconjurător. Acesta este saltul de la Word2Vec la BERT: de la static la contextual. Faza 7 acoperă jumătatea Transformer.
Problema cuvintelor din afara vocabularului este celălalt eșec. Word2Vec nu a văzut niciodată Zoomer-approved dacă nu era în datele de antrenare. Nu are rezervă. fastText rezolvă aceasta prin compunerea subcuvintelor (lecția 04).
Notă tehnică a traducerii: Reprezentările contextuale atenuează polisemie, dar nu elimină ambiguitatea, schimbarea de domeniu sau părtinirile. Modelul static Word2Vec nu poate produce un vector pentru o cheie OOV, iar fastText oferă o compunere de subcuvinte, nu garanția unui sens corect pentru un termen nou.
Livrați
Salvați ca outputs/skill-embedding-probe.md:
---
name: embedding-probe
description: Inspectați un model word2vec. Rulați analogii, găsiți vecini, diagnosticați calitatea.
version: 1.0.0
phase: 5
lesson: 03
tags: [nlp, embeddings, debugging]
---
Examinați reprezentări vectoriale de cuvinte antrenate pentru a verifica dacă funcționează. Dat fiind un obiect `gensim.models.KeyedVectors` și un vocabular, rulați:
1. Trei teste canonice de analogie. `king : man :: queen : woman`. `paris : france :: tokyo : japan`. `walking : walked :: swimming : ?`. Raportați rezultatul top-1 și cosinusul său.
2. Cinci teste ale celor mai apropiați vecini pentru cuvinte specifice domeniului furnizate de utilizator. Afișați primii 5 vecini cu cosinusuri.
3. O verificare de simetrie. `similarity(a, b) == similarity(b, a)` până la precizia în virgulă mobilă.
4. O verificare degenerată. Dacă vreun embedding are o normă sub 0.01 sau peste 100, modelul are un bug de antrenare. Semnalați-l.
Refuzați să declarați un model bun numai pe baza preciziei analogiilor. Benchmarkurile de analogii pot fi optimizate artificial și nu se transferă la sarcinile din aval. Recomandați împreună evaluare intrinsecă și downstream.
Notă tehnică a traducerii: Simetria cosinusului este în principal o proprietate matematică a metricii, nu o verificare a calității modelului. Pragurile de normă
0.01și100sunt arbitrare și depind de inițializare, regularizare și obiectiv. Folosiți teste de date, pierdere, acoperire OOV și evaluări downstream; nu declarați un bug sau un model bun numai din aceste patru sonde.
Exerciții
- Ușor. Rulați bucla de antrenare pe un corpus mic (20 de propoziții despre pisici și câini). După 200 de epoci, verificați că
nearest(vocab, W, W[vocab["cat"]])returneazădogîn primii 3. Dacă nu, creșteți numărul de epoci sau vocabularul. - Mediu. Adăugați subeșantionarea cuvintelor frecvente. Cuvintele cu frecvența peste
10^-5sunt eliminate din perechile de antrenare cu o probabilitate proporțională cu frecvența lor. Măsurați efectul asupra similarității cuvintelor rare. - Dificil. Antrenați un model pe corpusul 20 Newsgroups. Calculați două axe de părtinire:
he - sheșidoctor - nurse. Proiectați cuvinte despre ocupații pe ambele axe. Raportați ocupațiile cu cel mai mare decalaj de părtinire. Acesta este tipul de sondă folosit de cercetătorii în echitate.
Notă tehnică a traducerii: Exercițiul 1 nu are un rezultat garantat pe un corpus mic; fixați corpusul, seed-ul și criteriul de evaluare. Pentru exercițiul 2, formula completă a probabilității de subeșantionare trebuie aleasă și documentată; pragul singur nu o definește. Pentru exercițiul 3, proiecțiile descriu asocieri ale setului de date, nu o măsură suficientă de echitate; raportați incertitudinea, procesarea și limitele interpretării.
Termeni-cheie
| Termen | Ce spun oamenii | Ce înseamnă de fapt |
|---|---|---|
| Reprezentare vectorială a cuvântului (word embedding) | Cuvânt ca vector | Reprezentare densă, cu dimensiune mică (de obicei 100–300), învățată din context. |
| Skip-gram | Trucul Word2Vec | Prezice cuvintele de context din cuvântul central. Mai lent decât CBOW, mai bun pentru cuvinte rare. |
| Eșantionare negativă | Scurtătură de antrenare | Înlocuiește softmax peste vocabularul complet cu clasificare binară față de k cuvinte aleatoare. |
| Reprezentare statică | Un vector pentru fiecare cuvânt | Același vector indiferent de context. Eșuează la polisemie. |
| Reprezentare contextuală | Vector sensibil la context | Vector diferit pentru fiecare apariție, bazat pe cuvintele din jur. Ceea ce produc Transformerele. |
| OOV | În afara vocabularului | Cuvânt nevăzut la antrenare. Word2Vec nu poate produce un vector pentru el. |
Lecturi suplimentare
- Mikolov et al. (2013). Reprezentări distribuite ale cuvintelor și frazelor și compoziționalitatea lor — lucrarea despre negative sampling. Scurtă și ușor de citit.
- Rong, X. (2014). Învățarea parametrilor word2vec explicată — cea mai clară derivare a gradienților, dacă matematica lucrării originale pare densă.
- Tutorialul gensim Word2Vec — setări de antrenare pentru producție.
Sursă: Originalul în limba engleză
Navigare: ← Lecția 05.02 — Sacul de cuvinte, TF-IDF și reprezentarea textului · Faza 5 — NLP: de la fundamente la subiecte avansate · Lecția 05.04 — GloVe, FastText și reprezentări vectoriale de subcuvinte → · Catalog complet