Améliorations du Deep Q Learning: double DQN en duel, rediffusion d'expérience prioritaire et correction…

Cet article fait partie du cours d'apprentissage par renforcement profond avec Tensorflow? ️. Consultez le programme ici.

Dans notre dernier article sur Deep Q Learning avec Tensorflow, nous avons implémenté un agent qui apprend à jouer à une version simple de Doom. Dans la version vidéo, nous avons formé un agent DQN qui joue Space invaders.

Cependant, lors de la formation, nous avons constaté qu'il y avait beaucoup de variabilité.

Deep Q-Learning a été introduit en 2014. Depuis, de nombreuses améliorations ont été apportées. Donc, aujourd'hui, nous verrons quatre stratégies qui améliorent - de façon spectaculaire - la formation et les résultats de nos agents DQN:

  • cibles Q fixes
  • double DQN
  • duel DQN (alias DDQN)
  • Replay d'expérience prioritaire (aka PER)

Nous allons implémenter un agent qui apprend à jouer à Doom Deadly corridor. Notre IA doit naviguer vers l'objectif fondamental (le gilet) et s'assurer qu'ils survivent en même temps en tuant des ennemis.

Cibles Q fixes

Théorie

Nous avons vu dans l'article Deep Q Learning que, lorsque nous voulons calculer l'erreur TD (aka la perte), nous calculons la différence entre la cible TD (Q_target) et la valeur Q actuelle (estimation de Q).

Mais nous n'avons aucune idée de la véritable cible de TD. Nous devons l’estimer. En utilisant l'équation de Bellman, nous avons vu que la cible TD n'est que la récompense de cette action à cet état plus la valeur Q la plus élevée actualisée pour l'état suivant.

Cependant, le problème est que nous utilisons les mêmes paramètres (poids) pour estimer la cible et la valeur Q. En conséquence, il existe une forte corrélation entre la cible TD et les paramètres (w) que nous modifions.

Par conséquent, cela signifie qu'à chaque étape de la formation, nos valeurs Q changent mais aussi la valeur cible change. Donc, nous nous rapprochons de notre objectif mais la cible évolue également. C'est comme chasser une cible en mouvement! Cela a conduit à une grande oscillation dans la formation.

C'est comme si vous étiez un cow-boy (l'estimation Q) et que vous vouliez attraper la vache (la cible Q), vous devez vous rapprocher (réduire l'erreur).

A chaque pas de temps, vous essayez d'approcher la vache, qui se déplace également à chaque pas de temps (car vous utilisez les mêmes paramètres).

Cela conduit à un chemin très étrange de poursuite (une grande oscillation à l'entraînement).

Au lieu de cela, nous pouvons utiliser l'idée de Q-cibles fixes introduite par DeepMind:

  • Utilisation d'un réseau séparé avec un paramètre fixe (appelons-le w-) pour estimer la cible TD.
  • A chaque étape Tau, nous copions les paramètres de notre réseau DQN pour mettre à jour le réseau cible.

Grâce à cette procédure, nous aurons un apprentissage plus stable car la fonction cible reste fixe pendant un certain temps.

la mise en oeuvre

La mise en œuvre de q-cibles fixes est assez simple:

  • Tout d'abord, nous créons deux réseaux ( DQNetwork, TargetNetwork)
  • Ensuite, nous créons une fonction qui prendra nos DQNetworkparamètres et les copiera dans notreTargetNetwork
  • Enfin, lors de la formation, nous calculons la cible TD en utilisant notre réseau cible. Nous mettons à jour le réseau cible à DQNetworkchaque tauétape ( tauc'est un hyper-paramètre que nous définissons).

Double DQN

Théorie

Le double DQN, ou double apprentissage, a été introduit par Hado van Hasselt. Cette méthode gère le problème de la surestimation des valeurs Q.

Pour comprendre ce problème, rappelez-vous comment nous calculons la cible TD:

En calculant la cible TD, nous sommes confrontés à un problème simple: comment pouvons-nous être sûrs que la meilleure action pour l'état suivant est l'action avec la valeur Q la plus élevée?

Nous savons que la précision des valeurs q dépend de l'action que nous avons essayée et des états voisins que nous avons explorés.

Par conséquent, au début de la formation, nous n'avons pas suffisamment d'informations sur la meilleure action à entreprendre. Par conséquent, prendre la valeur q maximale (qui est bruyante) comme la meilleure action à entreprendre peut conduire à des faux positifs. Si des actions non optimales reçoivent régulièrement une valeur Q plus élevée que la meilleure action optimale, l'apprentissage sera compliqué.

La solution est la suivante: lorsque nous calculons la cible Q, nous utilisons deux réseaux pour découpler la sélection d'action de la génération de valeur Q cible. Nous:

  • utilisez notre réseau DQN pour sélectionner la meilleure action à entreprendre pour l'état suivant (l'action avec la valeur Q la plus élevée).
  • utilisez notre réseau cible pour calculer la valeur Q cible de cette action à l'état suivant.

Par conséquent, Double DQN nous aide à réduire la surestimation des valeurs q et, par conséquent, nous aide à nous entraîner plus rapidement et à avoir un apprentissage plus stable.

la mise en oeuvre

Duel DQN (alias DDQN)

Théorie

Rappelez-vous que les valeurs Q correspondent à la qualité d'être dans cet état et d'effectuer une action dans cet état Q (s, a).

Nous pouvons donc décomposer Q (s, a) comme la somme de:

  • V (s) : la valeur d'être à cet état
  • A (s, a) : l'avantage de prendre cette action à cet état (combien il vaut mieux faire cette action par rapport à toutes les autres actions possibles à cet état).

Avec DDQN, nous voulons séparer l'estimateur de ces deux éléments, en utilisant deux nouveaux flux:

  • celui qui estime la valeur d'état V (s)
  • celui qui estime l' avantage pour chaque action A (s, a)

Et puis nous combinons ces deux flux via une couche d'agrégation spéciale pour obtenir une estimation de Q (s, a).

Attendez? Mais pourquoi avons-nous besoin de calculer ces deux éléments séparément si nous les combinons?

En découplant l'estimation, notre DDQN peut intuitivement apprendre quels états sont (ou ne sont pas) valables sans avoir à apprendre l'effet de chaque action à chaque état (puisqu'il calcule également V (s)).

Avec notre DQN normal, nous devons calculer la valeur de chaque action à cet état. Mais à quoi bon si la valeur de l'État est mauvaise? Quel est l'intérêt de calculer toutes les actions dans un même état lorsque toutes ces actions mènent à la mort?

En conséquence, en découplant, nous pouvons calculer V (s). Ceci est particulièrement utile pour les États où leurs actions n'affectent pas l'environnement de manière significative. Dans ce cas, il n'est pas nécessaire de calculer la valeur de chaque action. Par exemple, se déplacer à droite ou à gauche n'a d'importance que s'il y a un risque de collision. Et, dans la plupart des États, le choix de l'action n'a aucun effet sur ce qui se passe.

Ce sera plus clair si nous prenons l'exemple du papier Dueling Network Architectures for Deep Reinforcement Learning.

On voit que les flux du réseau de valeur prête attention (le flou orange) à la route, et en particulier à l'horizon où les voitures naissent. Il fait également attention au score.

En revanche, le flux d'avantage dans le premier cadre à droite ne fait pas beaucoup attention à la route, car il n'y a pas de voitures devant (le choix d'action est donc pratiquement sans importance). Mais, dans le deuxième cadre, il fait attention, car il y a une voiture juste devant elle, et faire un choix d'action est crucial et très pertinent.

Concernant la couche d'agrégation, nous voulons générer les valeurs q pour chaque action à cet état. Nous pourrions être tentés de combiner les flux comme suit:

Mais si nous faisons cela, nous tomberons dans leproblème d'identifiabilité , c'est-à-dire, étant donné Q (s, a), nous ne pouvons pas trouver A (s, a) et V (s).

Et ne pas être capable de trouver V (s) et A (s, a) donné Q (s, a) sera un problème pour notre propagation arrière. Pour éviter ce problème, nous pouvons forcer notre estimateur de fonction d'avantage à avoir un avantage de 0 à l'action choisie.

Pour ce faire, nous soustrayons l'avantage moyen de toutes les actions possibles de l'État.

Par conséquent, cette architecture nous aide à accélérer la formation. Nous pouvons calculer la valeur d'un état sans calculer le Q (s, a) pour chaque action à cet état. Et cela peut nous aider à trouver des valeurs Q beaucoup plus fiables pour chaque action en découplant l'estimation entre deux flux.

la mise en oeuvre

La seule chose à faire est de modifier l'architecture DQN en ajoutant ces nouveaux flux:

Replay d'expérience prioritaire

Théorie

Prioritized Experience Replay (PER) a été introduit en 2015 par Tom Schaul. L'idée est que certaines expériences peuvent être plus importantes que d'autres pour notre formation, mais peuvent se produire moins fréquemment.

Parce que nous échantillonnons le lot de manière uniforme (en sélectionnant les expériences au hasard), ces expériences riches qui se produisent rarement n'ont pratiquement aucune chance d'être sélectionnées.

C'est pourquoi, avec PER, nous essayons de changer la distribution d'échantillonnage en utilisant un critère pour définir la priorité de chaque tuple d'expérience.

Nous voulons privilégier l' expérience là où il y a une grande différence entre notre prédiction et la cible TD, car cela signifie que nous avons beaucoup à apprendre à ce sujet.

Nous utilisons la valeur absolue de la magnitude de notre erreur TD:

Et nous mettons cette priorité dans l'expérience de chaque tampon de relecture.

Mais nous ne pouvons pas simplement faire une priorisation gourmande, car cela conduira à toujours entraîner les mêmes expériences (qui ont une grande priorité), et donc sur-ajustement.

Nous introduisons donc une priorisation stochastique, qui génère la probabilité d'être choisi pour une rediffusion.

En conséquence, à chaque pas de temps, nous obtiendrons unlot d'échantillons avec cette distribution de probabilité et formez notre réseau dessus.

Mais, nous avons toujours un problème ici. N'oubliez pas qu'avec Experience Replay normale, nous utilisons une règle de mise à jour stochastique. Par conséquent, la façon dont nous échantillonnons les expériences doit correspondre à la distribution sous-jacente dont elles proviennent.

Lorsque nous avons une expérience normale, nous sélectionnons nos expériences dans une distribution normale - en termes simples, nous sélectionnons nos expériences au hasard. Il n'y a pas de biais, car chaque expérience a la même chance d'être prise, nous pouvons donc mettre à jour nos poids normalement.

Mais , parce que nous utilisons l'échantillonnage prioritaire, l'échantillonnage purement aléatoire est abandonné. En conséquence, nous introduisons un biais en faveur des échantillons hautement prioritaires (plus de chances d'être sélectionnés).

Et, si nous mettons à jour nos poids normalement, nous prenons un risque de sur-ajustement. Les échantillons qui ont une priorité élevée sont susceptibles d'être utilisés pour la formation plusieurs fois par rapport aux expériences de faible priorité (= biais). En conséquence, nous mettrons à jour nos pondérations avec seulement une petite partie des expériences que nous considérons comme vraiment intéressantes.

Pour corriger ce biais, nous utilisons des poids d'échantillonnage d'importance (IS) qui ajusteront la mise à jour en réduisant les poids des échantillons souvent observés.

Les poids correspondant aux échantillons de haute priorité ont très peu d'ajustement (car le réseau verra ces expériences plusieurs fois), tandis que ceux correspondant aux échantillons de faible priorité auront une mise à jour complète.

Le rôle de b est de contrôler dans quelle mesure ces poids d'échantillonnage d'importance affectent l'apprentissage. En pratique, le paramètre b est recuit jusqu'à 1 sur la durée de l'apprentissage, car ces poids sont plus importants en fin d'apprentissage lorsque nos valeurs q commencent à converger. La nature impartiale des mises à jour est la plus importante près de la convergence, comme expliqué dans cet article.

la mise en oeuvre

Cette fois, l'implémentation sera un peu plus sophistiquée.

Tout d'abord, nous ne pouvons pas simplement implémenter PER en triant tous les tampons de relecture d'expérience en fonction de leurs priorités. Cela ne sera pas du tout efficace en raison de O (nlogn) pour l'insertion et O (n) pour l'échantillonnage.

Comme expliqué dans ce très bon article, nous devons utiliser une autre structure de données au lieu de trier un tableau - un sumtree non trié.

Un sumtree est un arbre binaire, c'est-à-dire un arbre avec seulement un maximum de deux enfants pour chaque nœud. Les feuilles (nœuds les plus profonds) contiennent les valeurs de priorité et un tableau de données qui pointe vers les feuilles contient les expériences.

La mise à jour de l'arbre et l'échantillonnage seront vraiment efficaces (O (log n)).

Ensuite, nous créons un objet mémoire qui contiendra notre sumtree et nos données.

Ensuite, pour échantillonner un minibatch de taille k, la plage [0, total_priority] sera divisée en k plages. Une valeur est uniformément échantillonnée dans chaque plage.

Enfin, les transitions (expériences) qui correspondent à chacune de ces valeurs échantillonnées sont extraites de l'arbre de somme.

Ce sera beaucoup plus clair lorsque nous plongerons sur les détails complets dans le cahier.

Agent du match à mort funeste

Cet agent est un Dueling Double Deep Q Learning avec PER et cibles q fixes.

Nous avons fait un tutoriel vidéo de l'implémentation: Le cahier est ici

C'est tout! Vous venez de créer un agent plus intelligent qui apprend à jouer à Doom. Impressionnant! N'oubliez pas que si vous voulez avoir un agent avec de très bonnes performances, vous avez besoin de beaucoup plus d'heures GPU (environ deux jours de formation)!

Cependant, avec seulement 2 à 3 heures d'entraînement sur le processeur (oui le processeur), notre agent a compris qu'il fallait tuer les ennemis avant de pouvoir avancer. S'ils avancent sans tuer d'ennemis, ils seront tués avant d'obtenir le gilet.

N'oubliez pas d'implémenter vous-même chaque partie du code. Il est vraiment important d'essayer de modifier le code que je vous ai donné. Essayez d'ajouter des époques, changez l'architecture, ajoutez des valeurs Q fixes, changez le taux d'apprentissage, utilisez un environnement plus dur… et ainsi de suite. Expérimentez, amusez-vous!

N'oubliez pas qu'il s'agissait d'un article important, alors assurez-vous de bien comprendre pourquoi nous utilisons ces nouvelles stratégies, comment elles fonctionnent et les avantages de les utiliser.

Dans le prochain article, nous découvrirons une méthode hybride géniale entre des algorithmes d'apprentissage par renforcement basés sur la valeur et basés sur des politiques. Il s'agit d'une base de référence pour les algorithmes de pointe : Advantage Actor Critic (A2C). Vous implémenterez un agent qui apprendra à jouer à Outrun!

Si vous avez aimé mon article, veuillez cliquer sur le? ci-dessous autant de fois que vous avez aimé l'article afin que d'autres personnes le voient ici sur Medium. Et n'oubliez pas de me suivre!

Si vous avez des idées, des commentaires, des questions, n'hésitez pas à commenter ci-dessous ou envoyez-moi un email: [email protected], ou tweetez-moi @ThomasSimonini.

Continuez à apprendre, restez génial!

Cours d'apprentissage par renforcement profond avec Tensorflow? ️

? Programme

? Version vidéo

Partie 1: Une introduction à l'apprentissage par renforcement

Partie 2: Approfondir l'apprentissage par renforcement avec Q-Learning

Partie 3: Une introduction à Deep Q-Learning: jouons à Doom

Partie 3+: Améliorations de l'apprentissage en profondeur Q: double DQN en duel, relecture d'expérience prioritaire et cibles Q fixes

Partie 4: Une introduction aux dégradés de politique avec Doom et Cartpole

Partie 5: Une introduction aux méthodes Advantage Actor Critic: jouons à Sonic the Hedgehog!

Partie 6: Optimisation de la politique proximale (PPO) avec Sonic the Hedgehog 2 et 3

Partie 7: L'apprentissage guidé par la curiosité simplifié Partie I