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.