Maison > Périphériques technologiques > IA > Un guide complet pour construire un modèle de transformateur avec Pytorch

Un guide complet pour construire un modèle de transformateur avec Pytorch

William Shakespeare
Libérer: 2025-03-10 09:30:13
original
260 Les gens l'ont consulté

Le but de ce tutoriel est de fournir une compréhension complète de la façon de construire un modèle de transformateur à l'aide de pytorch. Le transformateur est l'un des modèles les plus puissants de l'apprentissage automatique moderne. Ils ont révolutionné le domaine, en particulier dans les tâches de traitement du langage naturel (NLP) telles que la traduction du langage et la résumé de texte. Les réseaux de mémoire à court terme (LSTM) ont été remplacés par des transformateurs dans ces tâches en raison de leur capacité à gérer les dépendances à longue portée et les calculs parallèles.

L'outil utilisé dans ce guide pour construire le transformateur est Pytorch, une bibliothèque d'apprentissage machine-source ouverte populaire connue pour sa simplicité, sa polyvalence et son efficacité. Avec un graphique de calcul dynamique et des bibliothèques étendues, Pytorch est devenu un incontournable pour les chercheurs et les développeurs dans le domaine de l'apprentissage automatique et de l'intelligence artificielle.

Pour ceux qui ne sont pas familiers avec Pytorch, une visite au cours de Datacamp, l'introduction à l'apprentissage en profondeur avec Pytorch est recommandée pour une solide mise à la terre.

Contexte et théorie

Introduit pour la première fois dans l'attention du papier est tout ce dont vous avez besoin par Vaswani et al., Les transformateurs sont depuis devenus la pierre angulaire de nombreuses tâches PNL en raison de leur conception et de leur efficacité uniques.

Au cœur des transformateurs se trouve le mécanisme d'attention, en particulier le concept d '«auto-attention», qui permet au modèle de peser et de hiérarchiser différentes parties des données d'entrée. Ce mécanisme est ce qui permet aux transformateurs de gérer les dépendances à longue portée dans les données. Il s'agit fondamentalement d'un schéma de pondération qui permet à un modèle de se concentrer sur différentes parties de l'entrée lors de la production d'une sortie.

Ce mécanisme permet au modèle de considérer différents mots ou caractéristiques dans la séquence d'entrée, en attribuant à chacun un «poids» qui signifie son importance pour produire une sortie donnée.

Par exemple, dans une tâche de traduction de phrase, tout en traduisant un mot particulier, le modèle peut attribuer des poids d'attention plus élevés à des mots grammaticalement ou sémantiquement liés au mot cible. Ce processus permet au transformateur de capturer les dépendances entre les mots ou les caractéristiques, quelle que soit leur distance les unes des autres dans la séquence.

L'impact des transformateurs

dans le domaine de la PNL ne peut pas être surestimé. Ils ont surclassé les modèles traditionnels dans de nombreuses tâches, démontrant une capacité supérieure à comprendre et à générer un langage humain de manière plus nuancée.

Pour une compréhension plus profonde de la PNL, l'introduction de Datacamp au traitement du langage naturel dans le cours Python est une ressource recommandée.

Configuration de Pytorch

Avant de plonger dans la construction d'un transformateur, il est essentiel de configurer correctement l'environnement de travail. D'abord et avant tout, Pytorch doit être installé. Pytorch (version stable actuelle - 2.0.1) peut être facilement installée via des gestionnaires de packages PIP ou conda.

Pour PIP, utilisez la commande:

pip3 install torch torchvision torchaudio
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Pour conda, utilisez la commande:

pip3 install torch torchvision torchaudio
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

pour l'utilisation de pytorch avec un processeur, visitez la documentation Pytorch.

De plus, il est avantageux d'avoir une compréhension de base des concepts d'apprentissage en profondeur, car ceux-ci seront fondamentaux pour comprendre le fonctionnement des transformateurs. Pour ceux qui ont besoin d'un rafraîchissement, le cours Datacamp Deep Learning in Python est une ressource précieuse qui couvre les concepts clés de l'apprentissage en profondeur.

Construire le modèle de transformateur avec pytorch

Pour construire le modèle de transformateur, les étapes suivantes sont nécessaires:

  1. Importation des bibliothèques et des modules
  2. Définir les éléments de base - ATTENTION MULTIQUE-TEAUX, réseaux de Feed-Forward en position de position, codage positionnel
  3. Construire le bloc d'encodeur
  4. Construire le bloc de décodeur
  5. combinant les couches d'encodeur et de décodeur pour créer le réseau de transformateur complet

1. Importation des bibliothèques et modules nécessaires

Nous allons commencer par l'importation de la bibliothèque Pytorch pour les fonctionnalités de base, le module de réseau neuronal pour la création de réseaux de neurones, le module d'optimisation pour les réseaux de formation et les fonctions d'utilité de données pour gérer les données. De plus, nous importerons le module de mathématiques Python standard pour les opérations mathématiques et le module de copie pour créer des copies d'objets complexes.

Ces outils définissent les bases de la définition de l'architecture du modèle, de la gestion des données et de l'établissement du processus de formation.

conda install pytorch torchvision torchaudio pytorch-cuda=11.7 -c pytorch -c nvidia
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

2. Définir les éléments de base: attention multiples, réseaux de marche-fort en position de position, codage de position

Attention multiples

Le mécanisme d'attention multi-tête calcule l'attention entre chaque paire de positions dans une séquence. Il se compose de plusieurs «têtes d'attention» qui capturent différents aspects de la séquence d'entrée.

Pour en savoir plus sur l'attention multi-tête, consultez cette section Mécanismes d'attention du cours des concepts de modèles de grande langue (LLMS).

Un guide complet pour construire un modèle de transformateur avec Pytorch

Figure 1. Attention multi-tête (source: image créée par l'auteur)

import torch
import torch.nn as nn
import torch.optim as optim
import torch.utils.data as data
import math
import copy
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Définition et initialisation de classe:

class MultiHeadAttention(nn.Module):
    def __init__(self, d_model, num_heads):
        super(MultiHeadAttention, self).__init__()
        # Ensure that the model dimension (d_model) is divisible by the number of heads
        assert d_model % num_heads == 0, "d_model must be divisible by num_heads"
        
        # Initialize dimensions
        self.d_model = d_model # Model's dimension
        self.num_heads = num_heads # Number of attention heads
        self.d_k = d_model // num_heads # Dimension of each head's key, query, and value
        
        # Linear layers for transforming inputs
        self.W_q = nn.Linear(d_model, d_model) # Query transformation
        self.W_k = nn.Linear(d_model, d_model) # Key transformation
        self.W_v = nn.Linear(d_model, d_model) # Value transformation
        self.W_o = nn.Linear(d_model, d_model) # Output transformation
        
    def scaled_dot_product_attention(self, Q, K, V, mask=None):
        # Calculate attention scores
        attn_scores = torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(self.d_k)
        
        # Apply mask if provided (useful for preventing attention to certain parts like padding)
        if mask is not None:
            attn_scores = attn_scores.masked_fill(mask == 0, -1e9)
        
        # Softmax is applied to obtain attention probabilities
        attn_probs = torch.softmax(attn_scores, dim=-1)
        
        # Multiply by values to obtain the final output
        output = torch.matmul(attn_probs, V)
        return output
        
    def split_heads(self, x):
        # Reshape the input to have num_heads for multi-head attention
        batch_size, seq_length, d_model = x.size()
        return x.view(batch_size, seq_length, self.num_heads, self.d_k).transpose(1, 2)
        
    def combine_heads(self, x):
        # Combine the multiple heads back to original shape
        batch_size, _, seq_length, d_k = x.size()
        return x.transpose(1, 2).contiguous().view(batch_size, seq_length, self.d_model)
        
    def forward(self, Q, K, V, mask=None):
        # Apply linear transformations and split heads
        Q = self.split_heads(self.W_q(Q))
        K = self.split_heads(self.W_k(K))
        V = self.split_heads(self.W_v(V))
        
        # Perform scaled dot-product attention
        attn_output = self.scaled_dot_product_attention(Q, K, V, mask)
        
        # Combine heads and apply output transformation
        output = self.W_o(self.combine_heads(attn_output))
        return output
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

La classe est définie comme une sous-classe du nn.module de Pytorch.

  1. d_model: dimensionnalité de l'entrée.
  2. num_heads: le nombre de têtes d'attention pour diviser l'entrée en.

L'initialisation vérifie si d_model est divisible par num_heads, puis définit les poids de transformation pour la requête, la clé, la valeur et la sortie.

Attention au produit de point à l'échelle:

pip3 install torch torchvision torchaudio
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
  1. Calcul des scores d'attention: ATTN_SCORES = TORCH.MATMUL (Q, K.TRANSPOSE (-2, -1)) / MATH.SQRT (Self.D_K). Ici, les scores d'attention sont calculés en prenant le produit DOT des requêtes (Q) et des clés (K), puis en évoluant par la racine carrée de la dimension de clé (d_k).
  2. Application du masque: Si un masque est fourni, il est appliqué aux scores d'attention pour masquer des valeurs spécifiques.
  3. Calcul des poids d'attention: les scores d'attention sont passés à travers une fonction softmax pour les convertir en probabilités qui résument à 1.
  4. Sortie calculatrice: La sortie finale de l'attention est calculée en multipliant les poids d'attention par les valeurs (v).

Têtes de fractionnement:

conda install pytorch torchvision torchaudio pytorch-cuda=11.7 -c pytorch -c nvidia
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Cette méthode remodèle l'entrée x dans la forme (Batch_size, num_heads, seq_length, d_k). Il permet au modèle de traiter simultanément les têtes d'attention, permettant un calcul parallèle.

combinant têtes:

import torch
import torch.nn as nn
import torch.optim as optim
import torch.utils.data as data
import math
import copy
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Après avoir appliqué l'attention à chaque tête séparément, cette méthode combine les résultats dans un seul tenseur de forme (Batch_size, seq_length, d_model). Cela prépare le résultat pour un traitement ultérieur.

Méthode avant:

class MultiHeadAttention(nn.Module):
    def __init__(self, d_model, num_heads):
        super(MultiHeadAttention, self).__init__()
        # Ensure that the model dimension (d_model) is divisible by the number of heads
        assert d_model % num_heads == 0, "d_model must be divisible by num_heads"
        
        # Initialize dimensions
        self.d_model = d_model # Model's dimension
        self.num_heads = num_heads # Number of attention heads
        self.d_k = d_model // num_heads # Dimension of each head's key, query, and value
        
        # Linear layers for transforming inputs
        self.W_q = nn.Linear(d_model, d_model) # Query transformation
        self.W_k = nn.Linear(d_model, d_model) # Key transformation
        self.W_v = nn.Linear(d_model, d_model) # Value transformation
        self.W_o = nn.Linear(d_model, d_model) # Output transformation
        
    def scaled_dot_product_attention(self, Q, K, V, mask=None):
        # Calculate attention scores
        attn_scores = torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(self.d_k)
        
        # Apply mask if provided (useful for preventing attention to certain parts like padding)
        if mask is not None:
            attn_scores = attn_scores.masked_fill(mask == 0, -1e9)
        
        # Softmax is applied to obtain attention probabilities
        attn_probs = torch.softmax(attn_scores, dim=-1)
        
        # Multiply by values to obtain the final output
        output = torch.matmul(attn_probs, V)
        return output
        
    def split_heads(self, x):
        # Reshape the input to have num_heads for multi-head attention
        batch_size, seq_length, d_model = x.size()
        return x.view(batch_size, seq_length, self.num_heads, self.d_k).transpose(1, 2)
        
    def combine_heads(self, x):
        # Combine the multiple heads back to original shape
        batch_size, _, seq_length, d_k = x.size()
        return x.transpose(1, 2).contiguous().view(batch_size, seq_length, self.d_model)
        
    def forward(self, Q, K, V, mask=None):
        # Apply linear transformations and split heads
        Q = self.split_heads(self.W_q(Q))
        K = self.split_heads(self.W_k(K))
        V = self.split_heads(self.W_v(V))
        
        # Perform scaled dot-product attention
        attn_output = self.scaled_dot_product_attention(Q, K, V, mask)
        
        # Combine heads and apply output transformation
        output = self.W_o(self.combine_heads(attn_output))
        return output
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

La méthode avant est l'endroit où le calcul réel se produit:

  1. Appliquer des transformations linéaires: les requêtes (q), les clés (k) et les valeurs (v) sont d'abord passées à travers des transformations linéaires en utilisant les poids définis dans l'initialisation.
  2. Têtes divisées: les Q, K, V transformés sont divisés en plusieurs têtes en utilisant la méthode Split_heads.
  3. Appliquer une attention à l'échelle du produit de point: la méthode scaled_dot_product_attention est appelée sur les têtes divisées.
  4. combiner têtes: les résultats de chaque tête sont combinés dans un seul tenseur en utilisant la méthode combinée.
  5. Appliquer la transformation de sortie: Enfin, le tenseur combiné est passé à travers une transformation linéaire de sortie.
En résumé, la classe Multi -headAntisert résume le mécanisme d'attention multi-tête couramment utilisé dans les modèles de transformateurs. Il s'occupe de diviser l'entrée en plusieurs têtes d'attention, d'appliquer l'attention sur chaque tête, puis de combiner les résultats. Ce faisant, le modèle peut saisir diverses relations dans les données d'entrée à différentes échelles, améliorant la capacité expressive du modèle.

Réseaux d'alimentation en position de position

class MultiHeadAttention(nn.Module):
    def __init__(self, d_model, num_heads):
Copier après la connexion
Copier après la connexion

Définition de classe:

def scaled_dot_product_attention(self, Q, K, V, mask=None):
Copier après la connexion
Copier après la connexion
La classe est une sous-classe du NN.Module de Pytorch, ce qui signifie qu'il héritera de toutes les fonctionnalités nécessaires pour travailler avec les couches de réseau neuronal.

Initialisation:

pip3 install torch torchvision torchaudio
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
  1. d_model: dimensionnalité de l'entrée et de la sortie du modèle.
  2. D_FF: Dimensionnalité de la couche intérieure dans le réseau d'alimentation.
  3. self.fc1 et self.fc2: deux couches entièrement connectées (linéaires) avec des dimensions d'entrée et de sortie telles que définies par d_model et d_ff.
  4. self.relu: fonction d'activation relu (unité linéaire rectifiée), qui introduit la non-linéarité entre les deux couches linéaires.

Méthode avant:

conda install pytorch torchvision torchaudio pytorch-cuda=11.7 -c pytorch -c nvidia
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
  1. x: l'entrée du réseau d'alimentation.
  2. self.fc1 (x): l'entrée est d'abord transmise à travers la première couche linéaire (fc1).
  3. self.relu (...): La sortie de FC1 est ensuite passé par une fonction d'activation de relu. RELU remplace toutes les valeurs négatives par des zéros, introduisant la non-linéarité dans le modèle.
  4. self.fc2 (...): La sortie activée est ensuite passé à travers la deuxième couche linéaire (FC2), produisant la sortie finale.

En résumé, la classe PositionwiseFeedForward définit un réseau neuronal alimentaire en position de position qui se compose de deux couches linéaires avec une fonction d'activation RELU entre les deux. Dans le contexte des modèles de transformateurs, ce réseau Feed-Forward est appliqué à chaque position séparément et identique. Il aide à transformer les caractéristiques apprises par les mécanismes d'attention dans le transformateur, agissant comme une étape de traitement supplémentaire pour les sorties d'attention.

Encodage de position

Le codage positionnel est utilisé pour injecter les informations de position de chaque jeton dans la séquence d'entrée. Il utilise les fonctions sinus et cosinus de différentes fréquences pour générer le codage positionnel.

import torch
import torch.nn as nn
import torch.optim as optim
import torch.utils.data as data
import math
import copy
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Définition de classe:

class MultiHeadAttention(nn.Module):
    def __init__(self, d_model, num_heads):
        super(MultiHeadAttention, self).__init__()
        # Ensure that the model dimension (d_model) is divisible by the number of heads
        assert d_model % num_heads == 0, "d_model must be divisible by num_heads"
        
        # Initialize dimensions
        self.d_model = d_model # Model's dimension
        self.num_heads = num_heads # Number of attention heads
        self.d_k = d_model // num_heads # Dimension of each head's key, query, and value
        
        # Linear layers for transforming inputs
        self.W_q = nn.Linear(d_model, d_model) # Query transformation
        self.W_k = nn.Linear(d_model, d_model) # Key transformation
        self.W_v = nn.Linear(d_model, d_model) # Value transformation
        self.W_o = nn.Linear(d_model, d_model) # Output transformation
        
    def scaled_dot_product_attention(self, Q, K, V, mask=None):
        # Calculate attention scores
        attn_scores = torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(self.d_k)
        
        # Apply mask if provided (useful for preventing attention to certain parts like padding)
        if mask is not None:
            attn_scores = attn_scores.masked_fill(mask == 0, -1e9)
        
        # Softmax is applied to obtain attention probabilities
        attn_probs = torch.softmax(attn_scores, dim=-1)
        
        # Multiply by values to obtain the final output
        output = torch.matmul(attn_probs, V)
        return output
        
    def split_heads(self, x):
        # Reshape the input to have num_heads for multi-head attention
        batch_size, seq_length, d_model = x.size()
        return x.view(batch_size, seq_length, self.num_heads, self.d_k).transpose(1, 2)
        
    def combine_heads(self, x):
        # Combine the multiple heads back to original shape
        batch_size, _, seq_length, d_k = x.size()
        return x.transpose(1, 2).contiguous().view(batch_size, seq_length, self.d_model)
        
    def forward(self, Q, K, V, mask=None):
        # Apply linear transformations and split heads
        Q = self.split_heads(self.W_q(Q))
        K = self.split_heads(self.W_k(K))
        V = self.split_heads(self.W_v(V))
        
        # Perform scaled dot-product attention
        attn_output = self.scaled_dot_product_attention(Q, K, V, mask)
        
        # Combine heads and apply output transformation
        output = self.W_o(self.combine_heads(attn_output))
        return output
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

La classe est définie comme une sous-classe de Nn.Module de Pytorch, ce qui lui permet d'être utilisé comme couche de pytorch standard.

Initialisation:

class MultiHeadAttention(nn.Module):
    def __init__(self, d_model, num_heads):
Copier après la connexion
Copier après la connexion
  1. d_model: la dimension de l'entrée du modèle.
  2. max_seq_length: la longueur maximale de la séquence pour lesquelles les codages de position sont pré-calculés.
  3. PE: un tenseur rempli de zéros, qui sera peuplé de codages positionnels.
  4. Position: un tenseur contenant les indices de position pour chaque position dans la séquence.
  5. div_term: un terme utilisé pour mettre à l'échelle les indices de position d'une manière spécifique.
  6. La fonction sinus est appliquée aux indices pair et à la fonction cosinus aux indices impairs de PE.
  7. Enfin, PE est enregistré en tant que tampon, ce qui signifie qu'il fera partie de l'état du module mais ne sera pas considéré comme un paramètre formable.

Méthode avant:

def scaled_dot_product_attention(self, Q, K, V, mask=None):
Copier après la connexion
Copier après la connexion

La méthode avant ajoute simplement les encodages de position à l'entrée x.

Il utilise les premiers éléments X.Size (1) de PE pour garantir que les encodages de position correspondent à la longueur de séquence réelle de x.

Résumé

La classe PositionAncoding ajoute des informations sur la position des jetons dans la séquence. Étant donné que le modèle de transformateur manque de connaissance inhérente à l'ordre des jetons (en raison de son mécanisme d'auto-agencement), cette classe aide le modèle à considérer la position des jetons dans la séquence. Les fonctions sinusoïdales utilisées sont choisies pour permettre au modèle d'apprendre facilement à assister à des positions relatives, car ils produisent un codage unique et lisse pour chaque position dans la séquence.

3. Construire les blocs d'encodeur

Un guide complet pour construire un modèle de transformateur avec Pytorch

Figure 2. La partie de l'encodeur du réseau transformateur (source: image du papier d'origine)

pip3 install torch torchvision torchaudio
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Définition de classe:

conda install pytorch torchvision torchaudio pytorch-cuda=11.7 -c pytorch -c nvidia
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

La classe est définie comme une sous-classe du Nn.Module de Pytorch, ce qui signifie qu'il peut être utilisé comme bloc de construction pour les réseaux de neurones à Pytorch.

Initialisation:

import torch
import torch.nn as nn
import torch.optim as optim
import torch.utils.data as data
import math
import copy
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Paramètres:

  1. d_model: la dimensionnalité de l'entrée.
  2. num_heads: le nombre de têtes d'attention dans l'attention multi-tête.
  3. D_FF: La dimensionnalité de la couche intérieure dans le réseau Feed-Forward en position de position.
  4. Dropout: le taux d'abandon utilisé pour la régularisation.

Composants:

  1. self.elf_attn: mécanisme d'attention multi-tête.
  2. self.feed_Forward: réseau neuronal de Feed-forward de position.
  3. self.norm1 et self.norm2: normalisation de la couche, appliquée pour lisser l'entrée de la couche.
  4. self.dropout: couche de dépôt, utilisée pour empêcher le sur-ajustement en définissant au hasard certaines activations à zéro pendant la formation.

Méthode avant:

class MultiHeadAttention(nn.Module):
    def __init__(self, d_model, num_heads):
        super(MultiHeadAttention, self).__init__()
        # Ensure that the model dimension (d_model) is divisible by the number of heads
        assert d_model % num_heads == 0, "d_model must be divisible by num_heads"
        
        # Initialize dimensions
        self.d_model = d_model # Model's dimension
        self.num_heads = num_heads # Number of attention heads
        self.d_k = d_model // num_heads # Dimension of each head's key, query, and value
        
        # Linear layers for transforming inputs
        self.W_q = nn.Linear(d_model, d_model) # Query transformation
        self.W_k = nn.Linear(d_model, d_model) # Key transformation
        self.W_v = nn.Linear(d_model, d_model) # Value transformation
        self.W_o = nn.Linear(d_model, d_model) # Output transformation
        
    def scaled_dot_product_attention(self, Q, K, V, mask=None):
        # Calculate attention scores
        attn_scores = torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(self.d_k)
        
        # Apply mask if provided (useful for preventing attention to certain parts like padding)
        if mask is not None:
            attn_scores = attn_scores.masked_fill(mask == 0, -1e9)
        
        # Softmax is applied to obtain attention probabilities
        attn_probs = torch.softmax(attn_scores, dim=-1)
        
        # Multiply by values to obtain the final output
        output = torch.matmul(attn_probs, V)
        return output
        
    def split_heads(self, x):
        # Reshape the input to have num_heads for multi-head attention
        batch_size, seq_length, d_model = x.size()
        return x.view(batch_size, seq_length, self.num_heads, self.d_k).transpose(1, 2)
        
    def combine_heads(self, x):
        # Combine the multiple heads back to original shape
        batch_size, _, seq_length, d_k = x.size()
        return x.transpose(1, 2).contiguous().view(batch_size, seq_length, self.d_model)
        
    def forward(self, Q, K, V, mask=None):
        # Apply linear transformations and split heads
        Q = self.split_heads(self.W_q(Q))
        K = self.split_heads(self.W_k(K))
        V = self.split_heads(self.W_v(V))
        
        # Perform scaled dot-product attention
        attn_output = self.scaled_dot_product_attention(Q, K, V, mask)
        
        # Combine heads and apply output transformation
        output = self.W_o(self.combine_heads(attn_output))
        return output
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Entrée:

  1. x: l'entrée de la couche de codeur.
  2. Masque: masque facultatif pour ignorer certaines parties de l'entrée.

Étapes de traitement:

  1. Automètre: l'entrée x est passé par le mécanisme d'auto-atténuer de plusieurs têtes.
  2. Ajouter et normaliser (après l'attention): la sortie d'attention est ajoutée à l'entrée d'origine (connexion résiduelle), suivie d'un dépôt et d'une normalisation à l'aide de NORM1.
  3. Réseau d'alimentation: la sortie de l'étape précédente est passée par le réseau d'alimentation de position de position.
  4. Ajouter et normaliser (après l'alimentation): Similaire à l'étape 2, la sortie de l'alimentation est ajoutée à l'entrée de cette étape (connexion résiduelle), suivie d'un dépôt et d'une normalisation à l'aide de NORM2.
  5. Sortie: le tenseur traité est renvoyé comme la sortie de la couche de codeur.

Résumé:

La classe d'encoderlayer définit une seule couche du codeur du transformateur. Il résume un mécanisme d'auto-atténuation à plusieurs têtes suivi d'un réseau neuronal de la position, avec des connexions résiduelles, une normalisation de la couche et un abandon appliquée, selon le cas. Ces composants permettent au codeur de capturer des relations complexes dans les données d'entrée et de les transformer en une représentation utile pour les tâches en aval. En règle générale, plusieurs couches d'encodeur sont empilées pour former la partie d'encodeur complète d'un modèle de transformateur.

4. Construire les blocs de décodeur

Un guide complet pour construire un modèle de transformateur avec Pytorch

pip3 install torch torchvision torchaudio
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Définition de classe:

conda install pytorch torchvision torchaudio pytorch-cuda=11.7 -c pytorch -c nvidia
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Initialisation:

import torch
import torch.nn as nn
import torch.optim as optim
import torch.utils.data as data
import math
import copy
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Paramètres :

  1. d_model: la dimensionnalité de l'entrée.
  2. num_heads: le nombre de têtes d'attention dans l'attention multi-tête.
  3. D_FF: La dimensionnalité de la couche intérieure dans le réseau d'alimentation.
  4. Dropout: le taux d'abandon pour la régularisation.

Composants :

  1. self.self_attn: mécanisme d'auto-atténuation multiples pour la séquence cible.
  2. self.cross_attn: mécanisme d'attention multi-tête qui s'occupe de la sortie de l'encodeur.
  3. self.feed_Forward: réseau neuronal de Feed-forward de position.
  4. self.norm1, self.norm2, self.norm3: composants de normalisation de la couche.
  5. self.dropout: couche abandonne pour la régularisation.

Forward Méthode :

class MultiHeadAttention(nn.Module):
    def __init__(self, d_model, num_heads):
        super(MultiHeadAttention, self).__init__()
        # Ensure that the model dimension (d_model) is divisible by the number of heads
        assert d_model % num_heads == 0, "d_model must be divisible by num_heads"
        
        # Initialize dimensions
        self.d_model = d_model # Model's dimension
        self.num_heads = num_heads # Number of attention heads
        self.d_k = d_model // num_heads # Dimension of each head's key, query, and value
        
        # Linear layers for transforming inputs
        self.W_q = nn.Linear(d_model, d_model) # Query transformation
        self.W_k = nn.Linear(d_model, d_model) # Key transformation
        self.W_v = nn.Linear(d_model, d_model) # Value transformation
        self.W_o = nn.Linear(d_model, d_model) # Output transformation
        
    def scaled_dot_product_attention(self, Q, K, V, mask=None):
        # Calculate attention scores
        attn_scores = torch.matmul(Q, K.transpose(-2, -1)) / math.sqrt(self.d_k)
        
        # Apply mask if provided (useful for preventing attention to certain parts like padding)
        if mask is not None:
            attn_scores = attn_scores.masked_fill(mask == 0, -1e9)
        
        # Softmax is applied to obtain attention probabilities
        attn_probs = torch.softmax(attn_scores, dim=-1)
        
        # Multiply by values to obtain the final output
        output = torch.matmul(attn_probs, V)
        return output
        
    def split_heads(self, x):
        # Reshape the input to have num_heads for multi-head attention
        batch_size, seq_length, d_model = x.size()
        return x.view(batch_size, seq_length, self.num_heads, self.d_k).transpose(1, 2)
        
    def combine_heads(self, x):
        # Combine the multiple heads back to original shape
        batch_size, _, seq_length, d_k = x.size()
        return x.transpose(1, 2).contiguous().view(batch_size, seq_length, self.d_model)
        
    def forward(self, Q, K, V, mask=None):
        # Apply linear transformations and split heads
        Q = self.split_heads(self.W_q(Q))
        K = self.split_heads(self.W_k(K))
        V = self.split_heads(self.W_v(V))
        
        # Perform scaled dot-product attention
        attn_output = self.scaled_dot_product_attention(Q, K, V, mask)
        
        # Combine heads and apply output transformation
        output = self.W_o(self.combine_heads(attn_output))
        return output
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

entrée :

  1. x: l'entrée de la couche de décodeur.
  2. ENC_Output: la sortie de l'encodeur correspondant (utilisé dans l'étape de l'attention croisée).
  3. src_mask: masque source pour ignorer certaines parties de la sortie de l'encodeur.
  4. tgt_mask: masque cible pour ignorer certaines parties de l'entrée du décodeur.

Étapes de traitement:

  1. Auto-attention sur la séquence cible: l'entrée x est traitée par un mécanisme d'auto-agencement.
  2. Ajouter et normaliser (après l'auto-agence d'auto): la sortie de l'auto-assertion est ajoutée au X d'origine, suivi d'un dépôt et d'une normalisation en utilisant Norm1.
  3. Cross-Atention avec sortie du codeur: La sortie normalisée de l'étape précédente est traitée via un mécanisme de transtention croisée qui s'occupe de la sortie de l'encodeur ENC_Output.
  4. Ajouter et normaliser (après l'attention croisée): la sortie de l'attention croisée est ajoutée à l'entrée de cette étape, suivie d'un abandon et d'une normalisation en utilisant NORM2.
  5. Réseau d'alimentation: la sortie de l'étape précédente est passé par le réseau d'alimentation.
  6. Ajouter et normaliser (après l'alimentation): La sortie de l'alimentation est ajoutée à l'entrée de cette étape, suivie d'un abandon et d'une normalisation en utilisant NORM3.
  7. Sortie: le tenseur traité est renvoyé comme la sortie de la couche de décodeur.

Résumé:

La classe DecoderLayer définit une seule couche du décodeur du transformateur. Il se compose d'un mécanisme d'auto-atténuation multiples, d'un mécanisme de transtention multiples (qui s'occupe de la sortie de l'encodeur), d'un réseau neuronal alimentaire en position de position et des connexions résiduelles correspondantes, de la normalisation des calques et des couches d'abandon. Cette combinaison permet au décodeur de générer des sorties significatives en fonction des représentations de l'encodeur, en tenant compte à la fois de la séquence cible et de la séquence source. Comme pour l'encodeur, plusieurs couches de décodeur sont généralement empilées pour former la partie du décodeur complète d'un modèle de transformateur.

Ensuite, les blocs d'encodeur et de décodeur sont réunis pour construire le modèle de transformateur complet.

5. Combinant les couches d'encodeur et de décodeur pour créer le réseau de transformateur complet

Un guide complet pour construire un modèle de transformateur avec Pytorch

Figure 4. Le réseau de transformateur (source: image du papier d'origine)

pip3 install torch torchvision torchaudio
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Définition de classe:

conda install pytorch torchvision torchaudio pytorch-cuda=11.7 -c pytorch -c nvidia
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Initialisation:

import torch
import torch.nn as nn
import torch.optim as optim
import torch.utils.data as data
import math
import copy
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Le constructeur prend les paramètres suivants:

  1. src_vocab_size: taille du vocabulaire source.
  2. tgt_vocab_size: taille de vocabulaire cible.
  3. d_model: la dimensionnalité des intérêts du modèle.
  4. num_heads: nombre de têtes d'attention dans le mécanisme d'attention multi-tête.
  5. num_layers: nombre de couches pour le codeur et le décodeur.
  6. D_FF: Dimensionnalité de la couche intérieure dans le réseau d'alimentation.
  7. max_seq_length: longueur de séquence maximale pour le codage positionnel.
  8. Dropout: taux d'abandon pour la régularisation.

et il définit les composants suivants:

  1. self.encoder_embedding: incorporer la couche pour la séquence source.
  2. self.decoder_embedding: couche d'intégration pour la séquence cible.
  3. self.positional_encoding: composant de codage positionnel.
  4. self.encoder_layers: une liste des couches d'encodeur.
  5. self.decoder_layers: une liste de couches de décodeur.
  6. self.fc: mappage de couche entièrement connecté (linéaire) final pour cibler la taille du vocabulaire.
  7. self.dropout: couche de dépôt.

Générer la méthode du masque:

pip3 install torch torchvision torchaudio
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Cette méthode est utilisée pour créer des masques pour les séquences source et cible, garantissant que les jetons de rembourrage sont ignorés et que les futurs jetons ne sont pas visibles lors de l'entraînement pour la séquence cible.

Méthode avant:

conda install pytorch torchvision torchaudio pytorch-cuda=11.7 -c pytorch -c nvidia
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Cette méthode définit la passe avant pour le transformateur, prenant des séquences source et cible et produisant les prévisions de sortie.

  1. Entrée d'intégration et codage positionnel: les séquences source et cible sont d'abord intégrées à l'aide de leurs couches d'incorporation respectives, puis ajoutées à leurs codages de position.
  2. Couches d'encodeur: La séquence source est passée à travers les couches d'encodeur, avec la sortie du codeur final représentant la séquence source traitée.
  3. Couches de décodeur: la séquence cible et la sortie du codeur sont passées à travers les couches de décodeur, résultant en la sortie du décodeur.
  4. Couche linéaire finale: La sortie du décodeur est mappée à la taille du vocabulaire cible à l'aide d'une couche entièrement connectée (linéaire).

Sortie:

La sortie finale est un tenseur représentant les prédictions du modèle pour la séquence cible.

Résumé:

La classe de transformateur rassemble les différentes composantes d'un modèle de transformateur, y compris les intégres, le codage positionnel, les couches d'encodeur et les couches de décodeur. Il fournit une interface pratique pour la formation et l'inférence, encapsulant les complexités de l'attention multi-tête, des réseaux à partager et la normalisation des calques.

Cette implémentation suit l'architecture du transformateur standard, ce qui le rend adapté aux tâches de séquence à séquence comme la traduction automatique, la résumé de texte, etc.

Ces étapes séquentielles permettent au modèle du transformateur de traiter efficacement les séquences d'entrée et de produire des séquences de sortie correspondantes.

Formation du modèle de transformateur Pytorch

Préparation des données d'échantillon

À des fins illustratives, un ensemble de données factices sera fabriqué dans cet exemple. Cependant, dans un scénario pratique, un ensemble de données plus substantiel serait utilisé, et le processus impliquerait le prétraitement du texte ainsi que la création de mappages de vocabulaire pour les langues source et cible.

pip3 install torch torchvision torchaudio
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

hyperparamètres:

Ces valeurs définissent l'architecture et le comportement du modèle de transformateur:

  1. src_vocab_size, tgt_vocab_size: tailles de vocabulaire pour les séquences source et cible, tous deux définis sur 5000.
  2. d_model: dimensionnalité des intégres du modèle, réglé sur 512.
  3. num_heads: nombre de têtes d'attention dans le mécanisme d'attention multi-tête, réglé sur 8.
  4. num_layers: nombre de couches pour l'encodeur et le décodeur, réglé sur 6.
  5. D_FF: Dimensionnalité de la couche intérieure dans le réseau d'alimentation, définie en 2048.
  6. max_seq_length: longueur de séquence maximale pour le codage positionnel, réglé sur 100.
  7. Dropout: taux d'abandon pour la régularisation, réglé à 0,1.

Création d'une instance de transformateur:

conda install pytorch torchvision torchaudio pytorch-cuda=11.7 -c pytorch -c nvidia
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Cette ligne crée une instance de la classe de transformateur, l'initialisant avec les hyperparamètres donnés. L'instance aura l'architecture et le comportement défini par ces hyperparamètres.

Génération de données d'échantillons aléatoires:

Les lignes suivantes génèrent des séquences de source et cible aléatoires:

  1. src_data: entiers aléatoires entre 1 et src_vocab_size, représentant un lot de séquences source avec forme (64, max_seq_length).
  2. tgt_data: entiers aléatoires entre 1 et tgt_vocab_size, représentant un lot de séquences cibles avec forme (64, max_seq_length).
  3. Ces séquences aléatoires peuvent être utilisées comme entrées au modèle de transformateur, simulant un lot de données avec 64 exemples et séquences de longueur 100.

Résumé:

L'extrait de code montre comment initialiser un modèle de transformateur et générer des séquences de source et cible aléatoires qui peuvent être introduites dans le modèle. Les hyperparamètres choisis déterminent la structure et les propriétés spécifiques du transformateur. Cette configuration pourrait faire partie d'un script plus grand où le modèle est formé et évalué sur les tâches de séquence à séquence réelles, telles que la traduction machine ou la résumé de texte.

Formation du modèle

Ensuite, le modèle sera formé en utilisant les données d'échantillon susmentionnées. Cependant, dans un scénario du monde réel, un ensemble de données beaucoup plus important serait utilisé, qui serait généralement partitionné en ensembles distincts à des fins de formation et de validation.

import torch
import torch.nn as nn
import torch.optim as optim
import torch.utils.data as data
import math
import copy
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Fonction de perte et optimiseur:

  1. critère = nn.crossentropyloss (ignore_index = 0): définit la fonction de perte comme une perte d'entrée croisée. L'argument IGNORE_INDEX est défini sur 0, ce qui signifie que la perte ne considérera pas les cibles avec un indice de 0 (généralement réservé aux jetons de rembourrage).
  2. Optimizer = Optim.Adam (...): définit l'optimiseur comme Adam avec un taux d'apprentissage de 0,0001 et des valeurs bêta spécifiques.

Mode de formation du modèle:

  1. transformateur.train (): définit le modèle de transformateur en mode de formation, permettant des comportements comme Dropout qui ne s'appliquent que pendant la formation.

Boucle de formation:

L'extrait de code forme le modèle pour 100 époques à l'aide d'une boucle de formation typique:

  1. pour l'époque dans la gamme (100): itère plus de 100 époques d'entraînement.
  2. Optimizer.zero_grad (): efface les gradients de l'itération précédente.
  3. output = transformateur (src_data, tgt_data [:,: -1]): transmet les données source et les données cibles (à l'exclusion du dernier jeton dans chaque séquence) via le transformateur. Ceci est courant dans les tâches de séquence à séquence où la cible est décalée par un jeton.
  4. perte = critère (...): calcule la perte entre les prévisions du modèle et les données cibles (à l'exclusion du premier jeton dans chaque séquence). La perte est calculée en remodelant les données dans des tenseurs unidimensionnels et en utilisant la fonction de perte entre entropie.
  5. perte.backward (): calcule les gradients de la perte par rapport aux paramètres du modèle.
  6. Optimizer.Step (): met à jour les paramètres du modèle à l'aide des gradients calculés.
  7. print (f "epoch: {epoch 1}, perte: {pertes.item ()}"): imprime le numéro de l'époque actuel et la valeur de perte pour cette époque.

Résumé:

Cet extrait de code entraîne le modèle de transformateur sur des séquences source et cibles générées aléatoires pour 100 époques. Il utilise l'optimiseur ADAM et la fonction de perte de l'entropie croisée. La perte est imprimée pour chaque époque, vous permettant de suivre les progrès de la formation. Dans un scénario du monde réel, vous remplaceriez la source aléatoire et les séquences cibles par des données réelles de votre tâche, telles que la traduction automatique.

Évaluation des performances du modèle du transformateur

Après la formation du modèle, ses performances peuvent être évaluées sur un ensemble de données de validation ou un ensemble de données de test. Ce qui suit est un exemple de la façon dont cela pourrait être fait:

pip3 install torch torchvision torchaudio
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Mode d'évaluation:

  1. transformateur.eval (): met le modèle de transformateur en mode d'évaluation. Ceci est important car il désactive certains comportements comme un abandon qui ne sont utilisés que pendant la formation.

Générer des données de validation aléatoire:

  1. val_src_data: des entiers aléatoires entre 1 et src_vocab_size, représentant un lot de séquences source de validation avec forme (64, max_seq_length).
  2. val_tgt_data: des entiers aléatoires entre 1 et tgt_vocab_size, représentant un lot de séquences cibles de validation avec forme (64, max_seq_length).

Boucle de validation:

  1. avec torch.no_grad (): désactive le calcul du gradient, car nous n'avons pas besoin de calculer les gradients pendant la validation. Cela peut réduire la consommation de mémoire et accélérer les calculs.
  2. val_output = transformateur (val_src_data, val_tgt_data [:,: -1]): passe les données source de validation et les données cibles de validation (à l'exclusion du dernier jeton dans chaque séquence) via le transformateur.
  3. val_loss = critère (...): calcule la perte entre les prévisions du modèle et les données cibles de validation (à l'exclusion du premier jeton dans chaque séquence). La perte est calculée en remodelant les données dans des tenseurs unidimensionnels et en utilisant la fonction de perte entre entropie transversale précédemment définie.
  4. print (f "Perte de validation: {val_loss.item ()}"): imprime la valeur de perte de validation.

Résumé:

Cet extrait de code évalue le modèle de transformateur sur un ensemble de données de validation généré de manière aléatoire, calcule la perte de validation et l'imprime. Dans un scénario du monde réel, les données de validation aléatoires doivent être remplacées par des données de validation réelles de la tâche sur laquelle vous travaillez. La perte de validation peut vous donner une indication de la performance de votre modèle sur des données invisibles, ce qui est une mesure critique de la capacité de généralisation du modèle.

Pour plus de détails sur les transformateurs et les étreintes, notre tutoriel, une introduction à l'utilisation des transformateurs et des étreintes, est utile.

Conclusion et ressources supplémentaires

En conclusion, ce tutoriel a démontré comment construire un modèle de transformateur à l'aide de Pytorch, l'un des outils les plus polyvalents pour l'apprentissage en profondeur. Avec leur capacité de parallélisation et la capacité de capturer les dépendances à long terme dans les données, les transformateurs ont un immense potentiel dans divers domaines, en particulier les tâches NLP comme la traduction, la résumé et l'analyse des sentiments.

Pour ceux qui ont hâte d'approfondir leur compréhension des concepts et techniques avancés d'apprentissage en profondeur, envisagez d'explorer le cours avancé d'apprentissage en profondeur avec Keras sur DataCamp. Vous pouvez également lire sur la création d'un simple réseau de neurones avec Pytorch dans un tutoriel séparé.

Gagnez une certification AI supérieure

démontrer que vous pouvez utiliser efficacement et de manière responsable AI.get certifié, obtenez un IntelligenceSython de l'intelligencesartificiels.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal