Embeddings d’images et de fichiers exécutables
L’embedding d’images dans des représentations de petite dimension inférieure est un champ de recherche en plein essor du Deep Learning. Avec une petite représentation vectorielle de chaque image, de nouvelles tâches peuvent être effectuées facilement, dont l’apprentissage sans exemple (zero-shot learning - ZSL) et la similarité entre images.
Par exemple, dans la tâche qui consiste à déterminer la similarité entre des images, les embeddings de celles qui sont semblables sont proches, aussi un simple calcul des distances entre les embeddings des images permet d’identifier celles similaires.
Dans cette illustration, nous supposons que nous disposons d’un ensemble d’images sur lequel nous avons utilisé le réseau de neurones pour calculer leurs embeddings. Dès lors, quand nous avons une nouvelle image et voulons récupérer celle qui lui ressemble le plus dans cet ensemble, il nous suffit d’utiliser le réseau de neurones pour obtenir son embedding et calculer la distance entre cette représentation vectorielle et celles calculés auparavant !
Nous avons récemment effectué des recherches poussées sur l’embedding de fichiers exécutables avec des réseaux neuronaux convolutifs (Convolutional Neural Networks – CNN) pour identifier des similitudes entre les fichiers exécutables. Durant ce travail, nous sommes tombés sur des écarts surprenants entre les prédictions à l’entraînement et à l’inférence.
Pour lancer nos recherches, nous avons simplifié la tâche au maximum et commencé avec très peu de fichiers de trois familles différentes, pour un total de 5 000 fichiers. Avec aussi peu de données, l’entraînement a été très rapide.
Prédictions anormales en testant le modèle
Sans surprise, les prédictions en inférence sur les données de test étaient erronées. Nous nous y attendions, car du fait de la petite quantité de données le modèle a surappris le jeu de données d’apprentissage (overfitting). En cas de surapprentissage, il apprend à identifier le bruit spécifique au jeu de données d’apprentissage, ce qui le rend incapable d’être généralisé à des données qu’il n’a pas encore vues.
Cependant, lorsqu’on prédit en inférence sur les fichiers qui ont été vus pendant l’entraînement, nous obtenons aussi des prédictions hautement inexactes. Il est clair que les prédictions du modèle sont très différentes à l’entraînement et à l’inférence, et ce sur les mêmes fichiers !
C’est généralement le signe qu’il y a une différence dans la manière dont les données sont gérées et prétraitées. Si les données fournies au modèle pendant l’apprentissage et durant l’inférence sont traitées différemment, le modèle produit des prédictions différentes. Toutefois, nous étions sûrs que le prétraitement était exactement le même.
Après de plus amples recherches, nous avons constaté que les couches de normalisation par batch dans les CNN présentent des comportements différents à l’entraînement et à l’inférence dans les frameworks courants de Deep Learning (TensorFlow et Pytorch). Les questions suivantes se posent donc : pourquoi la normalisation par batch se comporte-t-elle différemment en entraînement et en inférence ? Pourquoi est-elle utilisée ? Comment résoudre notre problème ?
Plongée dans la normalisation par batch
Ce qu’est la normalisation par batch
La normalisation par batch est fréquemment employée pour améliorer la performance et la stabilité des réseaux de neurones, son utilisation est un atout de taille. Nous nous penchons ici sur ce qu’est la normalisation par batch, sur la manière dont elle fonctionne, et sur les raisons pour lesquelles elle est utile.
En résumé, il s’agit d’une technique visant à normaliser les entrées de chaque couche d’un réseau de neurones. À cette fin, pour chaque batch, elle soustrait la moyenne et divise par l’écart type de l’entrée (à savoir, le résultat de la précédente couche convolutive).
L’un des principaux avantages de la normalisation par batch tient dans le fait qu’elle permet l’utilisation de learning rates bien plus élevés à l’entraînement, ainsi que d’architectures neuronales plus complexes. En effet, normaliser les entrées évite qu’elles deviennent trop grandes ou trop petites. Ceci aide à éviter les problèmes d’explosion et de disparition de gradients, souvent confrontés à des learning rates élevés et à des architectures complexes, comme expliqué dans cet article.
Autre avantage de la normalisation par batch : elle peut rendre les modèles de Deep Learning plus robustes face aux variations dans les données, et peut mener à une meilleure performance de généralisation. Enfin, la normalisation par batch aide aussi à limiter le nombre de paramètres au sein du réseau, et limiter encore davantage le surapprentissage.
Pour résumer, la normalisation par batch doit figurer dans votre boite à outils pour améliorer la performance et la stabilité des réseaux de neurones ; elle est largement utilisée en Deep Learning. Bien qu’elle présente quelques inconvénients (processus d’entraînement moins interprétable, calculs fastidieux, etc.), ses avantages dépassent souvent ses inconvénients ; cela vaut clairement la peine de l’utiliser.
Pourquoi des comportements différents à l’entrainement et à l’inférence ?
La plupart du temps, l’inférence porte sur un seul élément et non un ensemble de données. Dans ce contexte, calculer la moyenne et la variance n’a pas de sens. Pour résoudre ce problème, la normalisation par batch présente un comportement différent à l’inférence et à l’entrainement. La moyenne et la variance calculées pour les batchs à l’entraînement sont sauvegardées et utilisées à l’inférence pour inférer une moyenne et une variance quand un seul élément est donné. Elles sont mise à jour selon une fenêtre mobile avec un momentum prédéfini (entre 0 et 1) :
En inférence, la moyenne mobile et la variance mobile sont fixées une fois l’entraînement effectué ; elles sont utilisées pour normaliser le résultat des couches.
La raison derrière notre problème ?
Alors pourquoi notre modèle — après un bref surapprentissage sur quelques échantillons — a-t-il proposé des prédictions complètement différentes pour les mêmes échantillons ?
Comme notre ensemble de données est très réduit et le modèle surapprend très rapidement, le nombre total de batchs traités était lui aussi très réduit. Aussi, la moyenne mobile et la variance mobile n’ont pas totalement convergé en fin d’entraînement. Elles restent très proches de leurs valeurs initiales (0 pour la moyenne et 1 pour la variance). Les prédictions du modèle en inférence s’en trouvent complètement déformées.
Conclusion
La solution la plus simple consiste à se passer la normalisation par batchs. Dans notre cas, sur un ensemble limité de données, cela nous permet d’itérer rapidement et d’améliorer notre solution. Une fois validés le premier prototype de l’architecture neuronale et la méthodologie, nous pouvons, une fois mis à l’échelle, appliquer le prototype à de larges ensembles de données. Dans ce cas, de nombreux batchs seront traités et la normalisation par batch disposera d’assez d’itérations pour converger ; nous pourrons alors l’ajouter à nouveau. Son efficacité est montrée dans le scénario suivant :
Scores de pertinence pendant les phases d’entraînement.
Classification faite sur les embeddings des images.
En Bleu, avec normalisation par batch ; en Rose sans normalisation par batch
Comme pour plusieurs autres applications, la normalisation par batch fait aussi la preuve de son efficacité sur notre cas d’usage. Avec un peu de chance, cet article vous aura aidé à mieux comprendre cette méthode de Deep Learning !
Pour approfondir le sujet de la normalisation par batch, nous envisageons de tester une nouvelle méthode, la normalisation par batch « moyenne » (‘average’ batch normalization), plutôt que la méthode classique de la moyenne mobile décrite ici. Charles Gaillard et Rémy Brossard abordent cette nouvelle méthode dans leur article. Nous vous tiendrons informés des résultats !