Comprendre le mécanisme d’attention : la clé du succès en Deep Learning
Le mécanisme d’attention en Deep learning est une technique clé indispensable qui joue un rôle central dans la construction du Transformer. Cette méthode a connu un succès retentissant dans de nombreuses applications de Deep Learning, telles que la traduction automatique, la reconnaissance d’images et la génération de texte.
Il existe plusieurs versions du mécanisme d’attention. Dans cet article on présente la version de l’article « Attention is all you need », qui introduit les deux opérations suivantes:
- Le Scaled Dot-Product Attention qui est une sorte d’opération d’activation.
- Et le Multi-Head Attention qui est une couche de neurones entraînables utilisant des couches linéaires et des activations Scaled Dot-Product Attention.
Cet article explique le calcul du Scaled Dot-Product Attention. Quant au Multi-Head Attention, il fera l’objet d’un autre article.
Approche intuitive
Pour comprendre la formule de calcul de l’attention, on va d’abord expliquer l’exemple suivant.
Imaginons un dictionnaire formé d’une liste de t paires (k_i, v_i)_{i=1 \dots t} (clé-valeur), où les k_i sont des entiers et où les v_i sont des nombres réels.
Soit un entier q. Pour trouver la valeur du dictionnaire associée à q, il faut trouver i tel que k_i = q puis renvoyer v_i.
De manière algébrique, cela revient à calculer la somme pondérée:
où 1(k_i=q) représente la fonction indicatrice.
Le mécanisme d’attention généralise cette formule lorsque les k_i, v_i, q sont des valeurs de sortie d’une couche d’un réseau de neurones.
Fonctionnement du Scaled Dot-Product Attention
Le Scaled Dot-Product Attention est une forme particulière d’activation.
En général, une activation est utilisé pour transformer un tenseur. Parmi les activations courantes, on peut citer : sigmoïde, ReLU, Softmax (voir cet article), Dropout, BatchNormalization, etc…
Cependant, contrairement aux exemples susmentionnés, le Scaled Dot-Product Attention ne traite pas un seul tenseur en entrée, mais trois, que l’on appelle : query (requête), keys (clés) et values (valeurs).
- Les keys, notée \mathbf{K}, est une liste (\mathbf{k}_1, \mathbf{k}_2, \cdots,\mathbf{k}_t ) , de taille t et où les \mathbf{k}_i sont des vecteurs de dimension d_{\mathrm{key}}.
- Les values, notée \mathbf{V}, est une liste (\mathbf{v}_1, \mathbf{v}_2, \cdots,\mathbf{v}_t ) , de même taille que keys et où les \mathbf{v}_i sont des vecteurs de dimension d_{\mathrm{val}}.
- La query, noté \mathbf{q}, est un vecteur de dimension d_{\mathrm{key}}, la même que les \mathbf{k}_i.
Pour calculer le Scaled Dot-Product Attention de (\mathbf{q}, \mathbf{K}, \mathbf{V}), voici les étapes à suivre:
- On calcule les scores de corrélations entre \mathbf{q} et les \mathbf{k}_i. Le score de corrélation est le produit scalaire:
- On transfome (c_1,c_2, \dots, c_t) en un vecteur de probabilité en appliquant Softmax:
- Le résultat est la somme des \mathbf{v}_i pondérée par les c_i:
Ainsi, on obtient le Scaled Dot-Product Attention en suivant ces différentes étapes ! 👌
En termes concrets, voici ce qui se passe : on dispose d’une liste de paires (\mathbf{k}_i, \mathbf{v}_i), et la valeur \mathbf{q} sert à calculer une combinaison linéaire des \mathbf{v}_i pondérée par la corrélation de \mathbf{q} avec \mathbf{k}_i.
Note: dans l’article, les auteurs utilisent une variante qui consiste à diviser la corrélation par \sqrt{d_{\mathrm{key}}}. Ils justifient ce choix en disant que le produit scalaire a tendance à prendre des valeurs trop fortes.
Implémentation en Python
D’abord avant d’implémenter l’attention, on va le généraliser dans le cas de plusieurs requêtes.
Si \mathrm{Q} := (\mathbf{q}_1, \dots, \mathbf{q}_s) est une liste de s requêtes, alors \mathrm{Attention}(\mathbf{Q}, \mathbf{K}, \mathbf{V}) est simplement la liste des s attentions:
Le résultat peut être alors vu comme un tenseur de format (s, d_{\mathrm{val}}).
Ceci étant dit, voilà l’implémentation du calcul de \mathrm{Attention}(\mathbf{Q}, \mathbf{K}, \mathbf{V}).
1 2 3 4 5 6 7 8 9 10 11 12 | import numpy as np def scaled_dot_product_attention(Q, K, V): dk = K.shape[-1] scores = np.matmul(Q, K.transpose((0, 2, 1))) / np.sqrt(dk) weights = softmax(scores) output = np.matmul(weights, V) return output def softmax(x): exp_x = np.exp(x - np.max(x, axis=-1, keepdims=True)) return exp_x / np.sum(exp_x, axis=-1, keepdims=True) |
Je t’invite à tester ce code pour mieux comprendre comment ça marche.
A titre d’information, ce code a été généré par ChatGPT (et de manière correcte !). Noter bien que dans ce code, les tenseurs contiennent la dimension batch.
Voilà pour cet article ! N’hésite pas à partager tes pensées et poser des questions dans les commentaires ci-dessous !. 👍
0 commentaire