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Чтобы сделать политику детерминированной
py
Курс по теме
Пройдите курс «Python с нуля» — по шагам, с проверкой
8 уроков · ~14 ч · теория, упражнения и экзамен с бейджем
Открыть курс →