Policy Gradient Methods

Les méthodes de gradient de politique (Policy Gradient Methods) sont une classe d’algorithmes d’apprentissage par renforcement où l’agent apprend directement une fonction de politique (plutôt qu’une fonction de valeur comme dans le Q-learning ou SARSA). Ces méthodes visent à optimiser la politique en ajustant les paramètres de la politique à l’aide de gradients de la fonction de récompense attendue par rapport aux paramètres de la politique.

Les algorithmes de gradient de politique utilisent la derivée de la fonction de récompense pour mettre à jour la politique et maximiser la somme des récompenses accumulées. Ces méthodes sont particulièrement utiles dans des environnements complexes avec des espaces d’actions continus ou avec des actions stochastiques.

Formule du Gradient de Politique :

La mise à jour des paramètres θ\theta de la politique est effectuée en utilisant le gradient de la fonction de performance par rapport aux paramètres de la politique θ\theta :

 

θt+1=θt+αθJ(θ)\theta_{t+1} = \theta_t + \alpha \nabla_{\theta} J(\theta)

 

Où :

Fonctions :

  • Policy Gradient Methods (exemple)

    Voici un exemple d'un agent utilisant Policy Gradient dans un environnement CartPole-v1 de OpenAI Gym en utilisant TensorFlow pour créer le réseau de neurones de la politique :

    Exemple de code :

    import gymnasium as gym
    import numpy as np
    import tensorflow as tf
    from tensorflow.keras import layers
    
    env = gym.make('CartPole-v1')
    state_size = env.observation_space.shape[0]
    action_size = env.action_space.n
    
    # Hyperparamètres
    learning_rate = 0.01
    gamma = 0.99
    episodes = 10
    
    # Modèle de politique (policy network)
    model = tf.keras.Sequential([
        layers.Dense(24, activation='relu', input_shape=(state_size,)),
        layers.Dense(24, activation='relu'),
        layers.Dense(action_size, activation='softmax')  # distribution de probas sur les actions
    ])
    
    optimizer = tf.keras.optimizers.Adam(learning_rate=learning_rate)
    
    def choose_action(state):
        state = state.reshape([1, state_size])
        prob = model(state).numpy()[0]
        return np.random.choice(action_size, p=prob)
    
    def discount_rewards(rewards, gamma):
        discounted = np.zeros_like(rewards, dtype=np.float32)
        cumulative = 0.0
        for i in reversed(range(len(rewards))):
            cumulative = rewards[i] + gamma * cumulative
            discounted[i] = cumulative
        return discounted
    
    for episode in range(episodes):
        state, _ = env.reset()
        done = False
    
        states = []
        actions = []
        rewards = []
    
        while not done:
            action = choose_action(state)
            next_state, reward, terminated, truncated, _ = env.step(action)
            done = terminated or truncated
    
            states.append(state)
            actions.append(action)
            rewards.append(reward)
    
            state = next_state
    
        # Calcul des récompenses cumulées
        discounted_rewards = discount_rewards(rewards, gamma)
        discounted_rewards -= np.mean(discounted_rewards)
        discounted_rewards /= (np.std(discounted_rewards) + 1e-8)
    
        with tf.GradientTape() as tape:
            loss = 0
            for i in range(len(states)):
                state_input = states[i].reshape([1, state_size])
                probs = model(state_input)
                action_prob = probs[0, actions[i]]
                log_prob = tf.math.log(action_prob + 1e-8)
                loss += -log_prob * discounted_rewards[i]
            loss /= len(states)
    
        grads = tape.gradient(loss, model.trainable_variables)
        optimizer.apply_gradients(zip(grads, model.trainable_variables))
    
        total_reward = sum(rewards)
        print(f"Episode {episode+1}: Total Reward = {total_reward}")

    Explication du code :

    1. Initialisation de l’environnement CartPole
    - Environnement : `CartPole-v1` de Gymnasium. - Taille de l’état (`state_size`) : 4. - Nombre d’actions (`action_size`) : 2.
    2. Modèle de politique (Policy Network)
    - Réseau neuronal séquentiel : - Couche dense 1 : 24 neurones, activation `relu`, input `(state_size,)`. - Couche dense 2 : 24 neurones, activation `relu`. - Couche de sortie : `action_size` neurones, activation `softmax` (distribution de probabilités sur les actions). - Optimiseur : Adam avec un taux d’apprentissage `learning_rate = 0.01`.
    3. Politique stochastique d’action
    - L’action est échantillonnée à partir de la distribution de probabilités sortie par le modèle (softmax). - Cette politique permet d’explorer naturellement l’espace des actions.
    4. Calcul des récompenses cumulées (discounted rewards)
    - Pour chaque épisode, les récompenses obtenues sont transformées en récompenses cumulées à facteur d’actualisation `gamma = 0.99` : \[ G_t = r_t + \gamma r_{t+1} + \gamma^2 r_{t+2} + \dots \] - Les récompenses cumulées sont ensuite centrées (soustraction de la moyenne) et normalisées (division par l’écart-type) pour stabiliser l’apprentissage.
    5. Mise à jour du modèle par Policy Gradient (REINFORCE)
    - Pour chaque étape de l’épisode : - Calcul de la probabilité de l’action prise par le modèle. - Calcul du logarithme de cette probabilité. - Pondération par la récompense cumulée correspondante (avantage). - La fonction de perte est la somme négative des log-probabilités pondérées par les récompenses cumulées (maximisation de la probabilité des actions ayant généré de bonnes récompenses). - Calcul du gradient via `tf.GradientTape`. - Application des gradients à l’aide de l’optimiseur Adam.
    6. Boucle d’entraînement
    - Pour chaque épisode (au total 500) : - Réinitialisation de l’environnement. - Collecte de la trajectoire complète (états, actions, récompenses). - Calcul des récompenses cumulées et normalisation. - Calcul et application de la mise à jour du modèle via Policy Gradient. - Affichage de la récompense totale de l’épisode.