Jekyll2024-01-05T14:03:04+00:00https://lbourdois.github.io/blog/feed.xmlLoïck BOURDOISBlog de Loïck BOURDOISLoïck BOURDOISÉVOLUTION DES STATE SPACE MODELS (SSM) EN 20232023-12-30T00:00:00+00:002023-12-30T00:00:00+00:00https://lbourdois.github.io/blog/ssm/ssm_en_2023<p>WIP</p>Loïck BOURDOISSSM - Revue de littérature des SSM parus lors de l'année 2023ÉVOLUTION DES STATE SPACE MODELS (SSM) EN 20222023-12-29T00:00:00+00:002023-12-29T00:00:00+00:00https://lbourdois.github.io/blog/ssm/ssm_en_2022<p>WIP</p>Loïck BOURDOISSSM - Revue de littérature des SSM parus lors de l'année 2022INTRODUCTION AUX STATE SPACE MODELS (SSM) ET AU S42023-12-09T00:00:00+00:002023-12-09T00:00:00+00:00https://lbourdois.github.io/blog/ssm/introduction_ssm<script type="text/javascript" async="" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-MML-AM_CHTML">
</script>
<h1 id="-avant-propos-"><span style="color: #FF0000"> <strong>Avant-Propos</strong> </span></h1>
<p>Je tiens à remercier chaleureusement Boris ALBAR, Pierre BEDU et Nicolas PREVOT d’avoir accepté de monter un groupe de travail sur le sujet des SSM et de m’avoir ainsi accompagné dans la découverte de ce type de modèle. Un remerciement supplémentaire au premier pour avoir pris le temps de relire cet article de blog.
<br /><br /><br /></p>
<h1 id="-introduction-"><span style="color: #FF0000"> <strong>Introduction</strong> </span></h1>
<p>Les <strong><em>States Spaces Models</em></strong> (ou Modèles en Espace d’Etat en français) sont utilisés traditionnellement en théorie du contrôle afin de modéliser un système dynamique via des variables d’état.</p>
<p>Dans le cadre de l’apprentissage profond, lorsque l’on parle de SSM, on ne se réfère en réalité qu’à un sous-ensemble des représentations existantes, à savoir les systèmes linéaires invariants (ou stationnaires).<br />
Ces modèles ont montré des performances impressionnantes dès octobre 2021 avec l’article « <a href="https://arxiv.org/abs/2111.00396"><em>Efficiently Modeling Long Sequences with Structured State Spaces</em></a> » d’Albert GU et al., au point de se positionner comme une alternative aux <em>transformers</em>.<br />
Dans cet article, nous allons définir les bases d’un SSM en apprentissage profond en nous appuyant sur le S4. A l’image du papier « <a href="https://arxiv.org/abs/1706.03762"><em>Attention is all you need</em></a> » d’Ashish VASWANI et al. (2017) pour les <em>transformers</em>, le S4 est le fondement d’un nouveau type d’architecture de réseau de neurones qui se doit d’être connu, mais ce n’est pas un modèle qui est utilisé tel quel en pratique (d’autres SSM plus performants ou plus faciles à implémenter étant maintenant disponibles). Sorti une semaine plus tôt que le S4, le <a href="https://arxiv.org/abs/2110.13985">LSSL</a>, par les mêmes auteurs, est également une source importante d’informations sur le sujet. Nous verrons les différentes évolutions qui découlent du S4 dans un prochain article de blog. Plongeons nous auparavant dans les bases des SSM.
<br /><br /><br /></p>
<h1 id="-définition-dun-ssm-en-apprentissage-profond-"><span style="color: #FF0000"> <strong>Définition d’un SSM en apprentissage profond</strong> </span></h1>
<p>Utilisons l’image ci-dessous afin de définir un SSM :</p>
<table>
<thead>
<tr>
<th style="text-align: center"><img src="https://cdn-uploads.huggingface.co/production/uploads/613b0a62a14099d5afed7830/G7icfkYoxIqHZcJGHM7UD.png" alt="image/png" /></th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center">Figure 1 : <em>Vue d’un SSM continu et invariant dans le temps (Source : <a href="https://en.wikipedia.org/wiki/State-space_representation">https://en.wikipedia.org/wiki/State-space_representation</a>)</em></td>
</tr>
</tbody>
</table>
<p><br /></p>
<p>On peut observer qu’un SSM repose sur trois variables dépendant du temps \(t\) :</p>
<ul>
<li>\(x(t) \in \mathbb {C}^{n}\) représente les \(n\) variables d’état,</li>
<li>\(u(t) \in \mathbb {C}^{m}\) représente les \(m\) entrées d’état,</li>
<li>\(y(t) \in \mathbb {C}^{p}\) représente les \(p\) sorties,</li>
</ul>
<p>On peut aussi observer qu’il est composé de quatre matrices pouvant être apprises : \(\mathbf A, \mathbf B, \mathbf C\) et \(\mathbf D\).</p>
<ul>
<li>\(\mathbf A \in \mathbb {C}^{m \times n}\) est la matrice d’état (contrôlant l’état lattent \(x\)),</li>
<li>\(\mathbf B \in \mathbb {C}^{n \times m}\) est la matrice de contrôle,</li>
<li>\(\mathbf C \in \mathbb {C}^{p \times n}\) est la matrice de sortie,</li>
<li>\(\mathbf D \in \mathbb {C}^{p \times m}\) est la matrice de commande,</li>
</ul>
<p>Il est possible de ramener l’image ci-dessus au système d’équations suivant :</p>
\[\begin{aligned}
x'(t) &= \mathbf{A}x(t) + \mathbf{B}u(t) \\
y(t) &= \mathbf{C}x(t) + \mathbf{D}u(t)
\end{aligned}\]
<p>Note : nous utilisons ici la notation \(x'\) pour désigner la dérivée de \(x\). Il n’est pas exclu de rencontrer à la place la notation \(ẋ\) dans la littérature.</p>
<p>De même, puisqu’il est implicite que les variables dépendent du temps, l’équation précédente est généralement écrite sous la forme suivante par souci d’allègement :</p>
\[\begin{aligned}
x' &= \mathbf{A}x + \mathbf{B}u \\
y &= \mathbf{C}x + \mathbf{D}u
\end{aligned}\]
<p>Ce système peut s’alléger même davantage, car dans les SSM en apprentissage profond, \(\mathbf{D}u = 0\) est vue comme une <em>skip connexion</em> facilement calculable.</p>
\[\begin{aligned}
x' &= \mathbf{A}x + \mathbf{B}u \\
y &= \mathbf{C}x
\end{aligned}\]
<p>Ce système est continu. Il doit donc d’abord être discrétisé afin de pouvoir être fourni à un ordinateur.
<br /><br /><br /></p>
<h1 id="-discrétisation-"><span style="color: #FF0000"> <strong>Discrétisation</strong> </span></h1>
<p>La discrétisation est l’un, voire le point le plus important dans les SSM. Toute l’efficacité de cette architecture réside dans cette étape puisqu’elle permet de passer de la vue continue du SSM à ses deux autres vues : la <strong>vue récursive</strong> et la <strong>vue convolutive</strong>.<br />
S’il n’y a qu’une chose à retenir de cet article, c’est bien celle-ci.</p>
<table>
<thead>
<tr>
<th style="text-align: center"><img src="https://github.com/lbourdois/blog/assets/58078086/12bbe1cf-3911-4bad-9a3b-3f427bc6bc82" alt="image" /></th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center">Figure 2 : <em>Image provenant de l’article de blog « <a href="https://hazyresearch.stanford.edu/blog/2022-01-14-s4-3">Structured State Spaces: Combining Continuous-Time, Recurrent, and Convolutional Models</a> » d’Albert GU et al. (2022)</em></td>
</tr>
</tbody>
</table>
<p><br /></p>
<p>Nous verrons dans les prochains articles qu’il existe plusieurs discrétisations possibles. Ce point forme l’une des différences principales entre les diverses architectures de SSM existantes.<br />
Pour ce premier article, appliquons la discrétisation « originale » proposée dans le S4 afin d’illustrer les deux vues supplémentaires d’un SSM.
<br /><br /><br /></p>
<h1 id="-vue-récursive-dun-ssm-"><span style="color: #FF0000"> <strong>Vue récursive d’un SSM</strong> </span></h1>
<p>Pour discrétiser le cas continu, utilisons la <a href="https://fr.wikipedia.org/wiki/Transformation_bilin%C3%A9aire#Approximation_trap%C3%A9zo%C3%AFdale">méthode des trapèzes</a> où le principe est d’assimiler la région sous la courbe représentative d’une fonction \(f\) définie sur un segment \([t_n , t_{n+1}]\) à un trapèze et d’en calculer l’aire \(T\) : \(T=(t_{n+1} - t_n){\frac {f(t_n)+f(t_{n+1})}{2}}\).</p>
<p>On a alors : \(x_{n+1} - x_n = \frac{1}{2}\Delta(f(t_n) + f(t_{n+1}))\) avec \(\Delta = t_{n+1} - t_n\).<br />
Si \(x'_n = \mathbf{A}x_n + \mathbf{B} u_n\) (première ligne de l’équation d’un SSM), correspond à \(f\), alors :</p>
\[\begin{align}
x_{n+1} & = x_n + \frac{\Delta}{2} (\mathbf{A}x_n + \mathbf{B} u_n + \mathbf{A}x_{n+1} + \mathbf{B} u_{n+1}) \\
\Longleftrightarrow x_{n+1} - \frac{\Delta}{2}\mathbf{A}x_{n+1} & = x_n + \frac{\Delta}{2}\mathbf{A}x_{n} + \frac{\Delta}{2}\mathbf{B}(u_{n+1} + u_n) \\
(*) \Longleftrightarrow (\mathbf{I} - \frac{\Delta}{2} \mathbf{A}) x_{n+1} & = (\mathbf{I} + \frac{\Delta}{2} \mathbf{A}) x_{n} + \Delta \mathbf{B} u_{n+1}\\
\Longleftrightarrow x_{n+1} & = (\mathbf{I} - \frac{\Delta}{2} \mathbf{A})^{-1} (\mathbf{I} + \frac{\Delta}{2} \mathbf{A}) x_n + (\mathbf{I} - \frac{\Delta}{2} \mathbf{A})^{-1} \Delta \mathbf{B} u_{n+1}
\end{align}\]
<p>(*) \(u_{n+1} \overset{\Delta}{\simeq} u_n\) (le vecteur de contrôle est supposé constant sur un petit \(\Delta\)).</p>
<p>Nous venons d’obtenir notre SSM discrétisé !<br />
Pour que cela soit complètement explicite, posons :</p>
\[\begin{aligned}
\mathbf{\bar{A}} &= (\mathbf {I} - \frac{\Delta}{2} \mathbf{A})^{-1}(\mathbf {I} + \frac{\Delta}{2} \mathbf{A}) \\
\mathbf {\bar{B}} &= (\mathbf{I} - \frac{\Delta}{2} \mathbf {A})^{-1} \Delta \mathbf{B} \\
\mathbf {\bar{C}} &= \mathbf{C}\\
\end{aligned}\]
<p>On a alors</p>
\[\begin{aligned}
x_k &= \mathbf{\bar{A}}x_{k-1} + \mathbf{\bar{B}}u_k \\
y_k &= \mathbf{\bar{C}}x_k
\end{aligned}\]
<p>La notation des matrices avec une barre a été introduite dans le S4 pour désigner les matrices dans le cas discret et est devenue depuis une convention dans le domaine des SSM appliqués à l’apprentissage profond.<br />
<br /><br /><br /></p>
<h1 id="-vue-convolutive-dun-ssm-"><span style="color: #FF0000"> <strong>Vue convolutive d’un SSM</strong> </span></h1>
<p>Cette récurrence peut s’écrire sous la forme d’une convolution. Pour cela, il suffit d’itérer les équations du système</p>
\[\begin{aligned}
x_k &= \mathbf{\bar{A}}x_{k-1} + \mathbf{\bar{B}}u_k \\
y_k &= \mathbf{\bar{C}}x_k
\end{aligned}\]
<p>Commençons par la première ligne du système :<br />
Etape 0 : \(x_0 = \mathbf{\bar{B}} u_0\)<br />
Etape 1 : \(x_1 = \mathbf{\bar{A}}x_{0} + \mathbf{\bar{B}}u_1 = \mathbf{\bar{A}} \mathbf{\bar{B}} u_0 + \mathbf{\bar{B}}u_1\)<br />
Etape 2 : \(x_2 = \mathbf{\bar{A}}x_{1} + \mathbf{\bar{B}}u_2 = \mathbf{\bar{A}} (\mathbf{\bar{A}} \mathbf{\bar{B}} u_0 + \mathbf{\bar{B}}u_1) + \mathbf{\bar{B}}u_2 = \mathbf{\bar{A}}^{2} \mathbf{\bar{B}} u_0 + \mathbf{\bar{A}} \mathbf{\bar{B}} u_1 + \mathbf{\bar{B}}u_2\)<br />
Nous avons \(x_k\) qui peut s’écrire sous la forme d’une fonction \(f\) paramétrée par \(u_0, u_1, … u_k\).</p>
<p>Passons ensuite à la seconde ligne du système où il est à présent possible d’injecter les valeurs \(x_k\) calculées à l’instant :<br />
Etape 0 : \(y_0 = \mathbf{\bar{C}} x_0 = \mathbf{\bar{C}} \mathbf{\bar{B}} u_0\)<br />
Etape 1 : \(y_1 = \mathbf{\bar{C}} x_1 = \mathbf{\bar{C}} ( \mathbf{\bar{A}} \mathbf{\bar{B}} u_0 + \mathbf{\bar{B}}u_1) = \mathbf{\bar{C}} \mathbf{\bar{A}} \mathbf{\bar{B}} u_0 + \mathbf{\bar{C}} \mathbf{\bar{B}}u_1\)<br />
Etape 2 : \(y_2 = \mathbf{\bar{C}} x_2 = \mathbf{\bar{C}}(\mathbf{\bar{A}}^{2} \mathbf{\bar{B}} u_0 + \mathbf{\bar{A}} \mathbf{\bar{B}} u_1 + \mathbf{\bar{B}}u_2 ) = \mathbf{\bar{C}}\mathbf{\bar{A}}^{2} \mathbf{\bar{B}} u_0 + \mathbf{\bar{C}}\mathbf{\bar{A}} \mathbf{\bar{B}} u_1 + \mathbf{\bar{C}}\mathbf{\bar{B}}u_2\)<br />
On peut observer le noyau de convolution \(\mathbf{\bar{K}} _k = (\mathbf{\bar{C}} \mathbf{\bar{B}}, \mathbf{\bar{C}} \mathbf{\bar{A}} \mathbf{\bar{B}}, …, \mathbf{\bar{C}} \mathbf{\bar{A}}^{k} \mathbf{\bar{B}})\) applicable aux \(u_k\), d’où \(K \ast u\).</p>
<p>Comme pour les matrices, nous appliquons une barre sur le \(\mathbf{\bar{K}}\) pour spécifier qu’il s’agit du noyau de convolution obtenu après discrétisation. Il est généralement appelé <strong>noyau de convolution SSM</strong> dans la littérature et sa taille est équivalente à l’entièreté de la séquence d’entrée.<br />
Ce noyau de convolution est calculé par <a href="https://fr.wikipedia.org/wiki/Transformation_de_Fourier_rapide">Transformation de Fourier Rapide</a> (FFT) et sera explicité dans les prochains articles (vous aimez la Flash Attention des <em>transformers</em> ? Vous adorerez la Flash FFT Convolution que nous verrons dans le troisième article de blog).
<br /><br /><br /></p>
<h1 id="-avantages-et-limites-de-chacune-des-trois-vues-"><span style="color: #FF0000"> <strong>Avantages et limites de chacune des trois vues</strong> </span></h1>
<table>
<thead>
<tr>
<th style="text-align: center"><img src="https://github.com/lbourdois/blog/assets/58078086/cb2dca34-9a3e-481a-8773-2360a1ceaa1c" alt="image" /></th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center">Figure 3 : <em>Image provenant du papier « <a href="https://arxiv.org/abs/2110.13985">Combining Recurrent, Convolutional, and Continuous-time Models with Linear State-Space Layers</a> » d’Albert GU et al., sorti à une semaine d’intervalle du S4</em></td>
</tr>
</tbody>
</table>
<p><br /></p>
<p>Les vues différentes du SSM ont chacunes des avantages et des inconvénients, détaillons-les.</p>
<p>Pour la <u><b>vue continue</b></u>, les avantages et inconvénients sont les suivants :<br />
✓ Gère automatiquement les données continues (signaux audio, séries temporelles, par exemple). Cela représente énorme avantage pratique pour traiter des données à échantillonnage irrégulier ou décalé dans le temps.<br />
✓ Analyse mathématiquement réalisable, par exemple en calculant des trajectoires exactes ou en construisant des systèmes de mémorisation (HiPPO).<br />
✗ Extrêmement lent à la fois pour la formation et l’inférence.</p>
<p>Pour la <u><b>vue récursive</b></u>, il s’agit ici des avantages et inconvénients bien connus des réseaux de neurones récurrents (voir l’<a href="https://lbourdois.github.io/blog/nlp/RNN-LSTM-GRU-ELMO/">article</a> qui leur est consacré sur le blog) à savoir :<br />
✓ Un biais inductif naturel pour les données séquentielles, et en principe un contexte non borné.<br />
✓ Une inférence efficace (mises à jour d’état en temps constant).<br />
✗ Un apprentissage lent (manque de parallélisme).<br />
✗ Une disparition ou explosion du gradient lors de l’entraînement de séquence trop longues.</p>
<p>Pour la <u><b>vue convolutive</b></u>, il s’agit ici des avantages et inconvénients bien connus des réseaux de neurones convolutifs (nous sommes ici dans le cadre de leur version unidimensionnelle), à savoir :<br />
✓ Caractéristiques locales et interprétables.<br />
✓ Entraînement efficace (parallélisable).<br />
✗ Lenteur dans les contextes en ligne ou autorégressifs (doit recalculer l’ensemble de l’entrée pour chaque nouveau point de données).<br />
✗ Taille de contexte fixe.</p>
<p>Ainsi, en fonction de l’étape du processus (entraînement ou inférence) ou du type de données à notre disposition, il est possible de passer d’une vue à une autre afin de retomber sur un cadre favorable permettant de tirer le meilleur parti du modèle. <br />
Nous priviliègierons la vue convolutive pour l’entraînement pour un entraînement rapide via la parallélisation, la vue récursive pour une inférence efficace, et la vue continue pour traiter des données continues.<br />
<br /><br /><br /></p>
<h1 id="-apprentissage-des-matrices-"><span style="color: #FF0000"> <strong>Apprentissage des matrices</strong> </span></h1>
<p>Dans le noyau de convolution développé plus haut, \(\mathbf{\bar{C}}\) et \(\mathbf{\bar{B}}\), sont des scalaires apprenables. <br />
Concernant \(\mathbf{\bar{A}}\), nous avons vu que dans notre noyau de convolution, elle s’exprime comme une puissance de \(k\) au temps \(k\). Cela peut être très long à calculer c’est pourquoi, on cherche à avoir \(\mathbf{\bar{A}}\) fixe. Pour cela, la meilleure option est de l’avoir diagonale :</p>
\[\mathbf{A} = \begin{bmatrix}
\lambda_{1} & 0 & \cdots & 0 \\
0 & \lambda_{2} & \cdots & 0 \\
\vdots & \vdots & \ddots & \vdots \\
0 & 0 & \cdots & \lambda_{n}
\end{bmatrix}
\Rightarrow
\mathbf{A^k} = \begin{bmatrix}
\lambda_{1}^k & 0 & \cdots & 0 \\
0 & \lambda_{2}^k & \cdots & 0 \\
\vdots & \vdots & \ddots & \vdots \\
0 & 0 & \cdots & \lambda_{n}^k
\end{bmatrix}\]
<p>Par le <a href="https://fr.wikipedia.org/wiki/Th%C3%A9or%C3%A8me_spectral">théorème spectral</a> de l’algèbre linéaire, il s’agit exactement de la classe des <a href="https://fr.wikipedia.org/wiki/Matrice_normale">matrices normales</a>. <br />
En plus du choix de la discrétisation citée ci-dessus, la manière de définir et initier \(\mathbf{\bar{A}}\) est l’un des points qui différencient les diverses architectures de SSM développées dans la littérature que nous développerons dans le prochain article de blog. En effet, empiriquement, il apparait qu’un SSM initialisé avec une matrice \(\mathbf{A}\) aléatoire conduit à de mauvais résultats alors qu’une initialisation effectuée à partir de la matrice \(HiPPO\) (pour <em>High-Order Polynomial Projection Operator</em>) donne des résultats très bons (passage de de 60% à 98% sur le benchmark MNIST sequential).</p>
<p>La matrice \(HiPPO\) a été introduite par les auteurs du S4 dans un précédent <a href="https://arxiv.org/abs/2008.07669">papier</a> (2020). Elle est reprise dans le <a href="https://arxiv.org/abs/2110.13985">papier LSSL</a> (2021), aussi par les auteurs du S4, ainsi que dans l’appendix du S4.
Sa formule est la suivante :</p>
\[\mathbf{A} =
\begin{bmatrix}
1 \\
-1 & 2 \\
1 & -3 & 3 \\
-1 & 3 & -5 & 4 \\
1 & -3 & 5 & -7 & 5 \\
-1 & 3 & -5 & 7 & -9 & 6 \\
1 & -3 & 5 & -7 & 9 & -11 & 7 \\
-1 & 3 & -5 & 7 & -9 & 11 & -13 & 8 \\
\vdots & & & & & & & & \ddots \\
\end{bmatrix}
\\
\Rightarrow
\mathbf{A}_{nk} =
\begin{cases}%
(-1)^{n-k} (2k+1) & n > k \\
k+1 & n=k \\
0 & n<k
\end{cases}\]
<p>Cette matrice n’est pas normale mais elle peut être décomposée sous la forme d’une matrice normale plus une matrice de rang inférieur (résumé dans le papier par NPLR pour <em>Normal Plus Low Rank</em>). Les auteurs prouvent dans leur papier que ce type de matrice peut être calculé efficacement via trois techniques (voir l’algorithme 1 dans le papier) : <a href="https://fr.wikipedia.org/wiki/S%C3%A9rie_g%C3%A9n%C3%A9ratrice">série génératrice tronquée</a>, <a href="https://en.wikipedia.org/wiki/Cauchy_matrix">noyaux de Cauchy</a> et <a href="https://en.wikipedia.org/wiki/Woodbury_matrix_identity">identité de Woodbury</a>.</p>
<!--
Elle permet, in fine, de réécrire la vue réccurente sous la forme suivante :
$$
\begin{aligned}
x_{k} &= \mathbf{\overline{A}} x_{k-1} + \mathbf{\overline{B}} u_k \\
&= \mathbf{A_1} \mathbf{A_0} x_{k-1} + 2 \mathbf{A_1} \mathbf{B} u_k \\
y_k &= \mathbf{C} x_k
\end{aligned}
$$
avec $$ A_0 = frac{2}{\Lambda}\mathbf{I} + (\mathbf{\Lambda} - \mathbf{P} \mathbf{Q}^*)$$ et $$A_1 = (\frac{2}{\Delta}-\mathbf{\Lambda})^{-1} - (\frac{2}{\Delta}-\mathbf{\Lambda})^{-1} \mathbf{p} (\mathbf{I} + \mathbf{q}^* (\frac{2}{\Delta}-\mathbf{\Lambda} )^{-1} \mathbf{p})^{-1} \mathbf{q}^*( \frac{2}{\Delta}-\mathbf{\Lambda})^{-1}$$ où $$\Lambda$$ est une matrice diagonale, $$p$$ et $$q$$ des vecteurs $$\in ℂ^N\times1$$
-->
<!--
Les détails de la démonstration montrant qu'une matrice NPLR peut être calculée efficacement comme une matrice diagonale est basée sur des mathématiques pas forcément triviales mais très élégentes quand on prend le temps de la refaire. Le point principal est qu'elle s'étend sur plus de 8 pages dans l'appendix (voir la partie B et C) du papier. La reprendre entièrement rendrait cet article de blog trop long alors qu'il se veut être une introduction aux SSM. Je ne vais donc pas rentrer dans les détails de cette matrice.
-->
<p>Les détails de la démonstration montrant qu’une matrice NPLR peut être calculée efficacement comme une matrice diagonale peuvent être consultés dans l’appendix (voir la partie B et C) du papier.<br />
Les auteurs du S4 ont par la suite apporté des modifications à la matrice \(HiPPO\) (sur la manière de l’initier) dans leur papier « <a href="https://arxiv.org/abs/2206.12037v2"><em>How to Train Your HiPPO</em></a> » (2022). Le modèle résultant de ce papier est généralement appelé « S4 V2 » ou « S4 updated » dans la littérature à opposer au « S4 original » ou « S4 V1 ».<br />
Nous verrons dans le prochain article, que d’autres auteurs (notamment <a href="https://sites.google.com/view/ag1988/home">Ankit GUPTA</a>) ont proposé d’utiliser une matrice diagonale au lieu d’une matrice NPRL, approche qui est à présent privilégiée car plus simple à implémenter.</p>
<!--
Ainsi, la compréhenstion des mathématiques sous-jacentes à la matrice $$HiPPO$$ n'est pas un pré-requis obligatoire car elle n'est plus utilisée en pratique.
-->
<p><br /><br /><br /></p>
<h1 id="-résultats-des-expérimentations-"><span style="color: #FF0000"> <strong>Résultats des expérimentations</strong> </span></h1>
<p>Terminons cet article de blog en analysant une sélection des résultats du S4 sur diverses tâches et benchmarks afin de nous rendre compte du potentiel des SSM.</p>
<p>Commençons avec une tâche d’audio et le benchmark <a href="https://arxiv.org/abs/1804.03209v1"><em>Speech Commands</em></a> de WARDEN (2018).</p>
<table>
<thead>
<tr>
<th style="text-align: center"><img src="https://github.com/lbourdois/blog/assets/58078086/1a902a38-a499-47ef-b015-0644cf2cebc4" alt="image" /></th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center"><em>Figure 4 : Image provenant du papier « <a href="https://arxiv.org/abs/2206.11893">On the Parameterization and Initialization of Diagonal State Space Models</a> » d’Albert GU et al. (2022), aussi connu sous le nom de S4D parru après le S4 mais qui reprend sous une forme plus structurée les résultats du S4 pour ce benchmark (les résultats du S4D ayant été supprimés de l’image pour ne pas spoiler le prochain article ;)</em></td>
</tr>
</tbody>
</table>
<p><br /></p>
<p>On peut observer plusieurs choses sur ce tableau.<br />
Premièrement qu’à nombre de paramètres plus ou moins équivalent, le S4 fait beaucoup mieux (au moins + 13%) que les autres modèles, ici de type ConvNet.<br />
Deuxièmement, pour obtenir des performances équivalentes, un ConvNet nécessite 85 fois plus de paramètres.<br />
Troisièmement, un ConvNet entraîné sur du 16K Hz donne de très mauvais résultats quand il est ensuite appliqué sur des données 8K Hz. A contrario, le S4 conserve 95% de sa performance sur ce ré-échantillonage. Cela s’explique par la vue continue du SSM où il a suffit de diviser par deux la valeur de \(\Delta\) au moment de la phase de test.</p>
<p><br /></p>
<p>Continuons avec une tâche de séries temporelles (introduite dans une révision du S4).</p>
<table>
<thead>
<tr>
<th style="text-align: center"><img src="https://github.com/lbourdois/blog/assets/58078086/92b4b1aa-d3ab-4efb-a1a0-2fab1afdafa8" alt="image" /></th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center"><em>Figure 5 : Image provenant de l’appendix du S4</em></td>
</tr>
</tbody>
</table>
<p><br /></p>
<p>Les auteurs du papier reprennent la méthodologie du modèle « <a href="https://arxiv.org/abs/2012.07436">Informer</a> » de ZHOU et al. (2020) et montrent que leur modèle surpasse ce <em>transformer</em> sur 40 des 50 configurations. Les résultats du tableau sont montrés dans un cadre univarié mais la même chose est observable pour un cadre multivarié (table 14 dans l’appendix).</p>
<p><br /></p>
<p>Poursuivons avec une tâche de vision et le benchmark <a href="https://www.cs.toronto.edu/~kriz/learning-features-2009-TR.pdf"><em>sCIFAR-10</em></a> de KRIZHESKY (2009).</p>
<table>
<thead>
<tr>
<th style="text-align: center"><img src="https://github.com/lbourdois/blog/assets/58078086/0334101e-fc91-426a-a845-5b08448ad08c" alt="image" /></th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center"><em>Figure 6 : Image provenant de l’appendix du S4</em></td>
</tr>
</tbody>
</table>
<p><br /></p>
<p>Le S4 établit le SoTA sur sCIFAR-10 avec seulement 100 000 paramètres (les auteurs ne précisant pas leur nombre pour les autres méthodes).</p>
<p><br /></p>
<p>Concluons avec une tâche textuelle et le benchmark <a href="https://arxiv.org/abs/2011.04006"><em>Long Range Arena</em> (LRA)</a> de TAY et al. (2020).</p>
<table>
<thead>
<tr>
<th style="text-align: center"><img src="https://github.com/lbourdois/blog/assets/58078086/a9eab9ac-6753-4242-8788-c0f28616ccb0" alt="image" /></th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center"><em>Figure 7 : Image provenant de l’appendix du S4</em></td>
</tr>
</tbody>
</table>
<p><br /></p>
<p>Le LRA est composé de 6 tâches dont Path-X d’une longueur de 16K tokens pour laquelle le S4 est le premier modèle à la réussir démontrant ses performances sur des tâches de très longues séquences.<br />
Il faudra plus de 2 ans pour qu’AMOS et al. montre dans leur papier « <a href="https://arxiv.org/abs/2310.02980."><em>Never Train from Scratch: Fair Comparison of Long-Sequence Models Requires Data-Driven Priors</em></a> » (2023) que les <em>transformers</em> (non hybridés avec un SSM) peuvent aussi résoudre cette tâche. Ils n’arrivent cependant pas à passer le PathX-256 d’une longueur de 65K tokens contrairement aux SSM.</p>
<p>A noter néanmoins un point négatif concernant le texte pour le S4 : il obtient une perplexité plus élevée par rapport à celle d’un <em>transformer</em> (standard, des versions plus optimisées ayant une perplexité encore plus faible) sur <a href="https://arxiv.org/abs/1609.07843v1">WikiText-103</a> de MERITY et al. (2016).</p>
<table>
<thead>
<tr>
<th style="text-align: center"><img src="https://github.com/lbourdois/blog/assets/58078086/b2339a9a-415a-453a-8341-96ce2bd1a61d" alt="image" /></th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center"><em>Figure 8 : Image provenant de l’appendix du S4</em></td>
</tr>
</tbody>
</table>
<p><br /></p>
<p>Cela s’explique probablement par la nature non continue du texte (il n’a pas été échantillonné à partir d’un processus physique sous-jacent comme la parole ou les séries temporelles). Nous verrons dans l’article consacré aux évolutions des SSM en 2023 que ce point a fait l’objet de beaucoup de travaux et que les SSM ont aujourd’hui réussi à combler cet écart.
<br /><br /><br /></p>
<h1 id="-conclusion-"><span style="color: #FF0000"> <strong>Conclusion</strong> <span></span></span></h1>
<p>Les SSM sont des modèles possédant trois vues. Une vue continue, et lorsque nous la discrétisons, une vue récurrente ainsi que convolutive.<br />
Tout l’enjeu de ce type d’architecture consiste à savoir quand privilégier une vue plutôt qu’une autre en fonction de l’étape du processus (entraînement ou inférence) et du type de données traitées.<br />
Ce type de modèle est très versatile puisqu’il est applicable pour les tâches de texte, de vision, d’audio, de séries temporelles (ou encore aux graphes). <br />
Un de ses atouts est d’être capable de gérer de très longues séquences pour généralement un nombre de paramètres inférieurs aux autres modèles (ConvNet ou <em>transformers</em>) tout en étant très rapide.<br />
Nous verrons dans les prochains articles que les principales différences entre les diverses architectures de SSM existantes viennent principalement de la façon de discrétiser l’équation de base des SSM ou encore de définir la matrice \(\mathbf A\).
<br /><br /><br /></p>
<h1 id="-pour-aller-plus-loin-"><span style="color: #FF0000"> <strong>Pour aller plus loin</strong> <span></span></span></h1>
<p>Concernant le S4, vous pouvez consulter les ressources suivantes (toutes en anglais) :</p>
<ul>
<li>Vidéos :
<ul>
<li><a href="https://www.youtube.com/watch?v=EvQ3ncuriCM">Efficiently Modeling Long Sequences with Structured State Spaces - Albert Gu - Stanford MLSys #46</a> par Albert GU</li>
<li><a href="https://www.youtube.com/watch?v=luCBXCErkCs">MedAI #41: Efficiently Modeling Long Sequences with Structured State Spaces</a> par Albert GU (un peu plus longue car montre plus d’exemples traités)</li>
<li><a href="https://www.youtube.com/watch?v=GqwhkbrWDOI">JAX Talk: Generating Extremely Long Sequences with S4</a> par Sasha RUSH + les <a href="https://srush.github.io/annotated-s4/slides.html#22">slides</a> utilisées dans la vidéo</li>
</ul>
</li>
<li>Codes :
<ul>
<li><a href="https://srush.github.io/annotated-s4/">The Annotated S4 </a> (en Jax) par Sasha RUSH et Sidd KARAMCHETI</li>
<li><a href="https://github.com/state-spaces/s4">Le GitHub de l’implémentation officielle du S4</a> (en PyTorch)</li>
</ul>
</li>
<li>Articles de blog :
<ul>
<li>Les articles sur le S4 issus du blog Hazy Research qui est le groupe de recherche de Stanford où Albert GU a fait son doctorat ; <a href="https://hazyresearch.stanford.edu/blog/2022-01-14-s4-1">partie 1</a>, <a href="https://hazyresearch.stanford.edu/blog/2022-01-14-s4-2">partie 2</a> et <a href="https://hazyresearch.stanford.edu/blog/2022-01-14-s4-3">partie 3</a>.</li>
</ul>
</li>
<li>Papier :
<ul>
<li>Le prédécesseur du S4 est le <a href="https://proceedings.neurips.cc/paper/2019/file/952285b9b7e7a1be5aa7849f32ffff05-Paper.pdf">Legendre Memory Units: Continuous-Time Representation in Recurrent Neural Networks</a> (LMU) de VOELKER et al. (2019)</li>
</ul>
</li>
</ul>
<p>Concernant la matrice \(HiPPO\), vous pouvez consulter les ressources suivantes (toutes en anglais) :</p>
<ul>
<li>L’<a href="https://hazyresearch.stanford.edu/blog/2020-12-05-hippo">article du blog Hazy Research</a> consacré au sujet</li>
<li>Le papier <a href="https://arxiv.org/abs/2206.12037"><em>How to Train Your HiPPO: State Space Models with Generalized Orthogonal Basis Projections</em></a> d’Albert GU et al. (2022)</li>
</ul>
<p>Concernant les SSM, vous pouvez regarder :</p>
<ul>
<li>le cours (en français) sur les <a href="https://www.youtube.com/watch?v=sDD13PI89hA&list=PLImFpdng6y55wxYZgt7hxbocWkeMWHtCN">systèmes dynamiques</a> d’Ion HAZYUK, Maitre de Conferences à l’INSA de Toulouse (la partie les <a href="https://www.youtube.com/watch?v=XGhDvhHKjiY&list=PLImFpdng6y55wxYZgt7hxbocWkeMWHtCN&index=45">modèles en espace d’état</a> débutent à partie de la section 5.2)</li>
<li>la <a href="https://searchworks.stanford.edu/view/14784021">thèse de doctorat</a> (en anglais) d’Albert GU
<br /><br /><br /></li>
</ul>
<h1 id="-références-"><span style="color: #FF0000"> <strong>Références</strong> </span></h1>
<ul>
<li><a href="https://www.cs.toronto.edu/~kriz/learning-features-2009-TR.pdf">Learning Multiple Layers of Features from Tiny Images</a> d’Alex KRIZHESKY (2009)</li>
<li><a href="https://arxiv.org/abs/1609.07843v1">Pointer Sentinel Mixture Models</a> de Stephen MERITY, Caiming XIONG, James BRADBURY, Richard SOCHER (2016)</li>
<li><a href="https://arxiv.org/abs/1706.03762"><em>Attention is all you need</em></a> de Ashish VASWANI, Noam SHAZEER, Niki PARMAR, Jakob USZKOREIT, Llion JONES, Aidan N. GOMEZ, Lukasz KAISER, Illia POLOSUKHIN (2017)</li>
<li><a href="https://arxiv.org/abs/1804.03209v1">Speech Commands: A Dataset for Limited-Vocabulary Speech Recognition</a> de Pete WARDEN (2018)</li>
<li><a href="https://arxiv.org/abs/2011.04006">Long Range Arena: A Benchmark for Efficient Transformers</a> de Yi TAY, Mostafa DEHGHANI, Samira ABNAR, Yikang SHEN, Dara BAHRI, Philip PHAM, Jinfeng RAO, Liu YANG, Sebastian RUDER, Donald METZLER (2020)</li>
<li><a href="https://arxiv.org/abs/2012.07436">Informer: Beyond Efficient Transformer for Long Sequence Time-Series Forecasting</a> d’Haoyi ZHOU, Shanghang ZHANG, Jieqi peng, Shuai ZHANG, Jianxin LI, Hui XIONG, Wancai ZHANG (2020)</li>
<li><a href="https://arxiv.org/abs/2008.07669">HiPPO: Recurrent Memory with Optimal Polynomial Projections</a> d’Albert GU, Tri DAO, Stefano ERMON, Atri RUDRA, Christopher RÉ (2020)</li>
<li><a href="https://arxiv.org/abs/2110.13985">Combining Recurrent, Convolutional, and Continuous-time Models with Linear State-Space Layers</a> d’Albert GU, Isys JOHNSON, Karan GOEL, Khaled SAAB, Tri DAO, Atri RUDRA, Christopher RÉ (2021)</li>
<li><a href="https://arxiv.org/abs/2111.00396">Efficiently Modeling Long Sequences with Structured State Spaces</a> d’Albert GU, Karan GOEL, et Christopher RÉ (2021)</li>
<li><a href="https://arxiv.org/abs/2206.11893">On the Parameterization and Initialization of Diagonal State Space Models</a> d’Albert GU, Ankit GUPTA, Karan GOEL, Christopher RÉ (2022)</li>
<li><a href="https://arxiv.org/abs/2310.02980">Never Train from Scratch: Fair Comparison of Long-Sequence Models Requires Data-Driven Priors</a> d’Ido AMOS, Jonathan BERANT, Ankit GUPTA (2023)
<br /><br /><br /></li>
</ul>
<h1 id="-citation-"><span style="color: #FF0000"> <strong>Citation</strong> <span></span></span></h1>
<blockquote>
<p>@inproceedings{ssm_introduction_blog_post,<br />
author = {Loïck BOURDOIS},<br />
title = {Introduction aux State Space Models (SSM) et au S4},<br />
year = {2023},<br />
url = {https://lbourdois.github.io/blog/ssm/introduction_ssm}<br />
}</p>
</blockquote>Loïck BOURDOISSSM - Bases des SSM en apprentissage profond via le modèle S4JEUX DE DONNÉES AUDIO POUR LE FRANÇAIS2023-12-01T00:00:00+00:002023-12-01T00:00:00+00:00https://lbourdois.github.io/blog/audio/dataset_audio_fr<h1 id="-avant-propos-"><span style="color: #FF0000"> <strong>Avant-propos</strong> </span></h1>
<p>Ci-dessous, vous trouverez plusieurs listes de jeux de données afin de pouvoir entraîner vos modèles d’audio.
Seuls ceux ayant un nombre d’heures conséquents sont listés (volume disponible supérieur à la dizaine d’heures). Les « petits » jeux de données non listés sont trouvables sur <a href="https://www.ortolang.fr/market/corpora/cluster/speech_corpora">Ortholang</a>. <br />
A noter que tous les jeux de données n’étant pas forcément du même format audio et textuel, un nettoyage devra être effectué afin d’uniformiser les formats.
<br /><br /><br /></p>
<h1 id="-apprentissage-autosupervisé-"><span style="color: #FF0000"> <strong>Apprentissage autosupervisé</strong> </span></h1>
<p><br /></p>
<table>
<thead>
<tr>
<th style="text-align: center"><strong>Nom du jeu de données</strong></th>
<th style="text-align: center"><strong>Heures</strong></th>
<th style="text-align: center"><strong>Lien pour y accéder</strong></th>
<th style="text-align: center"><strong>Informations</strong></th>
<th style="text-align: center"><strong>Licence</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center"><strong>VoxpopuliV2</strong></td>
<td style="text-align: center">22 800 H</td>
<td style="text-align: center"><a href="https://github.com/facebookresearch/voxpopuli">Cliquer-ici</a></td>
<td style="text-align: center">Enregistrements récoltés au Parlement Européen entre 2009 et 2020.</td>
<td style="text-align: center">CC0</td>
</tr>
<tr>
<td style="text-align: center"><strong>Librivox</strong></td>
<td style="text-align: center">2 158 H</td>
<td style="text-align: center"><a href="https://librivox.org/search?primary_key=2&search_category=language&search_page=1&search_form=get_results">Cliquer-ici</a></td>
<td style="text-align: center">996 livres de grands auteurs français tombés dans le domaine public. Librivox étant un projet en constante évolution, le nombre d’heures disponibles augmentent donc au cours du temps. Le nombre d’heures renseigné ici correspond à un décompte effectué au 26 septembre 2023. Note : le jeu de données <a href="https://www.caito.de/2019/01/03/the-m-ailabs-speech-dataset/">M-AILABS French-v0.9</a> est basé en partie sur Librivox. De même pour <a href="https://arxiv.org/abs/2012.03411">Multilingual LibriSpeech</a> (seulement 1 300 H de Librivox dans ce jeu de données).</td>
<td style="text-align: center">Domaine public</td>
</tr>
</tbody>
</table>
<p><br /></p>
<p>Ce sont ainsi environ <strong>25 000 heures</strong> d’audio qui sont disponibles pour l’apprentissage autosupervisé.
<br /><br /><br /></p>
<h1 id="-finetuning-"><span style="color: #FF0000"> <strong><em>Finetuning</em></strong> </span></h1>
<h2 id="-automatic-speech-recognition-asr-"><span style="color: #FFBF00"> <strong><em>Automatic Speech Recognition</em> (ASR)</strong> </span></h2>
<h3 id="-données-en-libre-accès-"><span style="color: #51C353"> <strong>Données en libre accès</strong> </span></h3>
<p><br /></p>
<table>
<thead>
<tr>
<th style="text-align: center"><strong>Nom du jeu de données</strong></th>
<th style="text-align: center"><strong>Heures</strong></th>
<th style="text-align: center"><strong>Lien pour y accéder</strong></th>
<th style="text-align: center"><strong>Informations</strong></th>
<th style="text-align: center"><strong>Licence</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center"><strong>Common Voice</strong></td>
<td style="text-align: center">1 113 H</td>
<td style="text-align: center"><a href="https://commonvoice.mozilla.org/en/datasets">Cliquer-ici</a></td>
<td style="text-align: center">Chiffres indiqués pour la version 16, 981H sur les 1 113 ont été validées</td>
<td style="text-align: center">CC-0</td>
</tr>
<tr>
<td style="text-align: center"><strong>Corpus d’Etude pour le Français Contemporain (CEFC)</strong></td>
<td style="text-align: center">450 H</td>
<td style="text-align: center"><a href="https://repository.ortolang.fr/api/content/cefc-orfeo/10/documentation/site-orfeo/index.html">Cliquer-ici</a> ou <a href="https://www.ortolang.fr/market/corpora/cefc-orfeo">Cliquer-ici</a></td>
<td style="text-align: center">Regroupe 10 corpus sources (CFPP2000, CLAPI, C-ORAL-ROM, CRFP, FLEURON, FRENCH ORAL NARRATIVE, OFROM, TUFS, Valibel). Possibilité de trier ce que l’on souhaite (tv, radio, téléphone, face à face, etc.)</td>
<td style="text-align: center">CC-BY 4.0</td>
</tr>
<tr>
<td style="text-align: center"><strong>ESLO</strong></td>
<td style="text-align: center">300 H pour ESLO1 400 H pour ESLO2</td>
<td style="text-align: center"><a href="https://ct3.ortolang.fr/data/eslo/">Cliquer-ici</a> ou <a href="https://www.ortolang.fr/market/corpora/eslo/v1">Cliquer-ici</a></td>
<td style="text-align: center">ESLO1 contient des entretiens (formels ou informels de type conversation dans une rue) enregistrés entre 1968 et 1974. Les données ne sont pas forcément de bonnes qualités (grésillements). ESLO2 reprend le même principe que ESLO1 mais porte sur des entretiens datant de 2008 à 2020.</td>
<td style="text-align: center">CC-BY 4.0</td>
</tr>
<tr>
<td style="text-align: center"><strong>Conférences Pierre Mendès France</strong></td>
<td style="text-align: center">300 H</td>
<td style="text-align: center"><a href="https://www.data.gouv.fr/fr/datasets/transcriptionsxml-audiomp3-mefr-ccpmf-2012-2020-zip/">Cliquer-ici</a></td>
<td style="text-align: center">Audios au format MP3 et transcriptions au format XML des conférences du centre de conférences Pierre Mendès France du MEFR (2012-2020).</td>
<td style="text-align: center">Open Licence version 2.0</td>
</tr>
<tr>
<td style="text-align: center"><strong>VoxpopuliV2</strong></td>
<td style="text-align: center">211 H</td>
<td style="text-align: center"><a href="https://github.com/facebookresearch/voxpopuli">Cliquer-ici</a></td>
<td style="text-align: center">Parti annoté du corpus. Enregistrements annotés récoltés au Parlement Européen entre 2009 et 2020.</td>
<td style="text-align: center">CC0</td>
</tr>
<tr>
<td style="text-align: center"><strong>TCOF</strong></td>
<td style="text-align: center">146 H</td>
<td style="text-align: center"><a href="https://www.ortolang.fr/market/corpora/tcof">Cliquer-ici</a></td>
<td style="text-align: center">Des enregistrements d’interactions adultes-enfants (enfants jusque 7 ans) et des enregistrements d’interactions entre adultes.</td>
<td style="text-align: center">CC BY-NC-SA 2.0</td>
</tr>
<tr>
<td style="text-align: center"><strong>PFC</strong></td>
<td style="text-align: center">131 H</td>
<td style="text-align: center"><a href="https://www.ortolang.fr/market/corpora/pfc">Cliquer-ici</a></td>
<td style="text-align: center">Le corpus complet contient plus de 50 enquêtes (soit plus de 400 locuteurs). Nous avons ici accès qu’à une sous-partie de ce corpus (16 enquêtes, soit 164 locuteurs) qui a été anonymisée.</td>
<td style="text-align: center">CC BY-NC 4.0</td>
</tr>
<tr>
<td style="text-align: center"><strong>SynPaFlex</strong></td>
<td style="text-align: center">87 H</td>
<td style="text-align: center"><a href="https://www.ortolang.fr/market/corpora/synpaflex-corpus">Cliquer-ici</a></td>
<td style="text-align: center">Annotation de 87h de corpus de livres-audios.</td>
<td style="text-align: center">CC-BY 2.0</td>
</tr>
<tr>
<td style="text-align: center"><strong>MPF</strong></td>
<td style="text-align: center">78 H</td>
<td style="text-align: center"><a href="https://www.ortolang.fr/market/corpora/mpf">Cliquer-ici</a></td>
<td style="text-align: center">Ce corpus vise à documenter des évolutions en cours dans le français, l’émergence d’un vernaculaire urbain contemporain, ainsi que les effets sur le français du contact avec les langues de l’immigration. Nécessite un compte (gratuit) sur Ortholang pour télécharger le corpus.</td>
<td style="text-align: center">CC-BY 4.0</td>
</tr>
<tr>
<td style="text-align: center"><strong>Lingua Libre</strong></td>
<td style="text-align: center">44 H</td>
<td style="text-align: center"><a href="https://lingualibre.org/LanguagesGallery/">Cliquer-ici</a></td>
<td style="text-align: center">Prononciation de mots</td>
<td style="text-align: center">CC BY-SA 4.0</td>
</tr>
<tr>
<td style="text-align: center"><strong>African Accented French</strong></td>
<td style="text-align: center">22 H</td>
<td style="text-align: center"><a href="http://www.openslr.org/57/">Cliquer-ici</a></td>
<td style="text-align: center">Interviews réalisées par l’armée américaine</td>
<td style="text-align: center">Apache 2.0</td>
</tr>
<tr>
<td style="text-align: center"><strong>ALIPE</strong></td>
<td style="text-align: center">15 H</td>
<td style="text-align: center"><a href="https://www.ortolang.fr/market/corpora/alipe-000853">Cliquer-ici</a></td>
<td style="text-align: center">Ce corpus contient la transcription d’environ 15H de conversations informelles entre enfant et parents.</td>
<td style="text-align: center">CC-BY-SA 4.0</td>
</tr>
<tr>
<td style="text-align: center"><strong>Fleurs</strong></td>
<td style="text-align: center">13 H</td>
<td style="text-align: center"><a href="https://huggingface.co/datasets/google/fleurs">Cliquer-ici</a></td>
<td style="text-align: center">Lecture de phrases issues du jeu de données <a href="https://arxiv.org/abs/2106.03193">FLoRes</a></td>
<td style="text-align: center">CC-BY 4.0</td>
</tr>
<tr>
<td style="text-align: center"><strong>SUMM-RE ASRU</strong></td>
<td style="text-align: center">12,5 H</td>
<td style="text-align: center"><a href="https://www.ortolang.fr/market/corpora/summ-re-asru">Cliquer-ici</a></td>
<td style="text-align: center">Réunions de 3 à 4 personnes transcrites avec Whisper puis corrigée manuellement</td>
<td style="text-align: center">CC-BY-SA 4.0</td>
</tr>
<tr>
<td style="text-align: center"><strong>SIWIS</strong></td>
<td style="text-align: center">~ 10 H</td>
<td style="text-align: center"><a href="https://datashare.ed.ac.uk/handle/10283/2353">Cliquer-ici</a></td>
<td style="text-align: center">Au total, 9750 énoncés provenant de sources diverses telles que des débats parlementaires et des romans.</td>
<td style="text-align: center">CC-BY 4.0</td>
</tr>
</tbody>
</table>
<p><br /></p>
<p>Ce sont ainsi environ <strong>3 300 heures</strong> d’audio qui sont disponibles librement pour l’apprentissage supervisé de la tâche d’ASR.
<br /><br /><br /></p>
<h3 id="-corpus-à-accès-limités-demandes-auprès-duniversité--labo-à-effectuer-"><span style="color: #51C353"> <strong>Corpus à accès limités (demandes auprès d’Université / Labo à effectuer)</strong> </span></h3>
<p><br /></p>
<table>
<thead>
<tr>
<th style="text-align: left"><strong>Nom du jeu de données</strong></th>
<th style="text-align: left"><strong>Heures</strong></th>
<th style="text-align: left"><strong>Lien pour y accéder</strong></th>
<th style="text-align: left"><strong>Informations</strong></th>
<th style="text-align: left"><strong>Licence</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left"><strong>INA</strong></td>
<td style="text-align: left">1200H sont disponibles et 3000H sont indiqués comme “à venir”</td>
<td style="text-align: left"><a href="https://dataset.ina.fr/">Cliquer-ici</a></td>
<td style="text-align: left">Données de l’INA disponibles dans différents sous jeux de données. Pour pouvoir avoir accès aux données il faut remplir un formulaire (cf. le lien). Il est précisé que “seuls sont autorisés à s’inscrire les laboratoires de recherche, les PME innovantes ainsi que toutes autres personnes morales disposant d’un service ou d’une activité de recherche scientifique.”</td>
<td style="text-align: left">Licence non précisée mais les CGU sont assez restrictives concernant leur utilisation à des fins non universitaires.</td>
</tr>
<tr>
<td style="text-align: left"><strong>Decoda-RATP</strong></td>
<td style="text-align: left">74H</td>
<td style="text-align: left"><a href="http://www.lrec-conf.org/proceedings/lrec2012/pdf/684_Paper.pdf">Cliquer-ici</a></td>
<td style="text-align: left">Appels téléphoniques à la RATP enregistrés et annotés (transcription, NER, etc.)</td>
<td style="text-align: left">Non précisé, il faut contacter les auteurs</td>
</tr>
<tr>
<td style="text-align: left"><strong>NCCFr</strong></td>
<td style="text-align: left">35H</td>
<td style="text-align: left"><a href="https://mirjamernestus.nl/Ernestus/NCCFr/index.php">Cliquer-ici</a></td>
<td style="text-align: left">Conversations entre amis annotées par des professionnels</td>
<td style="text-align: left">Non précisé, il faut contacter les auteurs</td>
</tr>
</tbody>
</table>
<p><br /></p>
<p>Ce sont ainsi environ <strong>1 300 heures</strong> d’audio qui sont disponibles sous condition d’accès aux données pour l’apprentissage supervisé de la tâche d’ASR.</p>
<p><br /></p>
<h3 id="-données-payantes-"><span style="color: #51C353"> <strong>Données payantes</strong> </span></h3>
<p><br /></p>
<table>
<thead>
<tr>
<th style="text-align: center"><strong>Nom du jeu de données</strong></th>
<th style="text-align: center"><strong>Heures</strong></th>
<th style="text-align: center"><strong>Lien pour y accéder</strong></th>
<th style="text-align: center"><strong>Informations</strong></th>
<th style="text-align: center"><strong>Licence</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center"><strong>ESTER</strong></td>
<td style="text-align: center">100 H annotées + 1700 H non annotées</td>
<td style="text-align: center"><a href="https://catalogue.elra.info/en-us/repository/browse/ELRA-S0241/">Cliquer-ici</a></td>
<td style="text-align: center">Corpus d’enregistrements d’émissions radiophoniques.</td>
<td style="text-align: center">3 types de licences (avec usage commercial ou non). Cf. le lien pour plus d’informations.</td>
</tr>
<tr>
<td style="text-align: center"><strong>ESTER 2</strong></td>
<td style="text-align: center">~200 H</td>
<td style="text-align: center"><a href="https://catalogue.elra.info/en-us/repository/browse/ELRA-S0338/">Cliquer-ici</a></td>
<td style="text-align: center">Inclus les 100H annotées d’ESTER1 + 100 nouvelles heures annotées. Corpus de transcriptions manuelles d’émissions radiophoniques et de transcriptions manuelles rapides de radios africaines.</td>
<td style="text-align: center">2 types de licences (avec usage commercial ou non). Cf. le lien pour plus d’informations.</td>
</tr>
<tr>
<td style="text-align: center"><strong>EPAC</strong></td>
<td style="text-align: center">~100 H</td>
<td style="text-align: center"><a href="https://catalogue.elra.info/en-us/repository/browse/ELRA-S0305/">Cliquer-ici</a></td>
<td style="text-align: center">100H de transcriptions manuelles réalisées à partir des 1 700 heures d’enregistrements non transcrits du jeu de données ESTER.</td>
<td style="text-align: center">2 types de licences (avec usage commercial ou non). Cf. le lien pour plus d’informations.</td>
</tr>
<tr>
<td style="text-align: center"><strong>MEDIA</strong></td>
<td style="text-align: center">70 H</td>
<td style="text-align: center"><a href="https://catalogue.elra.info/en-us/repository/browse/ELRA-S0272/">Cliquer-ici</a></td>
<td style="text-align: center">1 258 dialogues transcrits pour 250 locuteurs adultes sur le domaine du tourisme et de la réservation d’hôtel.</td>
<td style="text-align: center">2 types de licences (avec usage commercial ou non). Cf. le lien pour plus d’informations.</td>
</tr>
<tr>
<td style="text-align: center"><strong>ETAPE</strong></td>
<td style="text-align: center">30 H</td>
<td style="text-align: center"><a href="https://catalogue.elra.info/en-us/repository/browse/ELRA-E0046/">Cliquer-ici</a></td>
<td style="text-align: center">Environ 30H de radio et TV françaises incluant de la parole non planifiée et une proportion raisonnable de données multi-locuteurs. Des données transcrites soigneusement en incluant l’annotation des entités nommées.</td>
<td style="text-align: center">3 types de licences (avec usage commercial ou non). Cf. le lien pour plus d’informations.</td>
</tr>
</tbody>
</table>
<p><br /></p>
<p>Ce sont ainsi environ <strong>400 heures</strong> d’audio qui sont disponibles pour l’apprentissage supervisé et 1300 heures qui sont disponibles pour l’apprentissage autosupervisé en achetant ces corpus.</p>
<p><br /><br /></p>
<h2 id="-audio-classification"><span style="color: #FFBF00"> <strong>Audio Classification</strong></span></h2>
<h3 id="-données-en-libre-accès--1"><span style="color: #51C353"> <strong>Données en libre accès</strong> </span></h3>
<p><br /></p>
<table>
<thead>
<tr>
<th style="text-align: left"><strong>Nom du jeu de données</strong></th>
<th style="text-align: left"><strong>Heures</strong></th>
<th style="text-align: left"><strong>Lien pour y accéder</strong></th>
<th style="text-align: left"><strong>Qualité / Source</strong></th>
<th style="text-align: left"><strong>Licence</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left"><strong>Voxlingua107</strong></td>
<td style="text-align: left">67 H</td>
<td style="text-align: left"><a href="http://bark.phon.ioc.ee/voxlingua107/">Cliquer-ici</a></td>
<td style="text-align: left">Audios issues de YouTube</td>
<td style="text-align: left">CC-BY 4.0</td>
</tr>
<tr>
<td style="text-align: left"><strong>FLEURS-LangID</strong></td>
<td style="text-align: left">13H pour le français et ~1400H au total pour les 102 langues</td>
<td style="text-align: left"><a href="https://huggingface.co/datasets/google/fleurs">Cliquer-ici</a></td>
<td style="text-align: left">Identifier à quelle langue appartient un audio parmi une liste de 102 langues</td>
<td style="text-align: left">CC BY-NC 4.0</td>
</tr>
<tr>
<td style="text-align: left"><strong>Minds14</strong></td>
<td style="text-align: left">1h15</td>
<td style="text-align: left"><a href="https://huggingface.co/datasets/PolyAI/minds14">Cliquer-ici</a></td>
<td style="text-align: left">Audios à classer parmi 14 classes différentes</td>
<td style="text-align: left">CC BY-NC 4.0</td>
</tr>
</tbody>
</table>
<p><br /></p>
<p>Ce sont ainsi environ <strong>80 heures</strong> d’audio qui sont disponibles pour la tâche d’identification d’une langue (en pratique nettement plus si on inclus les jeux de données pour la traduction de la section suivante) et <strong>1h15</strong> pour la classification d’intentions.
<br /><br /></p>
<h3 id="-corpus-à-accès-limités-demandes-auprès-duniversité--labo-à-effectuer--1"><span style="color: #51C353"> <strong>Corpus à accès limités (demandes auprès d’Université / Labo à effectuer)</strong> </span></h3>
<p><br /></p>
<table>
<thead>
<tr>
<th style="text-align: left"><strong>Nom du jeu de données</strong></th>
<th style="text-align: left"><strong>Heures</strong></th>
<th style="text-align: left"><strong>Lien pour y accéder</strong></th>
<th style="text-align: left"><strong>Qualité / Source</strong></th>
<th style="text-align: left"><strong>Licence</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left"><strong>Allosat</strong></td>
<td style="text-align: left">~37H</td>
<td style="text-align: left"><a href="https://aclanthology.org/2020.lrec-1.197.pdf">Cliquer-ici</a></td>
<td style="text-align: left">Appels enregistrés à un centre d’appel dont les conversations portent sur des thèmes de type : énergie, agence de voyage, agence immobilière et assurances. Les données ont aussi été retranscrites mais automatiquement à l’aide de Kaldi</td>
<td style="text-align: left">Non précisé, il faut contacter les auteurs</td>
</tr>
<tr>
<td style="text-align: left"><strong>Cemo</strong></td>
<td style="text-align: left">20H</td>
<td style="text-align: left"><a href="https://arxiv.org/pdf/2110.14957.pdf">Cliquer-ici</a></td>
<td style="text-align: left">Appels aux urgences annotées. Il semble également que les données ont aussi été retranscrites d’après la conclusion du papier.</td>
<td style="text-align: left">Non précisé, il faut contacter les auteurs</td>
</tr>
<tr>
<td style="text-align: left"><strong>RECOLA</strong></td>
<td style="text-align: left">9,5H</td>
<td style="text-align: left"><a href="https://diuf.unifr.ch/main/diva/recola/download.html">Cliquer-ici</a></td>
<td style="text-align: left">Enregistrements audio, visuels et physiologiques (électrocardiogramme et activité électrodermale) d’interactions dyadiques en ligne entre 46 participants francophones, qui résolvaient une tâche en collaboration.</td>
<td style="text-align: left"><a href="https://diuf.unifr.ch/main/diva/recola/data/eula_recola_database.pdf">EULA</a></td>
</tr>
<tr>
<td style="text-align: left"><strong>mGEMEP</strong></td>
<td style="text-align: left">0,9H</td>
<td style="text-align: left"><a href="https://www.unige.ch/cisa/gemep">Cliquer-ici</a></td>
<td style="text-align: left">Données provenant d’acteurs</td>
<td style="text-align: left">Non précisé, il faut contacter les auteurs</td>
</tr>
</tbody>
</table>
<p><br />
Ce sont ainsi environ <strong>120 heures</strong> d’audio qui sont disponibles sous condition d’accès aux données afin d’entraîner un modèle de classification d’audio de type reconnaissance d’émotions.</p>
<p><br /><br /></p>
<h2 id="-automatic-speech-translation-ast-"><span style="color: #FFBF00"> <strong><em>Automatic Speech Translation</em> (AST)</strong> </span></h2>
<h3 id="-données-en-libre-accès--2"><span style="color: #51C353"> <strong>Données en libre accès</strong> </span></h3>
<p><br /></p>
<table>
<thead>
<tr>
<th style="text-align: left"><strong>Nom du jeu de données</strong></th>
<th style="text-align: left"><strong>Heures</strong></th>
<th style="text-align: left"><strong>Lien pour y accéder</strong></th>
<th style="text-align: left"><strong>Qualité / Source</strong></th>
<th style="text-align: left"><strong>Licence</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: left"><strong>Europarl-ST (fr->x) et (x->fr)</strong></td>
<td style="text-align: left">176H de fr->x et 179H de x->fr soit 355H au total</td>
<td style="text-align: left"><a href="https://mllp.upv.es/europarl-st/">Cliquer-ici</a></td>
<td style="text-align: left">Corpus multilingue (français, anglais, allemand, italien, espagnol, portugais, polonais, roumain, néerlandais) construits à partir des débats menés au Parlement européen entre 2008 et 2012.</td>
<td style="text-align: left">CC BY-NC 4.0</td>
</tr>
<tr>
<td style="text-align: left"><strong>MuST-C (en->fr)</strong></td>
<td style="text-align: left">236H</td>
<td style="text-align: left"><a href="https://mt.fbk.eu/must-c/">Cliquer-ici</a></td>
<td style="text-align: left">Provient de TEDs en anglais</td>
<td style="text-align: left">CC BY-NC-ND 4.0</td>
</tr>
<tr>
<td style="text-align: left"><strong>Covost2 (fr->en)</strong></td>
<td style="text-align: left">225H</td>
<td style="text-align: left"><a href="https://huggingface.co/datasets/covost2">Cliquer-ici</a></td>
<td style="text-align: left">Données basées sur Common Voice 4.0</td>
<td style="text-align: left">CC0</td>
</tr>
<tr>
<td style="text-align: left"><strong>mTEDx (fr->x)</strong></td>
<td style="text-align: left">25H à 50H en fonction de la langue cible, 189H au total</td>
<td style="text-align: left"><a href="http://www.openslr.org/100">Cliquer-ici</a></td>
<td style="text-align: left">Données issues des conférences TED. Les langues disponibles étant le français, l’espagnol, l’allemand, l’italien, le russe, le portugais, le grec, l’arabe et l’anglais</td>
<td style="text-align: left">CC BY-NC-ND 4.0</td>
</tr>
</tbody>
</table>
<p><br /></p>
<p>Ce sont ainsi environ <strong>1000 heures</strong> d’audio qui sont disponibles afin d’entraîner un modèle de traduction d’audio incluant à partir ou à destination du français.</p>
<p><br /><br /><br /></p>
<h1 id="-références-"><span style="color: #FF0000"> <strong>Références</strong> <span></span></span></h1>
<ul>
<li><a href="https://arxiv.org/abs/2101.00390">VoxPopuli: A Large-Scale Multilingual Speech Corpus for Representation Learning, Semi-Supervised Learning and Interpretation</a> de Wang et al. (2021)</li>
<li><a href="https://arxiv.org/abs/1912.06670">Common Voice: A Massively-Multilingual Speech Corpus</a> d’ Ardila et al. (2020)</li>
<li><a href="https://journals.openedition.org/corpus/2936">Le projet ORFÉO : un corpus d’études pour le français contemporain.</a> de Benzitoun et al. (2016).</li>
<li><a href="https://cocoon.huma-num.fr/exist/crdo/meta/cocoon-8bc96a4e-9899-30e4-99be-c72d216eb38b">Discours sur la ville. Corpus de Français Parlé Parisien des années 2000 (CFPP2000)</a> de Branca-Rosoff et al. (2020)</li>
<li><a href="https://journals.openedition.org/corpus/2991">CLAPI, une base de données multimodale pour la parole en interaction : apports et dilemmes</a> de Baldauf-Quilliatre et al. (2016)</li>
<li><a href="https://aclanthology.org/L04-1200/">The C-ORAL-ROM CORPUS. A Multilingual Resource of Spontaneous Speech for Romance Languages</a> de Cresti et al. (2004)</li>
<li><a href="https://shs.hal.science/halshs-01388193">Corpus de référence du français parlé</a> de Delic et al. (2004)</li>
<li><a href="https://journals.openedition.org/corpus/3060">De l’archive de parole au corpus de référence : la base de données orales du français de Suisse romande</a> d’Avanzi et al. (2016)</li>
<li><a href="https://journals.openedition.org/corpus/3006">Disfluences et vieillissement langagier. De la base de données VALIBEL aux corpus outillés en français parlé</a> de Bolly et al. (2016)</li>
<li><a href="https://aclanthology.org/2011.tal-3.2/">Un grand corpus oral disponible : le Corpus d’Orléans 1968-2012 [A Large available oral corpus: Orleans corpus 1968-2012]</a> d’Eshkol-Taravella et al. (2012)</li>
<li><a href="https://journals.openedition.org/pratiques/1597">Traitement de Corpus Oraux en Français</a> d’André et Canut (2010)</li>
<li><a href="https://www.researchgate.net/publication/49135381_Le_projet_PFC_Phonologie_du_Francais_Contemporain_une_source_de_donnees_primaires_structurees">Le projet PFC: une source de données primaires structurées</a> de Durand et al. (2009)</li>
<li><a href="https://aclanthology.org/L18-1677/">SynPaFlex-Corpus: An Expressive French Audiobooks Corpus dedicated to expressive speech synthesis.</a> de Sini et al (2018)</li>
<li><a href="https://journals.openedition.org/lidil/4854">Les parlers jeunes dans l’Île-de-France multiculturelle</a> de Gadet et al. (2017)</li>
<li><a href="https://lrl.uca.fr/projet_du_labo/alipe-fr/">ALIPE (Acquisition de la Liaison et Interactions Parents Enfants)</a> de Chabanal et al. (2013)</li>
<li>[Transcribing And Aligning Conversational Speech: A Hybrid Pipeline Applied To French Conversations] de Yamasaki et al. (2023)</li>
<li><a href="https://datashare.ed.ac.uk/handle/10283/2353">The SIWIS French Speech Synthesis Database</a> de Yamagishi et al. (2017)</li>
<li><a href="https://aclanthology.org/L16-1166/">Enhancing The RATP-DECODA Corpus With Linguistic Annotations For Performing A Large Range Of NLP Tasks</a> de Lailler et al. (2016)</li>
<li><a href="https://mirjamernestus.nl/Ernestus/NCCFr/index.php">Nijmegen Corpus of Casual French</a> de Torreira et al. (2010)</li>
<li><a href="https://arxiv.org/abs/2104.08524">Multilingual and Cross-Lingual Intent Detection from Spoken Data</a> de Gerz, Su et al. (2021)</li>
<li><a href="https://arxiv.org/abs/2205.12446">FLEURS: Few-shot Learning Evaluation of Universal Representations of Speech</a> de Conneau et al. (2022)</li>
<li><a href="https://aclanthology.org/2020.lrec-1.197.pdf">On the use of Self-supervised Pre-trained Acoustic and Linguistic Features for Continuous Speech Emotion Recognition</a> de Macary et al. (2020)</li>
<li><a href="https://arxiv.org/pdf/2110.14957.pdf">End-to-End Speech Emotion Recognition: Challenges of Real-Life Emergency Call Centers Data Recordings</a> de Deschamps-Berger et al. (2021)</li>
<li><a href="https://drive.google.com/file/d/0B2V_I9XKBODhNENKUnZWNFdVXzQ/view?resourcekey=0-pkUwtWY7x82Gw5zurnQNag">Introducing the RECOLA Multimodal Corpus of Remote Collaborative and Affective Interactions</a> de Ringeval et al. (2013)</li>
<li><a href="https://pubmed.ncbi.nlm.nih.gov/22081890/">Introducing the Geneva Multimodal expression corpus for experimental research on emotion perception</a> de Bänziger et al. (2012)</li>
<li><a href="https://arxiv.org/abs/1911.03167">Europarl-ST: A Multilingual Corpus For Speech Translation Of Parliamentary Debates</a> d’Iranzo-Sánchez et al. (2019)</li>
<li><a href="https://aclanthology.org/N19-1202/">MuST-C: a Multilingual Speech Translation Corpus</a> de Di Gangi et al. (2019)</li>
<li><a href="https://arxiv.org/abs/2007.10310">CoVoST 2: A Massively Multilingual Speech-to-Text Translation Corpus</a> de Wang, Wu et Pino (2020)</li>
<li><a href="https://arxiv.org/abs/2102.01757">The Multilingual TEDx Corpus for Speech Recognition and Translation</a> de Salesky et al. (2021)</li>
<li><a href="https://arxiv.org/abs/2011.12998">VoxLingua107: a Dataset for Spoken Language Recognition</a> de Valk et Alumäe (2020)</li>
</ul>
<p><br /><br /><br /></p>
<blockquote>
<p>@inproceedings{french_audio_datasets_blog_post,<br />
author = {Loïck BOURDOIS},<br />
title = {Jeux de données audio pour le français},<br />
year = {2023},<br />
url = {https://lbourdois.github.io/blog/audio/dataset_audio_fr}<br />
}</p>
</blockquote>Loïck BOURDOISAudio - Jeux de données pour pré-entraîner un modèle d'audio puis le finetuner sur une tâche en particulierCOURS SUR L’APPRENTISSAGE PROFOND (EDITION 2021) DE YANN LE CUN ET ALFREDO CANZIANI2022-09-07T00:00:00+00:002022-09-07T00:00:00+00:00https://lbourdois.github.io/blog/projets/cours-dl-21-nyu<h1 id="-contenu-du-cours-"><span style="color: #FF0000"> <strong>Contenu du cours</strong> </span></h1>
<p>De mars 2022 à juin 2022, j’ai traduit l’édition 2021 du cours d’<strong>Introduction à l’apprentissage profond de Yann Le Cun et Alfredo Canziani</strong> dispensé à l’<a href="https://cds.nyu.edu/deep-learning/">Université de New York</a>.
Pour cette édition, seules les nouveautés par rapport à l’<a href="https://lbourdois.github.io/blog/projets/cours-dl-nyu/">édition 2020</a> ont été traduites.</p>
<p>Il s’agit des vidéos 🎥 des intervenants invités, à savoir :</p>
<ul>
<li><a href="https://twitter.com/imisra_">Ishan Misra</a> présentant l’apprentissage autosupervisé en vision (PIRL, SwAV, SEER, Barlow Twins) : <a href="https://www.youtube.com/watch?v=8L10w1KoOU8">https://www.youtube.com/watch?v=8L10w1KoOU8</a></li>
<li><a href="https://twitter.com/awnihannun">Awni Hannun</a> abordant la reconnaissance vocale et les GTNs (CTC, Beam Search, GTN) : <a href="https://www.youtube.com/watch?v=Of9s8epjflU">https://www.youtube.com/watch?v=Of9s8epjflU</a></li>
<li><a href="https://twitter.com/MarcRanzato">Marc’Aurelio Ranzato</a> exposant la traduction automatique avec peu de données (MAD, FLoRes, adaptation au domaine) : <a href="https://www.youtube.com/watch?v=fR42OOy9ROo">https://www.youtube.com/watch?v=fR42OOy9ROo</a></li>
</ul>
<p>L’année précédente, les invités étaient :</p>
<ul>
<li><a href="https://twitter.com/aaron_defazio">Aaron DeFazio</a> parlant d’optimisation : <a href="https://www.youtube.com/watch?v=--NZb480zlg">https://www.youtube.com/watch?v=–NZb480zlg</a></li>
<li><a href="https://twitter.com/imisra_">Ishan Misra</a> présentant l’apprentissage autosupervisé en vision (l’édition 2021 étant la continuité de l’édition 2020) : <a href="https://www.youtube.com/watch?v=0KeR6i1_56g">https://www.youtube.com/watch?v=0KeR6i1_56g</a></li>
<li><a href="https://twitter.com/ml_perception">Mike Lewis</a> évoquant les <em>transformers</em> : <a href="https://www.youtube.com/watch?v=6D4EWKJgNn0">https://www.youtube.com/watch?v=6D4EWKJgNn0</a></li>
<li><a href="https://twitter.com/xbresson">Xavier Bresson</a> traitant les réseaux de neurones convolutifs pour graphes (GCNs) : <a href="https://www.youtube.com/watch?v=Iiv9R6BjxHM">https://www.youtube.com/watch?v=Iiv9R6BjxHM</a></li>
</ul>
<p>⚠Les vidéos sont paramétrées de sorte que les sous-titres en français apparaissent automatiquement pour les personnes situées dans les pays francophones. S’ils n’apparaissent pas, pensez à les activer manuellement dans ⚙ Paramètres → Sous-titres → Français.</p>
<p>Pour le reste du contenu, je vous invite à consulter le site web 🌐 du cours qui a été conçu de façon à répertorier les nouveautés et sinon à renvoyer vers le contenu de l’édition 2020 : <a href="https://atcold.github.io/NYU-DLSP21/fr/">https://atcold.github.io/NYU-DLSP21/fr/</a></p>
<p>Les notebooks Jupyter 📓 restent inchangés et sont toujours disponibles ici : <a href="https://github.com/lbourdois/pytorch-Deep-Learning-Notebooks-in-French">https://github.com/lbourdois/pytorch-Deep-Learning-Notebooks-in-French</a></p>
<p>Toutes les informations utiles à connaître (choix effectués pour la traduction, temps à consacrer au cours, licence du cours, etc.) sont disponibles dans la FAQ du site, consultable ici <a href="https://atcold.github.io/NYU-DLSP21/fr/faq/">https://atcold.github.io/NYU-DLSP21/fr/faq/</a></p>
<p>En espérant que cela vous plaise et vous soit utile.<br />
Bon visionnage et bonne lecture ! :)</p>Loïck BOURDOISProjet - Cours sur l'apprentissage profond (édition 2021) de Yann Le Cun et Alfredo CanzianiCOURS SUR L’APPRENTISSAGE PROFOND (EDITION 2020) DE YANN LE CUN ET ALFREDO CANZIANI2021-09-05T00:00:00+00:002021-09-05T00:00:00+00:00https://lbourdois.github.io/blog/projets/cours-dl-nyu<h1 id="-avant-propos-"><span style="color: #FF0000"> <strong>Avant-propos</strong> </span></h1>
<p>Je n’ai publié aucun nouvel article sur le blog pendant une année car je travaillais sur un projet particulièrement long et chronophage.
Ce projet étant arrivé à son terme, il est à présent temps de le présenter.
Je tiens à remercier <a href="https://twitter.com/alfcnz">Alfredo Canziani</a> et <a href="https://twitter.com/ylecun">Yann Le Cun</a> pour leurs retours durant ce projet ainsi que pour leur confiance :)
<br /><br /></p>
<h1 id="-contenu-du-cours-"><span style="color: #FF0000"> <strong>Contenu du cours</strong> </span></h1>
<p>D’août 2020 à août 2021, j’ai traduit l’édition 2020 du cours d’<strong>Introduction à l’apprentissage profond de Yann Le Cun et Alfredo Canziani</strong> dispensé à l’<a href="https://cds.nyu.edu/deep-learning/">Université de New York</a>.
Ce travail a nécessité environ 600h de travail afin de pouvoir proposer une traduction en français des :</p>
<ul>
<li><a href="https://www.youtube.com/watch?v=0bMe_vCZo30&list=PLLHTzKZzVU9eaEyErdV26ikyolxOsz6mq">28 vidéos</a> 🎥 de cours (cours magistraux et travaux dirigés) d’une durée totale d’environ 40h,</li>
<li>59 pages du <a href="https://atcold.github.io/pytorch-Deep-Learning/fr/">site web</a> 🌐 résumant les vidéos à travers les notes prises par les étudiants pendant le cours,</li>
<li><a href="https://github.com/lbourdois/pytorch-Deep-Learning-Notebooks-in-French">16 notebooks</a> 📓 utilisés lors des travaux dirigés</li>
</ul>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/DLSP20/NYU%20Deep%20Learning.png" />
</figure>
</center>
<p>Le programme de cette édition 2020 du cours porte sur :</p>
<ul>
<li>l’histoire de l’apprentissage profond et ses motivations</li>
<li>la descente de gradient et la rétropropagation</li>
<li>les réseaux de neurones convolutifs</li>
<li>les réseaux de neurones récurrents, les LSTMs, les systèmes d’attention et de séquences à séquences</li>
<li>les techniques d’optimisation</li>
<li>les modèles à base d’énergie (EBMs)</li>
<li>les méthodes contrastives et génératives (GANs)</li>
<li>les auto-encodeurs et leurs dérivées (DAEs, VAEs)</li>
<li>l’apprentissage autosupervisé appliqué à la vision par ordinateur</li>
<li>les <em>transformers</em></li>
<li>les réseaux de neurones pour graphes (GNNs)<br />
et pleins d’autres choses !
<br /><br /></li>
</ul>
<p>Toutes les informations utiles à connaître (choix des traductions, temps à consacrer au cours, licence du cours, etc.) sont disponibles sur cette <a href="https://atcold.github.io/pytorch-Deep-Learning/fr/faq/">page</a>.<br /><br /></p>
<p>En espérant que cela vous plaise et vous soit utile.<br />
Bon visionnage et bonne lecture ! :)</p>Loïck BOURDOISProjet - Cours sur l'apprentissage profond (édition 2020) de Yann Le Cun et Alfredo CanzianiL’AUGMENTATION DE DONNEES EN NLP2020-05-20T00:00:00+00:002020-05-20T00:00:00+00:00https://lbourdois.github.io/blog/nlp/Data-augmentation-in-NLP<h1 id="-avant-propos-"><span style="color: #FF0000"> <strong>Avant-propos</strong> </span></h1>
<p>Cet article est une traduction de l’article de Amit Chaudhary : <a href="https://amitness.com/2020/05/data-augmentation-for-nlp/">A Visual Survey of Data Augmentation in NLP</a>. Merci à lui de m’avoir autorisé à effectuer cette traduction.
J’ai ajouté des éléments supplémentaires quand j’estimais que cela était pertinent.
<br /><br /><br /></p>
<h1 id="-introduction-"><span style="color: #FF0000"> <strong>Introduction</strong> </span></h1>
<p>Contrairement à la vision par ordinateur où l’augmentation de données d’images est une pratique courante, l’augmentation de données textuelles est moins répendue en traitement du langage naturel (NLP).
Cela s’explique par le fait que cette pratique est moins essentielle qu’en image car en NLP les données sont disponibles en abondance (les modèles de <em>transformers</em> étant entraînés par exemple sur les millions de pages de Wikipédia, Common Crawl, etc.). Néanmoins, pour certaines tâches il se peut que vous manquiez de données.
Voici un exemple simple que j’ai rencontré professionnellement lorsque je travaillais à l’INSERM :<br />
dans le cadre de la conception d’un outil de classification afin de déterminer la nature des traumatismes des patients passant par le service des urgences du centre hospitalier universitaire de Bordeaux nous nous sommes aperçus que pour avoir des résultats fiables, il faut environ 500 exemples d’entraînement par classes. A cela doit s’ajouter les effectifs nécessaires pour l’échantillon test. Un tel nombre ne pose pas de problème par exemple pour les chutes à domicile (le nombre de personnes âgées admises aux urgences pour une chute est monstrueux), les accidents de la route, le sport, etc. Mais pour d’autres classes, il manque (heureusement) des effectifs comme par exemple pour les noyades, les morsures d’animaux, les tentatives de suicides, etc. Même en ayant plus de 7 années d’historique de données.
Ainsi pour obtenir des résultats probants, il nous faut augmenter artificiellement les effectifs de certaines classes.<br />
L’objectif de cet article est de donner un aperçu des approches actuelles utilisées pour augmenter les données textuelles.
<br /><br /><br /></p>
<h1 id="-1-la-substitution-lexicale-"><span style="color: #FF0000"> <strong>1. La substitution lexicale</strong> </span></h1>
<p>Cette approche consiste à substituer des mots présents dans un texte sans pour autant changer le sens de la phrase.
<br /></p>
<h2 id="-11-substitution-basée-sur-un-thésaurus-"><span style="color: #FFBF00"> <strong>1.1 Substitution basée sur un thésaurus</strong> </span></h2>
<p>Dans cette technique, nous prenons un mot aléatoire de la phrase et le remplaçons par son synonyme à l’aide d’un thésaurus. Par exemple, nous pouvons utiliser la base de données <a href="https://wordnet.princeton.edu/">WordNet</a> pour l’anglais afin de rechercher les synonymes et effectuer ensuite le remplacement. Il s’agit d’une base de données gérée manuellement avec des relations entre les mots.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/WordNet.png" />
</figure>
</center>
<p><a href="https://arxiv.org/abs/1509.01626">Zhang et al.</a> ont utilisé cette technique dans leur article de 2015 intitulé <em>Character-level Convolutional Networks for Text Classification</em>. Mueller et al. ont utilisé une stratégie similaire pour générer 10 000 exemples d’entraînement supplémentaires pour leur modèle de similarité des phrases.
<br /><br /></p>
<p>Pour le français, quatre bases sont disponibles. Elles consistent toutes en une traduction de WordNet :</p>
<ul>
<li>La partie en français de la base <a href="http://projects.illc.uva.nl/EuroWordNet/">EuroWordNet</a> qui répertorie plusieurs langues européennes. Elle est cependant limitée, n’est pas accessible librement, et commence à dater (1998)</li>
<li><a href="http://pauillac.inria.fr/~sagot/index.html#wolf">WOLF</a> de <a href="https://www.researchgate.net/publication/228809373_Construction_d'un_wordnet_libre_du_francais_a_partir_de_ressources_multilingues">Sagot Benoît et Fišer Darja</a>, datant de 2008</li>
<li><a href="https://www.researchgate.net/publication/268302040_JAWS_Just_Another_WordNet_Subset">JAWS</a> datant de 2010 qui est plus large que WOLF</li>
<li><a href="https://wonef.fr/">WoNef</a> datant de 2014 qui est peut être vu comme une extension de JAWS
<br /></li>
</ul>
<p>Il existe aussi une base de données appelée <a href="http://paraphrase.org/#/download">PPDB</a> contenant des millions de paraphrases (en anglais et multilingues) que vous pouvez télécharger et utiliser.
<br /><br /></p>
<h2 id="-12-substitution-basée-sur-du-word-embedding-"><span style="color: #FFBF00"> <strong>1.2 Substitution basée sur du <em>word embedding</em></strong> </span></h2>
<p>Dans cette approche, nous prenons des <a href="https://lbourdois.github.io/blog/nlp/word_embedding/">enchâssements de mots pré-entrainés tels que Word2Vec</a>, GloVe, FastText, Sent2Vec, et nous utilisons les mots les plus proches de celui que l’on souhaite remplacer dans l’espace des enchâssements. <a href="https://arxiv.org/abs/1909.10351">Jiao et al.</a> ont utilisé cette technique avec GloVe dans leur article <em>TinyBert</em> pour améliorer la généralisation de leur modèle linguistique. <a href="https://www.aclweb.org/anthology/D15-1306.pdf">Wang et al.</a> l’ont utilisée pour augmenter les tweets nécessaires à l’entraînement de leur modèle.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/NN word2vec.png" />
</figure>
</center>
<p>Par exemple, vous pouvez remplacer le mot par les 3 mots les plus similaires et obtenir trois variations du texte.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/word2vec synonyme.png" />
</figure>
</center>
<p>Pour l’anglais, il est facile d’utiliser des packages comme Gensim pour accéder à des vecteurs de mots pré-entraînés et obtenir les voisins les plus proches. Par exemple, nous trouvons ici les synonymes du mot <code class="language-plaintext highlighter-rouge">awesome</code> en utilisant des vecteurs de mots entraînés sur des tweets.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># pip install gensim
</span><span class="kn">import</span> <span class="nn">gensim.downloader</span> <span class="k">as</span> <span class="n">api</span>
<span class="n">model</span> <span class="o">=</span> <span class="n">api</span><span class="p">.</span><span class="n">load</span><span class="p">(</span><span class="s">'glove-twitter-25'</span><span class="p">)</span>
<span class="n">model</span><span class="p">.</span><span class="n">most_similar</span><span class="p">(</span><span class="s">'awesome'</span><span class="p">,</span> <span class="n">topn</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span>
</code></pre></div></div>
<p>Vous aurez alors en sortie les 5 mots les plus similaires ainsi que les similitudes calculées via le cosinus.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[(</span><span class="s">'amazing'</span><span class="p">,</span> <span class="mf">0.9687871932983398</span><span class="p">),</span>
<span class="p">(</span><span class="s">'best'</span><span class="p">,</span> <span class="mf">0.9600659608840942</span><span class="p">),</span>
<span class="p">(</span><span class="s">'fun'</span><span class="p">,</span> <span class="mf">0.9331520795822144</span><span class="p">),</span>
<span class="p">(</span><span class="s">'fantastic'</span><span class="p">,</span> <span class="mf">0.9313924312591553</span><span class="p">),</span>
<span class="p">(</span><span class="s">'perfect'</span><span class="p">,</span> <span class="mf">0.9243415594100952</span><span class="p">)]</span>
</code></pre></div></div>
<p><br />
Pour le français, plusieurs choix s’offrent à vous :</p>
<ul>
<li>Les différents enchâssements de mots mis à disposition par <a href="https://fauconnier.github.io/#data">Jean-Philippe Fauconnier</a> (exemple d’implémentation sur sa page)</li>
<li>Ceux de <a href="https://fasttext.cc/docs/en/crawl-vectors.html">FastText</a> (voir le tableau en bas du lien)
<br /><br /></li>
</ul>
<h2 id="-13-substitution-basée-sur-un-modèle-de-langage-masqué-"><span style="color: #FFBF00"> <strong>1.3 Substitution basée sur un modèle de langage masqué</strong> </span></h2>
<p>Des modèles de <em>transformers</em> tels que BERT (voir partie 2.2 de l’<a href="https://lbourdois.github.io/blog/nlp/BERT/#-21-architecture-du-mod%C3%A8le-">article du blog</a>), ROBERTA et ALBERT (voir partie 1.1 de l’<a href="https://lbourdois.github.io/blog/nlp/ALBERT/">article du blog</a> ont été entraînés sur une grande quantité de texte en utilisant la tâche de prétexte de modélisation du langage masqué où le modèle doit prédire des mots masqués en fonction du contexte.
<br />
Cette tâche peut être utilisée pour compléter certains textes. Par exemple, nous pourrions utiliser un modèle BERT pré-entraîné, masquer certaines parties du texte et demander au modèle BERT de prédire le <em>token</em> masqué.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/BERT Mask.png" />
</figure>
</center>
<p>Ainsi, nous pouvons générer des variations d’un texte en utilisant les prédictions du masque. Par rapport aux approches précédentes, le texte généré est plus cohérent d’un point de vue grammatical, car le modèle tient compte du contexte lors des prédictions.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/BERT Mask synonyme.png" />
</figure>
</center>
<p>Cette approche est facile à mettre en œuvre avec la librairie open source <a href="https://github.com/huggingface/transformers">Transformers d’Hugging Face</a>. Vous pouvez définir le jeton que vous souhaitez remplacer par <code class="language-plaintext highlighter-rouge"><mask></code> et générer des prédictions.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">transformers</span> <span class="kn">import</span> <span class="n">pipeline</span>
<span class="n">nlp</span> <span class="o">=</span> <span class="n">pipeline</span><span class="p">(</span><span class="s">'fill-mask'</span><span class="p">)</span>
<span class="n">nlp</span><span class="p">(</span><span class="s">'This is <mask> cool'</span><span class="p">)</span>
</code></pre></div></div>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[{</span><span class="s">'score'</span><span class="p">:</span> <span class="mf">0.515411913394928</span><span class="p">,</span>
<span class="s">'sequence'</span><span class="p">:</span> <span class="s">'<s> This is pretty cool</s>'</span><span class="p">,</span>
<span class="s">'token'</span><span class="p">:</span> <span class="mi">1256</span><span class="p">},</span>
<span class="p">{</span><span class="s">'score'</span><span class="p">:</span> <span class="mf">0.1166248694062233</span><span class="p">,</span>
<span class="s">'sequence'</span><span class="p">:</span> <span class="s">'<s> This is really cool</s>'</span><span class="p">,</span>
<span class="s">'token'</span><span class="p">:</span> <span class="mi">269</span><span class="p">},</span>
<span class="p">{</span><span class="s">'score'</span><span class="p">:</span> <span class="mf">0.07387523353099823</span><span class="p">,</span>
<span class="s">'sequence'</span><span class="p">:</span> <span class="s">'<s> This is super cool</s>'</span><span class="p">,</span>
<span class="s">'token'</span><span class="p">:</span> <span class="mi">2422</span><span class="p">},</span>
<span class="p">{</span><span class="s">'score'</span><span class="p">:</span> <span class="mf">0.04272908344864845</span><span class="p">,</span>
<span class="s">'sequence'</span><span class="p">:</span> <span class="s">'<s> This is kinda cool</s>'</span><span class="p">,</span>
<span class="s">'token'</span><span class="p">:</span> <span class="mi">24282</span><span class="p">},</span>
<span class="p">{</span><span class="s">'score'</span><span class="p">:</span> <span class="mf">0.034715913236141205</span><span class="p">,</span>
<span class="s">'sequence'</span><span class="p">:</span> <span class="s">'<s> This is very cool</s>'</span><span class="p">,</span>
<span class="s">'token'</span><span class="p">:</span> <span class="mi">182</span><span class="p">}]</span>
</code></pre></div></div>
<p>De même pour le français, vous pouvez utiliser le code suivant :</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">camembert_fill_mask</span> <span class="o">=</span> <span class="n">pipeline</span><span class="p">(</span><span class="s">"fill-mask"</span><span class="p">,</span> <span class="n">model</span><span class="o">=</span><span class="s">"camembert-base"</span><span class="p">,</span> <span class="n">tokenizer</span><span class="o">=</span><span class="s">"camembert-base"</span><span class="p">)</span>
<span class="n">results</span> <span class="o">=</span> <span class="n">camembert_fill_mask</span><span class="p">(</span><span class="s">"Le camembert est <mask> :)"</span><span class="p">)</span>
</code></pre></div></div>
<p>A noter cependant que pour cette méthode le fait de décider quelle partie du texte est à masquer n’est pas triviale. Vous devrez utiliser l’heuristique pour décider du masque, sinon le texte généré pourrait ne pas conserver le sens de la phrase originale.
<br /><br /></p>
<h2 id="-14-substitution-basée-sur-un-tf-idf-"><span style="color: #FFBF00"> <strong>1.4 Substitution basée sur un TF-IDF</strong> </span></h2>
<p>Cette méthode d’augmentation a été proposée par <a href="https://arxiv.org/abs/1904.12848">Xie et al.</a> dans le document intitulé <em>Unsupervised Data Augmentation</em>. L’idée de base est que les mots qui ont un score TF-IDF faible ne sont pas informatifs et peuvent donc être remplacés sans affecter le label d’une phrase.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/TF-IDF.png" />
</figure>
</center>
<p>Les mots qui remplacent le mot original sont choisis en calculant les scores TF-IDF des mots sur l’ensemble du document et en prenant les plus bas. Pour l’implémentation, vous pouvez vous référer au code fournit avec la publication, disponible <a href="https://github.com/google-research/uda/blob/master/text/augmentation/word_level_augment.py">ici</a>.
<br /><br /><br /></p>
<h1 id="-2-la-rétrotraduction-"><span style="color: #FF0000"> <strong>2. La rétrotraduction</strong> </span></h1>
<p>Dans cette approche, nous utilisons la traduction automatique pour paraphraser un texte tout en en retravaillant le sens. <a href="https://arxiv.org/abs/1904.12848">Xie et al.</a> ont utilisé cette méthode pour augmenter leur corpus de texte non labellisé et ont entraîné un modèle semi-supervisé sur un jeu de données <a href="https://fr.wikipedia.org/wiki/Internet_Movie_Database">IMDB</a> avec seulement 20 exemples étiquetés. Leur modèle a surpassé le précédent modèle de pointe entraîné sur 25 000 exemples étiquetés.
Le processus de rétro-traduction est le suivant :</p>
<ul>
<li>Prendre une phrase (par exemple en anglais) et la traduire dans une autre langue, par exemple français</li>
<li>Traduire la phrase en français obtenue précédemment en anglais</li>
<li>Vérifier si la nouvelle phrase est différente de la phrase d’origine. Si c’est le cas, utiliser cette nouvelle phrase comme une version augmentée du texte original</li>
</ul>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/Traduction1.png" />
</figure>
</center>
<p>Vous pouvez également effectuer une rétrotraduction en utilisant différentes langues à la fois pour générer plus de variations. Comme illustré ci-dessous, nous traduisons une phrase anglaise vers une langue cible et inversement vers l’anglais pour trois langues cibles : français, mandarin et italien.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/Traduction2.png" />
</figure>
</center>
<p>Cette technique a été utilisée par le gagnant du « <em>Toxic Comment Classification Challenge</em> » sur <a href="https://www.kaggle.com/c/jigsaw-toxic-comment-classification-challenge/discussion/52557">Kaggle</a>. Il l’a utilisée pour l’augmentation des données d’entraînement ainsi que pendant le test où les probabilités prédites pour la phrase anglaise ainsi que la rétrotraduction en trois langues (français, allemand, espagnol) ont été calculées pour obtenir la prédiction finale.
<br />
Pour la mise en œuvre de la rétrotraduction, vous pouvez utiliser la librairie <a href="https://textblob.readthedocs.io/en/dev/">TextBlob</a> et notamment la fonction <em>Translator</em>. Vous pouvez également utiliser Google Sheets et suivre les instructions données par <a href="https://amitness.com/2020/02/back-translation-in-google-sheets/">Amit</a> pour appliquer Google Translate (en anglais). Cette approche est néanmoins manuelle. Pour automatiser la chose, utilisez l’API <a href="https://pypi.org/project/googletrans/">Googletrans</a>. Attention cependant si vous avez des données sensibles, utilisez des outils à base de Google Translate siginifie que Google les lira.<br />
Une alternative consiste alors à utiliser un modèle de NLP entraîné à réaliser de la traduction. Vous pouvez par exemple utilisez ceux disponibles sur la libraire Hugging Face. Ils sont trouvables en utilisant le filtre «<em>translation</em>» : <a href="https://huggingface.co/models?filter=translation">https://huggingface.co/models?filter=translation</a>.
<br /><br /><br /></p>
<h1 id="-3-transformation-de-la-surface-du-texte-"><span style="color: #FF0000"> <strong>3. Transformation de la surface du texte</strong> </span></h1>
<p>Il s’agit de transformations introduites par Claude Coulombe dans sa <a href="https://arxiv.org/abs/1812.0471">publication</a> : <em>Text Data Augmentation Made Simple By Leveraging NLP Cloud APIs</em>.
<br />
Dans son article, il donne un exemple de transformation de formes verbales de la contraction à l’expansion et vice versa. Nous pouvons générer des textes augmentés en appliquant cette transformation.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/Contraction1.png" />
</figure>
</center>
<p>Comme la transformation ne doit pas changer le sens de la phrase, nous pouvons voir que cela peut échouer en cas d’expansion de formes verbales ambiguës comme :</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/Contraction2.png" />
</figure>
</center>
<p>Pour résoudre ce problème, le document propose de permettre des contractions ambiguës mais de sauter les expansions ambiguës.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/Contraction3.png" />
</figure>
</center>
<p>Vous pouvez trouver une liste des contractions pour la langue anglaise <a href="https://en.wikipedia.org/wiki/Wikipedia%3aList_of_English_contractions">ici</a>. Pour l’expansion, vous pouvez utiliser la librairie <a href="https://github.com/kootenpv/contractions">contractions</a> en Python.
<br />
Cette technique ne semble pas avoir d’intérêt pour la langue française puisque celle-ci ne contient pas de contraction/expansion comme en anglais.
<br /><br /><br /></p>
<h1 id="-4-injection-aléatoire-de-bruit-"><span style="color: #FF0000"> <strong>4. Injection aléatoire de bruit</strong> </span></h1>
<p>L’idée de ces méthodes est d’injecter du bruit dans le texte afin que le modèle entrainé soit robuste aux perturbations.
<br /></p>
<h2 id="-41-injection-de-fautes-dorthographe-"><span style="color: #FFBF00"> <strong>4.1 Injection de fautes d’orthographe</strong> </span></h2>
<p>Dans cette méthode, nous ajoutons des fautes d’orthographe à un mot aléatoire de la phrase. Ces fautes d’orthographe peuvent être ajoutées par programmation ou à l’aide d’un lexique des fautes d’orthographe courantes, comme cette <a href="https://github.com/makcedward/nlpaug/blob/master/model/spelling_en.txt">liste</a> pour l’anglais.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/Erreur_orthographe.png" />
</figure>
</center>
<p>Pour le français, j’ai essayé de trouver une liste comme celle en anglais citée à l’instant, sans succès.
<br /><br /></p>
<h2 id="-42-injection-de-fautes-de-frappe-"><span style="color: #FFBF00"> <strong>4.2 Injection de fautes de frappe</strong> </span></h2>
<p>Cette méthode tente de simuler les erreurs courantes qui se produisent lors de la saisie sur un clavier à disposition QWERTY en raison des touches très proches les unes des autres. Les erreurs sont injectées en fonction de la distance entre les touches du clavier.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/Erreur_QWERTY.png" />
</figure>
</center>
<p>Cette approche est bien sur reproductible pour les claviers AZERTY utilisés par les francophones.
<br /><br /></p>
<h2 id="-43-bruits-dunigramme-"><span style="color: #FFBF00"> <strong>4.3 Bruits d’unigramme</strong> </span></h2>
<p>Cette méthode a été utilisée par <a href="https://arxiv.org/abs/1703.02573">Xie et al.</a> ou encore par <a href="https://arxiv.org/abs/1904.12848">Qizhe Xie et al.</a>. L’idée est d’effectuer le remplacement en utilisant des mots échantillonnés à partir de la distribution de fréquence des unigrammes. Cette fréquence est essentiellement le nombre de fois que chaque mot apparaît dans le corpus d’entraînement.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/Erreur_unigramme.png" />
</figure>
</center>
<h2 id="-44-bruits-parasites-"><span style="color: #FFBF00"> <strong>4.4 Bruits parasites</strong> </span></h2>
<p>Cette méthode a été proposée par <a href="https://arxiv.org/abs/1703.02573">Xie et al.</a> dans leur article. L’idée est de remplacer aléatoirement un mot par un <em>token</em> que l’on aura choisi préalablement.
Dans l’article les auteurs utilisent « » comme caractère de remplacement. C’est un moyen d’éviter de trop s’adapter à des contextes spécifiques ainsi qu’un mécanisme de lissage du modèle linguistique. Cette technique a permis d’améliorer la perplexité et les scores BLEU.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/Erreur_blank.png" />
</figure>
</center>
<p><br /></p>
<h2 id="-45-mélanges-de-phrases-"><span style="color: #FFBF00"> <strong>4.5 Mélanges de phrases</strong> </span></h2>
<p>Il s’agit d’une technique naïve qui consiste à mélanger des phrases présentes dans un texte de d’entraînement afin de créer une version augmentée.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/Shuffle.png" />
</figure>
</center>
<h2 id="-46-insertion-aléatoire-"><span style="color: #FFBF00"> <strong>4.6 Insertion aléatoire</strong> </span></h2>
<p>Cette technique a été proposée par <a href="https://arxiv.org/abs/1901.11196">Wei et al.</a> dans leur article <em>Easy Data Augmentation</em>. Dans cette technique, nous choisissons d’abord un mot aléatoire dans la phrase qui n’est pas un mot d’arrêt. Ensuite, nous trouvons son synonyme et nous l’insérons dans une position aléatoire de la phrase.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/Random_insertion.png" />
</figure>
</center>
<h2 id="-47-echange-aléatoire-"><span style="color: #FFBF00"> <strong>4.7 Echange aléatoire</strong> </span></h2>
<p>Cette technique a également été proposée par Wei et al. dans leur article <em>Easy Data Augmentation</em>. L’idée est d’échanger de manière aléatoire deux mots quelconques dans la phrase.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/Swap.png" />
</figure>
</center>
<h2 id="-48-suppression-aléatoire-"><span style="color: #FFBF00"> <strong>4.8 Suppression aléatoire</strong> </span></h2>
<p>Cette technique a également été proposée par Wei et al. dans leur article <em>Easy Data Augmentation</em>. Dans ce cas, nous retirons aléatoirement chaque mot de la phrase avec une probabilité <em>p</em>.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/Deletion.png" />
</figure>
</center>
<p><br /><br /></p>
<h1 id="-5-augmentation-par-crossover-"><span style="color: #FF0000"> <strong>5. Augmentation par Crossover</strong> </span></h1>
<p>Cette technique a été introduite par <a href="https://arxiv.org/abs/1909.11241">Luque</a> dans son article sur l’analyse des sentiments pour la TASS 2019. Elle s’inspire de l’opération de <a href="https://fr.wikipedia.org/wiki/Enjambement_(g%C3%A9n%C3%A9tique)">croisement des chromosomes qui se produit en génétique</a>.
Dans cette méthode, un tweet est divisé en deux moitiés et deux tweet aléatoires ayant le même label que le tweet divisé voient leurs moitiés échangées (cf. image ci-dessous). L’hypothèse est que, même si le résultat sera peu grammatical et peu solide sur le plan sémantique, le nouveau texte préservera quand même le sentiment.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/crossover1.png" />
</figure>
</center>
<p>Les résultats de l’article montrent que cette technique n’a pas eu d’impact sur la précision mais a permis d’améliorer le F1-score, notamment pour les classes minoritaires (Neutral dans l’article).</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/crossover2.png" />
</figure>
</center>
<p><br /><br /></p>
<h1 id="-6-manipulation-de-larbre-syntaxique-"><span style="color: #FF0000"> <strong>6. Manipulation de l’arbre syntaxique</strong> </span></h1>
<p>Cette technique a été utilisée dans le papier de <a href="https://arxiv.org/abs/1812.04718">Coulombe</a>. L’idée est d’analyser et de générer l’arbre des dépendances de la phrase originale, de le transformer à l’aide de règles et de générer une phrase paraphrasée.
<br />
Par exemple, une transformation qui ne change pas le sens de la phrase est la transformation de la voix active à la voix passive de la phrase et vice versa.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/Active_voice.png" />
</figure>
</center>
<p>Dans la même logique on peut passer de singulier au pluriel une phrase et inversement, ou bien encore du masculin au féminin et inversement.
<br /><br /></p>
<h1 id="-7-le-mélange-de-texte-mixup-"><span style="color: #FF0000"> <strong>7. Le mélange de texte (MixUp)</strong> </span></h1>
<p>Le MixUp est une technique simple mais efficace d’augmentation d’images introduite par <a href="https://arxiv.org/abs/1710.09412">Zhang et al.</a> en 2017. L’idée est de combiner deux images aléatoires dans une certaine proportion dans un mini-batch afin de générer des exemples synthétiques pour l’entraînement. Pour les images, cela signifie combiner des pixels d’image de deux classes différentes. Cela agit comme une forme de régularisation pendant l’entraînement.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/Mixup1.png" />
</figure>
</center>
<p><a href="https://arxiv.org/abs/1905.08941">Guo et al.</a> ont appliqué cette idée au NLP pour travailler avec du texte. Ils proposent deux nouvelles approches pour appliquer Mixup au texte :
<br /><br /></p>
<h2 id="-71-wordmixup-"><span style="color: #FFBF00"> <strong>7.1 WordMixUp</strong> </span></h2>
<p>Dans cette méthode, deux phrases d’un mini-batch sont prises aléatoirement et dimensionnées à la même longueur. Ensuite, les mots qui les composent sont combinés dans une certaine proportion. L’enchâssement de mots qui en résulte est transmis au flux habituel pour la classification du texte. L’entropie croisée est calculée pour les deux labels du texte original dans la proportion donnée.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/Mixup2.png" />
</figure>
</center>
<h2 id="-72-sentmixup-"><span style="color: #FFBF00"> <strong>7.2 SentMixup</strong> </span></h2>
<p>Dans cette méthode, on prend deux phrases et on les met à la même longueur. Ensuite, leurs enchâssements de mots sont passés dans un encoder LSTM/ConvNet et nous prenons le dernier état caché comme enchâssement de la phrase. Ces enchâssements sont combinés dans une certaine proportion et sont ensuite transmis à la couche de classification finale. La perte d’entropie croisée est calculée sur la base des deux labels des phrases originales dans la proportion donnée.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/Mixup3.png" />
</figure>
</center>
<p><br /><br /></p>
<h1 id="-8-méthodes-génératives-"><span style="color: #FF0000"> <strong>8. Méthodes génératives</strong> </span></h1>
<p><a href="https://arxiv.org/abs/2003.02245">Kumar et al</a> proposent dans leur article d’utiliser des <em>transformers</em> pré-entrainés afin d’augmenter les données d’entraînement. La formulation du problème est la suivante :</p>
<ul>
<li>Ajouter le label de la classe à chaque texte de vos données d’entraînement</li>
</ul>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/Generative1.png" />
</figure>
</center>
<ul>
<li><em>Finetuner</em> un grand modèle de langue pré-entraîné (BERT/GPT2/BART) sur ces données d’entraînement modifiées. Pour le GPT2, la tâche est la génération tandis que pour BERT, l’objectif est la prédiction du jeton masqué.</li>
</ul>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/Generative2.png" />
</figure>
</center>
<ul>
<li>En utilisant le modèle de langage <em>finetuné</em>, de nouveaux échantillons peuvent être générés en utilisant le label de la classe et quelques mots initiaux comme « prompt ».</li>
</ul>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/Generative3.png" />
</figure>
</center>
<p><br />
Pour le français, cette méthode est difficilement applicable, c’est pourquoi je ne vous la recommande pas.
En français, il existe deux GPT2 entraînés avec un vocabulaire en français sur des données en français existant pour le moment : le <a href="https://github.com/antoiloui/belgpt2">BelGPT-2 d’Antoine Louis</a> et <a href="https://lair.lighton.ai/pagnol/">PAGnol</a> de Launay et al..
Pour le BelGPT2, quand on génère une phrase avec le modèle, celle-ci est la plupart du temps correcte. Cependant un problème apparait quand on génère plusieurs phrases : celles-ci sont individuellement correctes mais le tout devient incorrect d’un point de vue de la logique quand elles se succèdent. Le contexte passe du coq à l’âne.
Lors de quelques expérimentations, j’ai aussi pu constater que des phrases dans d’autres langues que le français étaient générées (anglais et wolof entre autres). Vous pouvez expérimenter par vous-même via l’<a href="https://huggingface.co/antoiloui/belgpt2">API d’HuggingFace</a>. Je n’ai pas eu l’occasion de faire d’expérimentations avec PAGnol. Vous pouvez le tester par vous-même via le <a href="https://pagnol.lighton.ai/">démonstrateur en ligne</a> proposé par les auteurs du modèle.<br />
Ainsi, je déconseille d’utiliser cette technique en l’état actuel. D’autres sont plus simples, plus rapides à mettre en place car ne nécessite pas de <em>finetuning</em>, sont moins lourdes (PAGnol faisant 1,5 milliard de paramètres par exemple), et donne de meilleurs résultats.
<br /><br /><br /></p>
<h1 id="-9-la-simplification-de-textes-"><span style="color: #FF0000"> <strong>9. La simplification de textes</strong> </span></h1>
<p>J’ajoute une méthode supplémentaire qu’Amit n’a pas cité dans son article : les modèles permettant la simplification de texte. Ils permettent de conserver le sens de la phrase mais avec une syntaxe différente et souvent plus courte. Deux approches sont envisageables. La première où le texte original est paraphrasé. La deuxième consiste à faire un résumé du texte original.</p>
<h2 id="-91-les-paraphrases-"><span style="color: #FFBF00"> <strong>9.1 Les paraphrases</strong> </span></h2>
<p>Pour la langue anglaise, le jeu de données <a href="https://github.com/facebookresearch/asset">ASSET</a> de <a href="https://arxiv.org/abs/2005.00352">Fernando Alva-Manchego, Louis Martin et al.</a> est disponible depuis mai 2020. Il permet de <em>finetuner</em> les modèles de simplification de texte.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Data_augmentation/ASSET.png" />
</figure>
</center>
<p>Pour la langue française, il existe le jeu de données <a href="https://alectorsite.wordpress.com/corpus/">ALECTOR</a> de <a href="https://www.researchgate.net/publication/339827111_Alector_A_Parallel_Corpus_of_Simplified_French_Texts_with_Alignments_of_Misreadings_by_Poor_and_Dyslexic_Readers">Gala et al.</a> extraits de sites proposant du matériel pédagogique pour les niveaux CE1, CE2 et CM1 de l’école primaire. Chaque texte original a été adapté (simplifié) au niveau du lexique (vocabulaire), de la morpho-syntaxe (catégories grammaticales, structures de phrase) et du discours (co-référence).<br />
Ou bien encore les données en français du jeu de données PPDB déjà cité dans la partie 1.1 de cet article.
Vous pouvez consulter également les travaux de <a href="https://arxiv.org/pdf/2005.00352.pdf">Martin et al.</a>, portant sur un outil permettant une simplification de phrases multilingues.
<br /><br /><br /></p>
<h2 id="-92-le-résumé-"><span style="color: #FFBF00"> <strong>9.2 Le résumé</strong> </span></h2>
<p>Dans cette approche, nous avons le texte original en entrée et un résumé de ce texte en sortie.
Cette approche est bien développée en anglais avec des jeux de données disponibles pour le <em>finetuning</em> (<a href="https://arxiv.org/pdf/1808.08745.pdf">XSum</a> de Narayan et al., <a href="https://papers.nips.cc/paper/2015/file/afdec7005cc9f14302cd0474fd0f3c96-Paper.pdf">CNN/DM</a> de Hermann et al.) et des modèles déjà entraînés à cette tâche (le <a href="https://arxiv.org/pdf/1910.10683.pdf">T5 de Raffel et al.</a>, <a href="https://arxiv.org/abs/1910.13461">BART de Lewis et al.</a>, etc.)
Pour l’implémentation, vous pouvez utiliser le code suivant reposant sur la fonction pipeline de la librairie Hugging Face :</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">summarizer</span> <span class="o">=</span> <span class="n">pipeline</span><span class="p">(</span><span class="s">"summarization"</span><span class="p">)</span> <span class="c1"># utilise BART par défaut
</span><span class="n">summarizer</span><span class="p">(</span><span class="s">"Sam Shleifer writes the best docstring examples in the whole world."</span><span class="p">,</span> <span class="n">min_length</span><span class="o">=</span><span class="mi">5</span><span class="p">,</span> <span class="n">max_length</span><span class="o">=</span><span class="mi">20</span><span class="p">)</span>
</code></pre></div></div>
<p>Ce qui donne :</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">Sam</span> <span class="n">Shleifer</span> <span class="n">writes</span> <span class="n">the</span> <span class="n">best</span> <span class="n">docstring</span> <span class="n">examples</span> <span class="ow">in</span> <span class="n">the</span> <span class="n">world</span>
</code></pre></div></div>
<p>Pour le français, vous pouvez utiliser la partie en français de la base de données multilingues <a href="https://arxiv.org/pdf/2004.14900.pdf">MLSUM</a> de Scialom et al. pour entraîner votre propre modèle ou bien la base <a href="https://arxiv.org/abs/2010.12321">OrangeSum</a> de Eddine et al. qui a été introduite avec leur modèle BARThez. Pour l’implémentation, vous pouvez utiliser le même code que pour l’anglais en changeant seulement le modèle et en donnant en entrée une phrase en français :</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">summarizer</span> <span class="o">=</span> <span class="n">pipeline</span><span class="p">(</span><span class="s">"summarization"</span><span class="p">,</span> <span class="n">model</span><span class="o">=</span><span class="s">"moussaKam/barthez-orangesum-abstract"</span><span class="p">,</span> <span class="n">tokenizer</span><span class="o">=</span><span class="s">"moussaKam/barthez"</span><span class="p">,)</span>
<span class="n">summarizer</span><span class="p">(</span><span class="s">"Votre texte"</span><span class="p">)</span>
</code></pre></div></div>
<p><br /><br /><br /></p>
<h1 id="-implémentation-"><span style="color: #FF0000"> <strong>Implémentation</strong> </span></h1>
<p>Les librairies Python comme <a href="https://github.com/makcedward/nlpaug">nlpaug</a> et <a href="https://github.com/QData/TextAttack">textattack</a> fournissent une API simple afin d’appliquer les méthodes ci-dessus pouvant ainsi être facilement intégrées dans un pipeline.
<br /><br /><br /></p>
<h1 id="-conclusion-"><span style="color: #FF0000"> <strong>Conclusion</strong> </span></h1>
<p>Dans la plupart des papiers liés à l’augmentation de données textuelles, les auteurs se limitent à présenter leur méthode : aucune comparaison n’est réalisée avec d’autres méthodes existantes.
Ce travail de comparaison est réalisé par Columbe dans sa <a href="https://r-libre.teluq.ca/1894/1/Th%C3%A8se_Coulombe.pdf">thèse</a> (2020). Celle-ci a été rédigée en français (application à des textes en anglais). Elle décrit bien les méthodes 1 à 7 de cet article, permettant de connaître les atouts et les limites de chacune d’elles.
Si vous avez du temps et êtes intéressés par ce sujet, je vous invite fortement à la lire (environ 200 pages).
<br /><br /><br /></p>
<h1 id="-références-"><span style="color: #FF0000"> <strong>Références</strong> </span></h1>
<ul>
<li><a href="https://arxiv.org/pdf/2005.00481.pdf">ASSET: A Dataset for Tuning and Evaluation of Sentence SimplificationModels with Multiple Rewriting Transformations</a> de Fernando Alva-Manchego, Louis Martin et al. (2020)</li>
<li><a href="https://hal.archives-ouvertes.fr/hal-02503986/document">Alector: A Parallel Corpus of Simplified French Texts with Alignments of Misreadings by Poor and Dyslexic Readers</a> de Gala et al. (2020)</li>
<li><a href="https://arxiv.org/abs/2005.00352">Multilingual Unsupervised Sentence Simplification</a> de Louis Martin et al. (2020)</li>
<li><a href="https://amitness.com/2020/05/data-augmentation-for-nlp/">A Visual Survey of Data Augmentation in NLP</a> de Amit Chaudhary (2020)</li>
<li><a href="https://r-libre.teluq.ca/1894/1/Th%C3%A8se_Coulombe.pdf">Techniques d’amplification des données textuelles pour l’apprentissage profond </a> de Claude Coulombe (2020)</li>
<li><a href="https://arxiv.org/abs/1812.04718">Text Data Augmentation Made Simple By Leveraging NLP Cloud APIs</a> de Coulombe (2018)</li>
<li><a href="https://fauconnier.github.io/#data">French Word Embeddings</a> de Fauconnier (2015)</li>
<li><a href="https://www.cis.upenn.edu/~ccb/publications/ppdb-multilingual.pdf">The Multilingual Paraphrase Database</a> de Ganitkevitch et Callison-Burch (2014)</li>
<li><a href="https://arxiv.org/abs/1905.08941">Augmenting Data with Mixup for Sentence Classification: An Empirical Study</a> de Guo et al. (2019)</li>
<li><a href="https://arxiv.org/abs/1909.10351">TinyBERT: Distilling BERT for Natural Language Understanding</a> de Jiao et al. (2019)</li>
<li><a href="https://arxiv.org/abs/2003.02245">Data Augmentation using Pre-trained Transformer Models</a> de Kumar et al. (2020)</li>
<li><a href="https://arxiv.org/abs/1909.11241">Atalaya at TASS 2019: Data Augmentation and Robust Embeddings for Sentiment Analysis</a> de Luque (2019)</li>
<li><a href="https://wordnet.princeton.edu/">WordNet: A Lexical Database for English</a> de Miller (1995)</li>
<li><a href="https://www.researchgate.net/publication/268302040_JAWS_Just_Another_WordNet_Subset">JAWS : Just Another WordNet Subset</a> de Mouton et Chalendar (2010)</li>
<li><a href="https://arxiv.org/abs/1812.00471">Global Monopole in Palatini f(R) gravity</a> de Nascimento et al. (2018)</li>
<li><a href="https://wonef.fr/">WoNeF</a> de Pradet et Baguenier-Desormeaux (2012)</li>
<li><a href="https://www.researchgate.net/publication/228809373_Construction_d'un_wordnet_libre_du_francais_a_partir_de_ressources_multilingues">Construction d’un wordnet libre du français à partir de ressources multilingues</a> de Sagot et Fiser (2008)</li>
<li><a href="https://arxiv.org/abs/1901.11196">EDA: Easy Data Augmentation Techniques for Boosting Performance on Text Classification Tasks</a> de Wei et Zou (2019)</li>
<li><a href="https://arxiv.org/abs/1703.02573">Data Noising as Smoothing in Neural Network Language Models</a> de Xie et al. (2017)</li>
<li><a href="https://arxiv.org/abs/1904.12848">Unsupervised Data Augmentation for Consistency Training</a> de Xie et al. (2019)</li>
<li><a href="https://www.aclweb.org/anthology/D15-1306.pdf">That’s So Annoying!!!: A Lexical and Frame-SemanticEmbedding Based Data Augmentation Approach to AutomaticCategorization of Annoying Behaviors using#petpeeveTweets</a> de Yang Wang et Yang (2015)</li>
<li><a href="https://arxiv.org/abs/1710.09412">mixup: Beyond Empirical Risk Minimization</a> de Zhang et al (2017)</li>
<li><a href="https://arxiv.org/abs/1509.01626">Character-level Convolutional Networks for Text Classification</a> de Zhang et al. (2015)</li>
<li><a href="https://arxiv.org/abs/1808.08745.pdf">Don’t Give Me the Details, Just the Summary!Topic-Aware Convolutional Neural Networks for Extreme Summarization</a> de Narayan et al. (2018)</li>
<li><a href="https://papers.nips.cc/paper/2015/file/afdec7005cc9f14302cd0474fd0f3c96-Paper.pdf">Teaching Machines to Read and Comprehend</a> de Hermann et al. (2015)</li>
<li><a href="https://arxiv.org/abs/1910.13461">BART: Denoising Sequence-to-Sequence Pre-training for Natural Language Generation, Translation, and Comprehension</a> de Lewis et al. (2019)</li>
<li><a href="https://arxiv.org/pdf/1910.10683.pdf">Exploring the Limits of Transfer Learning with a UnifiedText-to-Text Transformer</a> de Raffel et al. (2020)</li>
<li><a href="https://arxiv.org/abs/2004.14900.pdf">MLSUM: The Multilingual Summarization Corpus</a> de Scialom et al. (2020)</li>
<li><a href="https://arxiv.org/abs/2010.12321">BARThez: a Skilled Pretrained French Sequence-to-Sequence Model</a> de Eddine et al. (2020)
<br /><br /><br /></li>
</ul>
<h1 id="-citation-"><span style="color: #FF0000"> <strong>Citation</strong> </span></h1>
<blockquote>
<p>@inproceedings{nlp_data_augmentation_blog_post,<br />
author = {Loïck BOURDOIS},<br />
title = {L’augmentation de données en NLP},<br />
year = {2020},<br />
url = {https://lbourdois.github.io/blog/nlp/Data-augmentation-in-NLP/}<br />
}</p>
</blockquote>Loïck BOURDOISNLP - Un aperçu des techniques disponibles pour réaliser de l'augmentation de données textuelles en traitement du langage naturelILLUSTRATION D’ALBERT2020-03-12T00:00:00+00:002020-03-12T00:00:00+00:00https://lbourdois.github.io/blog/nlp/ALBERT<h1 id="-avant-propos-"><span style="color: #FF0000"> <strong>Avant-propos</strong> </span></h1>
<p>Cet article est une traduction de l’article de Amit Chaudhary : <a href="https://amitness.com/2020/02/albert-visual-summary/">Visual Paper Summary: ALBERT (A Lite BERT)</a>.
Merci à lui de m’avoir autorisé à effectuer cette traduction.
J’ai ajouté des éléments supplémentaires quand j’estimais que cela était pertinent.
<br /><br /><br /></p>
<h1 id="-introduction-"><span style="color: #FF0000"> <strong>Introduction</strong> </span></h1>
<p>Considérons une phrase donnée ci-dessous. En tant qu’humains, lorsque nous rencontrons le mot « orange », nous pourrions :</p>
<ul>
<li>associer le mot « orange » à notre représentation mentale du fruit,</li>
<li>associer « orange » au fruit plutôt qu’à l’entreprise en fonction du contexte</li>
<li>comprendre la situation globale : « Il mange une orange »
<br /></li>
</ul>
<p>Le principe de base des derniers développements en NLP est de donner aux machines la possibilité d’apprendre de telles représentations.<br /></p>
<p>En 2018, Google a publié <a href="https://www.aclweb.org/anthology/N19-1423.pdf">BERT</a> tentant d’apprendre des représentations en se basant sur quelques idées nouvelles.<br /></p>
<p>Dans cet article, nous allons succinctement rappeler ces approches pour ensuite nous focaliser sur leurs problèmes mais aussi les solutions apporter par les auteurs d’<a href="https://arxiv.org/pdf/1909.11942.pdf">ALBERT</a> afin de les résoudre.</p>
<h1 id="-1-récapitulatif-des-points-importants-de-bert-"><span style="color: #FF0000"> <strong>1. Récapitulatif des points importants de BERT</strong> </span></h1>
<h2 id="-11-modélisation-du-langage-masqué-mlm-"><span style="color: #FFBF00"> <strong>1.1 Modélisation du langage masqué (MLM)</strong> </span></h2>
<p>La modélisation du langage consiste essentiellement à prédire un mot en fonction de son contexte pour apprendre la représentation.
Traditionnellement, il s’agit de prédire le mot suivant dans une phrase donnée, compte tenu des mots.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/ALBERT/Orange.png" />
</figure>
</center>
<p><br />
BERT utilise quant à lui un modèle de langage masqué, dans lequel nous masquons aléatoirement des mots dans un document et essayons de les prédire en fonction du contexte environnant.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/ALBERT/MLM.png" />
</figure>
</center>
<p><br /><br /></p>
<h2 id="-12-prédiction-de-la-phrase-suivante-"><span style="color: #FFBF00"> <strong>1.2 Prédiction de la phrase suivante</strong> </span></h2>
<p>L’idée de la prédiction de la phrase suivante est de détecter si deux phrases sont cohérentes ou non lorsqu’elles sont placées l’une après l’autre.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/ALBERT/NSP.png" />
</figure>
</center>
<p><br />
Pour faire cela, des phrases consécutives tirées des données d’entraînement sont utilisées comme exemple positif.
Pour l’exemple négatif, nous prenons une phrase donnée et plaçons à la suite une phrase aléatoire prise dans un autre document.
Le modèle BERT est entraîné à cette tâche afin de déterminer si deux phrases peuvent être placées l’une à côté de l’autre.
<br /><br /></p>
<h2 id="-13-architecture-du-transformer-"><span style="color: #FFBF00"> <strong>1.3 Architecture du <em>transformer</em></strong> </span></h2>
<p>Pour résoudre les deux tâches ci-dessus, BERT utilise une pile de couches de blocs encodeurs du <em>transformer</em>.
Des vecteurs de mots sont passés à travers les couches pour capturer la signification et créer un vecteur de taille 768 pour le modèle de base.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/ALBERT/BERT_architecture.png" />
</figure>
</center>
<p><br />
Pour plus de détails, je vous invite à lire les articles du blog consacré au <a href="https://lbourdois.github.io/blog/nlp/Transformer/"><em>transformer</em></a> et à <a href="https://lbourdois.github.io/blog/nlp/BERT/">BERT</a>.
<br /><br /><br /></p>
<h1 id="-2-les-problèmes-de-bert-"><span style="color: #FF0000"> <strong>2. Les problèmes de BERT</strong> </span></h1>
<p>Lors de sa publication BERT a produit des résultats de pointe sur de nombreuses tâches de NLP.
Cependant ce modèle est de très grande taille, ce qui a entraîné quelques problèmes.
Le modèle ALBERT met en évidence ces problèmes dans deux catégories :</p>
<h2 id="-21-limitation-de-la-mémoire-et-coût-de-communication-"><span style="color: #FFBF00"> <strong>2.1 Limitation de la mémoire et coût de communication</strong> </span></h2>
<p>Considérons un simple réseau neuronal avec un neurone d’entrée, deux cachés et un de sortie.
En tenant compte des poids et des biais de chaque neurone, ce réseau très simple a 7 paramètres à apprendre :</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/ALBERT/NN_simple.png" />
</figure>
</center>
<p><br />
BERT-large a 340 millions de paramètres en raison de ses 24 couches cachées, des têtes d’attentions et des neurones dans le réseau <em>feed-forward</em>.
Si vous vouliez vous appuyer sur le travail effectué sur BERT et y apporter des améliorations, vous auriez besoin de grosses capacités de calcul pour l’entraîner à partir de zéro.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/ALBERT/bert-heavy-on-gpu.png" />
</figure>
</center>
<p><br />
Ces besoins de calcul concernent principalement les GPUs et les TPUs, mais ces dispositifs ont une limitation de mémoire. Il y a donc une limite à la taille des modèles.
<br />
Pour entraîner, BERT-large, les auteurs ont dû procéder à du parallélisme : les données d’entraînement ont été divisées en deux machines.
<br />
Comme le montre la figure ci-dessous, vous pouvez remarquer comment le grand nombre de paramètres à transférer lors de la synchronisation des gradients peut ralentir le processus d’entraînement. Il est également nécessaire de stocker les différentes parties du modèle (paramètres) sur différentes machines.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/ALBERT/bert-communication-overhead.png" />
</figure>
</center>
<p><br /></p>
<h2 id="-22-dégradation-du-modèle-"><span style="color: #FFBF00"> <strong>2.2 Dégradation du modèle</strong> </span></h2>
<p>La tendance récente dans la communauté des chercheurs en NLP est d’utiliser des modèles de plus en plus grands afin d’obtenir de meilleures performances. Les auteurs d’ALBERT montre que cela peut au contraire dégrader les résultats.
<br />
En effet, dans leur article, ils ont réalisé une expérience intéressante : si des modèles plus grands conduisent à de meilleures performances, pourquoi ne pas doubler les unités de la couche cachée du plus grand modèle BERT disponible (BERT-large) de 1024 unités à 2048 unités ?
<br />
Ils l’appellent BERT-xlarge. Celui-ci se révèle moins performant que le modèle BERT-large, aussi bien pour les tâches de modélisation linguistique que pour les tests de compréhension de la lecture (RACE).</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/ALBERT/bert-doubled-performance-race.png" />
</figure>
</center>
<p><br /><br /><br /></p>
<h1 id="-3-de-bert-à-albert-"><span style="color: #FF0000"> <strong>3. De BERT à ALBERT</strong> </span></h1>
<h2 id="-31-factorisation-des-enchâssements-"><span style="color: #FFBF00"> <strong>3.1 Factorisation des enchâssements</strong> </span></h2>
<h3 id="-311-la-logique-appliquée-par-les-auteurs-"><span style="color: #51C353"> <strong>3.1.1 La logique appliquée par les auteurs</strong> </span></h3>
<p>Dans BERT, la taille des enchâssements utilisés (<em>word piece embeddings</em>) est liée à la taille des couches cachées des blocs <em>transformer</em>. Les <em>word piece embeddings</em> ont été entraîné à partir de la représentation one hot d’un vocabulaire de taille 30 000 et sont projetées directement sur l’espace caché de la couche cachée.
<br />
Supposons que nous avons un vocabulaire de taille 30K, un <em>word piece embedding</em> de dimension E=768 et une couche cachée de taille H=768. Si nous augmentons les unités cachées dans le bloc, alors nous devons également ajouter une nouvelle dimension à chaque enchâssement. Ce problème se pose également pour <a href="https://arxiv.org/pdf/1906.08237.pdf">XLNET</a> et <a href="https://arxiv.org/pdf/1907.11692.pdf">ROBERTA</a>.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/ALBERT/bert-embedding.png" />
</figure>
</center>
<p><br />
ALBERT résout ce problème en factorisant la matrice des enchâssements en deux matrices plus petites. Cela permet de séparer la taille des couches cachées de la taille des embedding du vocabulaire et de passer d’une complexité O(V×H) à une complexité en O(V×E+E×H). Cette réduction a un intérêt lorsque H > > E.
<br />
Illustration : nous projetons le vecteur <em>one hot encoding</em> dans l’espace de dimension inférieure de taille E=100 et ensuite cet espace d’enchâssement dans l’espace caché H=768.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/ALBERT/embedding-decompose-albert.png" />
</figure>
</center>
<p><br />
Ainsi ce qu’il faut retenir de ce point, est que nous pouvons augmenter la taille des couches cachées sans augmenter de manière significative la taille des paramètres des enchâssements du vocabulaire.
<br /></p>
<h3 id="-312-les-résultats-"><span style="color: #51C353"> <strong>3.1.2 Les résultats</strong> </span></h3>
<p>Pour effectuer leur comparaison avec BERT, les auteurs d’ALBERT ont suivis les mêmes configurations : vocabulaire de taille 30K, entraînement sur les textes de BOOKCORPUS et Wikipédia (en anglais), limitation à des séquences de 512 <em>tokens</em>.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/ALBERT/Speedup.png" />
</figure>
</center>
<p><br />
En analysant le tableau ci-dessus, nous pouvons remarquer une importante diminution du nombre de paramètres à configuration égale (par exemple ALBERT large a 18 fois moins de paramètres que BERT large). Cette diminution s’accompagne d’une accélération du temps de calcul (à TPUs identiques).
<br /><br /></p>
<h2 id="-32-partage-des-paramètres-entre-les-couches-"><span style="color: #FFBF00"> <strong>3.2 Partage des paramètres entre les couches</strong> </span></h2>
<h3 id="-321-la-logique-appliquée-par-les-auteurs-"><span style="color: #51C353"> <strong>3.2.1 La logique appliquée par les auteurs</strong> </span></h3>
<p>BERT large a 24 couches alors que sa version de base en a 12. Plus nous ajoutons de couches, plus le nombre de paramètres augmente de manière exponentielle :</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/ALBERT/bert-parameters.png" />
</figure>
</center>
<p><br />
Pour résoudre ce problème, ALBERT utilise le concept de partage des paramètres entre les couches.
<br />
Pour illustrer cela, prenons l’exemple du modèle BERT-base à 12 couches. Au lieu d’apprendre des paramètres uniques pour chacune des 12 couches, nous n’apprenons des paramètres que pour le premier bloc, et nous réutilisons le bloc dans les 11 couches suivantes.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/ALBERT/albert-parameter-sharing.png" />
</figure>
</center>
<p><br />
Nous pouvons procéder à différents partages de paramètres. Par exemple :</p>
<ul>
<li>partager uniquement les paramètres de la couche <em>feed-forward</em> (<em>shared-FFN</em> dans le tableau ci-après),</li>
<li>partager uniquement les paramètres d’attention (<em>shared-attention</em> dans le tableau ci-après)</li>
<li>partager les paramètres de l’ensemble du bloc (<em>all-shared</em> dans le tableau ci-après).
<br /></li>
</ul>
<h3 id="-322-les-résultats-"><span style="color: #51C353"> <strong>3.2.2 Les résultats</strong> </span></h3>
<p>Par rapport aux 110 millions de paramètres de BERT-base, le modèle ALBERT ne compte alors plus que 31 millions de paramètres tout en utilisant le même nombre de couches et 768 unités cachées.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/ALBERT/albert-parameter-sharing-results.png" />
<figcaption>Pour les colonnes liées à SQuAD, le premier nombre est le F1, le second l’EM</figcaption>
</figure>
</center>
<p><br />
Vous pouvez constater que pour tous les cas où les auteurs ont procédé à un partage de paramètres, une taille d’enchâssement E=128 permet d’obtenir de meilleurs résultats qu’une taille E=768.
Ainsi dans la suite, tous les résultats indiqués correspondent à une taille E=128.</p>
<h2 id="-33-prédiciton-de-lordre-des-phrases-"><span style="color: #FFBF00"> <strong>3.3 Prédiciton de l’ordre des phrases</strong> </span></h2>
<h3 id="-331-la-logique-appliquée-par-les-auteurs-"><span style="color: #51C353"> <strong>3.3.1 La logique appliquée par les auteurs</strong> </span></h3>
<p>La prédiction de la phrase suivante (NSP pour introduit <em>Next Sentence Prediction</em>) par BERT a été spécifiquement créée pour améliorer les performances des tâches qui utilisent des paires de phrases comme l’inférence en langage naturel (NLI).
Des publications comme <a href="https://arxiv.org/abs/1907.11692">ROBERTA</a> et <a href="https://arxiv.org/abs/1906.08237">XLNET</a> ont mis en lumière l’inefficacité de la NSP et ont constaté que son impact n’était pas fiable. En éliminant la tâche de NSP, la performance de plusieurs tâches s’est améliorée.</p>
<p>ALBERT propose quant à lui une tâche alternative appelée prédiciton de l’ordre des phrases (SOP pour <em>Sentence Order Prediction</em>). L’idée clé est la suivante :</p>
<ul>
<li>Prendre deux segments consécutifs du même document comme classe positive</li>
<li>Échanger l’ordre du même segment et utiliser cela comme exemple négatif</li>
</ul>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/ALBERT/SOP.png" />
</figure>
</center>
<p><br />
Cela oblige le modèle à apprendre une distinction plus fine des propriétés de cohérence au niveau du discours.<br /></p>
<p>Les auteurs d’ALBERT affirment que la NSP est inefficace car c’est une tâche non difficile à mettre en œuvre par rapport à la modélisation masquée du langage. Elle mélange à la fois la prédiction du sujet et la prédiction de la cohérence. La partie prédiction du sujet est facile à apprendre car elle chevauche la perte du modèle de langage masqué. Ainsi, la NSP donnera des scores plus élevés même s’il n’a pas appris la prédiction de cohérence.
<br /></p>
<h3 id="-332-les-résultats-"><span style="color: #51C353"> <strong>3.3.2 Les résultats</strong> </span></h3>
<p>La SOP améliore les performances des tâches de SQUAD 1.1, 2.0, MNLI et RACE :</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/ALBERT/sop-results-albert.png" />
<figcaption>None correspond à des modèles comme XLNet- et RoBERTa, NSP à un modèle comme BERT et SOP à ALBERT. Les résultats du tableau correspondent à une configuration ALBERT-base.</figcaption>
</figure>
</center>
<p><br /><br /><br /></p>
<h1 id="-4-autres-résultats-"><span style="color: #FF0000"> <strong>4. Autres résultats</strong> </span></h1>
<h2 id="-41-comparaison-basée-sur-le-temps-dentraînement-"><span style="color: #FFBF00"> <strong>4.1 Comparaison basée sur le temps d’entraînement</strong> </span></h2>
<p>Comme un entraînement plus long entraîne généralement de meilleures performances, les auteurs ont effectué une comparaison dans laquelle, au lieu de contrôler le nombre d’étapes d’entraînement, ils ont contrôlé le temps d’entraînement. Le but étant de comparer les performances à temps d’entraînement égaux.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/ALBERT/Comparaison temporelle.png" />
</figure>
</center>
<p><br />
On peut alors constater qu’ALBERT obtient de meilleur résultat que BERT et notamment sur la base RACE.
<br /><br /></p>
<h2 id="-42-ajout-de-données-"><span style="color: #FFBF00"> <strong>4.2 Ajout de données</strong> </span></h2>
<p>Les expériences réalisées jusqu’à présent utilisent les jeux de données Wikipedia et BOOKCORPUS, comme dans BERT. Les auteurs ont testé d’ajouter les données d’entraînement supplémentaires utilisées par XLNet et RoBERTa.
<br />
Ils ont obtenu les résultats suivants :</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/ALBERT/données_supplémentaires.png" />
</figure>
</center>
<p><br />
Nous observons une amélioration des performances à l’exception des repères SQuAD (qui sont basés sur Wikipédia et sont donc affectés négativement par les données d’entraînement hors domaine).
<br />
Visuellement, cet ajout de données est observable sur la phase d’entraînement :</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/ALBERT/données_supplémentaires_graphe.png" />
</figure>
</center>
<p><br /><br /></p>
<h2 id="-43-limpact-du-dropout-"><span style="color: #FFBF00"> <strong>4.3 L’impact du <em>dropout</em></strong> </span></h2>
<p>Les auteurs ont constaté que même après un entraînement de 1 million d’étapes, leurs plus grands modèles ne se sont toujours pas adaptés à leurs données d’entraînement.
<br />
Ils ont alors décidé de supprimer le <em>dropout</em> afin d’augmenter la capacité des modèles. Le graphique ci-dessous montre que la suppression du <em>dropout</em> améliore considérablement la précision du MLM.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/ALBERT/impact_dropout.png" />
</figure>
</center>
<p><br />
Cela s’observe également lors des applications aux différentes bases de données :</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/ALBERT/impact_dropout_graphe.png" />
</figure>
</center>
<p><br />
Il existe des preuves empiriques (Szegedy et al., 2017) et théoriques (Liet al., 2019) montrant qu’une combinaison de <em>batch normalization</em> et de <em>dropout</em> peut avoir des résultats néfastes sur les réseaux de neurones convolutifs.
<br />
À la connaissance des auteurs d’ALBERT, il s’agit des premiers à montrer que le dropout peut nuire aux performances des grands modèles basés sur des <em>transformers</em>. Cependant, la structure du réseau sous-jacent d’ALBERT est un cas particulier de <em>transformer</em> et des expériences supplémentaires sont nécessaires pour voir si ce phénomène apparaît ou non avec d’autres architectures.
<br /><br /><br /></p>
<h1 id="-conclusion-"><span style="color: #FF0000"> <strong>Conclusion</strong> </span></h1>
<p>ALBERT-xxlarge a moins de paramètres que BERT-large et obtient des résultats nettement meilleurs.
Néanmoins il est plus coûteux en termes de calcul en raison de sa structure plus large.<br />
Les auteurs indiquent en conclusion de leur publication, qu’ils prévoient de travailler à accélérer l’entraînement et la vitesse d’inférence de leurs modèles avec des méthodes telles que la <em>sparse attention</em> (<a href="https://arxiv.org/pdf/1904.10509.pdf">Child et al.(2019)</a>) et la <em>block attention</em> (<a href="https://arxiv.org/pdf/1804.00857.pdf">Shen et al. (2018)</a>).
<br /></p>
<p>Pour ma part, je vous invite à aller lire la publication, notamment les <em>benchmarks</em> dans la partie 4.9 (p.9 et 10) qui sont consacrés à GLUE, SQuAD et RACE et que je n’ai pas abordé dans cet article.
L’appendix de la publication indique est également intéressante puisqu’elle aborde la configuration des hyperparamètres utilisés ainsi que l’impact du nombre de couches sur les résultats.
<br /><br /><br /></p>
<h1 id="-références-"><span style="color: #FF0000"> <strong>Références</strong> <span></span></span></h1>
<ul>
<li><a href="https://amitness.com/2020/02/albert-visual-summary/">Visual Paper Summary: ALBERT (A Lite BERT)</a> de Amit Chaudhary (2020)</li>
<li><a href="https://arxiv.org/abs/1904.10509">Generating Long Sequences with Sparse Transformers</a> de Child et al. (2019)</li>
<li><a href="https://arxiv.org/abs/1810.04805">BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding</a> de Devlin et al. (2018)</li>
<li><a href="https://arxiv.org/abs/1909.11942">ALBERT: A Lite BERT for Self-supervised Learning of Language Representations</a> de Lan et al. (2019)</li>
<li><a href="https://arxiv.org/abs/1907.11692">RoBERTa: A Robustly Optimized BERT Pretraining Approach</a> de Liu et al. (2019)</li>
<li><a href="https://arxiv.org/abs/1804.00857">Bi-Directional Block Self-Attention for Fast and Memory-Efficient Sequence Modeling</a> de Shen at al. (2018)</li>
<li><a href="https://arxiv.org/abs/1906.08237">XLNet: Generalized Autoregressive Pretrainingfor Language Understanding</a> de Yang, Dai et Al. (2019)</li>
</ul>
<p><br /><br /><br /></p>
<h1 id="-citation-"><span style="color: #FF0000"> <strong>Citation</strong> <span></span></span></h1>
<blockquote>
<p>@inproceedings{albert_blog_post,<br />
author = {Loïck BOURDOIS},<br />
title = {Illustration d’ALBERT},<br />
year = {2020},<br />
url = {https://lbourdois.github.io/blog/nlp/ALBERT}<br />
}</p>
</blockquote>Loïck BOURDOISNLP - Illustration du modèle ALBERT de Lan et al.ILLUSTRATION DU REFORMER2020-02-12T00:00:00+00:002020-02-12T00:00:00+00:00https://lbourdois.github.io/blog/nlp/Reformer<h1 id="-avant-propos-"><span style="color: #FF0000"> <strong>Avant-propos</strong> </span></h1>
<p>Cet article est une traduction de l’article de Alireza Dirafzoon : <a href="https://towardsdatascience.com/illustrating-the-reformer-393575ac6ba0">Illustrating the Reformer</a>.
Merci à lui de m’avoir autorisé à effectuer cette traduction. J’ai ajouté des éléments supplémentaires quand j’estimais que cela était pertinent.
<br /><br /><br /></p>
<h1 id="-introduction-"><span style="color: #FF0000"> <strong>Introduction</strong> </span></h1>
<p>Récemment, Google a introduit l’architecture <a href="https://ai.googleblog.com/2020/01/reformer-efficient-transformer.html">Reformer</a>,
un modèle de <em>transformer</em> conçu pour traiter efficacement de très longues séquences de données (par exemple jusqu’à 1 million de mots).
L’exécution de <em>reformer</em> nécessite une consommation de mémoire beaucoup plus faible que les <em>transformers</em> classiques et permet d’obtenir des performances impressionnantes en utilisant un seul GPU.
La publication <a href="https://arxiv.org/pdf/2001.04451.pdf"><em>Reformer : The efficient Transformer</em></a> de Kitaev, Kaiser et Levskaya sera officiellement présentée au ICLR 2020 mais est déjà actuellement disponible en <a href="https://openreview.net/forum?id=rkgNKkHtvB">open review</a>.
Le modèle <em>reformer</em> devrait avoir un impact significatif en allant au-delà des applications linguistiques (par exemple, la génération de musique, de parole, d’images et de vidéos).<br /><br /></p>
<p>Avant de poursuivre cet article, sachez que le Reformer est une version optimisée du <a href="https://arxiv.org/abs/1706.03762">Transformer</a> de Vaswani et al.
Ainsi, si vous n’êtes pas familier avec dernier lisez d’abord l’article du blog qui lui est consacré : <a href="https://lbourdois.github.io/blog/nlp/Transformer/">Illustration du transformer</a>.
<br /><br /><br /></p>
<h1 id="-1-le-reformer-à-la-rescousse-des-problèmes-du-transformer-"><span style="color: #FF0000"> <strong>1. Le <em>reformer</em> à la rescousse des problèmes du <em>transformer</em></strong> </span></h1>
<p>Les modèles de <em>transformers</em> (BERT et ses dérivés, le GPT2, etc.) donnent de bons résultats mais beaucoup de ces modèles ne peuvent être entraînés que sur de grandes plateformes de calcul industrielles et ne peuvent pas être affinés sur un seul GPU pour certaines en raison de leurs besoins en mémoire.
Par exemple, le modèle GPT-2 complet se compose d’environ 1,5 milliard de paramètres.<br />
Le <em>reformer</em> apporte une solution à ce problème en modifiant la manière dont sont effectués les calculs à plusieurs endroits du <em>transformer</em>.<br />
Regardons ces modifications plus en détails. Voici une version simplifiée du <em>transformer</em> :</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Reformer/r%C3%A9sum%C3%A9_transformer.png" />
<figcaption><center>Résumé simplifié du <i>transformer</i></center></figcaption>
</figure>
</center>
<p><br /></p>
<p>Sur le schéma ci-dessus, des logos de lunettes de 3 couleurs différentes sont présents.
Chacun de ces logos représente une partie du modèle du <em>transformer</em> que les auteurs de <em>reformer</em> ont considéré comme une source de problèmes de calcul et de mémoire :</p>
<ul>
<li>
<p>Problème 1 (lunettes rouges) : le calcul de l’attention<br />
Calculer l’attention sur des séquences de longueur L est de complexité O(L²) (à la fois temps et mémoire). Imaginez ce qui se passe si nous avons une séquence de longueur 64K.</p>
</li>
<li>
<p>Problème 2 (lunettes noires) : le nombre de couches<br />
Un modèle à N couches consomme N fois plus de mémoire qu’un modèle à une seule couche car les activations dans chaque couche doivent être stockées pour la rétropropagation.</p>
</li>
<li>
<p>Problème 3 (lunettes vertes) : la profondeur des couches <em>feed-forward</em><br />
La profondeur des couches <em>feed-forward</em> intermédiaires est souvent beaucoup plus importante que la profondeur des activations de l’attention.</p>
</li>
</ul>
<p>Le modèle <em>reformer</em> s’attaque aux trois principales sources de consommation de mémoire du <em>transformer</em> mentionnées ci-dessus et les améliore de telle sorte que le modèle <em>reformer</em> peut gérer des fenêtres contextuelles allant jusqu’à un million de mots, le tout sur un seul GPU de seulement 16Go de mémoire.
Pour cela, le modèle Reformer combine deux techniques pour résoudre les problèmes d’attention et d’allocation de mémoire : le <em>locality-sensitive-hashing</em> (LSH) pour réduire la complexité de l’attention sur de longues séquences, et les couches résiduelles réversibles pour utiliser plus efficacement la mémoire disponible.
Détaillons ces deux techniques.
<br /><br /><br /></p>
<h1 id="-2-lattention-lsh-locality-sensitive-hashing-"><span style="color: #FF0000"> <strong>2. L’Attention LSH (Locality sensitive hashing)</strong> </span></h1>
<p>Penchons-nous sur le premier problème soulevé : le calcul de l’attention.</p>
<h2 id="-21-attention-et-voisins-les-plus-proches-"><span style="color: #FFBF00"> <strong>2.1 Attention et voisins les plus proches</strong> </span></h2>
<p>En NLP, l’attention est un mécanisme qui permet au réseau de se concentrer attentivement sur différentes parties d’un contexte en fonction de leur relation avec l’étape temporelle traitée.
Il existe 3 types de mécanisme d’attention dans le modèle de <em>transformer</em> comme ci-dessous :</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Reformer/m%C3%A9chanismes_d'attention_transformer.png" />
<figcaption><center>Image provenant de la présentation de Łukasz Kaiser</center></figcaption>
</figure>
</center>
<p><br /></p>
<p>Dans le <em>transformer</em>, l’attention est calculée via le produit scalaire, formulé comme :</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Reformer/Attention%20produit%20scalaire.png" />
</figure>
<figcaption>
Pour l'ensemble de l'article nous adoptons la notation anglo-saxonne de la transposée
</figcaption>
</center>
<p><br />
D’après l’équation ci-dessus et la figure ci-dessous, on peut observer que les coûts de calcul et de mémoire de la multiplication QKᵀ sont tous deux en O(L²), qui est le principal goulot d’étranglement de la mémoire.<br /></p>
<p>Est-il nécessaire de calculer et de stocker la matrice complète QKᵀ ? La réponse est non, car nous ne sommes intéressés que par softmax(QKᵀ), qui est dominé par les éléments les plus grands d’une matrice éparse.
Par conséquent, pour chaque requête q, nous ne devons prêter attention qu’aux clés k qui sont les plus proches de q.
Par exemple, si K a une longueur de 64K, pour chaque q, nous ne pourrions considérer qu’un petit sous-ensemble des 32 ou 64 clés les plus proches.
Le mécanisme d’attention du <em>transformer</em> trouve les clés les plus proches d’une requête, mais de manière inefficace.<br /><br /></p>
<p>La première nouveauté du <em>reformer</em> vient du remplacement de l’attention via le calcul du produit scalaire par un l<em>ocality-sensitive hashing</em> (hachage sensible à la localité) que l’on résumera par la suite par LSH.
Cette transformation permet de passer d’une complexité de O(L²) à O(L log L).
<br /><br /></p>
<h2 id="-22-recherche-des-voisins-les-plus-proches-par-lsh-"><span style="color: #FFBF00"> <strong>2.2 Recherche des voisins les plus proches par LSH</strong> </span></h2>
<p><a href="https://fr.wikipedia.org/wiki/Locality_sensitive_hashing">LSH est un algorithme</a> permettant une recherche efficace et approximative des voisins les plus proches dans des ensembles de données de grandes dimensions.
L’idée principale de LSH est de sélectionner des fonctions de hachage telles que pour deux points « p » et « q », si « q » est proche de « p », alors avec une probabilité suffisante nous avons « hash(q) == hash(p) ».
<br /></p>
<h3 id="-221-lapproche-basique-"><span style="color: #51C353"> <strong>2.2.1 L’approche basique</strong> </span></h3>
<p>Le moyen le plus simple est de continuer à découper l’espace par des hyperplans aléatoires et d’ajouter sign(pᵀH) comme code de hachage de chaque point. Voyons un exemple ci-dessous :</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Reformer/LSH_m%C3%A9canisme_basique.gif" />
</figure>
</center>
<p><br />
Une fois que nous avons trouvé des codes de hachage d’une longueur souhaitée, nous divisons les points en groupes en fonction de leurs codes de hachage. Dans l’exemple ci-dessus, « a » et « b » appartiennent au même groupe puisque hash(a) == hash(b).
Maintenant, l’espace de recherche pour trouver les voisins les plus proches de chaque point se réduit considérablement, passant de l’ensemble des données au groupe auquel il appartient.
<br /></p>
<h3 id="-222-lapproche-angulaire-"><span style="color: #51C353"> <strong>2.2.2 L’approche angulaire</strong> </span></h3>
<p>Une variante de l’algorithme LSH simple, appelée LSH angulaire, projette les points sur un cercle unité qui a été divisé en régions prédéfinies, chacune avec un code distinct.
Ensuite, une série de rotations aléatoires des points définit le groupe auquel les points appartiennent.
Illustrons cela par un exemple simplifié en 2D, tiré de l’article de <em>reformer</em> :</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Reformer/LSH_m%C3%A9canisme_angulaire.gif" />
</figure>
</center>
<p>Ici, nous avons deux points qui sont projetés sur un cercle unité et tournés aléatoirement 3 fois avec des angles différents.
On peut observer qu’il est peu probable qu’ils partagent le même groupe de hachage.<br /></p>
<p>Dans l’exemple suivant, cependant, nous voyons que les deux points qui sont assez proches l’un de l’autre finiront par partager le même groupe de hachage après 3 rotations aléatoires :</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Reformer/LSH_m%C3%A9canisme_angulaire2.gif" />
</figure>
</center>
<h2 id="-23-visualisation-de-lattention-lsh-"><span style="color: #FFBF00"> <strong>2.3 Visualisation de l’attention LSH</strong> </span></h2>
<p>Si l’on se réfère à la formule d’attention standard, au lieu de calculer l’attention sur tous les vecteurs des matrices Q et K, nous faisons ce qui suit :</p>
<ul>
<li>Trouver les hachages LSH des matrices Q et K.</li>
<li>Calculer l’attention standard uniquement pour les vecteurs k et q dans les mêmes groupes de hachage.
On répète ensuite la procédure ci-dessus plusieurs fois pour augmenter la probabilité que des éléments similaires ne tombent pas dans des groupes différents (les auteurs détaillent ce calcul dans l’appendix de leur article).<br /></li>
</ul>
<p>L’animation ci-dessous illustre une version simplifiée de l’attention LSH basée sur la figure de l’article du <em>reformer</em> :</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Reformer/LSH_attention.gif" />
</figure>
</center>
<h2 id="-24-lattention-lsh-masquée-"><span style="color: #FFBF00"> <strong>2.4 L’attention LSH masquée</strong> </span></h2>
<p>Pour mettre en œuvre l’attention LSH masquée, les auteurs associent chaque vecteur requête/clé à un indice de position, réorganisent les indices de position en utilisant les mêmes permutations que celles utilisées pour trier les vecteurs requête/clé, puis utilisent une opération de comparaison pour calculer le masque.
<br /></p>
<p>Alors que calculer l’attention d’un <em>token</em> futur n’est pas autorisée, les implémentations typiques du <em>transformer</em> permettent à une position de s’occuper d’elle-même.<br />
Un tel comportement n’est pas souhaitable dans une formulation QK-partagé car le produit scalaire d’un vecteur requête avec lui-même sera presque toujours plus grand que le produit scalaire d’un vecteur requête avec un vecteur à une autre position.
Les auteurs modifient donc le masquage pour interdire à un <em>token</em> de s’occuper de lui-même, sauf dans les situations où un <em>token</em> n’a pas d’autres cibles d’attention valables (par exemple, le premier <em>token</em> d’une séquence).
<br /><br /><br /></p>
<h1 id="-3-transformer-réversible-et-découpage-"><span style="color: #FF0000"> <strong>3. <em>Transformer</em> réversible et découpage</strong> </span></h1>
<p>Regardons à présent le deuxième et le troisième problème du <em>transformer</em>, c’est-à-dire le nombre de couches d’encodeur et de décodeur, et la profondeur des couches <em>feed-forward</em>.
<br /></p>
<h2 id="-31-réseau-résiduel-réversible-revnet-"><span style="color: #FFBF00"> <strong>3.1 Réseau résiduel réversible (RevNet)</strong> </span></h2>
<p>En observant attentivement les blocs d’encodeur et de décodeur du <em>transformer</em> (la figure avec les lunettes), on se rend compte que chaque couche d’attention et chaque couche <em>feed-forward</em> est enveloppée dans un bloc résiduel (partie gauche de la figure en dessous).
Les réseaux résiduels (ResNets) présentés dans <a href="https://arxiv.org/pdf/1512.03385.pdf">cet article</a> par He et al. sont des composants puissants utilisés pour aider à résoudre le problème de la disparition du gradient dans les réseaux profonds (avec de nombreuses couches).
Cependant, la consommation de mémoire dans les ResNets est un goulot d’étranglement car il faut stocker en mémoire les activations de chaque couche afin de calculer les gradients lors de la rétropropagation.
Le coût de la mémoire est proportionnel au nombre d’unités dans le réseau.<br /></p>
<p>Pour résoudre ce problème, on peut utiliser le réseau résiduel réversible <a href="https://papers.nips.cc/paper/6816-the-reversible-residual-network-backpropagation-without-storing-activations.pdf">(RevNet)</a> de Gomez et Ren qui est composé d’une série de blocs réversibles.
Dans le Revnet, les activations de chaque couche peuvent être reconstruites exactement à partir des activations de la couche suivante, ce qui nous permet d’effectuer une rétropropagation sans stocker les activations en mémoire.
La figure ci-dessous illustre les blocs résiduels et les blocs résiduels réversibles.
Notez comment nous pouvons calculer les entrées du bloc (X₁, X₂) à partir de ses sorties (Y₁, Y₂).</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Reformer/RevNet.png" />
</figure>
</center>
<p><br /></p>
<h2 id="-32-transformer-réversible-"><span style="color: #FFBF00"> <strong>3.2 <em>Transformer</em> réversible</strong> </span></h2>
<p>Pour traiter notre deuxième problème, le <em>reformer</em> applique l’idée du RevNet au <em>transformer</em> en combinant les couches d’attention et de <em>feed-forward</em> à l’intérieur du bloc RevNet.
Dans la figure ci-dessus, F devient une couche d’attention et G la couche feed-forward et on a alors :<br />
Y₁ = X₁ + Attention(X₂),<br />
Y₂ = X₂ + FeedForward(Y₁)<br /></p>
<p>L’utilisation de couches résiduelles réversibles au lieu de couches résiduelles standard permet désormais de ne stocker les activations qu’une seule fois pendant le processus d’entraînement au lieu de N fois.
<br /><br /></p>
<h2 id="-33-découpage-"><span style="color: #FFBF00"> <strong>3.3 Découpage</strong> </span></h2>
<p>La dernière partie des améliorations apportées par le <em>reformer</em> porte sur le troisième problème, à savoir les vecteurs intermédiaires de grandes dimensions des couches <em>feed-forward</em> (pouvant aller jusqu’à des dimensions de 4000 et plus).</p>
<p>Comme les calculs des couches <em>feed-forward</em> sont indépendants entre les positions d’une séquence, les calculs des propagations avant et arrière ainsi que le calcul inverse peuvent tous être divisés en morceaux.
Par exemple pour la propagation vers l’avant on a :</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Reformer/formule.png" />
</figure>
</center>
<p><br /><br /></p>
<h1 id="-4-résultats-expérimentaux-"><span style="color: #FF0000"> <strong>4. Résultats expérimentaux</strong> </span></h1>
<p>Les auteurs ont mené des expériences sur deux tâches : la tâche de génération d’images imagenet64 (avec des séquences de longueur 12K) et la tâche de texte enwik8 (avec des séquences de longueur 64K), et ont évalué les effets des modifications sur la mémoire, la précision et la vitesse.
<br /></p>
<p>Les résultats de leur expérience ont montré que le <em>transformer</em> réversible permet d’économiser la mémoire sans sacrifier la précision :</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Reformer/reversibilit%C3%A9.png" />
</figure>
</center>
<p>Comme l’attention LSH est une approximation de l’attention totale, sa précision s’améliore à mesure que la valeur du hachage augmente. Lorsque la valeur de hachage est de 8, l’attention LSH est presque équivalente à l’attention complète (celle du <em>transformer</em>).</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Reformer/LSH_attention_res.png" />
</figure>
</center>
<p>Ils ont également démontré que l’attention du <em>transformer</em> ralentit à mesure que la longueur de la séquence augmente, tandis que la vitesse d’attention LSH reste constante, et qu’elle fonctionne sur des séquences de longueur ~100K à la vitesse habituelle sur des GPUs de 8GB :</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Reformer/attention_speed.png" />
</figure>
</center>
<p><br /></p>
<p>Le modèle final du <em>reformer</em> a donc des performances similaires à celles du modèle <em>transformer</em>, mais a montré une plus grande efficacité de stockage et une vitesse plus rapide sur les longues séquences.
<br /><br /><br /></p>
<h1 id="-conclusion-"><span style="color: #FF0000"> <strong>Conclusion</strong> </span></h1>
<p>Le <a href="https://github.com/google/trax/tree/master/trax/models/reformer">code</a> du <em>reformer</em> a été publié dans le cadre de la nouvelle bibliothèque <a href="https://github.com/google/trax/tree/master/trax/">Trax</a>.
Trax est une bibliothèque qui vise à vous permettre de comprendre l’apprentissage profond à partir de zéro.
Le code du <em>reformer</em> comprend plusieurs exemples de tâches tel que de la <a href="https://colab.research.google.com/github/google/trax/blob/master/trax/models/reformer/image_generation.ipynb">génération d’images</a> et de <a href="https://colab.research.google.com/github/google/trax/blob/master/trax/models/reformer/text_generation.ipynb">texte</a>.
<br /><br /><br /></p>
<h1 id="-références-"><span style="color: #FF0000"> <strong>Références</strong> <span></span></span></h1>
<ul>
<li><a href="https://towardsdatascience.com/illustrating-the-reformer-393575ac6ba0">Illustrating the Reformer</a> de Alireza Dirafzoon (2020)</li>
<li><a href="https://arxiv.org/abs/2001.04451">Reformer: The efficient Transformer</a> de Kitaev, Kaiser et Levskaya (2020)</li>
<li><a href="https://arxiv.org/abs/1706.03762">Attention Is All You Need</a> de Vaswani et al. (2017)</li>
<li><a href="https://arxiv.org/pdf/1512.03385.pdf">Deep Residual Learning for Image Recognition</a> de He et al. (2016)</li>
<li><a href="https://arxiv.org/abs/1707.04585">The Reversible Residual Network: Backpropagation Without Storing Activations</a> de N. Gomez, Ren et al. (2017)
<br /><br /><br /></li>
</ul>
<h1 id="-citation-"><span style="color: #FF0000"> <strong>Citation</strong> <span></span></span></h1>
<blockquote>
<p>@inproceedings{reformer_blog_post,<br />
author = {Loïck BOURDOIS},<br />
title = {Illustration du Reformer},<br />
year = {2023},<br />
url = {https://lbourdois.github.io/blog/nlp/Reformer/}<br />
}</p>
</blockquote>Loïck BOURDOISNLP - Illustration du modèle Reformer de Kitaev et KaiserLE PRETRAITEMENT ET LES TOKENIZERS EN NLP2020-01-15T00:00:00+00:002020-01-15T00:00:00+00:00https://lbourdois.github.io/blog/nlp/Les-tokenizers<script type="text/javascript" async="" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-MML-AM_CHTML"> </script>
<h1 id="-avant-propos-"><span style="color: #FF0000"> <strong>Avant-propos</strong> </span></h1>
<p>Cet article est une traduction de l’article de Keita Kurita : <a href="https://web.archive.org/web/20200330042220/https://mlexplained.com/2019/11/06/a-deep-dive-into-the-wonderful-world-of-preprocessing-in-nlp/">A Deep Dive into the Wonderful World of Preprocessing in NLP</a> (le site de Keita Kurita n’existant plus, le lien renvoie vers une version capturée par Wayback Machine).<br /> Merci à lui de m’avoir autorisé à effectuer cette traduction.
<br /><br /><br /></p>
<h1 id="-introduction-"><span style="color: #FF0000"> <strong>Introduction</strong> </span></h1>
<p>Le prétraitement est peut-être l’un des éléments les plus sous-évalués et les plus négligés en traitement du langage naturel actuellement.
En effet, si par exemple vous utilisez des <em>tranformers</em> pré-entrainés, le travail a déjà été effectué pour nous. Les publications scientifiques n’entrent d’ailleurs que très rarement dans le détail au moment d’aborder cette étape et se focalisent davantage sur le modèle développé et les résultats obtenus avec.
Malgré qu’il puisse paraître trivial, le prétraitement est subtil et extrêmement important pour obtenir de bonnes performances et prévenir les bugs (cf. cette <a href="https://arxiv.org/pdf/1804.08771.pdf">publication</a> de Matt Post).
Dans cet article, nous nous focaliserons donc sur le prétraitement en passent en revue les principales techniques de <em>tokenization</em> comme le <em>byte-pair encoding</em> (BPE), le <em>wordpiece</em> et le <em>sentencepiece</em>, ainsi que les choses auxquelles il faut faire attention.
<br /><br /><br /></p>
<h1 id="-vue-densemble-"><span style="color: #FF0000"> <strong>Vue d’ensemble</strong> </span></h1>
<p>Les modèles d’apprentissage machine nécessitent des entrées sous la forme de nombre pour pouvoir fonctionner. Le prétraitement est essentiellement le processus qui consiste à prendre un morceau de texte brut et à le convertir en nombres. Par conséquent, pour la plupart des applications, le prétraitement peut être divisé en trois étapes :</p>
<ul>
<li>Étape 1 : Normalisation (nettoyage)<br />
C’est là que nous nettoyons les données pour éliminer les entrées non désirées et pour convertir certains caractères/séquences en formes canoniques.</li>
<li>Etape 2 : Segmentation (<em>tokenization</em>)<br />
C’est là que nous divisons le flux continu de caractères en entités. C’est probablement l’étape la plus complexe du processus et est un point majeur de l’article.</li>
<li>Étape 3 : Numérisation<br />
C’est là que nous convertissons les entités textuelles en nombres/id pour pouvoir les donner à notre modèle. Bien que simple, cette étape peut introduire quelques problèmes désagréables dont nous parlerons plus tard.</li>
</ul>
<p>Notez que ces étapes ne sont pas toujours clairement divisées. Par exemple, certains <em>tokenizers</em> contiennent des étapes de normalisation et la segmentation est souvent étroitement couplée à la numérisation. Néanmoins, penser à ces étapes séparément rend les choses beaucoup plus faciles à comprendre et à expliquer, c’est pourquoi je m’en tiendrai à cette division légèrement arbitraire pour la suite.
<br /><br /><br /></p>
<h1 id="-1-étape-1--normalisation-nettoyage-"><span style="color: #FF0000"> <strong>1. Étape 1 : Normalisation (nettoyage)</strong> </span></h1>
<p>Dans le contexte du prétraitement en traitement du langage naturel, la normalisation se réfère au processus de nettoyage de l’entrée et de mise en correspondance des caractères/mots avec une forme canonique.</p>
<p>Un exemple très simple de normalisation est de mettre tous les caractères en minuscule. Cela permet d’éviter que des mots comme « Bonjour » et « bonjour » soient traités différemment. La similarité entre ces mots est claire pour un humain, mais lorsqu’ils sont simplement mis en correspondance avec un seul entier, le modèle en aval n’a aucun moyen de comprendre qu’il s’agit du même mot sous-jacent. La normalisation permet d’éviter cette divergence.</p>
<p>Voici quelques autres étapes de normalisation que vous pourriez vouloir utiliser :</p>
<ul>
<li>Gérer les caractères répétitifs (par exemple « cooooool » → « cool »)</li>
<li>Manipulation des homoglyphes (par exemple « $tupide » → « stupide »)</li>
<li>Transformation des entrées spéciales telles que les URL, les adresses e-mail et les balises HTML à une forme canonique (par exemple « https://lbourdois.github.io/blog/nlp/Les-tokenizers/ » → « [URL] »)</li>
<li>Normalisation unicode
Certains lecteurs n’ont peut-être jamais entendu parler de la normalisation unicode avant, faisons donc en un rapide aperçu. En unicode, certains caractères qui sont effectivement les mêmes peuvent être représentés de plusieurs façons. Par exemple, le caractère « ë » peut être représenté comme un seul caractère unicode (« ë » ou deux caractères unicode (le caractère « e » et un accent). La normalisation unicode fait correspondre ces deux caractères à une forme unique et canonique. Pour plus de détails vous pouvez lire ce <a href="https://withblue.ink/2019/03/11/why-you-need-to-normalize-unicode-strings.html">post</a> (en anglais).</li>
</ul>
<p>Vient maintenant la question importante : quels types de normalisation devrions-nous réellement appliquer ? Bien sûr, il n’y a pas de réponse claire à cette question, mais voici quelques lignes directrices et facteurs à prendre en considération :</p>
<ul>
<li>Quelle quantité d’informations cruciales la normalisation supprime-t-elle ? Par exemple, dans les médias sociaux, dire « HELLO » et « Hello » peut avoir des nuances différentes. En même temps, traiter différemment « Hello world » et « hello world » peut ne pas avoir beaucoup de sens. La majuscule peut indiquer une information grammaticale importante, comme le fait qu’un mot est un nom propre (par exemple, « New York »).</li>
<li>De combien de données disposez-vous ? Si vous avez beaucoup de données, vous aurez probablement besoin de moins de normalisation puisque le modèle pourrait simplement apprendre que « Hello » et « hello » sont le même mot sous-jacent à partir de leurs distributions. Si vous n’avez pas beaucoup de données alors pourriez vouloir une plus grande normalisation.</li>
<li>Une grande taille de vocabulaire est-elle préjudiciable à votre application ? Moins de normalisation tend à conduire à un vocabulaire plus important, bien que cela dépende du type de tokenisation que vous utilisez. Si vous entraînez un modèle génératif, la couche de softmax de sortie peut être un goulot d’étranglement majeur. Une taille de vocabulaire plus importante peut ralentir l’entraînement de manière significative. Cela peut aussi causer des problèmes de mémoire, pouvant nécessiter des tailles de batch plus petites, ralentissant encore plus l’entraînement.
<br /><br /><br /></li>
</ul>
<h1 id="-2-étape-2--segmentation-tokenization-"><span style="color: #FF0000"> <strong>2. Étape 2 : Segmentation (<em>tokenization</em>)</strong> </span></h1>
<p>La segmentation/tokénisation est probablement la partie la plus complexe du pipeline de prétraitement. Nous allons donc en discuter en profondeur. Nous allons d’abord passer en revue quelques algorithmes naïfs de tokenisation, puis discuter des <em>tokenizers</em> à base de règles, et enfin passer en revue des <em>tokenizers</em> de sous-mots plus modernes qui sont appris sur des données.</p>
<h2 id="-21-tokeniser-sur-les-espaces--la-ponctuation-"><span style="color: #FFBF00"> <strong>2.1 Tokeniser sur les espaces / la ponctuation</strong> </span></h2>
<p>La forme la plus naïve de tokenisation (qui est utilisée étonnamment souvent puisque certaines applications utilisent simplement la fonction string.split en Python) est le fractionnement sur les espaces. Prenons la phrase suivante comme exemple :
<br /></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>“I saw a girl with a telescope.”
</code></pre></div></div>
<p><br />
Elle est divisée en :
<br /></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>“I”, “saw”, “a”, “girl”, “with”, “a”, “telescope.”
</code></pre></div></div>
<p><br /></p>
<p>Remarquez que le point est annexé au dernier mot. Nous ne voulons probablement pas cela, puisque le mot « télescope » a la même signification qu’il soit avec un point ou non. Cette approche est donc fortement déconseillée !</p>
<p>Une approche légèrement meilleure et qui fonctionne dans bien des cas consiste à utiliser des jetons basés sur la ponctuation comme :<br /></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>“I”, “saw”, “a”, “girl”, “with”, “a”, “telescope”, “.”
</code></pre></div></div>
<p><br /></p>
<p>Cependant, cette approche présente encore de nombreux problèmes. Que faites-vous, par exemple, avec les points de suspension ? Voulez-vous une division en trois points (<code class="language-plaintext highlighter-rouge">".", ".", "."</code>) ou préférez-vous un seul jeton ? Et pour les émoticônes comme <code class="language-plaintext highlighter-rouge">:)</code> et des abréviations comme <code class="language-plaintext highlighter-rouge">U.S.A.</code> ? Il est clair que le simple fait d’utiliser des signes de ponctuation et des espaces blancs est insuffisant si nous voulons obtenir la meilleure performance, ce qui nous motive à poursuivre des méthodes de tokenisation plus complexes, basées sur des règles.
<br /><br /></p>
<h2 id="-22-tokenization-basée-sur-des-règles-"><span style="color: #FFBF00"> <strong>2.2 Tokenization basée sur des règles</strong> </span></h2>
<p>Les <em>tokenizers</em> à base de règles nous permettent de tokeniser plus intelligemment au cas par cas. Ici, couvrons deux principaux tokenizers basés sur des règles : le tokenizer <em>Spacy</em> et le tokenizer <em>Moses</em>.</p>
<h3 id="-221--spacy-"><span style="color: #51C353"> <strong>2.2.1 Spacy</strong> </span></h3>
<p>Le <em>tokenizer Spacy</em> est un <em>tokenizer</em> moderne qui est largement utilisé pour une bonne raison : il est rapide, fournit des valeurs par défaut raisonnables et est facilement personnalisable.</p>
<p><em>Spacy</em> permet à l’utilisateur de spécifier des <em>tokens</em> spéciaux qui ne seront pas segmentés ou qui seront segmentés de certaines manières spécifiques. Par exemple, si vous voulez garder les points de suspension comme un seul <em>token</em>, vous pouvez le spécifier comme une règle et celle-ci aura la priorité sur les autres opérations de division. Pour en savoir plus sur le fonctionnement du <em>tokenizer Spacy</em>, <em>Spacy</em> divise en espaces et examine ensuite chaque sous-chaîne individuelle. Il recherche d’abord les <em>tokens</em> spéciaux et quand ils ne sont pas présents, il divise certains préfixes (comme la ponctuation), puis les suffixes et les infixes.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Tokenizers/Spacy.png" />
<figcaption>Exemple de fonctionnent du <i>tokenizer Spacy</i></figcaption>
</figure>
</center>
<p>Toutes ces étapes sont personnalisables, ce qui signifie que vous pouvez adapter les règles de tokenisation à vos envies. Vous pouvez consulter la <a href="https://spacy.io/usage/linguistic-features#how-tokenizer-works">documentation officielle</a> pour obtenir les informations les plus récentes et les plus approfondies.
<br /><br /></p>
<h3 id="-222-moses-"><span style="color: #51C353"> <strong>2.2.2 Moses</strong> </span></h3>
<p>Le <em>tokenizer Moses</em> est un <em>tokenizer</em> classique qui est beaucoup plus ancien que <em>Spacy</em> et qui est largement utilisé en traduction automatique. Comparé à Spacy il est moins personnalisable. Je n’entrerai pas dans les détails concernant les spécificités du tokenizer Moses, principalement parce qu’il s’agit d’une collection de logiques complexes de normalisation et de segmentation (vous pouvez jeter un oeil à une implémentation Python <a href="https://github.com/alvations/sacremoses/blob/master/sacremoses/tokenize.py">ici</a>).</p>
<p>Le <em>tokenizer Moses</em> remplace en interne certains tokens spéciaux (par exemple des points de suspension) par des <em>tokens</em> personnalisés et est un bon exemple de la façon dont la normalisation et la tokenisation ne sont pas toujours proprement divisées.</p>
<p><em>Moses</em> fonctionne assez bien sur une langue simple, mais si vous manipulez du texte comme du texte de médias sociaux, cela peut causer des problèmes avec certaines entrées comme les émoticônes.
<br /><br /></p>
<h3 id="-223-limitations-des-tokenizers-basés-sur-des-règles-"><span style="color: #51C353"> <strong>2.2.3 Limitations des <em>tokenizers</em> basés sur des règles</strong> </span></h3>
<p>Il y a quelques problèmes avec les <em>tokenizers</em> à base de règles. Le premier est leur capacité relativement limitée à gérer efficacement les mots rares. Par exemple, le mot « structurally » est relativement rare, mais le mot « structural » est commun, ce qui nous permet de déduire le sens de « structurellement » à partir d’un mot plus fréquent. Bien sûr, nous pourrions spécifier chaque mot rare comme une règle spéciale, mais cela devient clairement beaucoup trop complexe très rapidement. Cette incapacité à segmenter les mots en composantes significatives peut être particulièrement problématique pour des langues comme l’allemand où les mots sont souvent composés en mettant ensemble de nombreuses parties indépendantes (on parle alors de langues morphologiquement riches. Cet <a href="https://www.thoughtco.com/longest-german-word-in-the-world-4061494">article</a> en anglais montre l’exemple d’un mot allemand faisant plus de 63 lettres).
Un autre problème majeur est que toutes les langues ne divisent pas les mots via des espaces blancs. Le chinois et le japonais en sont d’excellents exemples. Ces langues exigent donc des règles beaucoup plus sophistiquées ce qui signifie plus de complexité et potentiellement d’erreurs.
Il existe une classe d’algorithmes qui tentent de résoudre ces problèmes, communément appelés méthodes de <em>tokenization en subword</em>, que nous allons aborder dans la suite.
<br /><br /></p>
<h2 id="-23-3-tokénisation-en-sous-mots-subword-tokenization-"><span style="color: #FFBF00"> <strong>2.3 3. Tokénisation en sous-mots (subword Tokenization)</strong> </span></h2>
<p>Tous les algorithmes de tokenisation en sous-mots partagent l’idée fondamentale que les mots les plus fréquents devraient recevoir des identificateurs uniques, alors que les mots moins fréquents devraient être décomposés en sous-mots qui conservent le mieux leur signification. Par exemple, nous pouvons vouloir retenir le mot « wonderfully” comme un seul mot puisqu’il apparaît souvent dans notre jeu de données et que nous pouvons nous attendre à ce que le modèle en apprenne la signification. D’autre part, nous pouvons vouloir diviser « structurally » en « structural » et « ly » puisque « structurally » est peu courant et que nous voulons aider le modèle en lui donnant de l’information sur sa composition.
Nous allons passer en revue quatre algorithmes majeurs de tokenisation en sous-mots : le <em>byte-pair encoding</em> (BPE), le <em>wordpiece</em>, l’<em>unigram language model</em>, et le <em>sentencepiece</em>.
<br /><br /></p>
<h3 id="-231-le-byte-pair-encoding-bpe-"><span style="color: #51C353"> <strong>2.3.1 Le <em>Byte-Pair Encoding</em> (BPE)</strong> </span></h3>
<p>Le <em>Byte-pair encoding</em> (BPE) pour sous-mots a été proposée dans cette <a href="https://arxiv.org/pdf/1508.07909.pdf">publication</a> par Sennrich, Haddow et Birch. L’idée de base (qui est un algorithme de compression) existe néanmoins depuis 1994. Ce n’est pas une coïncidence si le BPE tire ses racines du domaine de la théorie de l’information et de la compression. L’idée de représenter des mots fréquents avec moins de symboles, et des mots moins fréquents avec plus de symboles est exactement l’idée derrière de nombreux schémas d’encodage tels que l’encodage de Huffman. Le BPE applique simplement les mêmes principes et techniques de façon intelligente à la tokenization.
BPE est un algorithme de tokenisation ascendante de sous-mots qui apprend un vocabulaire de sous-mots d’une certaine taille (la taille du vocabulaire étant un hyperparamètre). L’idée de base est la suivante :</p>
<ol>
<li>
<p>Commencez par diviser tous les mots en caractères unicode. Chaque caractère unicode correspond à un symbole dans le vocabulaire final. Nous commencerons avec ce vocabulaire minimal et l’élargirons progressivement.</p>
</li>
<li>
<p>Tant qu’il reste de la place dans le vocabulaire, faites ce qui suit :</p>
<ol>
<li>Trouvez le symbole bigramme le plus fréquent (paire de symboles)</li>
<li>Fusionnez ces symboles pour créer un nouveau symbole et ajoutez-le au vocabulaire. Ceci augmente la taille du vocabulaire de 1.
<br /></li>
</ol>
</li>
</ol>
<p>Pour illustrer cela, prenons un exemple. Supposons que nous ayons les mots « bed », « ted », « sad », « beds » et « mad » à partir desquels nous voulons construire un vocabulaire BPE de taille 10. Nous commençons avec le vocabulaire minimal et les mots segmentés en caractères individuels.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Tokenizers/bpe1.png" />
</figure>
</center>
<p>Le symbole bigramme le plus fréquent est « ed » qui apparaît 3 fois. Nous les fusionnons donc et ajoutons un nouveau symbole au vocabulaire.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Tokenizers/bpe2.png" />
</figure>
</center>
<p>Le symbole suivant le plus fréquent (à égalité avec 2 apparitions) est « ad ». Nous les fusionnons et ajoutons le nouveau symbole au vocabulaire une fois de plus. Cela porte la taille du vocabulaire à 9.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Tokenizers/bpe3.png" />
</figure>
</center>
<p>Enfin, nous fusionnons « b » et « ed » car cette paire de symboles apparaît également deux fois, ce qui porte la taille du vocabulaire à 10 et met fin à notre construction de vocabulaire. La segmentation qui en résulte est ce que nous utiliserons pour la tokenisation en utilisant notre modèle BPE appris.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Tokenizers/bpe4.png" />
</figure>
</center>
<p>Bien sûr, nous voulons faire la distinction entre « ed » comme un seul mot et le suffixe « ed », donc en réalité nous représenterions le suffixe comme « ##ed ». (Si ce symbole « ## » préfixé vous semble familier, c’est parce que de nombreux modèles modernes pré-entrainés utilisent la tokenisation de sous-mots ; en d’autres termes, si vous voyez vos entrées tokénisées de cette façon, il est probable qu’il y ait une tokenisation en sous-mots qui se déroule quelque part dans les coulisses).</p>
<p>L’exemple ci-dessus utilise des mots individuels, ce qui soulève la question suivante : que se passe-t-il lorsque nous utilisons des phrases entières ? Une des caractéristiques délicates du BPE est qu’il commence par tokeniser l’entrée et ne fusionne que les bigrammes de symboles dans un seul <em>token</em>. C’est pour l’efficacité du calcul, puisque trouver le bigramme le plus fréquent est une opération coûteuse (s’il y a N symboles, c’est une opération O(N²)).
Une autre question que vous pourriez vous poser est de savoir ce qui se passe si nous rencontrons un caractère unicode inédit dans le vocabulaire. Il existe plusieurs solutions à ce problème. L’une d’entre elles consiste simplement à associer des caractères invisibles à un token « unk » (pour inconnu). Une autre est d’allouer un id à chaque caractère unicode possible même si nous ne le rencontrons pas dans le texte (ce n’est clairement pas réaliste et c’est plus pour le plaisir de l’argumentation).</p>
<p>Une approche intelligente proposée par l’équipe d’Open AI dans son <a href="https://d4mucfpksywv.cloudfront.net/better-language-models/language_models_are_unsupervised_multitask_learners.pdf">article sur le GPT-2</a> est de traiter l’entrée comme une séquence d’octets au lieu de caractères unicode et d’attribuer un identifiant à chaque octet possible. Puisque les caractères unicode sont représentés par un nombre variable d’octets, même si nous rencontrons un tout nouveau caractère, nous pouvons le décomposer en ses octets constitutifs dans le pire des cas, empêchant ainsi l’apparition de <em>tokens</em> inconnus.
<br /><br /></p>
<h3 id="-232-wordpiece-"><span style="color: #51C353"> <strong>2.3.2 <em>Wordpiece</em></strong> </span></h3>
<p>Peut-être le plus célèbre en raison de son utilisation dans BERT, <em>wordpiece</em> est un autre algorithme de tokenisation en sous-mots largement utilisé. L’algorithme (décrit dans la <a href="https://static.googleusercontent.com/media/research.google.com/ja//pubs/archive/37842.pdf">publication</a> de Schuster et Kaisuke) est en fait pratiquement identique à BPE. La seule différence est qu’au lieu de fusionner le bigramme de symbole le plus fréquent, le modèle fusionne le bigramme qui, une fois fusionné, augmenterait la probabilité d’un modèle de langage unigramme entrainé sur les données d’entraînement.
<br /></p>
<p>Attention. Ici et jusqu’à la fin de cette section 2.3.2, je traduis ce que l’auteur de l’article original à compris de cette méthode. En effet, il précise qu’il n’a pas trouvé de code source d’une implémentation de cette méthode et n’a donc pas pu la décortiquer en entier. Il explique donc ce qu’il a compris mais précise qu’il n’exclut pas de s’être tromper en absence de code pour confirmer ou infirmer ses explications.</p>
<p>Si son raisonnement est correct, cela signifie qu’en plus de la fréquence du bigramme, la fréquence des symboles originaux qui constituent le bigramme est également prise en compte. Le logarithme de la probabilité d’une phrase dans un modèle de langage unigramme (en supposant l’indépendance entre les mots d’une phrase) est simplement la somme des logarithmes des fréquences des symboles qui la composent. Cela signifie que la fusion de deux symboles augmentera le logarithme de la probabilité totale du symbole fusionné et la diminuera le logarithme de la probabilité des deux symboles originaux.
En supposant que nous fusionnons les symboles x et y, l’augmentation du logarithme de la probabilité est :</p>
\[\log p(x,y) - \log p(x) - \log p(y) = \log \displaystyle \frac{\log p(x) }{\log p(x) \log p(y) }\]
<p>De nouveau, si le raisonnement est correct, ceci est donc équivalent à l’information mutuelle entre deux symboles, donc <em>wordpiece</em> peut être considéré comme une variante de BPE qui fusionne sur la base de l’information mutuelle au lieu de la fréquence.<br />
<a href="https://arxiv.org/pdf/1907.11692.pdf">RoBERTa</a> est une version « optimisée » de BERT. Dans leur publication, les auteurs utilisent BPE au lieu du <em>wordpiece</em> de BERT et ont trouvé que cette décision ne faisait pas une grande différence.
<br /><br /></p>
<h3 id="-233-unigram-language-model-"><span style="color: #51C353"> <strong>2.3.3 <em>Unigram Language Model</em></strong> </span></h3>
<p>L’algorithme de tokenization de l’<em>unigram language model</em> a été proposé à l’origine dans cet <a href="https://arxiv.org/pdf/1804.10959.pdf">article</a> par Taku Kudo. Bien qu’il utilise des principes similaires aux méthodes décrites précédemment, il est en fait entraîné très différemment dans la pratique.</p>
<p>L’idée de base de ce <em>tokenizer</em> est d’entraîner un modèle de langage en unigramme, en supposant que tous les mots se produisent indépendamment les uns des autres. Il utilise ensuite ce modèle pour trouver la segmentation la plus probable de chaque mot. L’avantage de cette méthode est qu’elle utilise un modèle probabiliste, ce qui signifie qu’en plus de trouver la segmentation la plus probable, vous pouvez échantillonner des segmentations à partir d’une distribution de probabilités. Ceci est utilisé dans une méthode d’augmentation des données abordée plus loin dans la partie 3 de l’article.</p>
<p>La différence entre cette méthode et le <em>wordpiece</em> est que le <em>wordpiece</em> maximise la probabilité d’un modèle linguistique unigramme en fusionnant les symboles. Cela est possible car <em>wordpiece</em> ne fait pas directement référence au modèle de langue, ce qui rend la segmentation indépendante de celui-ci.</p>
<p>Dans le <em>tokenizer</em> de l’<em>unigram language model</em>, la segmentation dépend du modèle de langue. Cela crée une dépendance cyclique : pour entraîner un modèle de langue, nous devons compter la fréquence de tous les mots d’un vocabulaire, ce qui nécessite de savoir comment segmenter le texte dans le corpus d’entraînement en premier lieu. Mais pour savoir comment segmenter le texte dans le corpus d’entraînement, nous avons besoin du modèle de langue !
Pour gérer cette dépendance cyclique, le modèle de langue unigramme est entraîné selon le processus suivant :</p>
<ol>
<li>Initialiser un grand vocabulaire provisoire. Ce vocabulaire pourrait être construit en utilisant un simple tokenizer à base de règles.</li>
<li>Entraîner le modèle de langage unigramme en utilisant l’<a href="https://fr.wikipedia.org/wiki/Algorithme_esp%C3%A9rance-maximisation">algorithme EM</a>.</li>
<li>Réduire la taille du vocabulaire en supprimant les symboles qui contribuent le moins à la probabilité globale du modèle de langage sur l’ensemble d’apprentissage.</li>
<li>Répétez les étapes 2 à 4 jusqu’à ce que la taille du vocabulaire soit suffisamment réduite.
L’<em>unigram language model</em> prend également soin de conserver les caractères individuels pour minimiser la probabilité de <em>tokens</em> hors du vocabulaire.
<br /><br /></li>
</ol>
<h3 id="-234-sentencepiece-"><span style="color: #51C353"> <strong>2.3.4 Sentencepiece</strong> </span></h3>
<p>Toutes les méthodes que nous avons étudiées jusqu’à présent nécessitent une forme de prétokenisation. Vous remarquerez que cela ne résout pas l’un des problèmes que nous avons exposés au début : toutes les langues ne peuvent pas être facilement tokenizées, en particulier celles qui ne sont pas séparées par des espaces. C’est un problème particulièrement épineux pour les applications multilingues, car cela signifie que vous devez potentiellement utiliser un <em>token</em> séparé pour chaque langue que vous traitez.</p>
<p>Un autre problème créé par la prétokenisation est qu’elle rend la détokenisation impossible dans certains cas. Par exemple, si un <em>tokenizer</em> se divise sur les espaces et la ponctuation, il va tokeniser les phrases :
<br /></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>I like natural language processing
</code></pre></div></div>
<p><br />
et
<br /></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>I &nbsp;&nbsp;&nbsp; like &nbsp;&nbsp;&nbsp; natural &nbsp;&nbsp;&nbsp; language &nbsp;&nbsp;&nbsp; processing
</code></pre></div></div>
<p><br />
de la même manière, ce qui signifie que nous ne pouvons pas récupérer la forme de la phrase originale.
<br /></p>
<p><a href="https://arxiv.org/pdf/1808.06226.pdf"><em>Sentencepiece</em></a> résout les deux problèmes en traitant l’entrée comme un flux brut de caractères unicode. Il utilise ensuite soit le codage BPE, soit le codage de l’<em>unigram language model</em> au niveau des caractères pour construire le vocabulaire approprié. Cela signifie que les espaces sont inclus dans la tokenisation. Par exemple, avec l’<em>unigram language model</em>, <code class="language-plaintext highlighter-rouge">I like natural language processing</code> peut être tokénissé comme
<br /></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>“I”, “_like”, “_natural”, “_lang”, “uage”, “_process”, “ing”
</code></pre></div></div>
<p><br />
où le caractère espace est remplacé par le trait de soulignement (“ _ “) pour plus de clarté.
<br />
Notez la distinction avec BPE, où la séquence ci-dessus avec les mêmes sous-mots est tokénisée par
<br /></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>“I”, “like”, “natural”, “lang”, “##uage”, “process”, “##ing”
</code></pre></div></div>
<p><br /></p>
<p>où les sous-mots sont précédés d’un marqueur spécial.
L’ajout de sous-mots avec un marqueur spécial n’a de sens qu’avec un modèle de prétokenisation, puisque <em>sentencepiece</em> ne connaît pas les limites des mots.
Maintenant, vous vous demandez peut-être pourquoi <em>sentencepiece</em> peut se permettre de traiter l’entrée comme un seul flux de caractères alors que nous avons établi plus tôt que trouver le symbole bigramme le plus fréquent est une opération d’un coût prohibitif avec BPE. La raison est que <em>sentencepiece</em> utilise un algorithme basé sur une file d’attente prioritaire, réduisant le temps d’exécution asymétrique de O(N²) à O(NlogN).
<br />
Notez également que <em>sentencepiece</em> permet en fait l’utilisation de la prétokenisation (dans ce cas, il devient essentiellement le même que le BPE/l’<em>unigram language model</em>).<br />
Un point où il faut être vigilant est que <em>sentencepiece</em> applique une certaine normalisation unicode en interne (il utilise la normalisation unicode NFKC par défaut). Ceci peut être personnalisé, donc si vous avez besoin de règles de normalisation personnalisées qui sont en contradiction avec la normalisation NFKC, alors vous devriez regarder cette fonctionnalité.
<br /><br /></p>
<h3 id="-235-limitations-des-subword-tokenizers-"><span style="color: #51C353"> <strong>2.3.5 Limitations des Subword Tokenizers</strong> </span></h3>
<p>Comme les <em>tokenizers</em> de sous-mots sont appris à partir de données, la qualité et la quantité des données sont cruciales pour obtenir de bonnes performances. Lorsque vous n’avez pas beaucoup de données, il peut être préférable d’utiliser un <em>tokenizer</em> basé sur des règles, tout comme les systèmes basés sur des règles peuvent être meilleurs que les systèmes basés sur l’apprentissage machine lorsque les données sont rares.<br />
Un autre problème avec certains <em>tokenizers</em> en sous-mots qui fonctionnent sur des flux de caractères/octets est qu’ils peuvent allouer de l’espace de vocabulaire à de multiples variations d’un même mot (par exemple « chien », « chien ! », « chien ? »). Pour éviter cela, les auteurs du GPT-2 proposent d’empêcher la fusion entre différents types de caractères (par exemple les caractères et la ponctuation) à l’exception des espaces.<br />
Un autre facteur à prendre en compte est que l’apprentissage d’un <em>tokenizer</em> est beaucoup plus coûteux que la tokenization réelle et peut être assez intensif en mémoire et coûteux en calcul puisqu’il doit garder les données en mémoire pour un comptage et une génération rapide de statistiques. Par conséquent, même si vous avez des téraoctets de données pour apprendre un modèle de phrase, cela peut ne pas être possible de tout utiliser.
<br /><br /><br /></p>
<h1 id="-3-étape-3--numérisation-"><span style="color: #FF0000"> <strong>3. Étape 3 : Numérisation</strong> </span></h1>
<p>Une fois que nous avons les données tokénisées, la construction du vocabulaire semble relativement simple. En particulier pour les méthodes comme <em>BPE</em> et <em>sentencepiece</em>, le vocabulaire est construit automatiquement. Donc, fin de l’histoire, n’est-ce pas ? Eh bien, pas tout à fait. Il y a encore pas mal de questions auxquelles nous devons réfléchir.
<br /><br /></p>
<h2 id="-31-manipulation-des-entrées-inconnues-"><span style="color: #FFBF00"> <strong>3.1 Manipulation des entrées inconnues</strong> </span></h2>
<p>Dans l’ensemble de test ou dans les données futures, nous pouvons rencontrer des caractères que nous n’avons pas rencontrés dans l’ensemble d’entraînement. Comme la plupart des <em>frameworks</em> de NLP modernes gèrent ces caractères inconnus en coulisses, cela peut conduire à des bugs insidieux dans votre code. Il est alors conseillé de vérifier périodiquement quels types de mots sont traités comme inconnus.
L’utilisation de l’encodage d’Open AI qui s’effectue au niveau de l’octet peut légèrement résoudre ce problème, mais même avec l’encodage au niveau de l’octet, vous rencontrerez des caractères qui n’ont jamais été trouvés dans le jeu d’entraînement. Cela signifie que l’enchâssement de ces caractères sera le même que lorsqu’ils ont été initialisés et donc probablement très différent de la distribution des enchâssements entrainés. Le simple fait que vous ayez un identifiant pour les caractères non vus ne signifie pas que votre modèle peut ou a appris à les manipuler, vous devez donc faire attention à ne pas vous laisser bercer par un faux sentiment de sécurité.
<br /><br /></p>
<h2 id="-32-gestion-du-vocabulaire-"><span style="color: #FFBF00"> <strong>3.2 Gestion du vocabulaire</strong> </span></h2>
<p>Un décalage entre le vocabulaire utilisé pour coder le jeu d’entraînement et celui du jeu de test est une erreur étonnamment courante. Cela peut se produire particulièrement facilement lorsque vous reconstruisez périodiquement le vocabulaire, ce qui peut être inévitable dans des domaines comme les médias sociaux où la distribution de la langue peut changer rapidement.
S’assurer que chaque modèle est explicitement lié à un ensemble de vocabulaire est une façon d’éviter ce problème. Un autre moyen est d’assurer la rétrocompatibilité entre les différents vocabulaires de sorte que les mots qui sont dans les deux vocabulaires soient toujours associés au même identifiant. Cependant, empêcher le vocabulaire d’exploser en taille et de manipuler des <em>tokens</em> inconnus devient un problème dans cette approche. Une autre solution (qui est utile dans d’autres contextes également) est d’utiliser des vocabulaires ouverts, décris dans le prochain paragraphe.
<br /><br /></p>
<h2 id="-33-vocabulaires-ouverts-"><span style="color: #FFBF00"> <strong>3.3 Vocabulaires ouverts</strong> </span></h2>
<p>Les vocabulaires ouverts sont essentiellement des paramètres où vous ne préconstruisez pas un vocabulaire mais où vous associez plutôt des <em>tokens</em> à des ids à la volée.</p>
<p>C’est particulièrement utile dans les situations où vous devez gérer des flux de texte continus et où l’actualisation du vocabulaire est coûteuse et sujette à erreur.
Les vocabulaires ouverts utilisent l’astuce du hachage, une méthode intelligente de numérisation qui fait correspondre les <em>tokens</em> aux ids en fonction de leurs valeurs de hachage. Par exemple, avec un id maximum de 100 000, vous pouvez utiliser une simple fonction de hachage (comme le hachage md5) pour transformer toute séquence de caractères unicode (ou d’octets) en un entier compris entre 0 et 100 000. Ce serait l’id du <em>token</em>. Puisque le vocabulaire est déterminé uniquement par la fonction de hachage, il n’a jamais besoin d’être reconstruit.</p>
<center>
<figure class="image">
<img src="https://raw.githubusercontent.com/lbourdois/blog/master/assets/images/Tokenizers/hachage.png" />
</figure>
</center>
<p>Cette approche simple a le problème évident des collisions de hachage : un seul identifiant pourrait correspondre à plusieurs tokens ayant des significations très différentes. La probabilité que cela arrive (étant donné une taille de vocabulaire suffisamment importante) est cependant extrêmement faible, d’autant plus que la plupart des mots sont très peu fréquents (les fréquences des mots obéissent typiquement à la <a href="https://fr.wikipedia.org/wiki/Loi_de_Zipf">loi de Zipf</a> qui stipule que la fréquence d’un mot est à peu près inversement proportionnelle à son classement en termes de fréquence). Par conséquent, pour certaines applications, quelques collisions de hachage pourraient être un petit prix à payer pour la simplicité d’un vocabulaire ouvert.
<br /><br /></p>
<h2 id="-34-surentraînement-du-vocabulaire-au-jeu-dentraînement-"><span style="color: #FFBF00"> <strong>3.4 Surentraînement du vocabulaire au jeu d’entraînement</strong> </span></h2>
<p>Une illustration du surentraînement du vocabulaire est la suivante. Imaginons la création d’un vocabulaire utilisant tous les mots du jeu d’entraînement sans en limiter la taille. Dans ce cas, tous les mots que le modèle verra pendant l’entraînement auront un identifiant unique associé à celui-ci. Cela signifie que le modèle ne rencontrera jamais un mot inconnu et n’apprendra donc jamais à le manipuler. Par conséquent, lorsque nous lui donnerons le jeu de test (qui contiendra très probablement des mots inconnus auparavant), il aura probablement de mauvaises performances sur les exemples avec des mots nouveaux. Comparons cela avec l’entraînement du vocabulaire sur un ensemble de validation. Dans ce cas, le modèle devrait apprendre à traiter les mots de l’ensemble d’entraînement qui ne sont pas dans le vocabulaire, peut-être en déduisant leur signification ou en les ignorant.</p>
<p>Cela peut aussi se produire dans le cas d’algorithmes comme le <em>BPE</em>, même s’il n’y a pas de <em>tokens</em> inconnus : le vocabulaire sera ajusté sur les fréquences du jeu d’entraînement, donc tous les <em>tokens</em> que le modèle voit pendant l’entraînement ont une fréquence artificiellement élevée. Cela peut faire que des mots qui ne sont pas courants en général ne soient pas tokenisés, ce qui empêche le modèle d’apprendre à utiliser efficacement les sous-mots.</p>
<p>Une solution potentielle à cela est d’entraîner un <em>tokenizer</em> en sous-mots sur un énorme corpus non labélisé afin qu’il puisse extraire des sous-mots pertinents pour la langue dans son ensemble et non pour un jeu de données particulier. C’est probablement la meilleure approche si vous avez suffisamment de données non étiquetées.
Lorsque vous n’avez pas assez de données non étiquetées, il y a quelques approches que vous pouvez effectuer. L’une d’elles consiste à utiliser le jeu d’entraînement pour entraîner votre <em>token</em> et votre vocabulaire et à espérer que tout ira bien. Une autre est d’utiliser un échantillon du jeu d’entraînement pour entraîner le <em>token</em> et le vocabulaire de sorte que le modèle rencontre des <em>tokens</em> inconnus avec une certaine probabilité. Vous pouvez également définir un seuil pour le vocabulaire afin que les mots ne reçoivent un identifiant unique que s’ils dépassent une certaine fréquence. Notez que cela suppose que la distribution des nouveaux mots dans le jeu de test reflétera la distribution des mots à faible fréquence dans le jeu d’entraînement, une hypothèse qui n’est pas toujours vraie.
<br /><br /></p>
<h2 id="-35-changement-des-vocabulaires-préfabriqués-"><span style="color: #FFBF00"> <strong>3.5 Changement des vocabulaires préfabriqués</strong> </span></h2>
<p>Malgré toute la discussion ci-dessus sur la façon de gérer et de construire des vocabulaires, dans certains cas, nous n’avons même pas notre mot à dire sur le vocabulaire. Par exemple, si nous utilisons BERT, nous sommes la plupart du temps coincés avec le vocabulaire que les auteurs nous ont donné. Cela peut être un problème, par exemple, si nous voulons réduire la taille du vocabulaire pour tronquer la matrice d’enchâssement afin que le modèle tienne sur un téléphone.
Cet <a href="https://arxiv.org/pdf/1909.11687.pdf">article</a> propose une approche intéressante pour résoudre ce problème. Il utilise une approche élève-enseignant (<em>student-teacher</em>) pour distiller un modèle enseignant, et entraine un modèle élève avec un vocabulaire réduit en donnant au modèle enseignant un mélange d’entrées tokénisées par le modèle élève et le modèle enseignant. Cette idée de mélanger les vocabulaires de l’élève et de l’enseignant est intéressante et semble être une idée qui mérite d’être explorée en dehors de la simple compression du modèle.
<br /><br /><br /></p>
<h1 id="-4-divers-"><span style="color: #FF0000"> <strong>4. Divers</strong> </span></h1>
<p>Terminons par quelques points non classables dans les parties précédentes.
<br /><br /></p>
<h2 id="-41-filtrage-des-données-de-faible-qualité-"><span style="color: #FFBF00"> <strong>4.1 Filtrage des données de faible qualité</strong> </span></h2>
<p>Jusqu’à présent, nous avons discuté de la façon de traiter les données quand vous avez déjà un jeu de données en place. Cependant, parfois, vous devez effectuer un filtrage supplémentaire avant/pendant la construction du jeu de données. Par exemple, si vous voulez entraîner un modèle de langage basé sur un grand corpus, vous pouvez utiliser les données de Twitter. Cependant, les données de Twitter peuvent être très bruitées, contenant du charabia, du contenu dupliqué, d’autres langues et d’autres données de mauvaise qualité/non pertinentes que vous voulez exclure. <br />
Cet <a href="https://arxiv.org/pdf/1911.00359.pdf">article</a> de G.Wenzek, M-A. Lachaux et al., traite de diverses préoccupations et méthodes concernant la construction de corpus monolingues de haute qualité pour diverses langues à l’aide de données Common Crawl. Leurs principales étapes de prétraitement comprennent la déduplication des documents à l’aide du hachage, la détection de la langue et le filtrage du contenu en fonction de leur score de perplexité sur un modèle linguistique.
<br /><br /></p>
<h2 id="-42-preprocessing-comme-augmentation-de-données-"><span style="color: #FFBF00"> <strong>4.2 <em>Preprocessing</em> comme augmentation de données</strong> </span></h2>
<p>Le fait que les décisions de prétraitement sont quelque peu arbitraires et peuvent causer du bruit peut en fait être utilisé à notre avantage. Par exemple, un modèle qui est entrainé sur des données d’entrée entièrement en minuscules et un modèle qui est entrainé avec du surajustements peuvent être assemblés efficacement. Keita Kurita (l’auteur de l’article dont fait l’objet cette traduction) a utilisé cette technique pour se classer dans le top <a href="http://mlexplained.com/2019/04/01/tricks-and-lessons-learned-from-getting-into-the-top-1-of-a-kaggle-competition/">1% d’une compétition Kaggle</a>. Dans certains concours Kaggle de NLP, l’assemblage de plusieurs modèles en utilisant différentes étapes de prétraitement a été la clé de la victoire.
L’idée d’utiliser le prétraitement comme augmentation des données est explorée dans cet <a href="https://arxiv.org/abs/1804.10959">article</a> de Taku Kudo où l’auteur utilise un modèle de langage unigramme pour échantillonner des tokenisations légèrement différentes du même texte.
<br /><br /></p>
<h2 id="-43-stemming-et-lemmatization-"><span style="color: #FFBF00"> <strong>4.3 <em>Stemming</em> et <em>Lemmatization</em></strong> </span></h2>
<p>Le <em>stemming</em> et la <em>lemmatization</em> sont des formes extrêmes de normalisation qui ne sont généralement pas rentables en traitement du langage moderne (depuis l’apparition des <em>transformers</em>). La plupart des problèmes que le <em>stemming</em> et la <em>lemmatization</em> adressent peuvent être résolus en utilisant des sous-mots symboliques, il n’y a donc tout simplement aucune raison d’utiliser ces étapes de prétraitement.
<br /><br /><br /></p>
<h1 id="-conclusion-"><span style="color: #FF0000"> <strong>Conclusion</strong> </span></h1>
<p>Résumons l’article avec les principaux points évoqués :</p>
<ul>
<li>Utilisez l’unicode. Cela permet de gérer à peut prêt toutes les langues.</li>
<li>Si vous utilisez un <em>transformer</em>, assurez-vous que votre prétraitement correspond à celui utilisé par le modèle.</li>
<li>Inspectez toujours manuellement vos entrées prétraitées. Vous serez surpris du nombre de bugs que vous pouvez attraper.</li>
<li>La normalisation est la première étape du prétraitement, et une considération majeure à cette étape est la quantité de données que vous avez. Plus vous avez de données, moins vous avez besoin de normalisation.</li>
<li>Les <em>tokenizers</em> à base de règles sont un bon point de départ pour de nombreuses langues mais peuvent être difficiles à mettre à l’échelle.</li>
<li>Les <em>tokenizers</em> en sous-mots apprennent les segmentations qui divisent les mots rares en sous-mots significatifs. Ils sont appris à partir de données et sont généralement efficaces pour traiter les mots rares et les langues riches comme l’allemand.</li>
<li>Les <em>tokenizers BPE</em>, <em>wordpiece</em>, et <em>unigram language model</em> ont besoin d’une précréation. <em>Sentencepiece</em> n’en a pas besoin.</li>
<li>La construction du vocabulaire comporte de nombreuses subtilités. En particulier, faites attention au surentraînement avec les données d’entraînement.
<br /><br /><br /></li>
</ul>
<h1 id="-références-"><span style="color: #FF0000"> <strong>Références</strong> </span></h1>
<ul>
<li>
<p><a href="thoughtco.com/longest-german-word-in-the-world-4061494">What Is the Longest German Word ?</a> de Flippo (2020)</p>
</li>
<li>
<p><a href="https://arxiv.org/abs/1808.06226">SentencePiece: A simple and language independent subword tokenizerand detokenizer for Neural Text Processing</a> de Kudo et Richardson (2018)</p>
</li>
<li>
<p><a href="https://arxiv.org/abs/1804.10959">Subword Regularization: Improving Neural Network Translation Models with Multiple Subword Candidates</a> de Taku Kudo (2018)</p>
</li>
<li>
<p><a href="https://mlexplained.com/2019/11/06/a-deep-dive-into-the-wonderful-world-of-preprocessing-in-nlp/">A Deep Dive into the Wonderful World of Preprocessing in NLP</a> de Keita Kurita (2020)</p>
</li>
<li>
<p><a href="https://arxiv.org/abs/1907.11692">RoBERTa: A Robustly Optimized BERT Pretraining Approach</a> de Liu et al. (2019)</p>
</li>
<li>
<p><a href="https://arxiv.org/abs/1804.08771">A Call for Clarity in Reporting BLEU Scores</a> de Matt Post (2018)</p>
</li>
<li>
<p><a href="https://d4mucfpksywv.cloudfront.net/better-language-models/language-models.pdf">Language Models are Unsupervised Multitask Learners</a> de Radford et al. (2019)</p>
</li>
<li>
<p><a href="https://ieeexplore.ieee.org/document/6289079/authors#authors">Japanese and Korean voice search</a> de Schuster et Nakajima (2012)</p>
</li>
<li>
<p><a href="https://withblue.ink/2019/03/11/why-you-need-to-normalize-unicode-strings.html">When “Zoë” !== “Zoë”. Or why you need to normalize Unicode strings</a> de Alessandro Segala (2019)</p>
</li>
<li>
<p><a href="https://arxiv.org/abs/1911.00359">CCNet: Extracting High Quality Monolingual Datasets from Web Crawl Data</a> de Wenzek, Lachaux et al. (2019)</p>
</li>
<li>
<p><a href="https://arxiv.org/abs/1909.11687">Extreme Language Model Compression with Optimal Subwords and Shared Projections</a> de Sanqiang Zhao et al. (2019)
<br /><br /><br /></p>
</li>
</ul>
<h1 id="-citation-"><span style="color: #FF0000"> <strong>Citation</strong> <span></span></span></h1>
<blockquote>
<p>@inproceedings{tokenizers_blog_post,<br />
author = {Loïck BOURDOIS},<br />
title = {Le prétraitement et les tokenizers en NLP},<br />
year = {2020},<br />
url = {https://lbourdois.github.io/blog/nlp/Les-tokenizers/}<br />
}</p>
</blockquote>Loïck BOURDOISNLP - Illustration des divers prétraitement réalisables en NLP ainsi que des différents tokenizers fréquemment utilisés