web-dev-qa-db-fra.com

Comment comprendre l'algorithme d'optimisation de stratégie proximale dans RL?

Je connais les bases de l'apprentissage par renforcement, mais quels termes il est nécessaire de comprendre pour pouvoir lire article PPO d'arxiv ?

Quelle est la feuille de route à apprendre et à utiliser PPO ?

31
Alexander Cyberman

Pour mieux comprendre PPO, il est utile d’examiner les principales contributions du document, à savoir: (1) l’objectif de substitution tronqué et (2) l’utilisation de "plusieurs époques de montée de gradient stochastique pour effectuer chaque mise à jour de politique".


Tout d’abord, pour fonder ces points dans l’original document PPO :

Nous avons introduit [PPO], une famille de méthodes d’optimisation de politique qui utilise plusieurs époques de montée de gradient stochastique pour effectuer chaque mise à jour de politique . Ces méthodes ont la stabilité et la fiabilité des méthodes de la région de confiance [ TRPO ], mais elles sont beaucoup plus simples à mettre en œuvre, nécessitant uniquement quelques lignes de code changent en une implémentation à gradient de politique Vanilla , applicable dans des paramètres plus généraux (par exemple, lors de l'utilisation d'une architecture conjointe pour la fonction de stratégie et de valeur) et ont de meilleures performances globales.


1. L’objectif de substitution découpé

L'objectif de remplacement tronqué est un remplacement immédiat de l'objectif de gradient de stratégie conçu pour améliorer la stabilité de l'entraînement en limitant les modifications apportées à votre stratégie à chaque étape.

Pour les gradients de stratégie de Vanilla (par exemple, REINFORCE) - que vous devriez connaître, ou familiarisez-vous avec avant de lire ceci - l'objectif utilisé pour optimiser le réseau de neurones ressemble à ceci:

PG objective

C'est la formule standard que vous verriez dans les livre de Sutton , et autreressources , où l'avantage (A chapeau) est souvent remplacé par le retour réduit. En prenant un pas de montée en pente sur cette perte par rapport aux paramètres du réseau, vous stimulerez les actions qui ont conduit à une plus grande récompense.

La méthode de gradient de stratégie Vanilla utilise la probabilité de consignation de votre action (log π (a | s)) pour suivre l'impact des actions, mais vous pouvez imaginer utiliser une autre fonction pour le faire. Une autre fonction de ce type, introduite dans le présent document , utilise la probabilité de l’action sous la politique actuelle (π (a | s)), divisée par la probabilité de l’action sous votre politique précédente (π_old (a | s)). Cela ressemble un peu à l'échantillonnage d'importance si vous êtes familier avec cela:

r eq

Ce r (θ) sera supérieur à 1 lorsque l'action est plus probable pour votre politique actuelle qu'elle ne l'est pour votre politique old; il sera compris entre 0 et 1 lorsque l'action est moins probable pour votre police actuelle que pour votre ancienne.

Maintenant, pour construire une fonction objectif avec ce r (θ), nous pouvons simplement l'échanger pour le terme log π (a | s). Voici ce que fait la méthode TRPO:

TRPO objective

Mais que se passerait-il ici si votre action est beaucoup plus probable (comme 100x plus) pour votre politique actuelle? r (θ ) aura tendance à être vraiment gros et à conduire à de grands pas de gradient qui pourraient ruiner votre politique. Pour remédier à ce problème et à d’autres, la méthode TRPO ajoute plusieurs options supplémentaires (contraintes de divergence KL, par exemple) afin de limiter les modifications pouvant être apportées à la stratégie et de garantir son amélioration monotone.

Au lieu d'ajouter tous ces éléments supplémentaires, que se passerait-il si nous pouvions intégrer ces propriétés à la fonction objectif? C'est ce que fait PPO. Il offre les mêmes avantages en termes de performances et évite les complications en optimisant ce simple (mais plutôt drôle) Clipped Surrogate Objective:

annotated clipped surrogate

Le premier terme (bleu) à l'intérieur de la minimisation est le même terme (r (θ) A) que nous avons vu dans l'objectif TRPO. Le second terme (en rouge) est une version où le (r (θ)) est coupé entre (1 - e, 1 + e). (Dans le document, ils indiquent une bonne valeur pour e est d'environ 0,2, donc r peut varier entre ~ (0,8, 1,2)). Enfin, finalement, la minimisation de ces deux termes est prise (vert).

Prenez votre temps, examinez attentivement l'équation et assurez-vous de bien comprendre la signification de tous les symboles et, mathématiquement, ce qui se passe. Regarder le code peut aussi aider; Voici la section pertinente dans les deux implémentations OpenAI baselines et anyrl-py .

Génial.

Ensuite, voyons quel effet la fonction de clip L crée. Voici un diagramme tiré du papier qui trace la valeur de l'objectif de la pince lorsque l'avantage est positif ou négatif:

Clip intro

Sur la moitié gauche du diagramme, où (A> 0), c’est là que l’action a eu un effet positif estimé sur le résultat. Sur la moitié droite du diagramme, où (A <0), c’est là que l’action a eu un effet négatif estimé sur le résultat.

Notez que sur la moitié gauche, la valeur r est coupée si elle est trop élevée. Cela se produira si l'action est devenue beaucoup plus probable avec la politique actuelle que pour l'ancienne politique. Lorsque cela se produit, nous ne voulons pas être trop gourmands ni aller trop loin (car il ne s'agit que d'une approximation locale et d'un échantillon de notre politique, de sorte que ce ne sera pas précis si nous allons trop loin), et nous découpons donc l'objectif d'empêcher de grandir. (Ceci aura pour effet dans la passe en arrière de bloquer le dégradé - la ligne plate causant le dégradé à 0).

Sur le côté droit du diagramme, où l'action a eu un effet estimé négatif sur le résultat, nous voyons que le clip s'active près de 0, où l'action sous la stratégie actuelle est peu probable. De la même manière, cette zone de découpage nous empêchera de mettre à jour trop pour rendre l’action beaucoup moins probable après que nous ayons déjà fait un grand pas en avant.

Nous voyons donc que ces deux régions de découpage nous empêchent d’être trop gourmands et d’essayer d’actualiser trop à la fois et de quitter la région où cet échantillon offre une bonne estimation.

Mais pourquoi laissons-nous le r (θ) croître indéfiniment à l'extrême droite du diagramme? Cela semble étrange en premier lieu, mais qu'est-ce qui ferait que r (θ) devienne vraiment très grand dans ce cas? beaucoup plus probable, et il s'avère que notre politique est pire. Si c'était le cas, nous voudrions pouvoir annuler cette étape de dégradé. Et il se trouve que la fonction de clip L le permet. La fonction est négative ici, donc la pente nous dira de marcher dans l'autre sens et de rendre l'action moins probable d'un montant proportionnel à ce que nous avons tout gâché. (Notez qu'il existe une région similaire à l'extrême gauche du diagramme, où l'action est bonne et que nous avons accidentellement rendue moins probable.)

Ces régions "défaites" expliquent pourquoi nous devons inclure le terme étrange de minimisation dans la fonction objectif. Ils correspondent au r (θ) A non écrêté ayant une valeur inférieure à la version découpée et renvoyé par la minimisation. C’est parce qu’ils allaient dans la mauvaise direction (par exemple, l’action était bonne mais nous l’avons accidentellement rendue moins probable). Si nous n'avions pas inclus le min dans la fonction objectif, ces régions seraient plates (gradient = 0) et nous ne serions pas en mesure de corriger les erreurs.

Voici un schéma résumant ceci:

L Clip Diagram

Et c'est là l'essentiel. L’objectif Clipping Surrogate n’est qu’un remplacement immédiat que vous pouvez utiliser dans le dégradé de la règle Vanilla. Le découpage limite le changement effectif que vous pouvez effectuer à chaque étape pour améliorer la stabilité, et la minimisation nous permet de corriger nos erreurs au cas où nous nous en serions occupés. Une chose dont je n’ai pas parlé est ce que l’on entend par "PPO" comme "limite inférieure", comme indiqué dans le document. Pour plus d'informations à ce sujet, je suggérerais cette partie d'une conférence donnée par l'auteur.

2. Plusieurs époques pour la mise à jour des politiques

Contrairement aux méthodes de gradient de règle Vanilla, et en raison de la fonction d'objet Clipping Surrogate, PPO vous permet d'exécuter plusieurs époques de montée en pente sur vos échantillons sans provoquer de mises à jour de stratégie destructrices. Cela vous permet de tirer davantage de vos données et de réduire l'inefficacité de l'échantillon.

PPO exécute la politique en utilisant N chacun des acteurs parallèles collectant des données, puis il échantillonne des mini-lots de ces données pour se former à K époques utilisant la fonction objectif de substitution tronquée. Voir l'algorithme complet ci-dessous (les valeurs approximatives de param sont: K = 3-15, M = 64-4096, T (horizon) = 128-2048):

PPO Algo

La partie acteurs parallèles a été popularisée par le A3C et est devenue un moyen assez standard de collecte de données.

La partie la plus récente est qu’ils sont capables de courir K époques d’ascension de gradient sur les échantillons de trajectoire. Comme ils le déclarent dans le document, il serait judicieux d'exécuter l'optimisation de gradient de politique Vanilla pour plusieurs passages sur les données afin que vous puissiez en apprendre davantage sur chaque échantillon. Cependant, cela échoue généralement dans la pratique pour les méthodes Vanilla car elles prennent trop de mesures sur les échantillons locaux, ce qui nuit à la stratégie. PPO, en revanche, dispose du mécanisme intégré pour empêcher une mise à jour excessive.

Pour chaque itération, après avoir échantillonné l'environnement avec π_old (ligne 3) et lorsque nous commençons à exécuter l'optimisation (ligne 6), notre politique π sera exactement égale à π_old. Ainsi, au début, aucune de nos mises à jour ne sera coupée et nous avons la garantie d'apprendre quelque chose de ces exemples. Cependant, à mesure que nous mettons à jour π en utilisant plusieurs périodes, l'objectif commence à atteindre les limites de découpage, le gradient passe à 0 pour ces échantillons et la formation s'arrête progressivement ... jusqu'à ce que nous passions à la prochaine itération et que nous en collections de nouveaux. .

....

Et c'est tout pour le moment. Si vous souhaitez mieux comprendre, je vous recommanderais de creuser davantage le document original , d'essayer de le mettre en œuvre vous-même ou de plonger dans le mise en œuvre de base et de jouer avec le code.

[edit: 2019/01/27]: Pour un meilleur arrière-plan et pour le lien qui existe entre PPO et d’autres RL algorithmes, je vous recommanderais aussi fortement de vérifier les ressources OpenAI ressources et implémentations Spinning Up .

81
matwilso

PPO est un algorithme simple, qui entre dans la classe des algorithmes d'optimisation de politique (par opposition aux méthodes basées sur la valeur telles que DQN). Si vous "connaissez" RL les bases (je veux dire si vous avez au moins lu attentivement les premiers chapitres de livre de Sutton par exemple)), une première étape logique consiste alors à: Familiarisez-vous avec les algorithmes de gradient de politique.Vous pouvez lire cet article ou le chapitre 13 de livre de Sutton nouvelle édition. Vous pouvez également lire cet article sur TRPO, qui est un travail précédent du premier auteur de PPO (cet article comporte de nombreuses erreurs de notation; il suffit de noter).

9
Mehdi

PPO, et y compris TRPO, tente de mettre à jour la stratégie de manière conservatrice, sans affecter négativement ses performances, entre chaque mise à jour de la stratégie.

Pour ce faire, vous avez besoin d'un moyen de mesurer le degré de modification de la stratégie après chaque mise à jour. Cette mesure est effectuée en regardant l'écart KL entre la politique mise à jour et l'ancienne politique.

Cela devient un problème d'optimisation contraint, nous voulons changer la politique dans le sens de la performance maximale, en respectant les contraintes que la divergence KL entre ma nouvelle politique et l'ancienne ne dépasse pas un seuil prédéfini (ou adaptatif).

Avec TRPO, nous calculons la contrainte KL lors de la mise à jour et trouvons le taux d'apprentissage de ce problème (via Fisher Matrix et gradient conjugué). C'est un peu compliqué à mettre en œuvre.

Avec PPO, nous simplifions le problème en transformant la divergence de KL d’une contrainte en un terme de pénalité, similaire à par exemple à une pénalité de poids L1, L2 (pour éviter que des poids ne grossissent de grandes valeurs). PPO apporte des modifications supplémentaires en éliminant la nécessité de calculer la divergence de KL dans son ensemble, en écrasant durement le ratio de la politique (ratio de la politique mise à jour avec l'ancienne) afin qu'il se situe dans une fourchette proche de 1,0, où 1,0 signifie que la nouvelle politique est identique à l'ancienne.

9
Sunrisetofu

Je pense que la mise en œuvre pour un espace d'action discret tel que Cartpole-v1 est plus facile que pour des espaces d'action continue. Mais pour les espaces d’action continue, c’est l’implémentation la plus simple que j’ai trouvée dans Pytorch car vous pouvez voir clairement comment ils obtiennent mu et std où je ne pouvais pas utiliser des implémentations plus renommées telles que Lignes de base Openai et bases de démarrage en rotation ou stables.

RL-Adventure PPO

Ces lignes du lien ci-dessus:

class ActorCritic(nn.Module):
    def __init__(self, num_inputs, num_outputs, hidden_size, std=0.0):
        super(ActorCritic, self).__init__()

        self.critic = nn.Sequential(
            nn.Linear(num_inputs, hidden_size),
            nn.ReLU(),
            nn.Linear(hidden_size, 1)
        )

        self.actor = nn.Sequential(
            nn.Linear(num_inputs, hidden_size),
            nn.ReLU(),
            nn.Linear(hidden_size, num_outputs),
        )
        self.log_std = nn.Parameter(torch.ones(1, num_outputs) * std)

        self.apply(init_weights)

    def forward(self, x):
        value = self.critic(x)
        mu    = self.actor(x)
        std   = self.log_std.exp().expand_as(mu)
        dist  = Normal(mu, std)
        return dist, value

et la coupure:

def ppo_update(ppo_epochs, mini_batch_size, states, actions, log_probs, returns, advantages, clip_param=0.2):
    for _ in range(ppo_epochs):
        for state, action, old_log_probs, return_, advantage in ppo_iter(mini_batch_size, states, actions, log_probs, returns, advantages):
            dist, value = model(state)
            entropy = dist.entropy().mean()
            new_log_probs = dist.log_prob(action)

            ratio = (new_log_probs - old_log_probs).exp()
            surr1 = ratio * advantage
            surr2 = torch.clamp(ratio, 1.0 - clip_param, 1.0 + clip_param) * advantage

J'ai trouvé le lien au dessus des commentaires sur cette vidéo sur Youtube:

arxiv insights PPO

1
mLstudent33