3. Token Embeddings
Reading time: 6 minutes
Token Embeddings
Après avoir tokenisé les données textuelles, l'étape critique suivante dans la préparation des données pour l'entraînement de modèles de langage de grande taille (LLMs) comme GPT est la création de token embeddings. Les token embeddings transforment des tokens discrets (comme des mots ou des sous-mots) en vecteurs numériques continus que le modèle peut traiter et apprendre. Cette explication décompose les token embeddings, leur initialisation, leur utilisation et le rôle des embeddings positionnels dans l'amélioration de la compréhension par le modèle des séquences de tokens.
tip
L'objectif de cette troisième phase est très simple : Attribuer à chacun des tokens précédents dans le vocabulaire un vecteur des dimensions souhaitées pour entraîner le modèle. Chaque mot dans le vocabulaire sera un point dans un espace de X dimensions.
Notez qu'initialement, la position de chaque mot dans l'espace est simplement initialisée "au hasard" et ces positions sont des paramètres entraînables (seront améliorés pendant l'entraînement).
De plus, pendant l'embedding de token, une autre couche d'embeddings est créée qui représente (dans ce cas) la position absolue du mot dans la phrase d'entraînement. De cette manière, un mot à différentes positions dans la phrase aura une représentation (signification) différente.
What Are Token Embeddings?
Token Embeddings sont des représentations numériques de tokens dans un espace vectoriel continu. Chaque token dans le vocabulaire est associé à un vecteur unique de dimensions fixes. Ces vecteurs capturent des informations sémantiques et syntaxiques sur les tokens, permettant au modèle de comprendre les relations et les motifs dans les données.
- Vocabulary Size: Le nombre total de tokens uniques (par exemple, mots, sous-mots) dans le vocabulaire du modèle.
- Embedding Dimensions: Le nombre de valeurs numériques (dimensions) dans le vecteur de chaque token. Des dimensions plus élevées peuvent capturer des informations plus nuancées mais nécessitent plus de ressources informatiques.
Example:
- Vocabulary Size: 6 tokens [1, 2, 3, 4, 5, 6]
- Embedding Dimensions: 3 (x, y, z)
Initializing Token Embeddings
Au début de l'entraînement, les token embeddings sont généralement initialisés avec de petites valeurs aléatoires. Ces valeurs initiales sont ajustées (affinées) pendant l'entraînement pour mieux représenter les significations des tokens en fonction des données d'entraînement.
PyTorch Example:
import torch
# Set a random seed for reproducibility
torch.manual_seed(123)
# Create an embedding layer with 6 tokens and 3 dimensions
embedding_layer = torch.nn.Embedding(6, 3)
# Display the initial weights (embeddings)
print(embedding_layer.weight)
Sortie :
luaCopy codeParameter containing:
tensor([[ 0.3374, -0.1778, -0.1690],
[ 0.9178, 1.5810, 1.3010],
[ 1.2753, -0.2010, -0.1606],
[-0.4015, 0.9666, -1.1481],
[-1.1589, 0.3255, -0.6315],
[-2.8400, -0.7849, -1.4096]], requires_grad=True)
Explication :
- Chaque ligne correspond à un token dans le vocabulaire.
- Chaque colonne représente une dimension dans le vecteur d'embedding.
- Par exemple, le token à l'index
3
a un vecteur d'embedding[-0.4015, 0.9666, -1.1481]
.
Accéder à l'embedding d'un token :
# Retrieve the embedding for the token at index 3
token_index = torch.tensor([3])
print(embedding_layer(token_index))
Sortie :
tensor([[-0.4015, 0.9666, -1.1481]], grad_fn=<EmbeddingBackward0>)
Interprétation :
- Le token à l'index
3
est représenté par le vecteur[-0.4015, 0.9666, -1.1481]
. - Ces valeurs sont des paramètres entraînables que le modèle ajustera pendant l'entraînement pour mieux représenter le contexte et la signification du token.
Comment fonctionnent les embeddings de tokens pendant l'entraînement
Pendant l'entraînement, chaque token dans les données d'entrée est converti en son vecteur d'embedding correspondant. Ces vecteurs sont ensuite utilisés dans divers calculs au sein du modèle, tels que les mécanismes d'attention et les couches de réseaux neuronaux.
Scénario d'exemple :
- Taille de lot : 8 (nombre d'échantillons traités simultanément)
- Longueur de séquence maximale : 4 (nombre de tokens par échantillon)
- Dimensions d'embedding : 256
Structure des données :
- Chaque lot est représenté comme un tenseur 3D avec la forme
(batch_size, max_length, embedding_dim)
. - Pour notre exemple, la forme serait
(8, 4, 256)
.
Visualisation :
cssCopy codeBatch
┌─────────────┐
│ Sample 1 │
│ ┌─────┐ │
│ │Token│ → [x₁₁, x₁₂, ..., x₁₂₅₆]
│ │ 1 │ │
│ │... │ │
│ │Token│ │
│ │ 4 │ │
│ └─────┘ │
│ Sample 2 │
│ ┌─────┐ │
│ │Token│ → [x₂₁, x₂₂, ..., x₂₂₅₆]
│ │ 1 │ │
│ │... │ │
│ │Token│ │
│ │ 4 │ │
│ └─────┘ │
│ ... │
│ Sample 8 │
│ ┌─────┐ │
│ │Token│ → [x₈₁, x₈₂, ..., x₈₂₅₆]
│ │ 1 │ │
│ │... │ │
│ │Token│ │
│ │ 4 │ │
│ └─────┘ │
└─────────────┘
Explication :
- Chaque token dans la séquence est représenté par un vecteur de 256 dimensions.
- Le modèle traite ces embeddings pour apprendre les motifs linguistiques et générer des prédictions.
Embeddings Positionnels : Ajouter du Contexte aux Embeddings de Tokens
Alors que les embeddings de tokens capturent le sens des tokens individuels, ils n'encode pas intrinsèquement la position des tokens dans une séquence. Comprendre l'ordre des tokens est crucial pour la compréhension du langage. C'est là que les embeddings positionnels entrent en jeu.
Pourquoi les Embeddings Positionnels Sont Nécessaires :
- L'Ordre des Tokens Compte : Dans les phrases, le sens dépend souvent de l'ordre des mots. Par exemple, "Le chat est assis sur le tapis" vs. "Le tapis est assis sur le chat."
- Limitation des Embeddings : Sans information positionnelle, le modèle traite les tokens comme un "sac de mots", ignorant leur séquence.
Types d'Embeddings Positionnels :
- Embeddings Positionnels Absolus :
- Attribuer un vecteur de position unique à chaque position dans la séquence.
- Exemple : Le premier token dans n'importe quelle séquence a le même embedding positionnel, le deuxième token en a un autre, et ainsi de suite.
- Utilisé Par : Les modèles GPT d'OpenAI.
- Embeddings Positionnels Relatifs :
- Encoder la distance relative entre les tokens plutôt que leurs positions absolues.
- Exemple : Indiquer à quelle distance deux tokens sont, indépendamment de leurs positions absolues dans la séquence.
- Utilisé Par : Des modèles comme Transformer-XL et certaines variantes de BERT.
Comment les Embeddings Positionnels Sont Intégrés :
- Mêmes Dimensions : Les embeddings positionnels ont la même dimensionalité que les embeddings de tokens.
- Addition : Ils sont ajoutés aux embeddings de tokens, combinant l'identité du token avec l'information positionnelle sans augmenter la dimensionalité globale.
Exemple d'Ajout d'Embeddings Positionnels :
Supposons qu'un vecteur d'embedding de token soit [0.5, -0.2, 0.1]
et que son vecteur d'embedding positionnel soit [0.1, 0.3, -0.1]
. L'embedding combiné utilisé par le modèle serait :
Combined Embedding = Token Embedding + Positional Embedding
= [0.5 + 0.1, -0.2 + 0.3, 0.1 + (-0.1)]
= [0.6, 0.1, 0.0]
Avantages des embeddings positionnels :
- Conscience contextuelle : Le modèle peut différencier les tokens en fonction de leurs positions.
- Compréhension de la séquence : Permet au modèle de comprendre la grammaire, la syntaxe et les significations dépendantes du contexte.
Exemple de code
Suivant l'exemple de code de https://github.com/rasbt/LLMs-from-scratch/blob/main/ch02/01_main-chapter-code/ch02.ipynb :
# Use previous code...
# Create dimensional emdeddings
"""
BPE uses a vocabulary of 50257 words
Let's supose we want to use 256 dimensions (instead of the millions used by LLMs)
"""
vocab_size = 50257
output_dim = 256
token_embedding_layer = torch.nn.Embedding(vocab_size, output_dim)
## Generate the dataloader like before
max_length = 4
dataloader = create_dataloader_v1(
raw_text, batch_size=8, max_length=max_length,
stride=max_length, shuffle=False
)
data_iter = iter(dataloader)
inputs, targets = next(data_iter)
# Apply embeddings
token_embeddings = token_embedding_layer(inputs)
print(token_embeddings.shape)
torch.Size([8, 4, 256]) # 8 x 4 x 256
# Generate absolute embeddings
context_length = max_length
pos_embedding_layer = torch.nn.Embedding(context_length, output_dim)
pos_embeddings = pos_embedding_layer(torch.arange(max_length))
input_embeddings = token_embeddings + pos_embeddings
print(input_embeddings.shape) # torch.Size([8, 4, 256])