Aller au contenu
Apprendre.
  • M1 · toutes les matières15 matières : Préparation de données, API & sécurité, CI/CD, Docker, Merise, Dataviz, KNIME, ML appliqué : projet LoL, SQL & UML, SQL avancé, Machine Learning, Git, IA frugale & responsable, Qualité des données, MathématiquesAnnée
  • M2 · toutes les matières4 matières : Deep Learning, AI Act, Comex & Fundraising, Gouvernance & DataMeshAnnée
  • Deep LearningM2 · 4 modules · Réseaux de neurones, CNN, texte, modèles génératifs.Matière
  • Préparation de donnéesM1 · 3 modules · Nettoyer, transformer et fusionner des données avec Python.Matière
  • API & sécuritéM1 · 2 modules · Consommer, concevoir et sécuriser des API.Matière
  • CI/CDM1 · 1 module · Intégration et livraison continues.Matière
  • DockerM1 · 3 modules · Conteneurs, images, volumes, réseaux, Compose.Matière
  • MeriseM1 · 2 modules · Modéliser une base : MCD, MLD, MPD.Matière
  • DatavizM1 · 2 modules · Visualiser pour comprendre et décider.Matière
  • KNIMEM1 · 1 module · Explorer et nettoyer des données en workflow.Matière
  • ML appliqué : projet LoLM1 · 2 modules · Du besoin métier au POC de vision par ordinateur.Matière
  • SQL & UMLM1 · 3 modules · Modèles UML et requêtes SQL.Matière
  • SQL avancéM1 · 3 modules · Jointures, fenêtres, CTE, optimisation.Matière
  • Machine LearningM1 · 3 modules · Régression, classification, segmentation, projet.Matière

↑↓ naviguer↵ ouvre le résultat en surbrillanceesc fermer

Partie 2 · En faire des vecteurs

Embeddings

Un numéro n'est pas une mesure. Donné tel quel à un neurone, « toux » (numéro 4) pèserait deux fois plus que « fièvre » (numéro 2), ce qui n'a aucun sens. Il faut une représentation où aucun token n'est plus grand qu'un autre : le one-hot. C'est un vecteur (une liste de nombres) avec une composante par token du vocabulaire (22 704 pour le vrai), toutes à 0 sauf celle du token, à 1.

Additionner les one-hot des tokens d'un résumé donne le sac de mots : chaque composante compte les apparitions de son token. Sa taille ne dépend plus de la longueur du texte. Compare deux phrases :

Le vocabulaire est celui de la diapositive (5 numéros). Inverse l'ordre des mots : le sac de mots ne bouge pas.

Deux limites du sac de mots : l'ordre est perdu (« toux sans fièvre » = « fièvre sans toux »), et il est énorme (22 704 composantes) sans rapprocher « patient » de « patients ». Mais d'abord, programmons-le : il suffit de compter, en utilisant chaque numéro comme position dans le vecteur.

À toi de coder

Le sac de mots

Le vecteur a une case par numéro du vocabulaire, toutes à 0 au départ. Pour chaque numéro du texte, tu ajoutes 1 à la case portant ce numéro (une addition, pas une affectation : un token répété doit compter deux fois). La taille du résultat est celle du vocabulaire, jamais celle du texte.

Ctrl/⌘+Entrée

L'embedding. Un vecteur à 2 composantes se dessine comme un point : la 1re composante donne la position horizontale, la 2e la verticale. Un embedding est un vecteur court attribué à un token (64 composantes dans le notebook). Deux embeddings proches sont deux points voisins : le réseau peut ainsi rapprocher des tokens qui jouent le même rôle. Déplace les points pour t'en faire une idée :

Valeurs de la diapositive : fièvre [1 ; 0], sans [0 ; 1], toux [1 ; 1], patient [0,5 ; −0,8], patients [0,6 ; −0,9]. Glisse les points ; l'étoile orange est la moyenne des tokens de la phrase.

La table d'embeddings range les embeddings de tous les tokens : une ligne par token. Ses nombres sont des poids : tirés au hasard au départ, puis ajustés par la descente de gradient. Il n'existe pas de « bon » embedding auquel les comparer : la perte compare les spécialités prédites aux vraies, et la rétropropagation remonte jusqu'à la table.

Un résumé entier : on additionne les embeddings composante par composante, puis on divise par le nombre de tokens. « fièvre sans toux » : ([1;0] + [0;1] + [1;1]) / 3 = [0,67 ; 0,67] ; « toux sans fièvre » donne la même chose : l'ordre est toujours perdu.

Le piège du paquet. Dans un paquet, chaque numéro, <rempl> compris, reçoit un embedding. Si on divise la somme par la longueur du paquet, les remplissages comptent comme de vrais tokens et tirent la moyenne vers 0. Voyons-le :

Ajoute des remplissages avec le curseur, puis coupe le masque : avec « fièvre » et 2 <rempl>, tu obtiens [0,33 ; 0] au lieu de [1 ; 0].

À toi de coder

La moyenne masquée

Deux gestes, dans cet ordre, et chacun a sa raison : 1) multiplier chaque embedding par son masque avant d'additionner, ce qui efface les remplissages de la somme ; 2) diviser par la somme du masque (le nombre de vrais tokens) et non par la longueur du paquet, sinon les remplissages gonflent le diviseur. La table 2D du cours est fournie ; ids et masque sont deux listes de même longueur (une ligne du paquet).

Ctrl/⌘+Entrée

En PyTorch, c'est exactement ce calcul, sur tout le paquet à la fois :

emb = nn.Embedding(len(vocab), 64, padding_idx=0)   # la table : une ligne de 64 poids par token
vecteurs = emb(paquet)                              # (paquet, longueur) → (paquet, longueur, 64)
poids = masque.unsqueeze(2)                         # (paquet, longueur) → (paquet, longueur, 1)
somme = (vecteurs * poids).sum(dim=1)               # les remplissages comptent 0
moyenne = somme / poids.sum(dim=1)                  # divisé par le nombre de vrais tokens

padding_idx=0 laisse à zéro la ligne de <rempl> et ne l'apprend pas. unsqueeze(2) ajoute une dimension de taille 1 pour que chaque 0 ou 1 du masque multiplie les 64 composantes d'un embedding. La table pèse 22 704 × 64 = 1 453 056 poids.