Aller au contenu
English

Comment les plongements apprennent le sens : word2vec et GloVe

  • Leçon facultative 2
  • 55 min
  • Module 8 : Sous le capot : les mathématiques · Facultative, non requise pour le certificat
Leçon facultative 2 sur 4 · L'apprentissage profond et les transformeurs expliquésComment les plongements apprennent le sens : word2vec et GloVe

Ce que vous saurez faire

Découvrez comment un réseau peut apprendre des vecteurs de mots à partir du texte seul, sans étiquettes. Vous suivez le skip-gram de word2vec étape par étape, puis GloVe et une simple factorisation de matrice. Les trois s’ajustent au même tableau de fréquences. Vous testez ensuite des vecteurs préentraînés, leurs limites et les biais qu’ils portent.

Carnet JupyterSkip-gram, PPMI et GloVe préentraîné, dans un carnetColab · Kaggle · GitHub · en anglais

Le carnet (notebook) Jupyter crée les paires (centre, contexte) des billets de soutien et implémente le skip-gram en environ 15 lignes. Il l’entraîne pendant 3 époques, en moins d’une minute sur un processeur gratuit de Colab. Il calcule ensuite la PPMI et une SVD de la matrice de cooccurrence. Enfin, il charge un petit sous-ensemble de GloVe préentraîné et essaie des analogies, y compris celles qui échouent. Environ 35 minutes.

Le carnet est en anglais. Colab et Kaggle ouvrent votre propre copie. Il faut un compte Google ou Kaggle gratuit. Vous êtes bloqué ? Consultez le carnet de solution.

Avant de commencerCe qu’il faut savoir et avoir sous la mainEnviron 55 minutes

Ce que vous devez savoir

Ce qu’il vous faut sur votre ordinateur

  • Un navigateur et une calculatrice. Le carnet s’ouvre dans Colab ou Kaggle, où PyTorch est déjà installé.

Cette leçon est facultative : elle n’est pas requise pour obtenir le certificat.

Vous avez vu l’idée dans Jetons et plongements : chaque jeton reçoit une ligne de nombres appris. Les mots utilisés de façon semblable reçoivent des lignes qui pointent dans la même direction. Dans cette leçon, les lignes apprenaient à partir des équipes : elles changeaient seulement pour mieux acheminer les billets. Des fréquences au sens : sac de mots, TF-IDF et plongements se terminait par la phrase de Firth : « On reconnaît un mot aux mots qui l’entourent ». C’est l’hypothèse distributionnelle. Cette page présente les mathématiques qui transforment cette phrase en vecteurs.

Peut-on apprendre des vecteurs de mots à partir du texte lui-même, sans étiquettes? Le texte nous donne une information sans effort : quels mots apparaissent près de quels autres mots. Comptez ces occurrences dans les 4 696 billets d’entraînement de Larkfield, avec une fenêtre de 5 jetons de chaque côté. Le résultat est un tableau avec une ligne et une colonne pour chacun des 2 862 jetons du vocabulaire. Cela donne 8,2 millions de cellules. Seulement 3,94 % d’entre elles sont non nulles. La plupart des paires de mots n’apparaissent jamais ensemble.

Les fréquences brutes posent un deuxième problème. « refund » et « delivery » apparaissent ensemble 25 fois, mais seulement parce que les deux sont fréquents. « password » et « reset » apparaissent ensemble 127 fois, et ces mots vont vraiment ensemble. Un vecteur utile doit distinguer ces deux cas.

Cette page présente trois réponses. Le skip-gram (word2vec) apprend à prédire les voisins de chaque mot. GloVe s’ajuste directement au logarithme des fréquences. La SVD factorise une version nettoyée des fréquences, sans aucun réseau de neurones. À la fin, vous voyez que les trois réponses sont étroitement liées.

Les trois méthodes donnent à chaque mot un vecteur de 50 nombres. Imaginez un point dans un espace à 50 directions. Personne ne choisit ce que les directions signifient. L’entraînement place les points pour rapprocher les mots utilisés dans les mêmes contextes. C’est pourquoi les directions sont dites latentes : elles sont cachées et apprises, plutôt que conçues.

Trois faits en découlent. Le reste de la page illustre chacun avec des nombres réels :

  • Proche signifie « utilisé de façon semblable ». Dans les vecteurs skip-gram entraînés ci-dessous, « password » et « reset » ont une similarité cosinus de 0,95.
  • Les directions peuvent représenter des relations. Dans les vecteurs préentraînés, le déplacement de « man » à « woman » pointe à peu près dans la même direction que celui de « king » à « queen ».
  • Une dimension seule est rarement interprétable. Les 6 premiers des 50 nombres de « password » sont −0,41, 0,31, 0,30, 0,16, 0,42, −0,77. Aucun nombre, à lui seul, ne signifie « compte » ou « secret ». Seul le vecteur entier, comparé à d’autres vecteurs, porte un sens.

Le skip-gram lit le texte avec une fenêtre glissante. Chaque jeton devient à son tour le mot central c. Chaque jeton situé à 5 positions ou moins de lui, de chaque côté, est un mot de contexte o. Chaque (c, o) est un exemple d’entraînement. La fenêtre ne passe jamais d’un billet au suivant.

window.py
from ticketnet import tokenize
tokens = tokenize("Can't log in and the password reset email never arrived. Please help.")
WINDOW = 5
c = tokens.index("password")
context = tokens[max(0, c - WINDOW):c] + tokens[c + 1:c + 1 + WINDOW]
print(len(tokens), "tokens; centre:", tokens[c])
print("context:", context)

La sortie :

16 tokens; centre: password
context: ['t', 'log', 'in', 'and', 'the', 'reset', 'email', 'never', 'arrived', '.']

Ce court billet donne 130 paires (centre, contexte). Tous les billets d’entraînement en donnent environ 1,36 million par passage. Aucune étiquette, seulement le texte.

L’article sur word2vec sous-échantillonne aussi les mots fréquents : à chaque passage, il supprime un jeton w au hasard avec une probabilité 1−t/f(w)1 - \sqrt{t / f(w)}. Ici, f(w) est la proportion de ce jeton parmi tous les jetons et t = 0,001. « the » représente 5,4 % des jetons; il reste donc dans seulement 14 % environ des passages. Un mot rare reste toujours. Cela élimine beaucoup de paires comme (password, the), qui apportent peu d’information.

Explorer

Les paires d'entraînement d'un billet

Billet T-60140 (account) : « Can't log in and the password reset email never arrived. Please help. »

  • mot central
  • fenêtre de contexte (5 jetons de chaque côté)
Mot central
password
Vraies paires
10
Mot de contexte le plus sûr
reset (0,96)
Gardé par sous-échantillonnage
toujours

Mot central password : 10 vraies paires tirées de ce billet. Le modèle entraîné est le plus sûr pour reset (0,96) et le moins sûr pour the (0,10). Ses 5 négatifs aléatoires obtiennent 0,12 en moyenne. Un négatif est aussi un vrai mot de contexte ici : un tirage aléatoire peut le faire, et l’entraînement tolère ce bruit.

Vraies paires : (password, mot de contexte). L’entraînement les pousse vers 1.
Mot de contexteBarreσ(u·v)
t0,22
log0,77
in0,35
and0,16
the0,10
reset0,96
email0,59
never0,86
arrived0,20
“.”0,10
5 négatifs aléatoires pour une paire. L’entraînement les pousse vers 0.
Mot aléatoireBarreσ(u·v)
breeze tiré à 0,008 %0,01
gone tiré à 0,052 %0,08
“'” tiré à 1,20 %0,14
thanks tiré à 0,34 %0,15
arrived tiré à 0,33 %0,20
Billet réel T-60140 des données d'entraînement. Les probabilités σ(u·v) viennent du modèle skip-gram entraîné sur tous les billets; les exemples négatifs proviennent d'un tirage réel dans la distribution unigramme^0,75.
Description textuelle de l’explorateur

L’explorateur présente le billet T-60140, « Can’t log in and the password reset email never arrived. Please help. », sous forme de 16 boutons de jetons. Un jeton est le mot central; les 5 jetons de chaque côté forment la fenêtre de contexte. Pour le mot central, un tableau présente chaque mot de contexte et sa probabilité σ(u·v) d’apparaître près du mot central, selon le modèle entraîné. Un deuxième tableau présente 5 mots négatifs aléatoires avec leurs probabilités. Pour le mot central password, les probabilités de contexte sont : reset 0,96, never 0,86, log 0,77, email 0,59, in 0,35, la lettre t 0,22, arrived 0,20, and 0,16, le point 0,11 et the 0,10. Les 5 exemples négatifs sont breeze 0,01, gone 0,08, l’apostrophe 0,14, thanks 0,15 et arrived 0,20. Le sous-échantillonnage conserve password à chaque passage. Pour le mot central the, il le conserve dans seulement 14 % des passages.

« reset », « never » et « log » obtiennent des probabilités élevées : ils apparaissent près de « password » dans beaucoup de billets. « the » et « . » en obtiennent de faibles, même s’ils sont dans la fenêtre. Ils apparaissent près de tous les mots et n’apportent donc aucune information sur « password ».

Le skip-gram donne à chaque mot deux vecteurs de 50 nombres. vwv_w est son vecteur comme mot central, et uwu_w est son vecteur comme mot de contexte. Ils se trouvent dans deux tables, V et U, chacune de 2 862 × 50. Le score du modèle pour une paire est le produit scalaire uo⋅vcu_o \cdot v_c. La sigmoïde σ transforme le score en probabilité que o apparaisse réellement près de c :

P(o appears near c)=σ(uo⋅vc)=11+e−uo⋅vcP(\text{o appears near c}) = \sigma(u_o \cdot v_c) = \frac{1}{1 + e^{-u_o \cdot v_c}}

En mots : plus les deux vecteurs pointent dans la même direction, plus le produit scalaire est grand. La probabilité se rapproche alors de 1. Un score de 0 donne exactement 0,5.

Pourquoi deux tables? Un mot apparaît rarement à côté de lui-même. Avec une seule table, le modèle aurait besoin d’un grand va⋅vbv_a \cdot v_b pour deux mots semblables. Il lui faudrait aussi un petit va⋅vav_a \cdot v_a pour le mot avec lui-même. C’est difficile : le produit scalaire d’un vecteur avec lui-même est le carré de sa longueur. Cette valeur n’est jamais petite pour un vecteur utile. Deux tables évitent ce problème. Après l’entraînement, word2vec conserve V comme vecteurs de mots.

Un tout petit exemple. Prenez vc=(0.5,0.5)v_c = (0.5, 0.5) pour « password » et uo=(1,0)u_o = (1, 0) pour « reset ». Le score est 0,5 × 1 + 0,5 × 0 = 0,5, et σ(0,5) = 1 ÷ (1 + e^−0,5) = 1 ÷ 1,607 = 0,62.

L’entraînement doit pousser σ(u_o·v_c) vers 1 pour chaque paire réelle. Mais si c’était le seul objectif, le modèle pourrait tricher. Il rendrait tous les vecteurs énormes et identiques, et tous les scores deviendraient grands. Il lui faut des contre-exemples. L’échantillonnage négatif tire K mots au hasard pour chaque paire réelle. Il apprend au modèle que ces mots ne sont pas des mots de contexte. Nous utilisons K = 5.

Pour une paire réelle (c, o) et K exemples négatifs k1,…,kKk_1, \dots, k_K, la perte est :

ℓ=−ln⁡σ(uo⋅vc)  −  ∑i=1Kln⁡σ(− uki⋅vc)\ell = -\ln \sigma(u_o \cdot v_c) \;-\; \sum_{i=1}^{K} \ln \sigma(-\,u_{k_i} \cdot v_c)

Le premier terme est l’entropie croisée vue dans La perte : à quel point le réseau se trompe-t-il?. La bonne réponse est « oui, un voisin ». Le deuxième terme utilise σ(−x) = 1 − σ(x), la probabilité de « non ». Chaque exemple négatif ajoute donc « la surprise si ce mot aléatoire était considéré comme un voisin ». La perte est faible quand les paires réelles ont des scores élevés et les paires aléatoires, des scores faibles.

D’où viennent les exemples négatifs? Des fréquences des mots élevées à la puissance 0,75, puis mises à l’échelle pour que leur somme donne 1 :

Pnoise(w)=count(w)0.75∑w′count(w′)0.75P_{\text{noise}}(w) = \frac{\text{count}(w)^{0.75}}{\sum_{w'} \text{count}(w')^{0.75}}

Pourquoi 0,75? Les fréquences simples (la distribution unigramme) feraient tirer « the » et « . » très souvent. Le modèle en apprendrait peu. Des probabilités égales feraient tirer beaucoup trop souvent des mots rares, comme les fautes de frappe. La puissance 0,75 se situe entre les deux : elle réduit les probabilités des mots fréquents et augmente celles des mots rares. Mikolov et ses collègues ont constaté que 0,75 fonctionnait le mieux dans leurs tests. C’est un choix ajusté, pas une loi.

noise.py
import numpy as np
# counts: how often each of the 2,862 tokens appears in the training tickets
p_unigram = counts / counts.sum()
p_noise = counts ** 0.75 / (counts ** 0.75).sum()
for w in ["the", "password", "warranty", "umbrella"]:
i = W2I[w]
print(f"{w:<9} seen {int(counts[i]):>6,} times unigram {p_unigram[i]:.5f} unigram^0.75 {p_noise[i]:.5f}"
f" x{p_noise[i] / p_unigram[i]:.2f}")

La sortie :

the seen 14,432 times unigram 0.05403 unigram^0.75 0.02378 x0.44
password seen 214 times unigram 0.00080 unigram^0.75 0.00101 x1.26
warranty seen 53 times unigram 0.00020 unigram^0.75 0.00035 x1.79
umbrella seen 5 times unigram 0.00002 unigram^0.75 0.00006 x3.23

Cette puissance réduit de plus de moitié la probabilité de « the » et triple celle de « umbrella ». Les 10 jetons les plus fréquents représentent 30,0 % des exemples négatifs avec les fréquences simples, contre 15,1 % avec la puissance 0,75.

Le schéma montre une étape d’entraînement pour le mot central « password », son vrai voisin « reset » et un tirage réel de 5 exemples négatifs.

Le mot central password prend sa ligne v dans la table V. Six lignes de la table U lui sont comparées : le vrai mot de contexte reset, avec un sigma du produit scalaire de u et v de 0,96 et une cible de 1, se rapproche de lui; et 5 exemples négatifs aléatoires, breeze 0,01, gone 0,08, une apostrophe 0,14, thanks 0,15 et arrived 0,20, chacun avec une cible de 0, s'en éloignent. En dessous : la perte égale moins ln sigma du produit scalaire de u_reset et v, moins la somme des ln sigma du produit scalaire de moins u_k et v.
Une étape de skip-gram pour le mot central « password ». Les probabilités sont celles du modèle entraîné; les exemples négatifs proviennent d'un tirage réel.
Description textuelle du diagramme

À gauche, le mot central password avec sa ligne v de la table V, les vecteurs centraux. Au milieu, six lignes de la table U, les vecteurs de contexte. D’abord, le vrai mot de contexte reset, puis 5 exemples négatifs aléatoires tirés dans la distribution unigramme^0,75 : breeze, gone, une apostrophe, thanks et arrived. Pour chaque ligne, la probabilité σ(u·v) du modèle entraîné : reset 0,96, breeze 0,01, gone 0,08, l’apostrophe 0,14, thanks 0,15, arrived 0,20. À droite, la cible : 1 pour reset, donc l’entraînement rapproche u et v; 0 pour chaque exemple négatif, donc l’entraînement éloigne u et v. En bas, la perte de cette étape : moins ln σ(u_reset · v), moins la somme sur les 5 exemples négatifs de ln σ(−u_k · v). Un exemple négatif, arrived, est aussi un vrai mot de contexte dans ce billet : un tirage aléatoire peut donner ce résultat.

Le gradient de la perte par rapport au vecteur central comprend une partie pour chaque terme :

∂ℓ∂vc=−(1−σ(uo⋅vc)) uo  +  ∑i=1Kσ(uki⋅vc) uki\frac{\partial \ell}{\partial v_c} = -\big(1 - \sigma(u_o \cdot v_c)\big)\, u_o \;+\; \sum_{i=1}^{K} \sigma(u_{k_i} \cdot v_c)\, u_{k_i}

Lisez-le en mots. Un pas de descente soustrait le gradient. Ainsi, vcv_c se déplace vers uou_o selon ce qu’il reste au modèle à corriger, 1 − σ. Il s’éloigne aussi de chaque exemple négatif uku_k, selon la probabilité que le modèle lui donne à tort. Une paire que le modèle traite déjà correctement bouge à peine. Les vecteurs u changent de la même façon : uou_o se déplace vers vcv_c, et chaque uku_k s’en éloigne. En bref : rapprocher le vrai contexte, éloigner les mots aléatoires.

Vérifiez une étape à la main avec des vecteurs inventés en 2D et un exemple négatif. Prenez vc=(0.5,0.5)v_c = (0.5, 0.5), uo=(1,0)u_o = (1, 0) et uk=(0,1)u_k = (0, 1). Les deux scores sont 0,5, donc les deux sigmoïdes donnent 0,6225.

  • Perte : −ln 0,6225 − ln(1 − 0,6225) = 0,474 + 0,974 = 1,448.
  • Gradient : −(1 − 0,6225) × (1, 0) + 0,6225 × (0, 1) = (−0,3775, 0,6225).
  • Un pas avec un taux d’apprentissage de 0,5 : (0,5, 0,5) − 0,5 × (−0,3775, 0,6225) = (0,689, 0,189).

Le score réel monte de 0,5 à 0,689, le score négatif descend de 0,5 à 0,189, et la perte descend à 1,199. Autograd de PyTorch confirme :

one_step.py
import torch
import torch.nn.functional as F
v_c = torch.tensor([0.5, 0.5], requires_grad=True) # centre word "password"
u_o = torch.tensor([1.0, 0.0], requires_grad=True) # true context word "reset"
u_k = torch.tensor([0.0, 1.0], requires_grad=True) # one negative, a random word
loss = -F.logsigmoid(u_o @ v_c) - F.logsigmoid(-(u_k @ v_c))
loss.backward()
print("sigma(u_o.v_c) =", round(torch.sigmoid(u_o @ v_c).item(), 4), " loss =", round(loss.item(), 4))
print("gradient for v_c:", [round(g, 4) for g in v_c.grad.tolist()])
with torch.no_grad():
v_new = v_c - 0.5 * v_c.grad # one step, learning rate 0.5
new_loss = -F.logsigmoid(u_o @ v_new) - F.logsigmoid(-(u_k @ v_new))
print("new v_c:", [round(x, 4) for x in v_new.tolist()], " u_o.v_c:", round((u_o @ v_new).item(), 4),
" u_k.v_c:", round((u_k @ v_new).item(), 4), " loss:", round(new_loss.item(), 4))

La sortie :

sigma(u_o.v_c) = 0.6225 loss = 1.4482
gradient for v_c: [-0.3775, 0.6225]
new v_c: [0.6888, 0.1888] u_o.v_c: 0.6888 u_k.v_c: 0.1888 loss: 1.1989

F.logsigmoid(x) calcule ln σ(x) en une seule étape qui reste précise pour les grands scores.

Le modèle entier comprend deux tables de plongements et la perte ci-dessus. Il est assez court pour être lu au complet :

skipgram.py
class SkipGram(torch.nn.Module):
def __init__(self, n, dim):
super().__init__()
self.v = torch.nn.Embedding(n, dim) # centre words
self.u = torch.nn.Embedding(n, dim) # context words
torch.nn.init.uniform_(self.v.weight, -0.5 / dim, 0.5 / dim)
torch.nn.init.zeros_(self.u.weight)
def forward(self, c, o, neg): # c, o: (B,) neg: (B, K)
vc = self.v(c) # (B, d)
pos = (self.u(o) * vc).sum(-1) # (B,) u_o . v_c
negs = torch.bmm(self.u(neg), vc.unsqueeze(-1)).squeeze(-1) # (B, K) u_k . v_c
loss = -F.logsigmoid(pos) - F.logsigmoid(-negs).sum(-1)
return loss.mean()
sg = SkipGram(2862, 50)
opt = torch.optim.Adam(sg.parameters(), lr=0.002)
# then 8 epochs: build the pairs (with subsampling), shuffle, batches of 512,
# draw 5 negatives per pair with torch.multinomial(p_noise, ...), and the five training steps

torch.bmm multiplie un lot de matrices : les 5 vecteurs négatifs de chaque paire, (5, 50), par son vecteur central, (50, 1). Comme dans le code original de word2vec, V commence avec de petits nombres aléatoires et U avec des zéros.

La sortie de l’exécution d’entraînement :

loss before training: 4.1589 6 ln 2 = 4.1589
epoch 1: 1,357,310 pairs, mean loss 2.638
epoch 2: 1,356,890 pairs, mean loss 2.414
epoch 3: 1,360,876 pairs, mean loss 2.363
epoch 4: 1,358,556 pairs, mean loss 2.335
epoch 5: 1,359,294 pairs, mean loss 2.319
epoch 6: 1,360,146 pairs, mean loss 2.308
epoch 7: 1,359,106 pairs, mean loss 2.298
epoch 8: 1,359,596 pairs, mean loss 2.293
20 s

Vérifiez la première ligne à la main. Avec U rempli de zéros, chaque score est 0 et chaque σ vaut 0,5. Chacun des 6 termes de la perte (1 paire réelle + 5 exemples négatifs) vaut −ln 0,5 = ln 2. Le départ est donc exactement 6 ln 2 = 4,159. Si votre première perte est loin de cette valeur, un signe ou une somme est incorrect.

Le sous-échantillonnage supprime des jetons différents à chaque passage, donc le nombre de paires varie un peu. Les 8 époques prennent de 17 à 20 secondes sur deux fils d’exécution du processeur d’un ordinateur partagé.

La perte du skip-gram sur les 267 129 jetons d'entraînement de Larkfield. L'époque 0 est le départ exact, 6 ln 2; chaque point suivant est la perte moyenne sur une époque.
Description textuelle du graphique

Un graphique en courbe. À l’époque 0, avant l’entraînement, la perte est de 4,159, soit 6 ln 2. Après l’époque 1, la perte moyenne est de 2,638, puis de 2,414, 2,363, 2,335, 2,319, 2,308, 2,298 et 2,293 après l’époque 8. La majeure partie de la baisse survient à la première époque; les suivantes apportent des gains de plus en plus petits.

La perte ne s’approche pas de 0, et c’est normal. Certains exemples négatifs aléatoires sont de vrais voisins, comme « arrived » dans l’explorateur. De plus, beaucoup de paires réelles, comme (password, the), apportent peu d’information.

Prenez maintenant la table V entraînée et cherchez les mots les plus proches par similarité cosinus, comme dans Jetons et plongements.

neighbours.py
Vn = V / np.linalg.norm(V, axis=1, keepdims=True) # every row to length 1
def nearest(word, k=5):
sims = Vn @ Vn[W2I[word]]
order = [i for i in np.argsort(-sims) if i != W2I[word]][:k]
return [(words[i], round(float(sims[i]), 2)) for i in order]
for w in ["password", "card", "broken", "late"]:
print(f"{w:<9} {int(counts[W2I[w]]):>5,}x", nearest(w))

La sortie :

password 214x [('reset', 0.95), ('resetting', 0.8), ('link', 0.79), ('forgot', 0.78), ('rejecting', 0.73)]
card 1,323x [('debit', 0.75), ('paid', 0.73), ('visa', 0.69), ('ending', 0.65), ('42', 0.63)]
broken 219x [('cracked', 0.83), ('faulty', 0.83), ('places', 0.77), ('bent', 0.77), ('join', 0.75)]
late 47x [('umbrella', 0.65), ('rescheduled', 0.63), ('autumn', 0.6), ('excuse', 0.6), ('august', 0.57)]

Les trois premières listes fonctionnent. « password » se trouve avec « reset », « link » et « forgot »; « card » avec « debit » et « visa »; « broken » avec « cracked » et « faulty ». Aucune étiquette n’a indiqué ces liens au modèle. Ils viennent uniquement des fenêtres. « ending » et « 42 » viennent de billets de soutien comme « my card ending in 42 ». Le modèle a appris comment les clients écrivent, pas un dictionnaire.

La dernière liste est du bruit. « late » apparaît seulement 47 fois. Quelques billets suffisent donc à décider où son vecteur se place. Ses voisins « umbrella », « autumn » et « august » ont peu en commun avec lui. C’est la limite réelle de 267 129 jetons (les jetons du vocabulaire; 269 231 en tout). Les vecteurs publiés de word2vec ont appris à partir d’environ 100 milliards de mots. Nos vecteurs apprennent les sujets des billets, soit les mots qui apparaissent dans le même type de billet. C’est utile pour l’acheminement, mais ce n’est pas le sens général des mots anglais.

La carte montre la même idée sous forme de points. Chaque mot a 50 nombres. La carte utilise donc l’ACP pour en projeter une ombre en 2D, comme dans Jetons et plongements. L’explorateur montre aussi les deux autres méthodes de cette page entraînées sur les billets et les vecteurs préentraînés présentés à la fin.

Explorer

27 mots de billets avec quatre ensembles de vecteurs

  • surtout dans les billets delivery
  • surtout dans les billets returns
  • surtout dans les billets payment
  • surtout dans les billets warranty
  • surtout dans les billets account
labelcourierdeliveryreturnparceldeliveredtrackingarrivedlatereturnedexchangecardchargedpaymentbrokenfaultywarrantystoppedpasswordemailresetrefundinvoicepaidrepairloginaccountparcel : surtout dans les billets deliverycourier : surtout dans les billets deliverydelivery : surtout dans les billets deliverydelivered : surtout dans les billets deliverytracking : surtout dans les billets deliveryarrived : surtout dans les billets deliverylate : surtout dans les billets deliveryreturn : surtout dans les billets returnsreturned : surtout dans les billets paymentlabel : surtout dans les billets returnsexchange : surtout dans les billets returnsrefund : surtout dans les billets paymentcard : surtout dans les billets paymentcharged : surtout dans les billets paymentinvoice : surtout dans les billets paymentpayment : surtout dans les billets paymentpaid : surtout dans les billets paymentbroken : surtout dans les billets deliveryfaulty : surtout dans les billets warrantyrepair : surtout dans les billets warrantywarranty : surtout dans les billets warrantystopped : surtout dans les billets warrantypassword : surtout dans les billets accountlogin : surtout dans les billets deliveryaccount : surtout dans les billets accountemail : surtout dans les billets paymentreset : surtout dans les billets accountLes distances viennent d’une ombre 2D (ACP) de 50 nombres par mot.
labelparcelcourierdeliverydeliveredreturnreturnedcardchargedpaidemailresettrackingarrivedlateexchangerefundinvoicepaymentbrokenfaultywarrantystoppedpasswordloginrepairaccountparcel : surtout dans les billets deliverycourier : surtout dans les billets deliverydelivery : surtout dans les billets deliverydelivered : surtout dans les billets deliverytracking : surtout dans les billets deliveryarrived : surtout dans les billets deliverylate : surtout dans les billets deliveryreturn : surtout dans les billets returnsreturned : surtout dans les billets paymentlabel : surtout dans les billets returnsexchange : surtout dans les billets returnsrefund : surtout dans les billets paymentcard : surtout dans les billets paymentcharged : surtout dans les billets paymentinvoice : surtout dans les billets paymentpayment : surtout dans les billets paymentpaid : surtout dans les billets paymentbroken : surtout dans les billets deliveryfaulty : surtout dans les billets warrantyrepair : surtout dans les billets warrantywarranty : surtout dans les billets warrantystopped : surtout dans les billets warrantypassword : surtout dans les billets accountlogin : surtout dans les billets deliveryaccount : surtout dans les billets accountemail : surtout dans les billets paymentreset : surtout dans les billets accountOmbre 2D (ACP) de 50 nombres; plus haute que large.

Skip-gram, entraîné sur les billets : les mots de livraison se regroupent en haut, les mots de paiement au milieu, les mots de garantie en bas à gauche, et password, reset et account ensemble en bas à droite, avec login tout près. « late » est à côté de « arrived », avec les mots de livraison. « broken » est avec les mots de garantie, même si la plupart de ses billets sont des billets de livraison. Score « même équipe » des 904 mots fréquents : 0,585 (hasard : 0,251).

ACP en 2D des vecteurs unitaires de 27 mots choisis dans les billets. Couleur et forme : l'équipe dont les billets d'entraînement utilisent le plus le mot. Le score de même équipe couvre les 904 mots fréquents, pas seulement cette carte.
Description textuelle de l’explorateur

Un nuage de points de 27 mots. Chaque mot porte la marque de l’équipe dont les billets l’utilisent le plus : parcel, courier, delivery, delivered, tracking, arrived, late, broken et login (livraison); return, label et exchange (retours); returned, refund, card, charged, invoice, payment, paid et email (paiement); faulty, repair, warranty et stopped (garantie); password, account et reset (comptes). Une commande permet de choisir parmi quatre ensembles de vecteurs de mots à 50 nombres. Avec skip-gram entraîné sur les billets, les mots forment des groupes par équipe. Les mots de livraison sont en haut, ceux de paiement au milieu, ceux de garantie en bas à gauche. password, reset et account sont en bas à droite. Le score de même équipe des 904 mots fréquents est de 0,585. Avec le petit ajustement GloVe, les groupes sont moins serrés; score de 0,432. Avec la SVD de la PPMI décalée, les groupes ressemblent à ceux de skip-gram; score de 0,492. Avec GloVe 6B préentraîné, les mots se regroupent selon leur sens anglais général plutôt que selon l’équipe de Larkfield. password reste près de login, mais account se déplace près de payment, refund et paid; score de 0,320. Le hasard donne 0,251.

Comparez la première et la dernière carte. Dans les vecteurs des billets, « password », « reset » et « account » forment un groupe, car ils partagent des billets. Dans les vecteurs préentraînés, « password » reste près de « login ». Mais « account » se déplace vers « payment », « refund » et « paid ». En anglais général, un « account » est souvent un compte bancaire. Les vecteurs ont appris le sens de leur propre texte.

Skip-gram parcourt le texte paire par paire. GloVe, de Pennington, Socher et Manning (2014), part plutôt de la table de fréquences complète. Soit XijX_{ij} le nombre de fois où le mot j apparaît dans la fenêtre du mot i. GloVe compte une paire séparée de 3 jetons comme 1/3, et généralement une paire séparée de r jetons comme 1/r. Les voisins proches comptent donc davantage. Il ajuste ensuite une équation pour chaque cellule non nulle :

wi⋅w~j+bi+b~j≈ln⁡Xijw_i \cdot \tilde{w}_j + b_i + \tilde{b}_j \approx \ln X_{ij}

Ici, wiw_i et w~j\tilde{w}_j sont deux vecteurs par mot, encore une fois un pour chaque rôle. bib_i et b~j\tilde{b}_j sont un nombre par mot, un biais. Les biais absorbent la fréquence de chaque mot. Il reste au produit scalaire le reste : combien les deux mots se rencontrent au-delà de ce qu’expliquent leurs fréquences. GloVe ajuste toutes les cellules en même temps par les moindres carrés pondérés :

J=∑Xij>0f(Xij)(wi⋅w~j+bi+b~j−ln⁡Xij)2f(x)=min⁡ ⁣(1,(x100)0.75)J = \sum_{X_{ij} > 0} f(X_{ij}) \left( w_i \cdot \tilde{w}_j + b_i + \tilde{b}_j - \ln X_{ij} \right)^2 \qquad f(x) = \min\!\left(1, \left(\tfrac{x}{100}\right)^{0.75}\right)

Le poids f évite deux problèmes. Les paires rares sont bruitées. Une paire vue une seule fois reçoit donc seulement f(1) = 0,032 du poids total. Les paires très fréquentes domineraient la somme. Ainsi, f s’arrête à 1 dès 100 cooccurrences. Entre les deux, f(10) = 0,178 et f(50) = 0,595. Le vecteur final du mot est w+w~w + \tilde{w}.

Voici un terme de l’ajustement sur les billets. « password » et « reset » ont une fréquence pondérée de 110,95, donc ln X = 4,709 et f = 1. Le produit scalaire ajusté est de 4,173 et les deux biais sont de 0,307 et 0,197 : ensemble, 4,677. L’erreur est de 4,677 − 4,709 = −0,032, et son carré pondéré ajoute seulement 0,001 à J. L’ajustement a utilisé les 322 363 cellules non nulles et 50 époques, en 2,2 secondes. J par cellule est passé de 0,198 à 0,0145.

Voici maintenant le résultat réel : sur les billets, notre ajustement GloVe est la plus faible des trois méthodes. Ses mots les plus proches de « refund » sont « had », « a », « got », « received » et « want ». Avec x_max = 100, presque chaque paire d’un petit corpus est rare et reçoit un faible poids. Les mots grammaticaux fréquents restent alors proches de tout. Nous avons gardé les paramètres de l’article plutôt que de les régler jusqu’à ce que GloVe gagne. GloVe a été conçu pour des milliards de jetons.

Les deux méthodes combattent le même ennemi : les fréquences brutes qui mesurent surtout la fréquence des mots. La correction habituelle est l’information mutuelle ponctuelle (PMI). Elle compare la fréquence des rencontres de deux mots à celle qu’ils auraient s’ils étaient indépendants :

PMI(i,j)=ln⁡P(i,j)P(i) P(j)=ln⁡Xij⋅TXi⋅Xj\text{PMI}(i, j) = \ln \frac{P(i, j)}{P(i)\,P(j)} = \ln \frac{X_{ij} \cdot T}{X_i \cdot X_j}

Ici, XiX_i est la somme de la ligne du mot i (toutes ses paires de fenêtre). T est la somme de toutes les cellules, soit 2 530 410 paires. La PMI vaut 0 pour des mots indépendants. Elle est positive quand ils se rencontrent plus souvent que par hasard, et négative quand ils se rencontrent moins souvent. La PPMI = max(PMI, 0) garde seulement la partie positive.

Calculez deux cellules à la main :

  • password–reset : Xij=127X_{ij} = 127, Xi=2,057X_i = 2{,}057, Xj=1,923X_j = 1{,}923. Alors 127 × 2 530 410 ÷ (2 057 × 1 923) = 81,2, et ln 81,2 = 4,40. Ils se rencontrent 81 fois plus souvent que par hasard.
  • refund–delivery : 25 × 2 530 410 ÷ (13 286 × 10 848) = 0,44, et ln 0,44 = −0,82. C’est moins souvent que par hasard, donc PPMI = 0, même s’ils se rencontrent 25 fois.

Explorer

Fréquences, PPMI et PPMI décalée pour dix mots de billets

password, reset
127
refund, card
191
refund, delivery
25

Les comptes bruts favorisent les mots fréquents : refund (1 358 fois dans les billets) et card se rencontrent 191 fois, et refund rencontre delivery 25 fois, en partie parce que les deux mots sont courants. Seulement 3,94 % de toutes les paires de mots se rencontrent au moins une fois.

  • plus foncé : valeur plus grande (par rapport à la plus grande cellule affichée)
Combien de fois le mot de la ligne et le mot de la colonne apparaissent à 5 jetons ou moins l’un de l’autre
parcelcourierdeliveryarrivedrefundcardchargedpasswordresetfaulty
parcel0251238130000
courier250166510000
delivery121610732571201
arrived386730374111214
refund15253721912112
card317419110185000
charged001121850010
password0021110021270
reset0002110112700
faulty0014200000
Un extrait de 10 × 10 de la véritable matrice de cooccurrence des billets d'entraînement (fenêtre de 5 de chaque côté). L'intensité est relative à la plus grande cellule de la vue actuelle.
Description textuelle de l’explorateur

Une carte thermique de 10 mots : parcel, courier, delivery, arrived, refund, card, charged, password, reset et faulty. Une commande affiche les cellules comme fréquences brutes, comme PPMI ou comme PPMI décalée. Dans la vue des fréquences, les plus grandes cellules sont refund avec card, 191, card avec charged, 185, password avec reset, 127, et delivery avec arrived, 73; refund avec delivery vaut 25. Dans la vue PPMI, password avec reset est la plus grande, 4,40. Viennent ensuite card avec charged, 2,38, parcel avec courier, 2,02, et refund avec card, 1,06; refund avec delivery vaut 0. Dans la vue PPMI décalée, soit PMI moins ln 5, seulement trois paires restent au-dessus de 0 : password avec reset, 2,79, card avec charged, 0,77, et parcel avec courier, 0,41.

Skip-gram ajuste la PMI décalée. Levy et Goldberg (2014) ont prouvé un résultat surprenant. Supposons que les vecteurs aient assez de nombres pour ajuster librement chaque paire. Alors la meilleure solution skip-gram avec K exemples négatifs a

vc⋅uo=PMI(c,o)−ln⁡Kv_c \cdot u_o = \text{PMI}(c, o) - \ln K

pour chaque paire. Ainsi, skip-gram factorise discrètement la matrice PMI, décalée vers le bas de ln K. Avec K = 5, le décalage est de ln 5 = 1,61. Notre modèle a seulement 50 nombres par mot, donc il ne peut qu’approcher ce résultat. Vérifiez-le sur les billets : pour password–reset, v⋅uv \cdot u entraîné vaut 3,25 et PMI − ln 5 vaut 2,79. Pour 4 949 paires de mots fréquents qui se rencontrent au moins 5 fois, les deux nombres ont une corrélation de Pearson de r = 0,852.

  • une paire de mots
  • v · u = PMI − ln 5, l'optimum de Levy et Goldberg
Each dot is a pair of frequent ticket words that meet at least 5 times (600 of the 4,949 pairs shown). The line is the Levy and Goldberg optimum. Correlation over all pairs: r = 0.852.
Description textuelle du graphique

Un nuage de points de 600 paires de mots. L’axe horizontal représente PMI moins ln 5, d’environ −4,3 à 4,2. L’axe vertical représente le produit scalaire v · u de skip-gram entraîné, d’environ −3,5 à 5,6. Les points suivent une bande montante autour de la droite v · u = PMI − ln 5. Sur les 4 949 paires, la corrélation est de 0,852. 87,5 % des paires sont à moins de 1 de la droite. La droite des moindres carrés est v · u = −0,39 + 0,70 × (PMI − ln 5). Elle est un peu moins inclinée que l’idéal, car 50 nombres par mot ne peuvent pas ajuster chaque paire.

Une troisième méthode : factorisez vous-même la matrice. Si skip-gram approche la matrice PPMI décalée, nous pouvons aussi factoriser directement cette matrice. La décomposition en valeurs singulières (SVD) écrit toute matrice M sous la forme USV⊤U S V^\top. Ce sont deux tables de directions et une liste de forces S, la plus grande en premier. (Ces U et V ne sont pas les tables de skip-gram.) Gardez les 50 directions les plus fortes, et chaque mot reçoit 50 nombres, W=U50S50W = U_{50} \sqrt{S_{50}}. Il n’y a ni réseau de neurones ni taux d’apprentissage : seulement un appel à np.linalg.svd. Les 50 directions gardent 14,9 % des valeurs singulières au carré de la matrice. Une grande partie du reste est du bruit provenant des paires rares. GloVe est aussi apparenté : il ajuste les logarithmes des fréquences, et ses biais font le travail de la division dans la PMI.

Les billets d'entraînement, 267 129 jetons, suivent deux chemins. Skip-gram prédit les voisins de chaque mot avec sigma et 5 exemples négatifs. Les fréquences de cooccurrence X forment une matrice de 2 862 par 2 862 avec une fenêtre de 5 et 3,94 % de cellules non nulles. Elles alimentent GloVe, qui ajuste un produit scalaire et deux biais à ln X. Elles alimentent aussi la PMI, puis la PPMI décalée, puis la SVD vers 50 nombres. Les trois donnent 50 nombres par mot. Une flèche pointillée de skip-gram vers la case PMI indique que v produit scalaire u vaut environ PMI moins ln 5, r = 0,852.
Trois chemins vers les vecteurs de mots des billets. Les trois aboutissent à 50 nombres par mot et ajustent les mêmes statistiques de cooccurrence.
Description textuelle du diagramme

Les billets d’entraînement, 267 129 jetons, alimentent deux chemins. Premier chemin : skip-gram lit le texte paire par paire et prédit les voisins de chaque mot, avec la sigmoïde et 5 exemples négatifs. Deuxième chemin : compter les cooccurrences dans une matrice X de 2 862 par 2 862 cellules, avec une fenêtre de 5, dont 3,94 % sont non nulles. À partir de X, GloVe ajuste un produit scalaire et deux biais à ln X par les moindres carrés pondérés. Le chemin PMI transforme X en PPMI décalée et la factorise avec une SVD pour obtenir 50 nombres. Les trois donnent 50 nombres par mot. Un lien pointillé entre skip-gram et le chemin PMI indique que les produits scalaires de skip-gram approchent PMI moins ln 5, avec une corrélation de 0,852 sur les billets.

Il est facile de choisir seulement les listes de mots proches qui nous conviennent. Mesurez plutôt les résultats. Pour chaque mot alphabétique vu au moins 20 fois (904 mots), trouvez son équipe dominante. C’est l’équipe dont les billets l’utilisent le plus. Vérifiez ensuite quelle proportion de ses 10 mots les plus proches ont la même équipe dominante. Des vecteurs aléatoires auraient un score de 0,251, la probabilité que deux mots partagent une équipe dominante. Ce score de même équipe est notre propre test pour cette tâche, pas un banc d’essai standard.

Proportion des 10 mots les plus proches de chaque mot qui appartiennent à son équipe. Les trois premières méthodes ont appris à partir des 267 129 jetons d'entraînement de Larkfield (SVD : de la PPMI décalée). GloVe 6B a appris à partir de 6 milliards de jetons de Wikipédia et de nouvelles.
Description textuelle du graphique

Un diagramme à colonnes. Skip-gram sur les billets obtient 0,585, la SVD de la PPMI décalée 0,492, l’ajustement GloVe sur les billets 0,432, GloVe 6B préentraîné 0,320, et le hasard 0,251.

La table complète ajoute deux variantes et un deuxième test. Pour ce test, calculez la moyenne des vecteurs de mots de chaque billet et entraînez une régression logistique sur ces moyennes.

Vecteurs score de même équipe vecteur moyen + régression logistique, validation
skip-gram, billets 0,585 94,5 %
SVD de la PPMI (sans décalage), billets 0,547 90,5 %
lignes de ln(1 + fréquences), 2 862 nombres 0,533 96,2 %
SVD de la PPMI décalée, billets 0,492 84,2 %
ajustement GloVe, billets 0,432 84,0 %
GloVe 6B préentraîné, 50 nombres 0,320 81,7 %

Skip-gram est le meilleur des vecteurs à 50 nombres aux deux tests. GloVe préentraîné, entraîné sur environ 22 000 fois plus de texte, arrive dernier. Les vecteurs généralistes apprennent l’anglais général. Dans ces vecteurs, « warranty » est près de « payment », « rental » et « paperwork », et « late » est près de « early ». Les équipes de Larkfield sont une distinction locale que Wikipédia n’a jamais vue. Et gardez l’ensemble du cours en vue : TF-IDF avec régression logistique achemine 98,8 % des billets de validation. Les vecteurs de mots moyennés sur un billet perdent les mots exacts qui déterminent l’équipe.

Le carnet (notebook) Jupyter fournit un petit sous-ensemble de GloVe 6B : 50 nombres pour chacun des 20 367 mots. Pennington, Socher et Manning (2014) ont entraîné les vecteurs complets sur 6 milliards de jetons de Wikipédia 2014 et Gigaword 5, avec 400 000 mots. Stanford les publie sous la licence Open Data Commons Public Domain Dedication and License (PDDL) 1.0. Nous pouvons donc partager le sous-ensemble. Le carnet donne la référence complète.

Les vecteurs d’un grand corpus montrent le deuxième fait des dimensions latentes : les directions peuvent porter des relations. Pour résoudre « homme est à femme ce que roi est à? », prenez a = king, b = man et c = woman. Calculez le vecteur cible a − b + c. Trouvez son mot le plus proche par similarité cosinus, en excluant les trois mots de la requête :

answer=arg⁡max⁡w∉{a,b,c}cos⁡ ⁣(w,  a−b+c)\text{answer} = \arg\max_{w \notin \{a, b, c\}} \cos\!\left(w,\; a - b + c\right)
analogies.py
d = np.load("glove6b-50d-subset.npz")
gwords, G = d["words"].tolist(), d["vectors"]
gi = {w: k for k, w in enumerate(gwords)}
Gn = G / np.linalg.norm(G, axis=1, keepdims=True)
def analogy(a, b, c, k=3):
t = Gn[gi[a]] - Gn[gi[b]] + Gn[gi[c]]
sims = Gn @ (t / np.linalg.norm(t))
for w in (a, b, c):
sims[gi[w]] = -np.inf # the three query words do not count
top = np.argsort(-sims)[:k]
return [(gwords[n], round(float(sims[n]), 3)) for n in top]
print(G.shape)
for a, b, c in [("king", "man", "woman"), ("paris", "france", "canada"), ("brother", "boy", "girl"),
("doctor", "man", "woman")]:
print(f"{a} - {b} + {c} ->", analogy(a, b, c))

La sortie :

(20367, 50)
king - man + woman -> [('queen', 0.852), ('throne', 0.766), ('prince', 0.759)]
paris - france + canada -> [('vancouver', 0.802), ('toronto', 0.792), ('london', 0.781)]
brother - boy + girl -> [('cousin', 0.924), ('son', 0.904), ('father', 0.9)]
doctor - man + woman -> [('nurse', 0.84), ('child', 0.766), ('pregnant', 0.757)]

L’image montre pourquoi la première analogie fonctionne. Dans une ombre en 2D, le déplacement de « man » vers « woman » et celui de « king » vers « queen » pointent dans une direction semblable. Ainsi, king − man + woman arrive près de queen.

King, queen, man and woman in pretrained GloVe, projected from 50 numbers to 2 with PCA of these four unit vectors (the two directions keep 95% of their spread). The two arrows are the steps man → woman and king → queen. The grey dot, target, is king − man + woman, projected the same way.
Description textuelle du graphique

Un graphique en 2D. Man est en bas à gauche et woman au-dessus; une flèche monte de man vers woman. King est en bas à droite et queen au-dessus; une flèche monte de king vers queen. Les deux flèches pointent dans une direction semblable : vers le haut, avec une petite composante latérale. Des lignes pointillées relient man à king et woman au point cible. Le point nommé cible, king moins man plus woman, se trouve entre king et queen, plus près de queen. Dans les 50 nombres complets, le cosinus des deux déplacements est de 0,58. Le parallélogramme n’est donc qu’approximatif.

Ne faites pas trop confiance à l’image. Dans les 50 nombres complets, les deux déplacements ont un cosinus de seulement 0,58. Queen gagne parce que c’est encore le mot le plus proche de la cible. La table complète, avec les rangs parmi les 400 000 mots :

Requête Réponse attendue Rang Meilleure réponse
king − man + woman queen 1 queen 0,852
paris − france + italy rome 1 rome 0,847
berlin − germany + japan tokyo 1 tokyo 0,860
walking − walk + swim swimming 1 swimming 0,807
bigger − big + small smaller 2 larger 0,924
paris − france + canada ottawa 12 vancouver 0,802
brother − boy + girl sister 15 cousin 0,924
refund − money + parcel delivery 44 574 diphu 0,659
doctor − man + woman nurse 1 nurse 0,840

Les analogies fonctionnent pour des relations connues, comme les capitales et les formes verbales. Elles échouent sans avertissement pour d’autres. La réponse « vancouver » semble plausible, et rien ne vous avertit qu’elle est fausse. Une « analogie de Larkfield » inventée, comme refund − money + parcel → delivery, n’a aucun sens pour les vecteurs : rang 44 574.

Les plongements apprennent les biais de leur texte. La dernière ligne n’est pas une réussite. « doctor − man + woman → nurse » au rang 1 est un stéréotype de genre absorbé des nouvelles et des encyclopédies. Personne ne l’a programmé; il est dans les fréquences de cooccurrence. Si ces vecteurs alimentent un système qui classe des personnes ou leurs textes, le stéréotype peut entraîner des décisions injustes. Avant d’utiliser des vecteurs préentraînés, testez-les pour les biais qui comptent dans votre tâche. Mesurez les résultats pour les groupes touchés plutôt que de vous fier à une belle liste de mots proches. Documentez ce que vous avez trouvé.

Chaque méthode de cette page donne à un mot un seul vecteur, peu importe les mots qui l’entourent dans le billet. « charged » a le même vecteur dans « my card was charged twice » et dans « the battery is not charged ». C’est la limite que Pourquoi l’ordre des mots et le contexte comptent a montrée en pratique.

Les plongements contextuels règlent ce problème. Un transformeur part d’une table de vecteurs de mots comme ceux-ci. Ensuite, l’attention intègre les autres mots du billet, couche par couche. Le même mot reçoit donc un vecteur différent dans chaque phrase. La prochaine leçon, Les mathématiques de l’attention, montre exactement comment. L’idée de skip-gram revient à une bien plus grande échelle dans Les objectifs d’entraînement : prédire des mots à partir de leur contexte, sans étiquettes.

Exercice guidé : entraîner skip-gram dans le carnet

Section intitulée « Exercice guidé : entraîner skip-gram dans le carnet »
  1. Ouvrez le carnet et exécutez les cellules de configuration. Elles téléchargent les billets et ticketnet.py.
  2. Exécutez « Build the pairs » (construire les paires). Vérifiez que le billet T-60140 donne 130 paires.
  3. Exécutez « The model » (le modèle). Avant l’entraînement, calculez la perte d’un lot. Elle doit être de 6 ln 2 = 4,159.
  4. Entraînez le modèle pendant 3 époques (la leçon en utilisait 8). Affichez la perte moyenne par époque.
  5. Affichez nearest("password"), nearest("card") et nearest("late"). Pour chaque liste, indiquez quels voisins sont logiques et lesquels ressemblent à du bruit.

Sortie attendue pour les étapes 4 et 5 (vos nombres peuvent varier un peu sur un autre ordinateur) :

epoch 1: 1,357,310 pairs, mean loss 2.638
epoch 2: 1,356,890 pairs, mean loss 2.414
epoch 3: 1,360,876 pairs, mean loss 2.363
password 214x [('reset', 0.95), ('resetting', 0.88), ('link', 0.88), ('forgot', 0.86), ('resend', 0.86)]
card 1323x [('debit', 0.84), ('ending', 0.8), ('visa', 0.8), ('paid', 0.75), ('mastercard', 0.75)]
late 47x [('umbrella', 0.72), ('rescheduled', 0.71), ('later', 0.7), ('excuse', 0.69), ('treat', 0.67)]
Afficher un exemple de réponse

La perte diminue le plus vite à l’époque 1, comme dans le graphique de la leçon. Les trois premières époques donnent les mêmes pertes que l’entraînement de 8 époques. Après 3 époques, « password » se trouve déjà avec « reset », « link », « forgot » et « resend ». « card » se trouve avec « debit », « visa » et « mastercard » : les mots fréquents et spécifiques sont appris en premier. « late » reçoit des voisins peu pertinents (« umbrella », « treat »). Il apparaît seulement 47 fois, donc quelques billets déterminent son vecteur. Les cosinus sont plus élevés qu’après 8 époques, car les vecteurs ne se sont pas encore dispersés.

Avant d’exécuter quoi que ce soit, faites une prédiction. Avec K = 15 exemples négatifs plutôt que 5, quelle est la perte avant l’entraînement? Et l’optimum de Levy et Goldberg monte-t-il ou descend-il? Vérifiez ensuite la première réponse dans le carnet.

Afficher la réponse

La perte initiale est (1 + K) ln 2 = 16 × 0,693 = 11,09. Chacun des 16 termes vaut ln 2 quand U est nul. L’optimum descend : v·u = PMI − ln 15 = PMI − 2,71, plutôt que PMI − 1,61. Davantage d’exemples négatifs font baisser le score de chaque paire. Seules les paires observées plus de 15 fois plus souvent que par hasard obtiennent donc un score positif.

Cas d’échec : l’analogie qui renvoie la question

Section intitulée « Cas d’échec : l’analogie qui renvoie la question »

Erreur courante

Recherche d'analogies sans exclure les mots de la requête

Symptôme : Tomás écrit sa propre recherche d’analogies. Il ramène les vecteurs à une longueur de 1, calcule king − man + woman et renvoie le mot le plus semblable. La réponse est king (cosinus de 0,885). Queen arrive en deuxième, avec 0,852. Il conclut que GloVe « ne connaît pas » l’analogie.

Cause : la cible a − b + c est construite à partir de a. Elle reste donc généralement très proche de a lui-même. Le mot le plus proche de la cible est alors un des mots de la requête, le plus souvent a. Les résultats célèbres et le tableau ci-dessus utilisent la règle habituelle : exclure a, b et c de la recherche.

Correction : fixez la similarité des trois mots de la requête à −∞ avant de sélectionner le premier mot. C’est ce que fait la fonction analogy ci-dessus. Indiquez cette règle avec vos résultats : sans elle, les scores d’analogie ne sont pas comparables.

Vérifiez votre compréhension

Dans skip-gram avec échantillonnage négatif, comment l'entraînement modifie-t-il le vecteur central v de password? Le mot de contexte est reset et les 5 exemples négatifs sont des mots aléatoires. Répondez en mots.

Afficher la réponse

Il rapproche v de u_reset, le vecteur de contexte du vrai voisin, selon l’erreur restante du modèle, 1 − σ(u_reset · v). Il éloigne v du vecteur u_k de chaque exemple négatif, selon la probabilité σ(u_k · v) que le modèle lui attribue à tort. Les vecteurs de contexte bougent aussi : u_reset se rapproche de v, et les exemples négatifs s’en éloignent. Rapprocher le vrai contexte, éloigner les mots aléatoires.

Vérifiez votre compréhension

La perte de skip-gram avant l'entraînement est exactement de 4,159. Pourquoi, et quelle serait-elle avec K = 2 exemples négatifs?

Afficher la réponse

La table de contexte U commence à zéro. Chaque score u · v vaut donc 0 et chaque sigmoïde vaut 0,5. La perte contient un terme pour la vraie paire et un pour chaque exemple négatif. Chaque terme vaut −ln 0,5 = ln 2. Avec K = 5, cela donne 6 ln 2 = 4,159. Avec K = 2, cela donne 3 ln 2 = 2,079.

Vérifiez votre compréhension

GloVe préentraîné a appris à partir de 6 milliards de jetons. Pourtant, il obtient le plus faible score au test de même équipe de Larkfield (0,320, contre 0,585 pour skip-gram entraîné sur les billets). Omar demande pourquoi le plus gros modèle perd. Que lui dites-vous?

Afficher la réponse

Les vecteurs répondent à la question posée par leur texte. GloVe 6B a appris comment Wikipédia et les nouvelles utilisent les mots. Il rapproche donc les mots selon leur sens général : late près de early, warranty près de rental. Les équipes de Larkfield sont une distinction locale que ce texte n’a jamais vue. Les vecteurs entraînés sur les billets sont petits et bruités pour les mots rares. Mais ils ont appris exactement quels mots apparaissent dans quels types de billets. C’est ce dont l’acheminement a besoin. Plus de données aide seulement si elles portent sur la bonne tâche.

Récapitulatif

  • Les vecteurs de mots placent chaque mot comme un point à 50 dimensions latentes. Les mots utilisés dans les mêmes contextes se retrouvent proches. Les directions peuvent représenter des relations, et une dimension seule n’est généralement pas interprétable.
  • Skip-gram attribue à une paire (centre, contexte) le score σ(u_o · v_c). Il minimise −ln σ(u_o · v_c) − Σ ln σ(−u_k · v_c), avec 5 exemples négatifs tirés de unigram^0.75. Son gradient rapproche les vrais contextes et éloigne les mots aléatoires. Sur les billets : 4,159 = 6 ln 2 → 2,293.
  • GloVe ajuste w_i · w̃_j + b_i + b̃_j à ln X_ij par les moindres carrés pondérés. Sur notre petit corpus, c’est la méthode la plus faible.
  • Les deux approchent une factorisation de la matrice PMI (r = 0,852 pour skip-gram). Une SVD de la PPMI décalée offre une troisième voie.
  • Skip-gram entraîné sur les billets convient le mieux à l’acheminement (0,585). GloVe préentraîné connaît l’anglais général, mais pas les équipes de Larkfield (0,320). Il échoue discrètement sur certaines analogies et porte les biais de son texte.
  • À suivre : l’attention donne à chaque mot un vecteur qui dépend de son contexte.

Leçon suivante : Les mathématiques de l'attention