Implémentation de modèles génératifs profonds pour les systèmes de recommandation dans Tensorflow

Mise en œuvre de VAE et de GAN

Cet article est la suite de mon dernier, je vais vous montrer comment implémenter le VAE et le GAN avec un exemple de code pour les systèmes de recommandation. Je vais me concentrer sur la mise en œuvre plutôt que sur la théorie qui la sous-tend. Néanmoins, je continuerai à donner quelques indications sur la perte et le concept principal de chaque modèle.

Nous allons implémenter les modèles en utilisant le nouveau mode d’exécution dans Tensorflow, appelé exécution rapide.

Les deux mesures que nous utiliserons sont le NDCG, qui mesure la qualité et l'utilité de l'ordre des éléments dans nos recommandations. L'indice de personnalisation mesure la pertinence des recommandations uniques pour un utilisateur.

Les modèles sont formés à l'aide du jeu de données MovieLens 20M.

Échantillon du fichier de notation

VAE

Les autoencodeurs variationnels (VAE) se décomposent en deux parties: le codeur, qui réduit la forme des données avec un goulot d'étranglement, et le décodeur, qui reconvertit le codage dans sa forme d'origine. Entre ces deux NN, il y a une couche d'échantillon, où la sortie du décodeur est décomposée en deux vecteurs: la moyenne et la variance, puis ces vecteurs sont utilisés pour l'échantillonnage gaussien. Cet exemple est utilisé comme entrée pour le décodeur.

Contrairement aux autres modèles, VAE donne une distribution de probabilité sur tous les éléments d'un chemin aller.

Diagramme VAE

Dans le contexte des systèmes de recommandation, ils peuvent être utilisés pour prévoir de nouvelles recommandations. L'entrée et la sortie sont à la fois le vecteur de clic (il est habituel pour un AE que l'entrée et la sortie soient les mêmes) et nous utiliserons la suppression après la couche d'entrée. Cela signifie que le modèle devra reconstituer le vecteur de clic car certains éléments de l'entrée seront manquants, d'où l'apprentissage de la prévision de la recommandation pour un vecteur de clic donné.

J'ai décrit l'architecture dans le diagramme ci-dessous. Comme expliqué ci-dessus, l'entrée et la sortie sont les mêmes.

Dans cette partie, je définirai la perte utilisée. Les éléments présentant un intérêt pour un utilisateur ont été modélisés comme une distribution multinomiale. Pour être plus précis, il est modélisé sous la forme de probabilités de cellules multinomiales (une extension du cas binomial), chaque élément a une probabilité p d'être intéressant pour l'utilisateur et xᵢ est le nombre de fois où l'élément i est sélectionné. Par conséquent, la distribution conjointe du vecteur des éléments choisis (x₁, x₂,.,., Xₙ) est distribuée comme une distribution multinomiale, avec pmf:

Distribution multinomiale

Pour obtenir la perte, j'ai utilisé l'estimation du maximum de vraisemblance (MLE) des probabilités des cellules multinomiales. Cela équivaut à maximiser le pmf de la distribution multinomiale. Pour que tout soit plus clair, j'ai utilisé le log-vraisemblance. Il est défini comme:

Log-vraisemblance de la distribution multinomiale

Nous pouvons maintenant prendre l'argmax de la log-vraisemblance. Comme pour les probabilités pᵢ, les deux premiers termes de l'équation disparaîtront.

Argmax de la LL

Si nous considérons f (x) comme sortie du décodeur et la dernière couche comme couche softmax (telle que la sortie soit une distribution de probabilité). La perte peut être définie comme:

Fonction de perte

Cette perte n'est pas suffisante, comme le prouvent d'autres articles. Comme nous voudrions avoir, dans une certaine mesure, une interpolation douce entre les différents points (entre les grappes implicites d’utilisateurs dans notre cas) dans l’espace variable latent. Nous devrons ajouter un terme de régularisation.

Espace latent pour différentes pertes - Source

Pour ce faire, nous ajoutons la divergence KL d'une distribution antérieure de l'espace latent. Dans notre cas, il s’agit d’un gaussien multivarié avec une matrice de covariance diagonale, c’est-à-dire un ensemble de n variables aléatoires normales indépendantes. Ce terme de régularisation, la divergence de KL, pénalisera le modèle si la distribution antérieure est loin de celle de Gauss. Cela forcera l'espace latent à être étroitement distribué à la distribution normale.

KL-Divergence de la distribution gaussienne

Pour pouvoir contrôler la force de la régularisation, on la multiplie par β.

Perte finale

Enfin, pour utiliser la rétro-propagation et calculer le gradient sur la couche d'échantillonnage, nous devons utiliser une astuce, car il n'est pas direct de calculer le gradient. L'astuce de reparamétrage permet de résoudre ce problème en utilisant l'équation z = ε × σ + µ, avec ε ~ N (0,1). La dérivation de σ et μ est maintenant possible.

Vanilla VAE - Mise en oeuvre

Dans cette section, je décrirai étape par étape comment mettre en œuvre une VAE.

Le réseau d'encodeur est défini ci-dessous, à l'aide de tf.keras.Sequential. C'est un simple NN avec une couche d'entrée de la taille du nombre d'éléments, une couche dense avec une activation tanh et une couche de sortie avec une activation linéaire.

Le réseau de décodage est un simple NN avec une couche d'entrée de la dimension latente, une couche dense avec une activation tanh et une couche de sortie de taille nombre d'éléments.

Nous définissons ci-dessous certaines fonctions des assistants. La fonction encodage utilisera un vecteur de clic et générera la moyenne et la variance (journal de la variance). La fonction de décodage prendra un échantillon gaussien (z). La fonction de reparamétrage est la mise en œuvre de l'astuce décrite ci-dessus (notons que nous multiplions par 0,5 lorsque nous prenons l'exponentielle).

La perte est définie ci-dessous. Nous mettons simplement en œuvre la perte décrite ci-dessus.

En utilisant la mise en œuvre ci-dessus, nous pouvons former le modèle à l'aide d'Adam Optimizer. Nous avons ajouté ci-dessous le NDCG @ 100 (défini dans mon dernier article) de VAE pour le jeu de validation.

Courbe d'apprentissage du NDCG @ 100 sur le jeu de validation

Nous avons calculé le NDCG et la personnalisation sur l’ensemble de tests:

  • NDCG @ 100: 0.413
  • Personnalisation: 0.102

VAE profonde

Nous allons maintenant tester une nouvelle architecture VAE avec un encodeur et un décodeur plus profonds pour voir si nous pouvons réellement améliorer les métriques.

Tout d'abord, nous définissons un encodeur profond. Dans notre cas, le modèle comporte 3 couches de taille décroissante jusqu’à l’espace latent.

Le réseau de décodeurs profonds a la même architecture que le codeur, mais est simplement orienté dans l'autre sens.

En utilisant la mise en œuvre ci-dessus, nous pouvons former le modèle à l'aide d'Adam Optimizer. Nous avons ajouté ci-dessous le NDCG @ 100 de la VAE profonde pour le jeu de validation.

Courbe d'apprentissage du NDCG @ 100 sur le jeu de validation

Nous avons calculé le NDCG et la personnalisation sur l’ensemble de tests:

  • NDCG @ 100: 0.380
  • Personnalisation: 0.099

Deep Decoder VAE

On pourrait également se demander si l’utilisation d’un décodeur ou d’un codeur profond pourrait donner de meilleurs résultats que le VAE profond dans lequel ses deux parties sont profondes. Pour répondre à cette question, j'ai d'abord testé le décodeur profond et un encodeur peu profond.

Deep Decoder VAE

J'ai combiné le codeur profond et le décodeur peu profond mis en œuvre ci-dessus. J'ai formé le modèle à l'aide d'Adam Optimizer. Ci-dessous, j'ai ajouté le NDCG @ 100 du VAE Deep Decoder pour le jeu de validation.

Courbe d'apprentissage du NDCG @ 100 sur le jeu de validation

Nous avons calculé le NDCG et la personnalisation sur l’ensemble de tests:

  • NDCG @ 100: 0.375
  • Personnalisation: 0.095

Nous obtenons des résultats un peu moins bons qu'avec le Deep VAE.

Deep Encoder VAE

Comme nous l'avons testé avec un encodeur profond, nous pouvons maintenant essayer avec seulement un encodeur profond.

J'ai combiné l'encodeur peu profond et le décodeur profond mis en œuvre ci-dessus.

Nous pouvons former le modèle à l'aide de Adam Optimizer. Ci-dessous, j'ai ajouté le NDCG @ 100 du logiciel VAE Deep Encoder pour le jeu de validation.

Courbe d'apprentissage du NDCG @ 100 sur le jeu de validation

Nous avons calculé le NDCG et la personnalisation sur l’ensemble de tests:

  • NDCG @ 100: 0.403
  • Personnalisation: 0.108

Nous obtenons des résultats légèrement meilleurs qu'avec le Deep VAE.

Deep VAE Split Train

Enfin, le dernier modèle lié à la VAE est le train fractionné Deep VAE. Comme indiqué ci-dessus, l'entraînement avec un seul encodeur profond donne de meilleurs résultats qu'avec un décodeur et un encodeur profonds. Par conséquent, je vais essayer un autre moyen de formation. Premièrement, je vais former un encodeur profond avec un décodeur peu profond, puis après quelques époques, je vais échanger le décodeur peu profond avec un décodeur plus profond.

J'ai donc décomposé la formation en 3 parties:

1. Entraînez le codeur profond et le décodeur peu profond

2. Entraînez le décodeur profond avec le codeur profond fixe (seul le décodeur est entraîné)

3. Entraînez le décodeur profond et le codeur profond.

Enfin, nous pouvons former le modèle avec Adam Optimizer. Ci-dessous, j'ai ajouté le NDCG @ 100 du Deep VAE Split Train pour le jeu de validation.

Courbe d'apprentissage du NDCG @ 100 sur le jeu de validation

Nous avons calculé le NDCG et la personnalisation sur l’ensemble de tests:

  • NDCG @ 100: 0.397
  • Personnalisation: 0.121

Nous obtenons des résultats légèrement meilleurs qu'avec le Deep VAE.

GAN

Les GAN ont été introduits pour la première fois en 2014 par Ian Goodfellow. Ces types spéciaux de modèles sont composés de deux parties: le discriminateur et le générateur. Dans le cas des systèmes de recommandation, le générateur prend un vecteur de clic et génère un vecteur de recommandation. Le discriminateur prendra ces vecteurs créés et les vecteurs de clic d'origine et les affichera s'ils sont vraisemblables ou non.

Le générateur et le discriminateur sont en concurrence les uns contre les autres. L'apprentissage est modélisé comme un jeu à somme nulle. L’apprentissage de ces modèles est difficile dans la pratique et pose de nombreux problèmes de convergence.

Diagramme GAN

Vanilla GAN

Dans cette section, je décrirai étape par étape comment mettre en œuvre un GAN en ce qui concerne les systèmes de recommandation.

Le générateur et le discriminateur sont définis ci-dessous, à l'aide de tf.keras.Sequential. Le générateur est un NN avec une couche d'entrée de la taille du nombre d'éléments et une couche dense avec une couche de sortie avec une activation softmax. Le discriminateur est un NN avec une couche d'entrée de la taille du nombre d'éléments et une couche dense avec une couche de sortie avec une activation sigmoïde.

Ensuite, j'ai défini des fonctions d'assistance. Les vecteurs générés sont masqués par les utilisateurs (multipliez le vecteur de recommandation par le vecteur de clic). Cela a été utile pendant la formation pour réduire les problèmes de convergence.

La perte est la perte GAN classique. Le discriminateur est la perte d'entropie croisée binaire où les étiquettes positives sont associées aux vecteurs de clic d'origine et les étiquettes négatives aux recommandations générées.

Perte discriminateur

La perte de générateur est définie comme l'entropie croisée binaire, où les étiquettes correctes sont associées à la sortie du discriminateur des recommandations générées.

Perte de générateur

Ci-dessous, je mets en œuvre ces pertes.

La formation se fait de manière alternative en utilisant Adam Optimizer. Pour chaque lot, entraînez le générateur avec le discriminateur fixe (ne mettez à jour que les paramètres du générateur), puis entraînez le discriminateur avec le générateur fixe.

Courbe d'apprentissage des pertes

Ci-dessous, j'ai tracé le NDCG @ 100 sur le jeu de validation.

Courbe d'apprentissage du NDCG @ 100 sur le jeu de validation

Nous avons calculé le NDCG et la personnalisation sur l’ensemble de tests:

  • NDCG @ 100: 0.260
  • Personnalisation: 0.443

WGAN-GP

Les GAN sont connus pour leur instabilité. Pour surmonter ce problème, de nombreuses recherches ont été menées sur les nouvelles fonctions et modèles de perte. La pénalité Wasserstein GAN-Gradient (WGAN-GP) en fait partie. Les principales différences entre les deux modèles sont la sortie du discriminateur et sa perte. L'activation de la sortie n'est plus un sigmoïde, la sortie est illimitée. Concernant la perte, ce modèle s'articule autour d'une nouvelle contrainte sur le discriminateur D (x): il doit s'agir d'une fonction 1-Lipschitz. Une fonction est 1-Lipschitz. Fonction si et seulement si la norme de son gradient est au plus 1. Pour assurer cette contrainte, nous devrons ajouter un terme de régularisation qui pénalisera le modèle si la norme du gradient du discriminateur est loin d'être 1 (le gradient ne sera évalué qu'en 1 point).

La perte de discriminateur est maintenant, avec ε ~ U (0,1):

Perte discriminante WGAN-GP

La perte du générateur pour le WGAN-GP est très similaire à celle du GAN.

La formation est similaire au GAN.

Courbe d'apprentissage des pertes

Ci-dessous, j'ai tracé le NDCG @ 100 sur le jeu de validation.

Courbe d'apprentissage du NDCG @ 100 sur le jeu de validation

Nous avons calculé le NDCG et la personnalisation sur l’ensemble de tests:

  • NDCG @ 100: 0.279
  • Personnalisation: 0.429

Nous constatons que nous obtenons un résultat légèrement supérieur à celui obtenu avec le GAN.

Conclusion

J'ai montré comment implémenter différents modèles avec le mode Tensorflow désireux. J'ai montré (sur le MovieLens 20M) qu'un simple VAE peu profond donne de meilleurs résultats qu'un VAE plus profond. Les modèles GAN sont moins efficaces que VAE et peuvent facilement s’effondrer (nécessité de se recycler à partir de zéro). Lorsque l'on pense au-delà de la recherche et que l'on met ces modèles en production, le GAN semble peu pratique dans le cas de recommandations automatisées et calculées quotidiennement.

Références

  1. Ishaan Gulrajani, Faruk Ahmed, Martin Arjovsky, Vincent Dumoulin et Aaron Courville: amélioration de la formation des GAN de Wasserstein, 2017
  2. Dawen Liang, Rahul G. Krishnan, Matthew D. Hoffman, Tony Jebara, Autoencodeurs variationnels pour filtrage collaboratif, 2018.
  3. Ishaan Gulrajani, Faruk Ahmed, Martin Arjovsky, Vincent Dumoulin, Aaron Courville, Formation améliorée des réseaux de points de vue de Wasserstein, 2017.
  4. http://statweb.stanford.edu/~susan/courses/s200/lectures/lect11.pdf
  5. https://towardsdatascience.com/intuitively-understanding-variational-autoencoders-1bfe67eb5daf