Au lieu d'estimer la valeur de chaque action, l'algorithme ajuste directement la stratégie : une probabilité de choisir chaque action dans chaque situation. Les actions qui ont rapporté plus que prévu deviennent plus probables. C'est la base des méthodes modernes comme PPO, et la voie naturelle quand les actions sont continues.
Un chargé de recouvrement suit un script de relance. Quand un dossier se termine mieux que d'habitude, il renforce un peu ses réflexes du moment ; quand il se termine moins bien, il les atténue. Son style évolue par petites touches.
Pour chaque situation, ici la semaine de retard, un score par action est converti en probabilités par la fonction softmax. Au départ, toutes les actions sont équiprobables.
L'algorithme tire ses actions selon ces probabilités jusqu'à la fin de l'épisode, ici le paiement ou le contentieux. Il note le gain obtenu à partir de chaque décision.
Chaque action jouée voit sa probabilité augmenter si le gain dépasse la moyenne habituelle (la référence), et baisser sinon. C'est une montée de gradient sur le gain espéré.
Chaque semaine pendant 4 semaines, trois options : attendre, envoyer un email (0,50 €), appeler (10 €). Le simulateur fixe la chance de paiement selon l'action et l'ancienneté du retard. Sans paiement au bout de 4 semaines, le dossier part au contentieux (20 € de frais).
L'algorithme converge vers : email les deux premières semaines, appel les deux suivantes. La stratégie s'affiche sous forme de probabilités, lisibles par le service recouvrement.
Montant encaissé, moins le coût des relances et les frais de contentieux. Dans l'exemple, la stratégie apprise rapporte 133 € par dossier en moyenne, contre 122 € quand on appelle chaque semaine.
REINFORCE, la version historique du policy gradient, a peu de réglages. Ils décident pourtant de la convergence.
Taille de chaque correction de la stratégie. Il dépend de l'échelle des gains : avec des gains en centaines d'euros, il faut un pas petit (0,001 dans l'exemple), sinon la stratégie saute d'un extrême à l'autre.
On compare le gain obtenu au gain moyen habituel plutôt qu'à zéro. La direction moyenne de l'apprentissage ne change pas, mais le bruit baisse fortement. Sans référence, avec des gains presque toujours positifs, toute action jouée serait renforcée : seule l'intensité ferait la différence, et l'apprentissage serait bien plus lent.
Chaque épisode donne une estimation très bruitée du gradient. Il en faut des milliers : on suit la courbe du gain moyen et on arrête quand elle se stabilise.
# Relances d'impayés : Policy Gradient (REINFORCE) en Python
import numpy as np
import pandas as pd
rng = np.random.default_rng(42)
cout_action = np.array([0.0, 0.5, 10.0])
# Probabilité que le client paie dans la semaine, par semaine (lignes) et action (colonnes)
p_paiement = np.array([[0.08, 0.22, 0.25], [0.08, 0.22, 0.25], [0.05, 0.10, 0.35], [0.05, 0.10, 0.35]])
theta = np.zeros((4, 3)) # la stratégie : un score par semaine et par action
reference = np.zeros(4) # gain moyen observé à partir de chaque semaine
politique = lambda s: np.exp(theta[s]) / np.exp(theta[s]).sum() # softmax : scores -> probabilités
def dossier(choix): # une facture de 200 € ; 20 € de frais de contentieux si impayée après 4 semaines
visites, gains = [], []
for s in range(4):
a = choix(s)
paye = rng.random() < p_paiement[s, a]
visites.append((s, a))
gains.append(200 * paye - cout_action[a] - 20 * (s == 3 and not paye))
if paye:
break
return visites, np.cumsum(gains[::-1])[::-1] # gain cumulé de chaque semaine jusqu'à la fin
for episode in range(30000):
visites, G = dossier(lambda s: rng.choice(3, p=politique(s)))
for (s, a), g in zip(visites, G):
gradient = np.eye(3)[a] - politique(s) # dérivée du log de la probabilité de l'action jouée
theta[s] += 0.001 * (g - reference[s]) * gradient # renforcer ce qui a payé mieux que prévu
reference[s] += 0.01 * (g - reference[s])
print(pd.DataFrame([politique(s) for s in range(4)], columns=["attendre", "email", "appel"], index=["sem. 1", "sem. 2", "sem. 3", "sem. 4"]).round(2))
print("Gain moyen, stratégie apprise :", round(np.mean([dossier(lambda s: politique(s).argmax())[1][0] for _ in range(20000)]), 1), "€")
print("Gain moyen, appel chaque semaine :", round(np.mean([dossier(lambda s: 2)[1][0] for _ in range(20000)]), 1), "€")
Le policy gradient se pratique en Python (NumPy pour la version pédagogique, PyTorch et stable-baselines3 en production) : pas d'équivalent R courant.
Le Q-learning apprend la valeur de chaque action, puis choisit la meilleure. Le policy gradient apprend directement la probabilité de choisir chaque action. Il gère plus naturellement les actions continues et les stratégies aléatoires, au prix d'un apprentissage plus bruité.
C'est le policy gradient le plus simple, publié par Ronald Williams en 1992. Après chaque épisode, il augmente la probabilité des actions jouées en proportion du gain obtenu, souvent diminué d'une référence pour réduire le bruit.
Une combinaison des deux approches. L'acteur est la stratégie, apprise par policy gradient ; le critique estime la valeur des situations et sert de référence. A2C et PPO fonctionnent sur ce principe.
Un policy gradient qui limite la taille de chaque mise à jour. C'est lui qu'on utilise en pratique.
Voir la fiche → l'approche par la valeurEstime la valeur de chaque action puis choisit la meilleure. Plus efficace sur les petits problèmes à actions discrètes.
Voir la fiche → l'application phareL'alignement des LLM repose sur un policy gradient : la stratégie est le modèle de langage, la récompense vient des préférences humaines.
Voir la fiche →Dataistudio forme les équipes au machine learning et à l'IA, sur des cas concrets.
Nous utilisons des cookies de mesure d'audience et de suivi publicitaire pour comprendre la fréquentation du site et l'efficacité de nos annonces. Rien n'est déposé sans votre accord. En savoir plus