PyTorch torchtext
Bien que l'écosystème PyTorch proposetorchvisionle traitement des données d'images,torchaudiole traitement des données audio, mais dans le domaine du traitement du texte, celle officiellement fournietorchtextLa bibliothèque a subi quelques changements. Cette section présente comment effectuer le prétraitement des données textuelles, la construction du vocabulaire, le chargement des données et d'autres opérations à l'aide de diverses méthodes.
Remarque : La bibliothèque torchtext a subi quelques refactorisations. Il est recommandé d'utilisertorchtext.legacyou de construire votre propre pipeline de traitement de texte. La dernière version de torchtext est revenue et fournit une API plus moderne.
Notions de base du prétraitement des données textuelles
Le prétraitement de texte est la première étape des tâches de NLP, incluant la tokenisation, la construction de vocabulaire, l'encodage et d'autres opérations.
1.1 Pipeline de base de traitement de texte
Exemple
from collections import Counter
class SimpleTokenizer:
"""
Tokeniseur simple : tokeniser en fonction des espaces et de la ponctuation
"""
def __init__(self):
# Mappage de ponctuation
self.punctuation = str.maketrans('', '', '.,!?;:"\'-()[]{}')
def tokenize(self, text):
# Convertir en minuscules
text = text.lower()
# Supprimer la ponctuation
text = text.translate(self.punctuation)
# Tokeniser
tokens = text.split()
return tokens
class Vocabulary:
"""
Construction du vocabulaire
"""
def __init__(self, min_freq=2, max_size=10000):
self.min_freq = min_freq
self.max_size = max_size
self.word2idx = {'<PAD>': 0, '<UNK>': 1}
self.idx2word = {0: '<PAD>', 1: '<UNK>'}
self.word_count = Counter()
def build_vocab(self, texts):
"""Construire le vocabulaire à partir d'une liste de textes"""
tokenizer = SimpleTokenizer()
# Compter les fréquences des mots
for text in texts:
tokens = tokenizer.tokenize(text)
self.word_count.update(tokens)
# Construire le vocabulaire
for word, count in self.word_count.most_common(self.max_size):
if count < self.min_freq:
break
if word not in self.word2idx:
idx = len(self.word2idx)
self.word2idx[word] = idx
self.idx2word[idx] = word
print(f"Taille du vocabulaire : {len(self.word2idx)}")
def encode(self, text, max_len=50):
"""Encoder le texte comme une séquence d'indices"""
tokenizer = SimpleTokenizer()
tokens = tokenizer.tokenize(text)[:max_len]
# Encodage
indices = [
self.word2idx.get(token, self.word2idx['<UNK>'])
for token in tokens
]
# Remplir avec des zéros
if len(indices) < max_len:
indices += [self.word2idx['<PAD>']] * (max_len - len(indices))
return indices
def decode(self, indices):
"""Décode une séquence d'indices en texte"""
tokens = [self.idx2word.get(idx, '<UNK>') for idx in indices]
return ' '.join(tokens)
# Exemple d'utilisation
textes = [
"Bonjour le monde",
"Ceci est un test",
"PyTorch est excellent pour l'apprentissage profond",
"Le traitement du langage naturel est amusant",
"L'apprentissage profond permet de nombreuses applications",
]
vocab = Vocabulary(min_freq=1, max_size=100)
vocab.build_vocab(texts)
# Encodage
encoded = vocab.encode("Bonjour le monde de l'apprentissage profond !", max_len=10)
print(f"Résultat encodé : {encoded}")
# Décodage
decoded = vocab.decode(encoded)
print(f"Résultat décodé : {decoded}")
2. Utilisation de torchtext (Legacy)
Si torchtext est installé, vous pouvez utiliser le module legacy pour le traitement de texte.
2.1 Installation et import
Exemple
# pip install torchtext
# Importer le module legacy
try:
import torchtext
from torchtext.legacy import data
from torchtext.legacy import datasets
print(f"Version de torchtext : {torchtext.__version__}")
TORCHTEXT_AVAILABLE = True
except ImportError:
print("torchtext n'est pas installé, utilisation d'une implémentation personnalisée")
TORCHTEXT_AVAILABLE = False
# Ou essayez la nouvelle version
try:
from torchtext import transforms
from torchtext.datasets import AG_NEWS
print("La nouvelle version de torchtext est disponible")
except ImportError:
print("La nouvelle version de torchtext n'est pas disponible")
2.2 Field et Dataset
Exemple
from torchtext.legacy import data
from torchtext.legacy import datasets
from torchtext.legacy.data import Field, TabularDataset, BucketIterator
# Définir les champs
TEXT = Field(
tokenize='spacy', # Utiliser spacy pour la tokenisation
tokenizer_language='en_core_web_sm',
lower=True, # Convertir en minuscules
include_lengths=True, # Retourner la longueur de la séquence
batch_first=True # Dimension batch en premier
)
LABEL = Field(
sequential=False,
use_vocab=False,
dtype=torch.long
)
# Définir le jeu de données
# Supposer un format de fichier CSV : label,text
# 1,Ceci est un avis positif
# 0,Ceci est un avis négatif
# Ou utilisez un jeu de données intégré (par ex., IMDB)
# train_data, test_data = datasets.IMDB.splits(TEXT, LABEL)
print("Configuration de Field et Dataset terminée")
2.3 Construction du vocabulaire et des itérateurs
Exemple
# TEXT.build_vocab(train_data, vectors="glove.6B.100d", max_size=10000)
# Créer un itérateur
# train_iterator, test_iterator = BucketIterator.splits(
# (train_data, test_data),
# batch_size=32,
# sort_within_batch=True,
# device=torch.device('cuda')
# )
# Itérer l'entraînement
# for batch in train_iterator:
# text, lengths = batch.text
# labels = batch.label
# # Code d'entraînement
print("Configuration du vocabulaire et de l'itérateur terminée")
3. Pipeline de données NLP personnalisé
Il est recommandé d'utiliser une approche personnalisée plus flexible de traitement des données qui ne dépend pas de torchtext.
3.1 Implémentation de la classe Dataset
Exemple
from torch.utils.data import Dataset, DataLoader
from collections import Counter
import re
class TextDataset(Dataset):
"""
Jeu de données textuelles
"""
def __init__(self, texts, labels, vocab=None, max_len=128, min_freq=2):
self.texts = texts
self.labels = labels
self.max_len = max_len
# Construire ou utiliser un vocabulaire existant
if vocab is None:
self.vocab = self._build_vocab(texts, min_freq)
else:
self.vocab = vocab
def _build_vocab(self, texts, min_freq):
"""Construire le vocabulaire"""
word_counts = Counter()
for text in texts:
tokens = self._tokenize(text)
word_counts.update(tokens)
# Créer le vocabulaire
word2idx = {'<PAD>': 0, '<UNK>': 1}
for word, count in word_counts.items():
if count >= min_freq:
word2idx[word] = len(word2idx)
return word2idx
def _tokenize(self, text):
"""Tokenisation simple"""
# Convertir en minuscules
text = text.lower()
# Supprimer les caractères spéciaux, conserver les caractères alphanumériques et les espaces
text = re.sub(r'[^a-z0-9\s]', ' ', text)
# Tokeniser
tokens = text.split()
return tokens
def _encode(self, text):
"""Encoder le texte"""
tokens = self._tokenize(text)[:self.max_len]
indices = [
self.vocab.get(token, self.vocab['<UNK>'])
for token in tokens
]
# Remplir avec des zéros
if len(indices) < self.max_len:
indices += [self.vocab['<PAD>']] * (self.max_len - len(indices))
return indices
def __len__(self):
return len(self.texts)
def __getitem__(self, idx):
text = self.texts[idx]
label = self.labels[idx]
encoded = self._encode(text)
return torch.tensor(encoded, dtype=torch.long), torch.tensor(label, dtype=torch.long)
# Exemple d'utilisation
textes = [
"C'est un excellent film",
"J'ai détesté ce film",
"Interprétation incroyable",
"Jeu d'acteur terrible",
"Je recommande vivement",
]
labels = [1, 0, 1, 0, 1]
dataset = TextDataset(texts, labels, max_len=10)
print(f"Taille du jeu de données: {len(dataset)}")
print(f"Taille du vocabulaire: {len(dataset.vocab)}")
# Obtenir un échantillon
text, label = dataset[0]
print(f"Encodage du texte : {text[:5]}...")
print(f"Étiquette : {label}")
3.2 Tokeniseurs avancés
Exemple
def tokenize_with_spacy(text):
"""Tokeniser avec spacy"""
try:
import spacy
nlp = spacy.load("en_core_web_sm")
doc = nlp(text)
return [token.text for token in doc]
except ImportError:
print("spacy n'est pas installé, utilisation d'une tokenisation simple")
return text.lower().split()
# Utiliser nltk pour la tokenisation et le stemming
def tokenize_with_nltk(text):
"""Tokeniser avec nltk"""
try:
import nltk
from nltk.tokenize import word_tokenize
from nltk.stem import PorterStemmer
# Tokeniser
tokens = word_tokenize(text.lower())
# Facultatif : racinisation
stemmer = PorterStemmer()
tokens = [stemmer.stem(token) for token in tokens if token.isalnum()]
return tokens
except ImportError:
return text.lower().split()
# Utiliser SentencePiece pour la tokenisation en sous-mots
class SentencePieceTokenizer:
"""
Utiliser SentencePiece pour la tokenisation en sous-mots
"""
def __init__(self, model_path=None):
self.model_path = model_path
self.sp = None
def train(self, texts, vocab_size=10000):
"""Entraîner le modèle SentencePiece"""
try:
import sentencepiece as spm
import tempfile
# Écrire dans un fichier temporaire
with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.txt') as f:
for text in texts:
f.write(text + '\n')
temp_file = f.name
# Entraîner
spm.SentencePieceTrainer.train(
input=temp_file,
model_prefix='spm_model',
vocab_size=vocab_size,
character_coverage=1.0,
model_type='unigram',
)
self.sp = spm.SentencePieceProcessor()
self.sp.load('spm_model.model')
except ImportError:
print("sentencepiece n'est pas installé")
def encode(self, text):
if self.sp:
return self.sp.encode(text, out_type=str)
return text.split()
def decode(self, ids):
if self.sp:
return self.sp.decode(ids)
return ' '.join(ids)
3.3 Chargeur de données complet
Exemple
from torch.utils.data import Dataset, DataLoader
from collections import Counter
class NLPDataset(Dataset):
"""
Classe complète de jeu de données NLP
Prend en charge les séquences de longueur variable, la construction du vocabulaire et le remplissage par lots
"""
def __init__(self, texts, labels, min_freq=2, max_vocab=30000):
self.texts = texts
self.labels = labels
self.min_freq = min_freq
# Construire le vocabulaire
self.word2idx, self.idx2word = self._build_vocab(texts, max_vocab)
self.pad_idx = self.word2idx['<PAD>']
self.unk_idx = self.word2idx['<UNK>']
def _tokenize(self, text):
text = text.lower()
text = re.sub(r'[^a-z0-9\s]', ' ', text)
return text.split()
def _build_vocab(self, texts, max_vocab):
"""Construire le vocabulaire"""
counter = Counter()
for text in texts:
tokens = self._tokenize(text)
counter.update(tokens)
# Construire le vocabulaire
word2idx = {'<PAD>': 0, '<UNK>': 1}
idx2word = {0: '<PAD>', 1: '<UNK>'}
for word, count in counter.most_common(max_vocab):
if count >= self.min_freq and word not in word2idx:
idx = len(word2idx)
word2idx[word] = idx
idx2word[idx] = word
return word2idx, idx2word
def __len__(self):
return len(self.texts)
def __getitem__(self, idx):
text = self.texts[idx]
tokens = self._tokenize(text)
indices = [self.word2idx.get(t, self.unk_idx) for t in tokens]
return {
'input': indices,
'label': self.labels[idx],
'length': len(indices)
}
def collate_fn(batch, pad_idx=0):
"""
Fonction de collate personnalisée : gérer les séquences de longueur variable
"""
# Trier par longueur par ordre décroissant
batch.sort(key=lambda x: x['length'], reverse=True)
texts = [item['input'] for item in batch]
labels = [item['label'] for item in batch]
lengths = [item['length'] for item in batch]
# Compléter à la même longueur
max_len = max(lengths)
padded = [text + [pad_idx] * (max_len - len(text)) for text in texts]
return {
'input': torch.tensor(padded, dtype=torch.long),
'labels': torch.tensor(labels, dtype=torch.long),
'lengths': torch.tensor(lengths, dtype=torch.long)
}
# Utiliser DataLoader
def create_dataloader(texts, labels, batch_size=32, shuffle=True):
"""Créer un chargeur de données"""
dataset = NLPDataset(texts, labels)
pad_idx = dataset.pad_idx
dataloader = DataLoader(
dataset,
batch_size=batch_size,
shuffle=shuffle,
collate_fn=lambda b: collate_fn(b, pad_idx)
)
return dataloader, dataset
# Simuler des données
textes = [
"J'adore ce film",
"C'est un mauvais film",
"Excellent film",
"Jeu d'acteur terrible",
"Je recommande ceci",
"Pas la peine de le regarder",
]
labels = [1, 0, 1, 0, 1, 0]
dataloader, dataset = create_dataloader(texts, labels, batch_size=2)
for batch in dataloader:
print("Forme de l'entrée :", batch['input'].shape)
print("Étiquettes :", batch['labels'])
print("Longueurs :", batch['lengths'])
print("---")
4. Chargement des vecteurs de mots pré-entraînés
L'utilisation de vecteurs de mots pré-entraînés peut améliorer les performances du modèle.
4.1 Vecteurs de mots GloVe
Exemple
import numpy as np
def load_glove_vectors(filepath, word2idx, embedding_dim=300):
"""
Charger les vecteurs de mots pré-entraînés GloVe
Paramètres :
filepath : chemin du fichier GloVe
word2idx: dictionnaire de vocabulaire
embedding_dim: dimension des vecteurs de mots
"""
print("Chargement des vecteurs de mots GloVe...")
# Initialiser la matrice d'embedding
num_words = len(word2idx)
embeddings = np.random.randn(num_words, embedding_dim).astype(np.float32)
embeddings[word2idx['<PAD>']] = np.zeros(embedding_dim) # Mettre le vecteur PAD à zéro
words_loaded = 0
with open(filepath, 'r', encoding='utf-8') as f:
for line in f:
values = line.strip().split()
word = values[0]
if word in word2idx:
idx = word2idx[word]
vector = np.asarray(values[1:], dtype=np.float32)
if len(vector) == embedding_dim:
embeddings[idx] = vector
words_loaded += 1
print(f"Vecteurs de mots chargés : {words_loaded}/{num_words}")
return torch.from_numpy(embeddings)
# Chargement simulé
def create_pretrained_embedding(word2idx, embedding_dim=300, pretrained_path=Aucune):
"""
Créer une couche de plongement pré-entraînée
"""
if pretrained_path and False: # Définir sur True et fournir un chemin valide
weights = load_glove_vectors(pretrained_path, word2idx, embedding_dim)
else:
# Utiliser une initialisation aléatoire
num_words = len(word2idx)
weights = torch.randn(num_words, embedding_dim) * 0.1
embedding = torch.nn.Embedding.from_pretrained(weights, padding_idx=0)
return embedding
# Exemple
word2idx = {'<PAD>': 0, '<UNK>': 1, 'hello': 2, 'world': 3, 'test': 4}
embedding = create_pretrained_embedding(word2idx, embedding_dim=100)
print(f"Forme de la couche d'embedding : {embedding.weight.shape}")
4.2 Chargement de Word2Vec avec gensim
Exemple
"""
Chargement de Word2Vec avec gensim
"""
try:
from gensim.models import KeyedVectors
# Charger le modèle
# model = KeyedVectors.load_word2vec_format(model_path, binary=True)
# Créer la matrice de plongement
embedding_dim = 300
num_words = len(word2idx)
embeddings = np.random.randn(num_words, embedding_dim).astype(np.float32)
# Remplir les vecteurs de mots
embeddings[word2idx['<PAD>']] = np.zeros(embedding_dim)
# Charger les vecteurs de mots
# for word, idx in word2idx.items():
# if word in model:
# embeddings[idx] = model[word]
return torch.from_numpy(embeddings)
except ImportError:
print("gensim n'est pas installé")
return None
4.3 Embeddings pré-entraînés personnalisés
Exemple
import torch.nn as nn
class PretrainedEmbedding(nn.Module):
"""
Couche Embedding qui prend en charge le chargement de vecteurs de mots pré-entraînés
"""
def __init__(self, vocab_size, embed_dim, pretrained_weights=Aucune,
padding_idx=0, freeze=False):
super().__init__()
self.embedding = nn.Embedding(
vocab_size,
embed_dim,
padding_idx=padding_idx
)
# Charger les poids pré-entraînés
if pretrained_weights is not None:
self.embedding.weight.data.copy_(pretrained_weights)
# Indique s'il faut geler
if freeze:
self.embedding.weight.requires_grad = False
def forward(self, x):
return self.embedding(x)
# Exemple d'utilisation
vocab_size = 10000
embed_dim = 300
pretrained = torch.randn(vocab_size, embed_dim) * 0.1
embedding_layer = PretrainedEmbedding(
vocab_size,
embed_dim,
pretrained_weights=pretrained,
padding_idx=0,
freeze=False # Définir sur True pour geler la couche d'embedding
)
# Test
x = torch.tensor([[1, 2, 3], [4, 5, 6]])
output = embedding_layer(x)
print(f"Forme de l'entrée : {x.shape}")
print(f"Forme de sortie : {output.shape}")
5. Augmentation des données textuelles
L'augmentation des données peut améliorer la capacité de généralisation du modèle.
5.1 Augmentation par rétro-traduction
Exemple
def back_translation_augment(text, translator):
"""
Augmentation par rétro-traduction : traduire le texte dans une autre langue, puis le traduire à nouveau
"""
# Traduire vers la langue cible
translated = translator.translate(text, dest='fr')
# Traduire à nouveau vers la langue source
back_translated = translator.translate(translated.text, dest='en')
return back_translated.text
# Exemple d'utilisation
# from googletrans import Translator
# translator = Translator()
# augmented_text = back_translation_augment("I love this movie", translator)
5.2 Remplacement de synonymes
Exemple
def synonym_replacement(text, n=1, stop_words=None):
"""
Remplacement par synonymes
"""
if stop_words is None:
stop_words = {'a', 'un', 'le', 'est', 'sont', 'était', 'étaient'}
words = text.lower().split()
replaceable = [i for i, w in enumerate(words) if w not in stop_words]
if not replaceable:
return text
n = min(n, len(replaceable))
replace_idx = random.sample(replaceable, n)
# Mappage simplifié des synonymes (devrait en fait utiliser WordNet)
synonym_map = {
'bon': ['génial', 'excellent', 'agréable'],
'mauvais': ['médiocre', 'terrible', 'affreux'],
'film': ['film', 'cinéma'],
'aimé': ['adoré', 'apprécié'],
}
for idx in replace_idx:
word = words[idx]
if word in synonym_map:
words[idx] = random.choice(synonym_map[word])
return ' '.join(words)
# Exemple d'utilisation
text = "J'ai aimé ce bon film"
augmented = synonym_replacement(text, n=2)
print(f"Phrase originale : {text}")
print(f"Augmenté : {augmented}")
5.3 Insertion et suppression aléatoires
Exemple
def random_insertion(text, n=1):
"""
Insertion aléatoire : insérer aléatoirement des mots dans le texte
"""
words = text.lower().split()
for _ in range(n):
if len(words) > 1:
idx = random.randint(0, len(words) - 1)
# Mots insérés simplifiés
insert_words = ['really', 'very', 'quite', 'actually']
words.insert(idx, random.choice(insert_words))
return ' '.join(words)
def random_deletion(text, p=0.1):
"""
Suppression aléatoire : supprimer des mots avec une probabilité p
"""
words = text.lower().split()
if len(words) == 1:
return text
remaining = [w for w in words if random.random() > p]
if len(remaining) == 0:
return random.choice(words)
return ' '.join(remaining)
def random_swap(text, n=1):
"""
Échange aléatoire : échanger aléatoirement les positions de deux mots
"""
words = text.lower().split()
if len(words) < 2:
return text
for _ in range(n):
idx1, idx2 = random.sample(range(len(words)), 2)
words[idx1], words[idx2] = words[idx2], words[idx1]
return ' '.join(words)
# Exemple d'utilisation
text = "C'est un excellent film sur l'amour et le bonheur"
print("Original :", text)
print("Inséré :", random_insertion(text, n=2))
print("Supprimé :", random_deletion(text, p=0.2))
print("Échangé :", random_swap(text, n=2))
6. Exemples de tâches NLP courantes
6.1 Pipeline complet de classification de texte
Exemple
import torch.nn as nn
from torch.utils.data import Dataset, DataLoader
# 1. Préparation des données
textes = [
"J'adore ce produit, il est incroyable !",
"Qualité terrible, gaspillage d'argent.",
"Très bon rapport qualité-prix.",
"Pas satisfait de l'achat.",
"Le meilleur achat que j'aie jamais fait !",
"Très déçu de cet article.",
]
labels = [1, 0, 1, 0, 1, 0] # 1 : positif, 0 : négatif
# 2. Jeu de données
class TextClassificationDataset(Dataset):
def __init__(self, texts, labels, max_len=50):
self.texts = texts
self.labels = labels
self.max_len = max_len
self.vocab = self._build_vocab(texts)
def _build_vocab(self, texts):
vocab = {'<PAD>': 0, '<UNK>': 1}
for text in texts:
for word in text.lower().split():
if word not in vocab:
vocab[word] = len(vocab)
return vocab
def __len__(self):
return len(self.texts)
def __getitem__(self, idx):
text = self.texts[idx]
label = self.labels[idx]
# Encodage simple
tokens = text.lower().split()[:self.max_len]
indices = [self.vocab.get(t, 1) for t in tokens]
# Remplissage
if len(indices) < self.max_len:
indices += [0] * (self.max_len - len(indices))
return torch.tensor(indices, dtype=torch.long), torch.tensor(label, dtype=torch.long)
# 3. Modèle
class TextClassifier(nn.Module):
def __init__(self, vocab_size, embed_dim=128, hidden_dim=64, num_classes=2):
super().__init__()
self.embedding = nn.Embedding(vocab_size, embed_dim, padding_idx=0)
self.lstm = nn.LSTM(embed_dim, hidden_dim, batch_first=True)
self.fc = nn.Linear(hidden_dim, num_classes)
def forward(self, x):
embedded = self.embedding(x)
_, (hidden, _) = self.lstm(embedded)
output = self.fc(hidden.squeeze(0))
return output
# 4. Entraînement
dataset = TextClassificationDataset(texts, labels)
dataloader = DataLoader(dataset, batch_size=2, shuffle=True)
model = TextClassifier(vocab_size=len(dataset.vocab))
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
# Entraîner pendant quelques époques
model.train()
for epoch in range(10):
total_loss = 0
for texts_batch, labels_batch in dataloader:
optimizer.zero_grad()
outputs = model(texts_batch)
loss = criterion(outputs, labels_batch)
loss.backward()
optimizer.step()
total_loss += loss.item()
print(f"Époque {epoch+1}, Perte : {total_loss/len(dataloader):.4f}")
print("Entraînement terminé !")
6.2 Exemple d'étiquetage de séquence (NER)
Exemple
import torch.nn as nn
from torch.utils.data import Dataset, DataLoader
# Jeu de données d'étiquetage de séquence
class NERDataset(Dataset):
"""
Jeu de données de reconnaissance d'entités nommées
Format : [(word, tag), ...]
"""
def __init__(self, sentences_tags, word2idx, tag2idx, max_len=50):
self.sentences_tags = sentences_tags
self.word2idx = word2idx
self.tag2idx = tag2idx
self.max_len = max_len
def __len__(self):
return len(self.sentences_tags)
def __getitem__(self, idx):
sentence_tags = self.sentences_tags[idx]
words = [wt[0] for wt in sentence_tags]
tags = [wt[1] for wt in sentence_tags]
# Encodage
word_ids = [self.word2idx.get(w.lower(), 1) for w in words[:self.max_len]]
tag_ids = [self.tag2idx[t] for t in tags[:self.max_len]]
# Remplissage
if len(word_ids) < self.max_len:
word_ids += [0] * (self.max_len - len(word_ids))
tag_ids += [0] * (self.max_len - len(tag_ids))
return {
'words': torch.tensor(word_ids, dtype=torch.long),
'tags': torch.tensor(tag_ids, dtype=torch.long)
}
# Modèle NER
class NERModel(nn.Module):
def __init__(self, vocab_size, tag_size, embed_dim=128, hidden_dim=256):
super().__init__()
self.embedding = nn.Embedding(vocab_size, embed_dim, padding_idx=0)
self.lstm = nn.LSTM(embed_dim, hidden_dim, batch_first=True, bidirectional=True)
self.fc = nn.Linear(hidden_dim * 2, tag_size)
def forward(self, x):
embedded = self.embedding(x)
lstm_out, _ = self.lstm(embedded)
logits = self.fc(lstm_out)
return logits
# Exemple de données
data = [
[("Jean", "B-PER"), ("vit", "O"), ("à", "O"), ("New", "B-LOC"), ("York", "I-LOC"), (".", "O")],
[("Apple", "B-ORG"), ("est", "O"), ("a", "O"), ("entreprise", "O"), (".", "O")],
]
# Construire le vocabulaire des mots et la table des tags
word2idx = {'<PAD>': 0, '<UNK>': 1}
tag2idx = {'O': 0, 'B-PER': 1, 'I-PER': 2, 'B-LOC': 3, 'I-LOC': 4, 'B-ORG': 5, 'I-ORG': 6}
for sent in data:
for word, tag in sent:
if word.lower() not in word2idx:
word2idx[word.lower()] = len(word2idx)
print(f"Taille du vocabulaire : {len(word2idx)}")
print(f"Nombre d'étiquettes : {len(tag2idx)}")
7. Alternatives recommandées
7.1 Autres bibliothèques de traitement du texte
| Nom de la bibliothèque | Fonctionnalités | Scénarios applicables |
|---|---|---|
| HuggingFace Datasets | Chargement et traitement des données | Tâches générales de NLP |
| spacy | Outils NLP avancés | Tokenisation, NER, analyse des dépendances |
| NLTK | Outils NLP classiques | Enseignement, prototypage |
| textblob | Simple et facile à utiliser | Traitement de texte rapide |
7.2 Utilisation de HuggingFace Datasets
Exemple
# pip install datasets
from datasets import load_dataset
# Charger le jeu de données
# dataset = load_dataset("imdb")
# dataset = load_dataset("squad")
# Prétraitement des données
# def preprocess_function(examples):
# return tokenizer(examples['text'], truncation=True, padding='max_length')
# tokenized_dataset = dataset.map(preprocess_function, batched=True)
print("Exemple d'utilisation de HuggingFace Datasets :")
print("from datasets import load_dataset")
print("dataset = load_dataset('imdb')")
8. Référence rapide de l’API
8.1 Opérations courantes de traitement de texte
| Opération | Méthode |
|---|---|
| Tokenisation | text.split(), spacy, nltk, jieba |
| Construction du vocabulaire | Counter, vocab.build_vocab() |
| Encodage | vocab.encode(), tokenizer.encode() |
| Décodage | vocab.decode(), tokenizer.decode() |
| Remplissage | pad_sequence, collate_fn |
| Chargement des vecteurs de mots | Chargement direct avec Gensim, GloVe |
8.2 Méthodes d'augmentation de données
| Méthode | Description |
|---|---|
| Remplacement par synonymes | Remplacer aléatoirement des mots par des synonymes |
| Insertion aléatoire | Insérer aléatoirement des mots |
| Suppression aléatoire | Supprimer aléatoirement des mots |
| Échange aléatoire | Échanger aléatoirement les positions des mots |
| Rétrotraduction | Traduire puis retraduire |
8.3 Pipeline de traitement des données recommandé
1. 数据清洗 - 去除 HTML 标签、特殊字符 - 统一编码、大小写 2. 分词 - 英文: spaCy / NLTK - 中文: jieba / pkuseg 3. 词表构建 - 过滤低频词 - 设定最大词表大小 4. 序列化 - 编码为索引 - 统一长度(填充/截断) 5. 数据增强(可选) - 同义词替换、回译 6. 批量加载 - DataLoader + 自定义 collate_fnAutres extensions