Plongement de mots PyTorch
Le plongement de mots est l'une des techniques les plus fondamentales et les plus importantes du traitement du langage naturel.
Le plongement de mots transforme les symboles de mots discrets en vecteurs denses continus, permettant aux machines de comprendre et de traiter les données textuelles.
PyTorch fournitnn.Embeddingmodule pour implémenter cette fonctionnalité, servant de base à la construction de divers modèles NLP.
1. Concepts de base du plongement de mots
Dans un ordinateur, le texte est essentiellement une séquence d'entiers. Chaque mot se voit attribuer un ID d'index unique, mais cette représentation discrète pose un problème : des mots sémantiquement similaires peuvent être proches par le sens, mais leurs ID n'ont absolument aucun rapport.
Le plongement de mots résout ce problème en apprenant unematrice de plongement:
\[ E \in \mathbb{R}^{V \times D} \]
Où \(V\) est la taille du vocabulaire et \(D\) est la dimension de plongement. Chaque ID de mot correspond à une ligne de la matrice de plongement, et sa représentation vectorielle est obtenue via une opération de recherche :
\[ \text{embedding} = E[\text{word\_id}] \]
Les avantages du plongement de mots incluent :
- Convertir des vecteurs one-hot creux de grande dimension en vecteurs denses de faible dimension, ce qui réduit considérablement le coût de calcul
- Les mots sémantiquement similaires sont plus proches dans l'espace vectoriel, et la similarité entre mots peut être calculée via la similarité cosinus
- Les vecteurs de plongement sont des paramètres apprenables et peuvent être ajustés automatiquement via la rétropropagation
2. nn.Embedding expliqué en détail
nn.Embeddingest la couche d'embedding de mots fournie par PyTorch, encapsulant la création de la matrice d'embedding et l'opération de recherche.
2.1 Utilisation de base
Exemple
import torch.nn as nn
# Créer une couche d'embedding
# num_embeddings : taille du vocabulaire (vocab_size)
# embedding_dim : dimension d'embedding (embedding_dim)
vocab_size = 10000
embedding_dim = 256
embedding = nn.Embedding(num_embeddings=vocab_size, embedding_dim=embedding_dim)
# Afficher la forme de la matrice d'embedding
print(embedding.weight.shape) # torch.Size([10000, 256])
# Indices de mots en entrée (LongTensor) pour obtenir des vecteurs d'embedding
word_ids = torch.tensor([0, 1, 2, 9999]) # Indices de mots arbitraires
embedded = embedding(word_ids)
print(embedded.shape) # torch.Size([4, 256])
# Chaque ID de mot correspond à un vecteur de 256 dimensions
2.2 Détails des paramètres de nn.Embedding
Exemple
embedding = nn.Embedding(
num_embeddings=10000, # Taille du vocabulaire, doit être supérieure ou égale à la valeur d'index maximale dans l'entrée
embedding_dim=256, # Dimension du vecteur d'embedding, généralement 50, 100, 200, 300, etc.
padding_idx=None, # Index du mot de remplissage ; le vecteur d'embedding pour le mot de remplissage est entièrement composé de zéros
max_norm=None, # Norme maximale du vecteur d'embedding, utilisée pour la normalisation
norm_type=2.0, # Type de normalisation, généralement la norme L2
scale_grad_by_freq=False,# Met à l'échelle les gradients en fonction de la fréquence des mots
sparse=False, # Indique s'il faut utiliser des gradients creux (économise la mémoire GPU, mais l'entraînement est plus lent)
_weight=None, # Poids prédéfinis, utilisés pour charger des embeddings pré-entraînés
)
# Afficher le nombre de paramètres
total_params = embedding.num_embeddings * embedding.embedding_dim
print(f"Nombre de paramètres de la couche d'embedding : {total_params:,}")
# 10000 * 256 = 2,560,000
Le nombre de paramètres dans la couche d'embedding = taille du vocabulaire × dimension d'embedding. Il s'agit d'une très grande matrice. Habituellement, la couche d'embedding d'un modèle NLP représente une grande proportion du nombre total de paramètres du modèle.
2.3 Indice de padding padding_idx
Lors du traitement de séquences de longueur variable, les séquences courtes doivent être complétées. L'utilisation depadding_idxpeut fixer le vecteur d'embedding du mot de padding à un vecteur nul, empêchant le contenu de padding d'affecter le modèle :
Exemple
import torch.nn as nn
# Définir padding_idx=0, ce qui signifie que l'indice 0 est le mot de padding
embedding = nn.Embedding(num_embeddings=10000, embedding_dim=128, padding_idx=0)
# Initialiser les poids
nn.init.uniform_(embedding.weight, -0.1, 0.1)
# Le vecteur d'embedding à l'indice 0 est entièrement nul
word_0 = embedding(torch.tensor([0]))
print(f"Embedding du mot de remplissage : {word_0}") # Tous les zéros
# Les autres indices restent normaux
word_5 = embedding(torch.tensor([5]))
print(f"Embedding du mot 5 : {word_5}") # Valeurs non nulles
2.4 Normalisation par norme maximale
Utilisationmax_normpeut limiter la norme des vecteurs d'embedding, en les empêchant de devenir trop grands pendant l'entraînement :
Exemple
import torch.nn as nn
# Définir la norme maximale à 1.0
embedding = nn.Embedding(num_embeddings=1000, embedding_dim=64, max_norm=1.0)
# Saisir des indices de mots arbitraires
ids = torch.tensor([1, 2, 3])
embedded = embedding(ids)
# Vérifier la norme L2 de chaque vecteur
norms = torch.norm(embedded, p=2, dim=1)
print(f"Normes de chaque vecteur : {norms}") # Toutes les valeurs sont proches de 1.0
3. Chargement de plongements de mots pré-entraînés
L'utilisation de plongements de mots pré-entraînés peut considérablement améliorer les performances du modèle, en particulier lorsque les données d'entraînement sont rares. Les plongements de mots pré-entraînés courants incluent Word2Vec, GloVe, FastText, etc.
3.1 Différence entre l'entraînement à partir de zéro et le chargement de plongements pré-entraînés
| Méthode | Avantages | Inconvénients | Scénarios applicables |
|---|---|---|---|
| Initialisation aléatoire et entraînement | Entièrement personnalisable, s'adapte à des tâches spécifiques | Nécessite une grande quantité de données d'entraînement | De nombreux mots spécifiques au domaine et suffisamment de données d'entraînement |
| Chargement de plongements pré-entraînés | Tire parti des connaissances de corpus à grande échelle, entraînement rapide et bons résultats | Couverture limitée du vocabulaire, ne peut pas gérer les mots hors vocabulaire | Tâches générales, données d'entraînement limitées |
| Geler les embeddings préentraînés | Entraînement rapide, faible utilisation de la mémoire GPU | Les embeddings ne peuvent pas être affinés | Ressources d'entraînement limitées, en se concentrant uniquement sur les couches supérieures du modèle |
| Affiner les embeddings préentraînés | Peut s'adapter à des tâches spécifiques | Entraînement plus lent, utilisation élevée de la mémoire GPU | Taille de données modérée, certaines différences de domaine |
3.2 Chargement des vecteurs de mots préentraînés GloVe
GloVe est un vecteur de mots préentraîné publié par l'université Stanford. Voici comment le charger :
Exemple
import torch.nn as nn
import numpy as np
# Simuler le chargement des vecteurs de mots GloVe (il faut en réalité télécharger les fichiers GloVe)
# Supposons qu'il existe déjà un fichier de vecteurs de mots au format : chaque ligne contient un mot suivi de ses vecteurs
def load_glove_embeddings(path, word2idx, embedding_dim=300):
"""
Charger les vecteurs de mots pré-entraînés GloVe
path: chemin vers le fichier de vecteurs de mots
word2idx: dictionnaire associant les mots aux indices
embedding_dim: dimension des vecteurs de mots
"""
embeddings = np.random.randn(len(word2idx), embedding_dim).astype(np.float32)
word_count = 0
with open(path, 'r', encoding='utf-8') as f:
for line in f:
values = line.strip().split()
word = values[0]
if word in word2idx:
word_idx = word2idx[word]
embeddings[word_idx] = np.asarray(values[1:], dtype=np.float32)
word_count += 1
print(f"{word_count}/{len(word2idx)} vecteurs de mots chargés")
return torch.from_numpy(embeddings)
# On suppose qu'il existe déjà un vocabulaire
word2idx = {'hello': 0, 'world': 1, 'example': 2, 'python': 3}
EMBED_DIM = 300
# Charger les embeddings pré-entraînés et créer une couche d'embedding
# pretrained_embeddings = load_glove_embeddings('glove.6B.300d.txt', word2idx, EMBED_DIM)
# embedding = nn.Embedding.from_pretrained(pretrained_embeddings, padding_idx=0)
# Exemple simplifié : utiliser une matrice pré-entraînée initialisée aléatoirement
pretrained_embeddings = torch.randn(len(word2idx), EMBED_DIM)
embedding = nn.Embedding.from_pretrained(pretrained_embeddings, padding_idx=0)
print(f"Forme de la couche d'embedding : {embedding.weight.shape}")
3.3 Gel et ajustement fin de la couche d'embedding
Selon les exigences de la tâche, vous pouvez choisir de geler ou d'affiner la couche d'embedding :
Exemple
import torch.nn as nn
embedding = nn.Embedding(num_embeddings=10000, embedding_dim=256)
# Méthode 1 : geler la couche d'embedding (ne participe pas à l'entraînement)
embedding.weight.requires_grad = False
# Pendant l'entraînement, seuls les paramètres avec embedding.weight.requires_grad = False ne seront pas mis à jour
# Méthode 2 : affiner la couche d'embedding (participe à l'entraînement)
embedding.weight.requires_grad = True
# Méthode 3 : geler une partie des vecteurs de mots (geler les mots très fréquents comme "the", "is")
# Supposons que les indices des mots à haute fréquence soient 0-99
embedding.weight.requires_grad = True
with torch.no_grad():
embedding.weight[0:100] *= 0 # Ou attribuer des valeurs fixes
# Exclure les paramètres gelés dans l'optimiseur
optimizer = torch.optim.Adam(
filter(lambda p: p.requires_grad, embedding.parameters()),
lr=1e-3
)
4. Combinaison de la couche d'embedding avec RNN/LSTM
L'embedding de mots est la première couche d'un modèle NLP. Il convertit les identifiants de texte en vecteurs denses, qui sont ensuite transmis à des modèles de séquence tels que RNN et LSTM pour traitement.
4.1 Couche d'embedding + Classification de texte par LSTM
Exemple
import torch.nn as nn
class TextClassifier(nn.Module):
"""
Modèle de classification de texte avec couche d'embedding + LSTM
"""
def __init__(self, vocab_size, embed_dim, hidden_size, num_classes, padding_idx=0):
super().__init__()
# Couche de plongement de mots
self.embedding = nn.Embedding(
num_embeddings=vocab_size,
embedding_dim=embed_dim,
padding_idx=padding_idx
)
# Couche LSTM
self.lstm = nn.LSTM(
input_size=embed_dim,
hidden_size=hidden_size,
num_layers=2,
batch_first=True,
bidirectional=True,
dropout=0.3
)
# Classificateur
self.fc = nn.Linear(hidden_size * 2, num_classes)
def forward(self, x):
# x: (batch_size, seq_len) - indices de mots
embedded = self.embedding(x) # (batch_size, seq_len, embed_dim)
# Sortie LSTM
output, (h_n, c_n) = self.lstm(embedded)
# Prendre l'état caché du dernier pas de temps (concaténation bidirectionnelle)
# Dernier état caché de la passe avant : h_n[-2]
# Dernier état caché de la passe arrière : h_n[-1]
h_combined = torch.cat([h_n[-2], h_n[-1]], dim=-1)
# Classification
logits = self.fc(h_combined)
return logits
# Instancier le modèle
VOCAB_SIZE = 10000
EMBED_DIM = 128
HIDDEN_SIZE = 128
NUM_CLASSES = 2
model = TextClassifier(VOCAB_SIZE, EMBED_DIM, HIDDEN_SIZE, NUM_CLASSES)
# Entrée simulée : batch_size=4, longueur de séquence=10
batch_input = torch.randint(1, VOCAB_SIZE, (4, 10))
output = model(batch_input)
print(f"Forme de l'entrée : {batch_input.shape}") # torch.Size([4, 10])
print(f"Forme de la sortie : {output.shape}") # torch.Size([4, 2])
4.2 Utilisation de vecteurs de mots pré-entraînés
Exemple
import torch.nn as nn
# Supposons que les vecteurs de mots pré-entraînés ont été chargés
pretrained_vectors = torch.randn(10000, 300) # Simuler des vecteurs pré-entraînés
# Créer une couche d'embedding et charger les poids pré-entraînés
embedding = nn.Embedding.from_pretrained(
pretrained_vectors,
padding_idx=0,
freeze=False # True : geler et ne pas entraîner, False : affiner
)
# Lors de l'utilisation de GloVe ou d'autres vecteurs de mots pré-entraînés, on gèle généralement d'abord pendant quelques époques, puis on dégèle pour affiner
# Pendant les premières époques, n'entraîner que les couches supérieures du modèle
embedding.weight.requires_grad = False
# Après plusieurs époques d'entraînement, dégeler la couche d'embedding pour affiner
# embedding.weight.requires_grad = True
5. Encodage positionnel
Contrairement aux RNN/LSTM, le modèle Transformer n'inclut pas d'information positionnelle. Un encodage positionnel doit être ajouté en plus pour permettre au modèle de percevoir l'ordre des mots dans une séquence.
5.1 Principe de l'encodage positionnel
L'encodage positionnel utilise les fonctions sinus et cosinus pour générer des vecteurs de position :
\[ \begin{aligned} PE_{(pos, 2i)} &= \sin\left(\frac{pos}{10000^{2i/d_{model}}}\right) \\ PE_{(pos, 2i+1)} &= \cos\left(\frac{pos}{10000^{2i/d_{model}}}\right) \end{aligned} \]
La particularité de cette méthode d'encodage est que les encodages à différentes positions peuvent être convertis les uns en les autres par des transformations linéaires, ce qui permet au modèle d'apprendre facilement les relations positionnelles.
5.2 Implémentation de l'encodage positionnel
Exemple
import torch.nn as nn
import math
class PositionalEncoding(nn.Module):
"""
Couche d'encodage positionnel
"""
def __init__(self, d_model, max_len=5000):
super().__init__()
# Créer la matrice d'encodage positionnel
pe = torch.zeros(max_len, d_model)
position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
# Calculer le terme diviseur
div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))
# Utiliser sin pour les indices pairs et cos pour les indices impairs
pe[:, 0::2] = torch.sin(position * div_term)
pe[:, 1::2] = torch.cos(position * div_term)
# Ajouter une dimension de batch et l'enregistrer comme tampon qui ne participe pas au calcul du gradient
pe = pe.unsqueeze(0) # (1, max_len, d_model)
self.register_buffer('pe', pe)
def forward(self, x):
"""
x: (batch_size, seq_len, d_model)
"""
seq_len = x.size(1)
# Découper l'encodage positionnel de la longueur correspondante et l'ajouter
x = x + self.pe[:, :seq_len, :]
return x
# Exemple d'utilisation
d_model = 256
max_len = 100
pos_encoding = PositionalEncoding(d_model, max_len)
# Entrée simulée : batch_size=4, seq_len=20, d_model=256
x = torch.randn(4, 20, d_model)
x = pos_encoding(x)
print(f"Forme de l'entrée : {x.shape}") # torch.Size([4, 20, 256])
L'encodage positionnel est un composant clé de l'architecture Transformer. Il permet au modèle de distinguer les mots à différentes positions, même si leurs vecteurs d'embedding sont identiques.
5.3 Encodage positionnel apprenable
Outre l'encodage positionnel fixe, on peut également utiliser un encodage positionnel apprenable :
Exemple
import torch.nn as nn
class LearnablePositionalEncoding(nn.Module):
"""
Encodage positionnel apprenable
"""
def __init__(self, d_model, max_len=5000):
super().__init__()
self.pos_embedding = nn.Embedding(max_len, d_model)
def forward(self, x):
batch_size, seq_len, d_model = x.size(1), x.size(1), x.size(2)
# Créer les indices de position [0, 1, 2, ..., seq_len-1]
positions = torch.arange(seq_len, device=x.device).unsqueeze(0).expand(batch_size, -1)
pos_encoded = self.pos_embedding(positions)
return x + pos_encoded
# Exemple d'utilisation
pos_encoding = LearnablePositionalEncoding(d_model=256, max_len=100)
x = torch.randn(4, 20, 256)
x = pos_encoding(x)
print(f"Forme de sortie : {x.shape}") # torch.Size([4, 20, 256])
6. Techniques avancées pour les couches d'embedding
6.1 Réduction de l'utilisation de la mémoire GPU
Lorsque le vocabulaire est très grand, la couche d'embedding consomme beaucoup de mémoire GPU. Les techniques suivantes peuvent être utilisées pour optimiser :
Exemple
import torch.nn as nn
# Technique 1 : Utiliser des gradients creux (sparse=True)
embedding = nn.Embedding(
num_embeddings=100000,
embedding_dim=256,
sparse=True # Les gradients sont stockés dans un format sparse, ce qui économise de la mémoire GPU
)
# Technique 2 : utiliser la quantification
# Convertir float32 en int8 ou float16
embedding_int8 = embedding.to(torch.int8)
# Technique 3 : geler les vecteurs de mots rarement utilisés
# Dans un vocabulaire à grande échelle, n'entraîner que les mots à haute fréquence ; garder les mots à basse fréquence gelés
embedding = nn.Embedding(num_embeddings=100000, embedding_dim=256)
embedding.weight.requires_grad = True
# Geler les vecteurs de mots dont l'indice est supérieur à 50000
with torch.no_grad():
embedding.weight[50000:] *= 0
embedding.weight.requires_grad = False
# N'entraîner que les mots à haute fréquence
embedding.weight[1:50000].requires_grad = True
6.2 Traitement des mots hors vocabulaire (OOV)
Les mots absents du vocabulaire (mots hors vocabulaire / OOV) peuvent apparaître dans l'ensemble de test et nécessitent un traitement particulier :
Exemple
import torch.nn as nn
class EmbeddingWithOOV(nn.Module):
"""
Couche de plongement prenant en charge les mots hors vocabulaire
"""
def __init__(self, vocab_size, embed_dim, oov_idx=Aucune):
super().__init__()
self.embedding = nn.Embedding(vocab_size + 1, embed_dim, padding_idx=0)
self.oov_idx = oov_idx if oov_idx is not None else vocab_size # Utiliser le dernier indice comme OOV
def forward(self, x):
# Remplacer les indices des mots OOV par oov_idx
oov_mask = x >= self.vocab_size
x = x.clone()
x[oov_mask] = self.oov_idx
return self.embedding(x)
# Utiliser des techniques de hachage pour gérer des vocabulaires plus grands
class HashEmbedding(nn.Module):
"""
Couche d'embedding utilisant le hachage pour gérer des vocabulaires de taille arbitraire
"""
def __init__(self, num_buckets, embed_dim):
super().__init__()
self.num_buckets = num_buckets
self.embedding = nn.Embedding(num_buckets, embed_dim)
def forward(self, x):
# Hacher les indices de mots dans des buckets
# Utiliser la méthode de hachage du dictionnaire Python
hashed = torch.remainder(x, self.num_buckets)
return self.embedding(hashed)
6.3 Embedding de sous-mots
Pour les langues morphologiquement riches (comme l'allemand et le russe), l'embedding de sous-mots peut gérer efficacement le problème des mots hors vocabulaire :
Exemple
import torch.nn as nn
class SubwordEmbedding(nn.Module):
"""
Exemple simplifié d'embedding de sous-mots
En pratique, des algorithmes tels que BPE et WordPiece devraient être utilisés pour la tokenisation
"""
def __init__(self, vocab_size, embed_dim, char_dim=50):
super().__init__()
# Embedding au niveau des caractères
self.char_embedding = nn.Embedding(vocab_size, char_dim)
# Embedding au niveau des mots
self.word_embedding = nn.Embedding(vocab_size, embed_dim - char_dim)
# LSTM au niveau des caractères pour combiner les vecteurs de caractères
self.char_lstm = nn.LSTM(
char_dim, char_dim,
batch_first=True, bidirectional=True
)
def forward(self, word_ids, char_ids):
"""
word_ids : indices de mots (batch_size, seq_len)
char_ids : indices de caractères (batch_size, seq_len, max_word_len)
"""
# Plongement de mots
word_emb = self.word_embedding(word_ids)
# Plongement de caractères + LSTM
batch_size, seq_len, max_word_len = char_ids.shape
char_ids_flat = char_ids.view(-1, max_word_len) # (batch_size * seq_len, max_word_len)
char_emb = self.char_embedding(char_ids_flat) # (batch_size * seq_len, max_word_len, char_dim)
char_output, (h_n, _) = self.char_lstm(char_emb)
# Prendre les états cachés finaux bidirectionnels et les concaténer
char_rep = torch.cat([h_n[-2], h_n[-1]], dim=-1) # (batch_size * seq_len, char_dim * 2)
char_rep = char_rep.view(batch_size, seq_len, -1) # (batch_size, seq_len, char_dim * 2)
# Concaténer l'embedding de mot et la représentation de caractères
combined = torch.cat([word_emb, char_rep], dim=-1)
return combined
7. Exemple pratique complet : modèle de classification de texte
Ci-dessous se trouve un exemple complet de modèle de classification de texte, comprenant une couche d'embedding, un LSTM et un classifieur :
Exemple
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# ── Paramètres de configuration ──────────────────────────────────────
VOCAB_SIZE = 10000
EMBED_DIM = 128
HIDDEN_SIZE = 128
NUM_LAYERS = 2
NUM_CLASSES = 5
DROPOUT = 0.3
MAX_LEN = 200
# ── Définition du modèle ──────────────────────────────────────
class TextClassificationModel(nn.Module):
def __init__(self, vocab_size, embed_dim, hidden_size,
num_layers, num_classes, dropout=0.3, padding_idx=0):
super().__init__()
# Couche d'embedding
self.embedding = nn.Embedding(
vocab_size,
embed_dim,
padding_idx=padding_idx
)
# BiLSTM
self.lstm = nn.LSTM(
embed_dim,
hidden_size,
num_layers=num_layers,
batch_first=True,
bidirectional=True,
dropout=dropout if num_layers > 1 else 0
)
# Classificateur
self.dropout = nn.Dropout(dropout)
self.fc = nn.Linear(hidden_size * 2, num_classes)
def forward(self, x):
# x: (batch_size, seq_len)
embedded = self.embedding(x) # (batch_size, seq_len, embed_dim)
# LSTM
output, (h_n, c_n) = self.lstm(embedded)
# Concaténer les états cachés finaux bidirectionnels
h_forward = h_n[-2] # (batch_size, hidden_size)
h_backward = h_n[-1] # (batch_size, hidden_size)
h_combined = torch.cat([h_forward, h_backward], dim=-1)
# Classification
dropped = self.dropout(h_combined)
logits = self.fc(droped)
return logits
# ── Jeu de données ──────────────────────────────────────
class TextDataset(Dataset):
def __init__(self, texts, labels, vocab, max_len=200):
self.texts = texts
self.labels = labels
self.vocab = vocab
self.max_len = max_len
def __len__(self):
return len(self.texts)
def __getitem__(self, idx):
text = self.texts[idx][:self.max_len]
# Convertir les mots en indices, les mots inconnus représentés par 1 (<UNK>)
ids = [self.vocab.get(word, 1) for word in text]
# Compléter avec des zéros jusqu'à une longueur fixe
if len(ids) < self.max_len:
ids += [0] * (self.max_len - len(ids))
return torch.tensor(ids), torch.tensor(self.labels[idx])
# ── Fonction d'entraînement ──────────────────────────────────────
def train_epoch(model, loader, optimizer, criterion, device):
model.train()
total_loss = 0
correct = 0
total = 0
for inputs, labels in loader:
inputs, labels = inputs.to(device), labels.to(device)
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
total_loss += loss.item() * inputs.size(0)
_, predicted = outputs.max(1)
correct += predicted.eq(labels).sum().item()
total += labels.size(0)
return total_loss / total, correct / total
# ── Initialisation et entraînement ──────────────────────────────────
# Supposons qu'un vocabulaire existe déjà
word2idx = {'<PAD>': 0, '<UNK>': 1} # Le vocabulaire doit être construit en fonction du corpus réel
model = TextClassificationModel(
VOCAB_SIZE, EMBED_DIM, HIDDEN_SIZE,
NUM_LAYERS, NUM_CLASSES, DROPOUT
).to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=1e-3)
# Entraînement simulé
print("Début de l'entraînement...")
for epoch in range(10):
train_loss, train_acc = train_epoch(model, None, optimizer, criterion, device)
print(f"Epoch {epoch+1}: Loss={train_loss:.4f}, Acc={train_acc:.4f}")
8. Référence rapide de l’API
8.1 Opérations courantes sur nn.Embedding
| Opération | Code |
|---|---|
| Créer une couche d'embedding | nn.Embedding(num_embeddings, embedding_dim) |
| Charger des embeddings pré-entraînés | nn.Embedding.from_pretrained(weights) |
| Table de recherche pour obtenir les embeddings | embedding(word_ids) |
| Geler les embeddings | embedding.weight.requires_grad = False |
| Obtenir les vecteurs d'embedding | embedding.weight[idx] |
8.2 Ressources de vecteurs de mots pré-entraînés
| Ressource | Dimension | Fonctionnalités |
|---|---|---|
| GloVe | 50, 100, 200, 300 | Statistiques de cooccurrence de mots, entraînement rapide |
| Word2Vec | 50-500 | Entraîné par Google, couverture étendue |
| FastText | 300 | Prend en charge les sous-mots, efficace pour gérer les OOV |
| BERT | 768+ | Selon le contexte, meilleures performances |
8.3 Recommandations pour le choix d'une couche d'embedding
数据量小(< 10K)
-> 使用预训练词向量(GloVe/FastText)+ 冻结或微调
数据量中等(10K ~ 100K)
-> 使用预训练词向量 + 微调
数据量大(> 100K)
-> 可考虑从头训练,或使用大规模预训练模型
领域差异大
-> 使用领域相关预训练模型或增量训练
资源受限
-> 冻结嵌入层,使用较小的嵌入维度
Autres extensions