Policy gradient и REINFORCE

Урок знакомит с другим семейством методов — policy gradient, которые учат политику напрямую.

Policy gradient — это класс методов, которые обучают параметризованную политику напрямую, повышая вероятность действий, приведших к высокой награде. REINFORCE — простейший такой алгоритм.

Два пути к политике

До сих пор мы шли value-based путём: учили Q, а политику получали как argmax. Policy gradient идёт иначе — напрямую параметризует политику pi(a|s) (например, нейросетью, выдающей вероятности действий) и подкручивает её параметры так, чтобы хорошие действия становились вероятнее.

Value-based (Q-learning)Policy-based (REINFORCE)
Что учимфункцию ценности Qполитику pi(a|s) напрямую
Действиеargmax Qсэмплируем из pi
Непрерывные действиясложноестественно

Идея REINFORCE

Логика проста и интуитивна: сыграй эпизод, посмотри на итоговый возврат. Если он высокий — увеличь вероятность действий, которые ты делал; если низкий — уменьши. Формально это градиентный подъём: параметры сдвигают в сторону, повышающую ожидаемую награду. Множитель «насколько сдвигать» — это возврат G: чем больше итоговая награда, тем сильнее закрепляем выбранные действия.

Обновление REINFORCE (идея):
  для каждого шага эпизода:
    параметры += alpha * G * градиент(log pi(a|s))
  где G — возврат с этого шага до конца эпизода

Интуиция формулы: log pi(a|s) растёт, когда мы повышаем вероятность действия a; умножая на возврат G, мы повышаем вероятности тем сильнее, чем удачнее оказался эпизод.

Почему стохастическая политика — это плюс

Policy gradient естественно работает со стохастическими политиками (распределением над действиями). Это удобно: исследование встроено в саму политику (мы сэмплируем действия), не нужен отдельный epsilon. А ещё это незаменимо для непрерывных действий (угол поворота руля, сила нажатия), где argmax по бесконечному множеству действий взять нельзя.

import random, math
random.seed(0)

# Стохастическая политика над 3 действиями через softmax от "предпочтений".
def softmax(prefs):
    m = max(prefs)
    exps = [math.exp(p - m) for p in prefs]
    s = sum(exps)
    return [e / s for e in exps]

prefs = [0.0, 0.0, 0.0]
true_reward = [0.2, 0.5, 0.9]   # действие 2 — лучшее
for _ in range(300):
    probs = softmax(prefs)
    r = random.random()
    a = 0 if r < probs[0] else (1 if r < probs[0] + probs[1] else 2)
    reward = 1.0 if random.random() < true_reward[a] else 0.0
    prefs[a] += 0.05 * (reward - 0.5)   # повышаем предпочтение удачных действий

probs = softmax(prefs)
print("Итоговые вероятности действий:", [round(p, 2) for p in probs])
print("Самое вероятное действие:", max(range(3), key=lambda i: prefs[i]))

Вывод:

Итоговые вероятности действий: [0.01, 0.02, 0.96]
Самое вероятное действие: 2

Это упрощённая иллюстрация духа policy gradient: вероятность выгодного действия растёт. Настоящий REINFORCE с нейросетью использует автодифференцирование (PyTorch) и здесь не запускается.

Как работает под капотом

Главная боль REINFORCE — высокая дисперсия градиента: возврат сильно «шумит» от эпизода к эпизоду, и обучение скачет. Стандартное лекарство — вычесть базовую линию (baseline), обычно оценку V(s): тогда множитель становится не G, а «преимущество» G − V(s) — насколько действие лучше среднего. Эта идея ведёт прямо к actor-critic из следующего урока.

Частые ошибки

  • Забыть про дисперсию. Чистый REINFORCE без baseline учится медленно и нестабильно.
  • Сделать политику детерминированной слишком рано. Тогда исчезает исследование и агент застревает.
  • Путать знак. Это градиентный подъём (максимизируем награду), а не спуск; легко ошибиться со знаком в коде.

Итоги

  • Policy gradient учит политику напрямую, повышая вероятность выгодных действий.
  • REINFORCE: сдвигаем параметры на alpha · G · градиент(log pi(a|s)).
  • Плюсы — стохастичность и непрерывные действия; минус — высокая дисперсия, которую снижает baseline.
Проверьте себя
1. Чем policy gradient отличается от value-based методов вроде Q-learning?
AОн не использует награды
BОн обучает политику напрямую, а не выводит её из функции ценности
CОн работает только с таблицами
DОн не требует среды
2. Что служит множителем при обновлении параметров в REINFORCE?
AСкорость обучения
BВозврат G — чем выше итоговая награда, тем сильнее закрепляются выбранные действия
CЧисло действий
DРазмер сети
3. Зачем в policy gradient вычитают базовую линию (baseline)?
AЧтобы ускорить GPU
BЧтобы снизить высокую дисперсию градиента, оценивая преимущество действия над средним
CЧтобы убрать награды
DЧтобы сделать политику детерминированной