Le traitement du langage naturel (NLP) est un pilier de l’IA moderne, qui permet aux machines de comprendre et de répondre au langage humain. Avec l’explosion des interactions numériques, son importance ne cesse de croître. PyTorch, bibliothèque open source de machine learning très populaire, offre des outils robustes pour les tâches de NLP grâce à sa flexibilité et à ses calculs de tenseurs efficaces. Son graphe computationnel dynamique facilite également la modification et la construction de modèles complexes, ce qui en fait un choix idéal pour ce tutoriel.
La configuration de l’environnement PyTorch peut parfois s’avérer délicate selon le système d’exploitation, le gestionnaire de paquets, le langage de programmation et la plateforme de calcul utilisés. Le processus d’installation peut donc légèrement varier et nécessiter des commandes spécifiques.
Pour obtenir la commande d’installation adéquate, rendez-vous sur la page officielle get started de PyTorch : sélectionnez vos préférences et suivez les instructions affichées.
Nous utiliserons DataLab pour ce tutoriel. Le code complet pour entraîner un modèle d’analyse de sentiment avec PyTorch est disponible dans ce workbook DataLab si vous souhaitez suivre pas à pas.
Introduction aux tenseurs
Les tenseurs sont des structures de données fondamentales en mathématiques et en physique, généralisant scalaires, vecteurs et matrices. Ce sont des tableaux multidimensionnels capables de stocker et de manipuler efficacement de grands volumes de données numériques. Les tenseurs ont une forme, une taille et un type d’unité définis, ce qui les rend très polyvalents pour diverses opérations de calcul.
Dans PyTorch, les tenseurs sont les blocs de construction et l’objet de représentation des données principal. Ils sont proches des tableaux NumPy, avec des fonctionnalités supplémentaires et des optimisations conçues pour l’apprentissage profond. Les opérations sur les tenseurs tirent parti de l’accélération matérielle, notamment des GPU, pour calculer efficacement des réseaux de neurones complexes.
Les tenseurs jouent un rôle crucial dans les tâches de NLP en raison de la nature séquentielle et hiérarchique du langage.
Le NLP consiste à traiter et à comprendre des informations textuelles. Les tenseurs permettent de représenter et de manipuler des textes en encodant des mots, des phrases ou des documents sous forme de vecteurs numériques.
Cette représentation numérique permet aux modèles d’apprentissage profond de traiter et d’apprendre efficacement à partir de textes. Les tenseurs facilitent la gestion de grands jeux de données, l’entraînement de réseaux de neurones et des techniques avancées comme les mécanismes d’attention pour des modèles de NLP plus précis.
Word embeddings
Les word embeddings sont des représentations vectorielles denses de mots dans un espace continu. Ils capturent les relations sémantiques et syntaxiques entre les mots, ce qui améliore la compréhension et la contextualisation des textes. En représentant les mots par des vecteurs numériques, les embeddings saisissent proximités et différences sémantiques, permettant aux algorithmes de manipuler des mots comme des entrées numériques porteuses de sens.
En clair, les embeddings sont une façon astucieuse de représenter les mots par des nombres. Ces nombres portent une signification qui reflète les relations entre mots : une sorte de code qui aide les ordinateurs à comprendre et traiter plus facilement le langage.
Word2Vec et GloVe sont deux méthodes populaires pour générer des embeddings. Word2Vec est un modèle à réseau de neurones qui apprend les représentations en prédisant les mots du contexte à partir d’un mot cible (CBOW) ou le mot cible à partir de son contexte (skip-gram).
GloVe (Global Vectors for Word Representation) est une méthode fondée sur les cooccurrences, qui construit des vecteurs de mots à partir des statistiques de coapparition dans un large corpus. Elle capture des relations globales et offre souvent de meilleures performances sur les analogies de mots.
Architecture de modèle NLP
Exemple d’architecture pour une tâche d’analyse de sentiment.
L’analyse de sentiment est une tâche courante en NLP qui vise à comprendre le sentiment exprimé dans un texte, le plus souvent classé en positif, négatif ou neutre. Pour l’aborder, on peut utiliser un réseau de neurones récurrent (RNN) simple ou une variante plus avancée appelée long short-term memory (LSTM).
RNN
L’architecture RNN traite le texte séquentiellement, mot par mot. Le réseau maintient un état caché qui évolue à chaque entrée et capture l’information accumulée jusque-là.
Cet état caché joue le rôle de mémoire du réseau. Cependant, les RNN standards peinent sur de longues séquences à cause du problème du gradient qui s’annule : la contribution des informations anciennes décroît avec le temps et le réseau finit par les oublier. Pour en savoir plus, consultez notre tutoriel RNN.
LSTM
Pour y remédier, les LSTM, une variante de RNN, ont été conçus. Un LSTM maintient un contexte plus long grâce à une structure interne plus complexe de son état caché. Il comporte des « portes » (d’entrée, d’oubli et de sortie) qui contrôlent le flux d’information dans et hors de l’état mémoire.
La porte d’entrée détermine quelle part de l’information entrante conserver, la porte d’oubli décide quoi écarter, et la porte de sortie règle la quantité d’état interne transmise à la prochaine unité LSTM.
Un modèle RNN ou LSTM prend en entrée une séquence de mots d’une phrase ou d’un document. Chaque mot est généralement représenté par un vecteur dense (embedding) capturant sa signification sémantique.
Le réseau traite la séquence mot par mot, en mettant à jour son état interne en fonction du mot courant et de l’état précédent.
L’état final sert ensuite à prédire le sentiment. Il est passé dans une couche complètement connectée, puis une fonction d’activation softmax pour produire une distribution de probabilités sur les classes de sentiment (p. ex. : positif, négatif, neutre).
La classe à la probabilité la plus élevée est retenue comme prédiction du modèle.
Ce dispositif de base peut être amélioré avec des LSTM bidirectionnels (traitement dans les deux sens) et des mécanismes d’attention (focalisation sur les parties importantes de la séquence), entre autres.
Entraîner un modèle LSTM avec PyTorch pour l’analyse de sentiment
Exemple de code Python de bout en bout pour construire un modèle d’analyse de sentiment avec PyTorch
1. Charger le jeu de données
Dans cet exemple, nous utilisons l’IMDB dataset of 50K Movie reviews. L’objectif est d’entraîner un modèle LSTM pour prédire le sentiment. Deux valeurs possibles : « positive » et « negative ». Il s’agit donc d’une classification binaire.
file_name ='IMDB Dataset.csv'
df = pd.read_csv(file_name)
df.head()Propulsé par
2. Analyse exploratoire
X,y = df['review'].values,df['sentiment'].values
x_train,x_test,y_train,y_test = train_test_split(X,y,stratify=y)print(f'train data shape: {x_train.shape}')print(f'test data shape: {x_test.shape}')
dd = pd.Series(y_train).value_counts()
sns.barplot(x=np.array(['negative','positive']),y=dd.values)
plt.show()Propulsé par
Sortie :
>>> train data shape:(37500,)>>> test data shape:(12500,)Propulsé par
3. Prétraitement du texte
Le prétraitement et la tokenisation sont une étape essentielle. Nous commençons par nettoyer le texte en supprimant la ponctuation, les espaces superflus et les chiffres.
Nous transformons ensuite les phrases en mots individuels, retirons les mots très fréquents (stop words) et conservons les 1000 mots les plus utilisés du jeu de données. Chaque mot reçoit un identifiant unique, constituant un dictionnaire pour l’encodage one-hot.
Le code convertit ainsi les phrases originales en séquences de ces identifiants : il traduit le langage humain dans un format compréhensible par un modèle de machine learning.
defpreprocess_string(s):# Remove all non-word characters (everything except numbers and letters)
s = re.sub(r"[^\w\s]",'', s)# Replace all runs of whitespaces with no space
s = re.sub(r"\s+",'', s)# replace digits with no space
s = re.sub(r"\d",'', s)return s
deftokenize(x_train,y_train,x_val,y_val):
word_list =[]
stop_words =set(stopwords.words('english'))for sent in x_train:for word in sent.lower().split():
word = preprocess_string(word)if word notin stop_words and word !='':
word_list.append(word)
corpus = Counter(word_list)# sorting on the basis of most common words
corpus_ =sorted(corpus,key=corpus.get,reverse=True)[:1000]# creating a dict
onehot_dict ={w:i+1for i,w inenumerate(corpus_)}# tokenize
final_list_train,final_list_test =[],[]for sent in x_train:
final_list_train.append([onehot_dict[preprocess_string(word)]for word in sent.lower().split()if preprocess_string(word)in onehot_dict.keys()])for sent in x_val:
final_list_test.append([onehot_dict[preprocess_string(word)]for word in sent.lower().split()if preprocess_string(word)in onehot_dict.keys()])
encoded_train =[1if label =='positive'else0for label in y_train]
encoded_test =[1if label =='positive'else0for label in y_val]return np.array(final_list_train), np.array(encoded_train),np.array(final_list_test), np.array(encoded_test),onehot_dict
x_train,y_train,x_test,y_test,vocab = tokenize(x_train,y_train,x_test,y_test)Propulsé par
Analysons la longueur des séquences de tokens dans x_train.
rev_len =[len(i)for i in x_train]
pd.Series(rev_len).hist()Propulsé par
4. Préparation des données pour le modèle
Les avis ayant des longueurs variables, il faut les standardiser. Comme la majorité contient moins de 500 tokens, nous fixerons la longueur à 500 pour tous les avis.
defpadding_(sentences, seq_len):
features = np.zeros((len(sentences), seq_len),dtype=int)for ii, review inenumerate(sentences):iflen(review)!=0:
features[ii,-len(review):]= np.array(review)[:seq_len]return features
x_train_pad = padding_(x_train,500)
x_test_pad = padding_(x_test,500)Propulsé par
Ensuite, nous utilisons la classe DataLoader pour créer le jeu de données final destiné à l’entraînement.
# create Tensor datasets
train_data = TensorDataset(torch.from_numpy(x_train_pad), torch.from_numpy(y_train))
valid_data = TensorDataset(torch.from_numpy(x_test_pad), torch.from_numpy(y_test))# dataloaders
batch_size =50# make sure to SHUFFLE your data
train_loader = DataLoader(train_data, shuffle=True, batch_size=batch_size)
valid_loader = DataLoader(valid_data, shuffle=True, batch_size=batch_size)# obtain one batch of training data
dataiter =iter(train_loader)
sample_x, sample_y =next(dataiter)print('Sample input size: ', sample_x.size())# batch_size, seq_lengthprint('Sample input: \n', sample_x)print('Sample output: \n', sample_y)Propulsé par
Sortie :
5. Définir le modèle LSTM
Cette partie définit un modèle d’analyse de sentiment basé sur une architecture de réseau de neurones récurrent, plus précisément un LSTM (Long Short-Term Memory) comme indiqué plus haut. La classe SentimentRNN est un modèle PyTorch qui commence par une couche d’embedding transformant les indices de mots en représentations denses capturant leur sens sémantique. Elle est suivie d’une couche LSTM qui traite la séquence d’embeddings.
L’état caché du LSTM passe par une couche de dropout (pour régulariser et éviter le surapprentissage) puis une couche complètement connectée qui projette les sorties du LSTM vers la prédiction finale. Une activation sigmoïde convertit ensuite la sortie brute en probabilités. La méthode forward définit la propagation avant, et init_hidden initialise les états cachés du LSTM à zéro.
classSentimentRNN(nn.Module):def__init__(self,no_layers,vocab_size,hidden_dim,embedding_dim,drop_prob=0.5):super(SentimentRNN,self).__init__()
self.output_dim = output_dim
self.hidden_dim = hidden_dim
self.no_layers = no_layers
self.vocab_size = vocab_size
# embedding and LSTM layers
self.embedding = nn.Embedding(vocab_size, embedding_dim)#lstm
self.lstm = nn.LSTM(input_size=embedding_dim,hidden_size=self.hidden_dim,
num_layers=no_layers, batch_first=True)# dropout layer
self.dropout = nn.Dropout(0.3)# linear and sigmoid layer
self.fc = nn.Linear(self.hidden_dim, output_dim)
self.sig = nn.Sigmoid()defforward(self,x,hidden):
batch_size = x.size(0)# embeddings and lstm_out
embeds = self.embedding(x)# shape: B x S x Feature since batch = True#print(embeds.shape) #[50, 500, 1000]
lstm_out, hidden = self.lstm(embeds, hidden)
lstm_out = lstm_out.contiguous().view(-1, self.hidden_dim)# dropout and fully connected layer
out = self.dropout(lstm_out)
out = self.fc(out)# sigmoid function
sig_out = self.sig(out)# reshape to be batch_size first
sig_out = sig_out.view(batch_size,-1)
sig_out = sig_out[:,-1]# get last batch of labels# return last sigmoid output and hidden statereturn sig_out, hidden
definit_hidden(self, batch_size):''' Initializes hidden state '''# Create two new tensors with sizes n_layers x batch_size x hidden_dim,# initialized to zero, for hidden state and cell state of LSTM
h0 = torch.zeros((self.no_layers,batch_size,self.hidden_dim)).to(device)
c0 = torch.zeros((self.no_layers,batch_size,self.hidden_dim)).to(device)
hidden =(h0,c0)return hidden Propulsé par
Nous allons maintenant initialiser la classe SentimentRNN avec les paramètres requis.
no_layers =2
vocab_size =len(vocab)+1#extra 1 for padding
embedding_dim =64
output_dim =1
hidden_dim =256
model = SentimentRNN(no_layers,vocab_size,hidden_dim,embedding_dim,drop_prob=0.5)#moving to gpu
model.to(device)print(model)Propulsé par
La dernière étape avant l’entraînement consiste à définir la fonction de perte et la méthode d’optimisation. Nous définissons ici la perte, l’optimiseur et une fonction utilitaire pour calculer la précision de notre modèle d’analyse de sentiment.
La fonction de perte utilisée est la Binary Cross-Entropy (nn.BCELoss), fréquente pour les classifications binaires. L’optimiseur est Adam (torch.optim.Adam), très répandu pour son efficacité et sa faible empreinte mémoire. Le taux d’apprentissage est fixé à 0,001.
La fonction acc calcule la précision : elle arrondit les probabilités prédites (0 ou 1), les compare aux étiquettes réelles et renvoie le pourcentage de prédictions correctes.
# loss and optimization functions
lr=0.001
criterion = nn.BCELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=lr)# function to predict accuracydefacc(pred,label):
pred = torch.round(pred.squeeze())return torch.sum(pred == label.squeeze()).item()Propulsé par
6. Lancer l’entraînement
Ici, nous entraînons et validons le modèle. Chaque époque comporte une phase d’apprentissage et une phase de validation. Pendant l’apprentissage, le modèle ajuste ses paramètres pour minimiser la perte.
En validation, on évalue ses performances sur un ensemble distinct pour vérifier la capacité de généralisation et éviter le simple mémorisation du jeu d’entraînement.
La boucle d’entraînement initialise les états cachés du LSTM et place le modèle en mode apprentissage. Pour chaque lot, on compare les prédictions aux étiquettes réelles, on calcule la perte et on rétropropage pour mettre à jour les paramètres.
Les gradients sont écrêtés à une valeur maximale afin d’éviter les explosions de gradient, fréquentes avec les RNN/LSTM.
En validation, le modèle est passé en mode évaluation et ses performances sont mesurées sans mise à jour des paramètres. Pour les deux phases, la perte et la précision par époque sont suivies.
Si la perte de validation s’améliore, les paramètres courants sont enregistrés afin de conserver le meilleur modèle.
Enfin, à chaque époque, la perte et la précision moyennes sont affichées pour suivre la progression de l’apprentissage.
clip =5
epochs =5
valid_loss_min = np.Inf
# train for some number of epochs
epoch_tr_loss,epoch_vl_loss =[],[]
epoch_tr_acc,epoch_vl_acc =[],[]for epoch inrange(epochs):
train_losses =[]
train_acc =0.0
model.train()# initialize hidden state
h = model.init_hidden(batch_size)for inputs, labels in train_loader:
inputs, labels = inputs.to(device), labels.to(device)# Creating new variables for the hidden state, otherwise# we'd backprop through the entire training history
h =tuple([each.data for each in h])
model.zero_grad()
output,h = model(inputs,h)# calculate the loss and perform backprop
loss = criterion(output.squeeze(), labels.float())
loss.backward()
train_losses.append(loss.item())# calculating accuracy
accuracy = acc(output,labels)
train_acc += accuracy
#`clip_grad_norm` helps prevent the exploding gradient problem in RNNs / LSTMs.
nn.utils.clip_grad_norm_(model.parameters(), clip)
optimizer.step()
val_h = model.init_hidden(batch_size)
val_losses =[]
val_acc =0.0
model.eval()for inputs, labels in valid_loader:
val_h =tuple([each.data for each in val_h])
inputs, labels = inputs.to(device), labels.to(device)
output, val_h = model(inputs, val_h)
val_loss = criterion(output.squeeze(), labels.float())
val_losses.append(val_loss.item())
accuracy = acc(output,labels)
val_acc += accuracy
epoch_train_loss = np.mean(train_losses)
epoch_val_loss = np.mean(val_losses)
epoch_train_acc = train_acc/len(train_loader.dataset)
epoch_val_acc = val_acc/len(valid_loader.dataset)
epoch_tr_loss.append(epoch_train_loss)
epoch_vl_loss.append(epoch_val_loss)
epoch_tr_acc.append(epoch_train_acc)
epoch_vl_acc.append(epoch_val_acc)print(f'Epoch {epoch+1}')print(f'train_loss : {epoch_train_loss} val_loss : {epoch_val_loss}')print(f'train_accuracy : {epoch_train_acc*100} val_accuracy : {epoch_val_acc*100}')if epoch_val_loss <= valid_loss_min:
torch.save(model.state_dict(),'state_dict.pt')print('Validation loss decreased ({:.6f} --> {:.6f}). Saving model ...'.format(valid_loss_min,epoch_val_loss))
valid_loss_min = epoch_val_loss
print(25*'==')Propulsé par
Sortie :
7. Évaluation du modèle
Cette partie génère deux graphiques récapitulant l’évolution de la précision et de la perte en apprentissage et en validation au fil des époques. Le premier sous-graphe trace la précision, utile pour juger l’apprentissage et la généralisation.
Le second sous-graphe trace la perte d’entraînement et de validation, afin de déceler surapprentissage, sous-apprentissage ou bon ajustement.
Nous définissons ici une fonction predict_text pour prédire le sentiment d’un texte donné, avec un exemple d’utilisation. La fonction prend une chaîne en entrée, la transforme en séquence d’indices de mots selon le vocabulaire, l’apprête pour le modèle via du padding et un remodelage, initialise les états cachés du LSTM, envoie l’entrée dans le modèle et renvoie la probabilité prédite.
defpredict_text(text):
word_seq = np.array([vocab[preprocess_string(word)]for word in text.split()if preprocess_string(word)in vocab.keys()])
word_seq = np.expand_dims(word_seq,axis=0)
pad = torch.from_numpy(padding_(word_seq,500))
inputs = pad.to(device)
batch_size =1
h = model.init_hidden(batch_size)
h =tuple([each.data for each in h])
output, h = model(inputs, h)return(output.item())
index =30print(df['review'][index])print('='*70)print(f'Actual sentiment is : {df["sentiment"][index]}')print('='*70)
pro = predict_text(df['review'][index])
status ="positive"if pro >0.5else"negative"
pro =(1- pro)if status =="negative"else pro
print(f'Predicted sentiment is {status} with a probability of {pro}')Propulsé par
Sortie :
Cet notebook complet a été développé avec DataLab et est accessible dans ce workbook. Notez que l’exécution du code peut prendre du temps sur CPU, alors que l’utilisation d’un GPU peut réduire significativement le temps d’entraînement.
Prochaines étapes / améliorer le modèle
Améliorer un modèle de NLP implique souvent plusieurs stratégies adaptées au contexte et aux contraintes de la tâche. Le réglage d’hyperparamètres est une approche classique : taux d’apprentissage, taille de lot, nombre de couches du réseau, etc.
Ces hyperparamètres influent fortement sur les performances et s’optimisent généralement via grid search ou random search.
Le transfert d’apprentissage, en particulier avec des modèles comme BERT ou GPT, a montré un fort potentiel pour améliorer les tâches de NLP. Pré-entraînés sur de larges corpus, ces modèles sont ensuite affinés sur une tâche cible et bénéficient ainsi d’une compréhension générale du langage acquise en amont. Cette approche a régulièrement fixé l’état de l’art, y compris en analyse de sentiment.
Cas d’usage réels du NLP avec PyTorch
Les modèles de traitement du langage naturel, notamment implémentés avec PyTorch, sont largement adoptés et transforment de nombreux aspects de nos vies numériques.
Les chatbots sont devenus centraux dans le service client : grâce au NLP, ils comprennent les requêtes et y répondent avec des interactions naturelles.
Dans les systèmes de recommandation, les modèles NLP analysent avis et commentaires pour cerner les préférences et personnaliser les suggestions.
L’analyse de sentiment s’appuie également fortement sur le NLP. Ces outils examinent réseaux sociaux, avis clients ou tout texte pour en inférer le sentiment. Les entreprises exploitent ces insights pour leurs études de marché ou pour jauger l’opinion publique sur leurs produits et services, et ainsi prendre des décisions basées sur les données.
PyTorch offre une plateforme puissante et flexible pour construire des modèles de NLP. Dans ce tutoriel, nous avons détaillé la création d’un modèle d’analyse de sentiment avec une architecture LSTM, du prétraitement à l’entraînement, la validation et la prédiction sur des données inconnues.
Ce n’est qu’un aperçu de ce qu’il est possible de réaliser avec le NLP et PyTorch. Les applications sont nombreuses : chatbots, systèmes de recommandation, outils d’analyse de sentiment, et bien plus.
L’évolution rapide du domaine, notamment avec les modèles de transfert d’apprentissage comme BERT et GPT, ouvre des perspectives encore plus stimulantes. Maîtriser le NLP avec PyTorch est exigeant mais très enrichissant, car cela ouvre une nouvelle façon de comprendre et d’interagir avec le monde.
Pour approfondir PyTorch, suivez notre cours Deep Learning with PyTorch. Vous commencerez par une introduction à la bibliothèque et à ses usages pour les réseaux de neurones et le deep learning, puis vous aborderez les réseaux de neurones artificiels et leur entraînement sur des données réelles.
Découvrez le match-case de Python : un guide sur sa syntaxe, ses applications en data science, ML, et une analyse comparative avec le switch-case traditionnel.
Découvrez les fonctions lambda Python, leur utilité et quand les utiliser. Comprend des exemples pratiques et des bonnes pratiques pour une mise en œuvre efficace.
Initiez-vous aux structures de données de Python : apprenez-en plus sur les types de données et les structures de données primitives et non primitives, telles que les chaînes de caractères, les listes, les piles, etc.
Apprenez à utiliser JSON en Python, notamment la sérialisation, la désérialisation, le formatage, l'optimisation des performances, la gestion des API, ainsi que les limites et les alternatives de JSON.
Apprenez les techniques permettant d'extraire des informations utiles à partir de textes et de les traiter dans un format adapté à l'apprentissage automatique.
Apprenez à transcrire et à extraire des informations intéressantes à partir de livres, de sites d'avis et d'articles en ligne grâce au traitement du langage naturel (NLP) en Python.
Introduction au NLP et à PyTorch
Le traitement du langage naturel (NLP) est un pilier de l’IA moderne, qui permet aux machines de comprendre et de répondre au langage humain. Avec l’explosion des interactions numériques, son importance ne cesse de croître. PyTorch, bibliothèque open source de machine learning très populaire, offre des outils robustes pour les tâches de NLP grâce à sa flexibilité et à ses calculs de tenseurs efficaces. Son graphe computationnel dynamique facilite également la modification et la construction de modèles complexes, ce qui en fait un choix idéal pour ce tutoriel.
Pour aller plus loin en NLP, consultez notre parcours de compétences Natural Language Processing in Python, ou si vous préférez apprendre les bases du NLP en R, découvrez le cours Introduction to Natural Language Processing in R sur DataCamp.
Mise en place de l’environnement
La configuration de l’environnement PyTorch peut parfois s’avérer délicate selon le système d’exploitation, le gestionnaire de paquets, le langage de programmation et la plateforme de calcul utilisés. Le processus d’installation peut donc légèrement varier et nécessiter des commandes spécifiques.
Pour obtenir la commande d’installation adéquate, rendez-vous sur la page officielle get started de PyTorch : sélectionnez vos préférences et suivez les instructions affichées.
Nous utiliserons DataLab pour ce tutoriel. Le code complet pour entraîner un modèle d’analyse de sentiment avec PyTorch est disponible dans ce workbook DataLab si vous souhaitez suivre pas à pas.
Introduction aux tenseurs
Les tenseurs sont des structures de données fondamentales en mathématiques et en physique, généralisant scalaires, vecteurs et matrices. Ce sont des tableaux multidimensionnels capables de stocker et de manipuler efficacement de grands volumes de données numériques. Les tenseurs ont une forme, une taille et un type d’unité définis, ce qui les rend très polyvalents pour diverses opérations de calcul.
Dans PyTorch, les tenseurs sont les blocs de construction et l’objet de représentation des données principal. Ils sont proches des tableaux NumPy, avec des fonctionnalités supplémentaires et des optimisations conçues pour l’apprentissage profond. Les opérations sur les tenseurs tirent parti de l’accélération matérielle, notamment des GPU, pour calculer efficacement des réseaux de neurones complexes.
Les tenseurs jouent un rôle crucial dans les tâches de NLP en raison de la nature séquentielle et hiérarchique du langage.
Le NLP consiste à traiter et à comprendre des informations textuelles. Les tenseurs permettent de représenter et de manipuler des textes en encodant des mots, des phrases ou des documents sous forme de vecteurs numériques.
Cette représentation numérique permet aux modèles d’apprentissage profond de traiter et d’apprendre efficacement à partir de textes. Les tenseurs facilitent la gestion de grands jeux de données, l’entraînement de réseaux de neurones et des techniques avancées comme les mécanismes d’attention pour des modèles de NLP plus précis.
Word embeddings
Les word embeddings sont des représentations vectorielles denses de mots dans un espace continu. Ils capturent les relations sémantiques et syntaxiques entre les mots, ce qui améliore la compréhension et la contextualisation des textes. En représentant les mots par des vecteurs numériques, les embeddings saisissent proximités et différences sémantiques, permettant aux algorithmes de manipuler des mots comme des entrées numériques porteuses de sens.
En clair, les embeddings sont une façon astucieuse de représenter les mots par des nombres. Ces nombres portent une signification qui reflète les relations entre mots : une sorte de code qui aide les ordinateurs à comprendre et traiter plus facilement le langage.
Word2Vec et GloVe sont deux méthodes populaires pour générer des embeddings. Word2Vec est un modèle à réseau de neurones qui apprend les représentations en prédisant les mots du contexte à partir d’un mot cible (CBOW) ou le mot cible à partir de son contexte (skip-gram).
GloVe (Global Vectors for Word Representation) est une méthode fondée sur les cooccurrences, qui construit des vecteurs de mots à partir des statistiques de coapparition dans un large corpus. Elle capture des relations globales et offre souvent de meilleures performances sur les analogies de mots.
Architecture de modèle NLP
Exemple d’architecture pour une tâche d’analyse de sentiment.
L’analyse de sentiment est une tâche courante en NLP qui vise à comprendre le sentiment exprimé dans un texte, le plus souvent classé en positif, négatif ou neutre. Pour l’aborder, on peut utiliser un réseau de neurones récurrent (RNN) simple ou une variante plus avancée appelée long short-term memory (LSTM).
RNN
L’architecture RNN traite le texte séquentiellement, mot par mot. Le réseau maintient un état caché qui évolue à chaque entrée et capture l’information accumulée jusque-là.
Cet état caché joue le rôle de mémoire du réseau. Cependant, les RNN standards peinent sur de longues séquences à cause du problème du gradient qui s’annule : la contribution des informations anciennes décroît avec le temps et le réseau finit par les oublier. Pour en savoir plus, consultez notre tutoriel RNN.
LSTM
Pour y remédier, les LSTM, une variante de RNN, ont été conçus. Un LSTM maintient un contexte plus long grâce à une structure interne plus complexe de son état caché. Il comporte des « portes » (d’entrée, d’oubli et de sortie) qui contrôlent le flux d’information dans et hors de l’état mémoire.
La porte d’entrée détermine quelle part de l’information entrante conserver, la porte d’oubli décide quoi écarter, et la porte de sortie règle la quantité d’état interne transmise à la prochaine unité LSTM.
Un modèle RNN ou LSTM prend en entrée une séquence de mots d’une phrase ou d’un document. Chaque mot est généralement représenté par un vecteur dense (embedding) capturant sa signification sémantique.
Le réseau traite la séquence mot par mot, en mettant à jour son état interne en fonction du mot courant et de l’état précédent.
L’état final sert ensuite à prédire le sentiment. Il est passé dans une couche complètement connectée, puis une fonction d’activation softmax pour produire une distribution de probabilités sur les classes de sentiment (p. ex. : positif, négatif, neutre).
La classe à la probabilité la plus élevée est retenue comme prédiction du modèle.
Ce dispositif de base peut être amélioré avec des LSTM bidirectionnels (traitement dans les deux sens) et des mécanismes d’attention (focalisation sur les parties importantes de la séquence), entre autres.
Entraîner un modèle LSTM avec PyTorch pour l’analyse de sentiment
Exemple de code Python de bout en bout pour construire un modèle d’analyse de sentiment avec PyTorch
1. Charger le jeu de données
Dans cet exemple, nous utilisons l’IMDB dataset of 50K Movie reviews. L’objectif est d’entraîner un modèle LSTM pour prédire le sentiment. Deux valeurs possibles : « positive » et « negative ». Il s’agit donc d’une classification binaire.
2. Analyse exploratoire
Sortie :
3. Prétraitement du texte
Le prétraitement et la tokenisation sont une étape essentielle. Nous commençons par nettoyer le texte en supprimant la ponctuation, les espaces superflus et les chiffres.
Nous transformons ensuite les phrases en mots individuels, retirons les mots très fréquents (stop words) et conservons les 1000 mots les plus utilisés du jeu de données. Chaque mot reçoit un identifiant unique, constituant un dictionnaire pour l’encodage one-hot.
Le code convertit ainsi les phrases originales en séquences de ces identifiants : il traduit le langage humain dans un format compréhensible par un modèle de machine learning.
Analysons la longueur des séquences de tokens dans
x_train.4. Préparation des données pour le modèle
Les avis ayant des longueurs variables, il faut les standardiser. Comme la majorité contient moins de 500 tokens, nous fixerons la longueur à 500 pour tous les avis.
Ensuite, nous utilisons la classe
DataLoaderpour créer le jeu de données final destiné à l’entraînement.Sortie :
5. Définir le modèle LSTM
Cette partie définit un modèle d’analyse de sentiment basé sur une architecture de réseau de neurones récurrent, plus précisément un LSTM (Long Short-Term Memory) comme indiqué plus haut. La classe SentimentRNN est un modèle PyTorch qui commence par une couche d’embedding transformant les indices de mots en représentations denses capturant leur sens sémantique. Elle est suivie d’une couche LSTM qui traite la séquence d’embeddings.
L’état caché du LSTM passe par une couche de dropout (pour régulariser et éviter le surapprentissage) puis une couche complètement connectée qui projette les sorties du LSTM vers la prédiction finale. Une activation sigmoïde convertit ensuite la sortie brute en probabilités. La méthode forward définit la propagation avant, et init_hidden initialise les états cachés du LSTM à zéro.
Nous allons maintenant initialiser la classe
SentimentRNNavec les paramètres requis.La dernière étape avant l’entraînement consiste à définir la fonction de perte et la méthode d’optimisation. Nous définissons ici la perte, l’optimiseur et une fonction utilitaire pour calculer la précision de notre modèle d’analyse de sentiment.
La fonction de perte utilisée est la Binary Cross-Entropy (nn.BCELoss), fréquente pour les classifications binaires. L’optimiseur est Adam (torch.optim.Adam), très répandu pour son efficacité et sa faible empreinte mémoire. Le taux d’apprentissage est fixé à 0,001.
La fonction
acccalcule la précision : elle arrondit les probabilités prédites (0 ou 1), les compare aux étiquettes réelles et renvoie le pourcentage de prédictions correctes.6. Lancer l’entraînement
Ici, nous entraînons et validons le modèle. Chaque époque comporte une phase d’apprentissage et une phase de validation. Pendant l’apprentissage, le modèle ajuste ses paramètres pour minimiser la perte.
En validation, on évalue ses performances sur un ensemble distinct pour vérifier la capacité de généralisation et éviter le simple mémorisation du jeu d’entraînement.
La boucle d’entraînement initialise les états cachés du LSTM et place le modèle en mode apprentissage. Pour chaque lot, on compare les prédictions aux étiquettes réelles, on calcule la perte et on rétropropage pour mettre à jour les paramètres.
Les gradients sont écrêtés à une valeur maximale afin d’éviter les explosions de gradient, fréquentes avec les RNN/LSTM.
En validation, le modèle est passé en mode évaluation et ses performances sont mesurées sans mise à jour des paramètres. Pour les deux phases, la perte et la précision par époque sont suivies.
Si la perte de validation s’améliore, les paramètres courants sont enregistrés afin de conserver le meilleur modèle.
Enfin, à chaque époque, la perte et la précision moyennes sont affichées pour suivre la progression de l’apprentissage.
Sortie :
7. Évaluation du modèle
Cette partie génère deux graphiques récapitulant l’évolution de la précision et de la perte en apprentissage et en validation au fil des époques. Le premier sous-graphe trace la précision, utile pour juger l’apprentissage et la généralisation.
Le second sous-graphe trace la perte d’entraînement et de validation, afin de déceler surapprentissage, sous-apprentissage ou bon ajustement.
Sortie :
8. Inférence / prédiction
Nous définissons ici une fonction
predict_textpour prédire le sentiment d’un texte donné, avec un exemple d’utilisation. La fonction prend une chaîne en entrée, la transforme en séquence d’indices de mots selon le vocabulaire, l’apprête pour le modèle via du padding et un remodelage, initialise les états cachés du LSTM, envoie l’entrée dans le modèle et renvoie la probabilité prédite.Sortie :
Cet notebook complet a été développé avec DataLab et est accessible dans ce workbook. Notez que l’exécution du code peut prendre du temps sur CPU, alors que l’utilisation d’un GPU peut réduire significativement le temps d’entraînement.
Prochaines étapes / améliorer le modèle
Améliorer un modèle de NLP implique souvent plusieurs stratégies adaptées au contexte et aux contraintes de la tâche. Le réglage d’hyperparamètres est une approche classique : taux d’apprentissage, taille de lot, nombre de couches du réseau, etc.
Ces hyperparamètres influent fortement sur les performances et s’optimisent généralement via grid search ou random search.
Le transfert d’apprentissage, en particulier avec des modèles comme BERT ou GPT, a montré un fort potentiel pour améliorer les tâches de NLP. Pré-entraînés sur de larges corpus, ces modèles sont ensuite affinés sur une tâche cible et bénéficient ainsi d’une compréhension générale du langage acquise en amont. Cette approche a régulièrement fixé l’état de l’art, y compris en analyse de sentiment.
Cas d’usage réels du NLP avec PyTorch
Les modèles de traitement du langage naturel, notamment implémentés avec PyTorch, sont largement adoptés et transforment de nombreux aspects de nos vies numériques.
Les chatbots sont devenus centraux dans le service client : grâce au NLP, ils comprennent les requêtes et y répondent avec des interactions naturelles.
Dans les systèmes de recommandation, les modèles NLP analysent avis et commentaires pour cerner les préférences et personnaliser les suggestions.
L’analyse de sentiment s’appuie également fortement sur le NLP. Ces outils examinent réseaux sociaux, avis clients ou tout texte pour en inférer le sentiment. Les entreprises exploitent ces insights pour leurs études de marché ou pour jauger l’opinion publique sur leurs produits et services, et ainsi prendre des décisions basées sur les données.
Découvrez d’autres cas d’usage concrets de Google BERT dans ce tutoriel de traitement du langage naturel.
Conclusion
PyTorch offre une plateforme puissante et flexible pour construire des modèles de NLP. Dans ce tutoriel, nous avons détaillé la création d’un modèle d’analyse de sentiment avec une architecture LSTM, du prétraitement à l’entraînement, la validation et la prédiction sur des données inconnues.
Ce n’est qu’un aperçu de ce qu’il est possible de réaliser avec le NLP et PyTorch. Les applications sont nombreuses : chatbots, systèmes de recommandation, outils d’analyse de sentiment, et bien plus.
L’évolution rapide du domaine, notamment avec les modèles de transfert d’apprentissage comme BERT et GPT, ouvre des perspectives encore plus stimulantes. Maîtriser le NLP avec PyTorch est exigeant mais très enrichissant, car cela ouvre une nouvelle façon de comprendre et d’interagir avec le monde.
Pour approfondir PyTorch, suivez notre cours Deep Learning with PyTorch. Vous commencerez par une introduction à la bibliothèque et à ses usages pour les réseaux de neurones et le deep learning, puis vous aborderez les réseaux de neurones artificiels et leur entraînement sur des données réelles.