Actor-critic, GAE и PPO полностью
Градиент политики с выводом на пальцах, REINFORCE, baseline и преимущество, актор и критик, GAE с числовым примером, PPO целиком — clipped objective, value loss, энтропия — и как всё это ложится на языковую модель.
Зачем это нужно
Заголовок раздела «Зачем это нужно»В прошлых уроках агент сначала учил ценности ( или ), а политику получал из них: «в каждом состоянии бери действие с наибольшим ». Для языковой модели этот путь неудобен. Действий — около 150 тысяч токенов, состояний — бесконечно много, а главное, после претрейна и SFT у нас уже есть хорошая политика: softmax над словарём. Естественно улучшать её напрямую — двигать параметры так, чтобы средняя награда росла. Это методы градиента политикиградиент политикиEN policy gradient∇J = E[r · ∇ log π(y|x)] — основа REINFORCE, PPO и GRPO..
Урок собирает их по кирпичику: градиент политики → REINFORCE → baseline и преимущество → актор и критик → GAE → PPO. PPO — именно тот алгоритм, которым OpenAI обучала InstructGPT, а GRPO из DeepSeek-R1 — его упрощение. После урока вы сможете прочитать их формулы целиком и сказать, что означает каждый символ.
Градиент политики на пальцах
Заголовок раздела «Градиент политики на пальцах»Политика — нейросеть с параметрами , которая выдаёт вероятности действий. Цель — средняя отдача , где — траекториятраекторияEN trajectoryПолная запись эпизода агента — все мысли, вызовы инструментов и наблюдения. Единица данных для оценки и agentic RL. эпизода, а — её отдача.
Проблема. Обычный backprop здесь не работает: действия сэмплируются (дискретная операция), а награду выдаёт среда — чёрный ящик, у которого нет производной.
Трюк с логарифмом. Распишем матожидание как сумму по траекториям и продифференцируем (урок 1.2.3). От зависят только вероятности:
Во втором равенстве использовано — просто производная логарифма: . Результат снова матожидание, а его можно оценить сэмплами — сыграть несколько эпизодов и усреднить.
Куда делась среда. Вероятность траектории — произведение вероятностей шагов: . Логарифм превращает произведение в сумму, а слагаемые среды и от не зависят и при дифференцировании исчезают. Остаётся
Как читать: — направление, в котором растёт вероятность выбранного действия. Шагаем в этом направлении с весом : действия из удачных эпизодов становятся вероятнее, из неудачных — реже. Модель среды не нужна — только умение играть эпизоды и считать .
Пример с числами. Два действия, «влево» и «вправо», логиты , вероятности по 0.5. Градиент по логитам — «one-hot минус вероятности» (вы считали его в уроке 2.2.2). Сыграли эпизод, выбрали «вправо», отдача . Градиент , шаг подъёма с даёт и . Модель стала чаще выбирать «вправо», хотя никто не говорил ей, что это правильно.
REINFORCE и reward-to-go
Заголовок раздела «REINFORCE и reward-to-go»Алгоритм REINFORCEREINFORCEEN REINFORCEАлгоритм Уильямса (1992) — оценка градиента политики по сэмплам эпизодов (метод Монте-Карло). (Уильямс, 1992) — прямое применение формулы: сыграть эпизоды текущей политикой, посчитать , сделать шаг, повторить.
Первое улучшение — причинность. Действие на шаге не может повлиять на награды, полученные до него. Значит, вместо отдачи всего эпизода каждое действие можно взвешивать только будущими наградами — отдачей из урока 6.0.1. Её называют reward-to-go. Матожидание градиента не меняется, а шум из прошлых наград уходит:
Важное свойство REINFORCE: он on-policyon-policy (обучение на данных текущей политики)EN on-policyПротивоположность — off-policy, обучение на данных другой политики.. Формула верна только для эпизодов, сыгранных текущей политикой. Сделали шаг — старые эпизоды «протухли», нужно играть заново.
Baseline и преимущество
Заголовок раздела «Baseline и преимущество»Второе улучшение лечит огромный разброс. Пусть «вправо» в среднем приносит 2, а «влево» — 1, и все отдачи положительны. Если в том же примере выпадет «влево» с отдачей 1, шаг даст , и вероятность «влево» вырастет до 0.525, хотя это худшее действие. Лучшее победит только в среднем по многим эпизодам — обучение шумное и медленное.
Лекарство — вычесть из веса базовую линиюбазовая линия (baseline)EN baselineЧисло, которое вычитают из награды; не смещает градиент политики, но снижает его дисперсию. , которая не зависит от действия:
Почему можно: . Вычитаемое в среднем даёт ноль, матожидание градиента не меняется, а разброс падает. Возьмём (среднюю отдачу). «Вправо» с получает вес , «влево» с — вес , и оба эпизода сдвигают логиты одинаково: , . Теперь даже неудачный эпизод учит правильному.
Какой baseline лучший? Почти оптимален — средняя отдача из этого состояния. Тогда вес — это оценка преимуществапреимущество (advantage)EN advantageA = r − b или A(s, a) = Q(s, a) − V(s): насколько действие лучше среднего в этой ситуации. из урока 6.0.1: «насколько это действие оказалось лучше, чем обычно бывает в этом состоянии». Знак решает, поднимать вероятность или опускать. Но нам неизвестна — её нужно учить.
Actor-critic: актор и критик
Заголовок раздела «Actor-critic: актор и критик»Схема актор-критикактор-критик (actor-critic)EN actor-criticДве сети — актор (политика) и критик (оценка V); критик даёт актору оценку преимущества. учит две модели одновременно:
- Актор — политика . Учится градиентом политики, где вес действия — оценка преимущества .
- Критиккритик, value-модельEN critic / value modelСеть, предсказывающая ожидаемую награду из текущего состояния; в PPO служит baseline для каждого токена. — функция ценности . Учится регрессией: предсказывать отдачу из состояния, loss , где — цель для критика (отдача или её оценка).
flowchart LR E["Среда"] -->|"состояния и награды"| C["Критик V_ψ(s)"] E --> B["Батч траекторий"] A["Актор: политика π_θ"] -->|"действия"| E C -->|"V(s_t)"| G["Оценка преимущества (GAE)"] B --> G G -->|"Â_t: что было лучше обычного"| A G -->|"цели R̂_t"| C
Как получить из критика? Вспомним TD-ошибку из урока 6.0.2:
В среднем по случайности среды — это , поэтому — оценка преимущества по одному шагу: шума мало (одна награда), но она целиком доверяет критику. Можно взять больше настоящих наград — -шаговая оценка. Удобный факт: она равна сумме TD-ошибок, потому что промежуточные взаимно сокращаются:
При до конца эпизода получаем — Монте-Карло с baseline: без смещения, но с полным шумом.
GAE: взвешенное среднее всех оценок
Заголовок раздела «GAE: взвешенное среднее всех оценок»Какое выбрать? GAEобобщённая оценка преимущества (GAE)EN generalized advantage estimation (GAE)Schulman и др., 2015. Смешивает оценки преимущества разной длины с коэффициентом λ. (generalized advantage estimation, Schulman et al., 2015) не выбирает, а смешивает все: -шаговая оценка берётся с весом . После перегруппировки слагаемых получается простая формула — экспоненциально затухающая сумма TD-ошибок:
Как читать: преимущество действия — его собственный «сюрприз» плюс сюрпризы следующих шагов, которые приписываются ему тем слабее, чем дальше они случились. — ручка между двумя крайностями:
- : — TD, мало шума, но ошибки критика переходят в преимущество (смещение);
- : — Монте-Карло, без смещения, но шумно.
Считают GAE одним проходом с конца траектории, как отдачу в уроке 6.0.1. Цели для критика — .
Откуда берётся формула (вывод в две строки)
-шаговая оценка — сумма первых TD-ошибок: . Смешаем их с весами (в сумме они дают 1) и поменяем порядок суммирования. Ошибка входит во все оценки с , а сумма их весов — геометрическая прогрессия:
Это и есть . В примере ниже проверим численно: при смесь оценок даёт то же , что и рекурсия.
Пример: робот-курьер
Заголовок раздела «Пример: робот-курьер»Эпизод из трёх шагов: робот забрал посылку (), проехал пустой участок (), доставил () — конец. Критик ожидал , после конца , . TD-ошибки:
На шаге 1 критик «разочаровался» (), но на шаге 2 всё кончилось лучше ожидаемого. Преимущества при разных ( — множитель в рекурсии):
| Смысл | ||||
|---|---|---|---|---|
| 0 | 1.0 | −0.6 | 0.35 | только свой шаг: «пустой участок» — плохое действие |
| 0.5 | 1.0 | −0.15 | 0.2825 | будущему верим наполовину |
| 0.95 | 1.0 | 0.255 | 0.568 | типичное значение в PPO |
| 1 | 1.0 | 0.3 | 0.62 | : |
Проверка формулы про шагов: и — совпало.
PPO целиком
Заголовок раздела «PPO целиком»PPOпроксимальная оптимизация политики (PPO)EN proximal policy optimization (PPO)Schulman и др., 2017. Ограничивает шаг обновления «клиппингом» отношения вероятностей. (proximal policy optimization, Schulman et al., 2017) — actor-critic с GAE и тремя инженерными решениями.
Несколько эпох на одном батче
Заголовок раздела «Несколько эпох на одном батче»Сыграть эпизоды — дорого (у LLM генерация — самая медленная часть). Хочется сделать по одному батчу несколько шагов оптимизации. Но после первого шага политика уже не та, что собирала данные: данные стали off-policy (урок 6.0.2). Поправка — выборка по значимостивыборка по значимости (importance sampling)EN importance samplingПеревзвешивание сэмплов старой политики отношением π_new / π_old — основа PPO.: каждый сэмпл взвешивают отношением вероятностей
Если новая политика выбирает действие вдвое чаще старой (), его вклад учитывают с весом 2 — и среднее по старым сэмплам совпадает со средним по новой политике. В момент, когда , градиент равен — ровно градиент политики с преимуществом.
Клиппинг: не уходить далеко
Заголовок раздела «Клиппинг: не уходить далеко»Поправка честна, только пока политики близки: если они разошлись, новая политика попадала бы в другие состояния, а этого отношение не учитывает. Предшественник PPO, TRPOTRPO (оптимизация политики в доверительной области)EN trust region policy optimization (TRPO)Schulman и др., 2015 — шаг политики с ограничением на KL к старой политике; предшественник PPO., ограничивал шаг условием на KL-дивергенцию и решал сложную задачу оптимизации с ограничением. PPO делает проще — обрезает до отрезка (обычно ) и берёт пессимистичный вариант:
Пять случаев при :
| min | Градиент | Смысл | ||||
|---|---|---|---|---|---|---|
| +1 | 1.1 | 1.1 | 1.1 | 1.1 | есть | хорошее действие, поднимаем дальше |
| +1 | 1.5 | 1.5 | 1.2 | 1.2 | 0 | уже подняли на 50% — хватит |
| +1 | 0.5 | 0.5 | 0.8 | 0.5 | есть | хорошее действие стало реже — исправляем |
| −1 | 0.7 | −0.7 | −0.8 | −0.8 | 0 | плохое уже опустили на 30% — хватит |
| −1 | 1.5 | −1.5 | −1.2 | −1.5 | есть | плохое стало чаще — исправляем |
Правило: PPO не даёт уйти слишком далеко в «выгодную» сторону, но всегда даёт исправить ошибку. Проверим кодом — посчитаем цель и её производную по (в неклиппированной ветке ):
import numpy as np
adv = np.array([1.0, 1.0, 1.0, -1.0, -1.0])ratio = np.array([1.1, 1.5, 0.5, 0.7, 1.5]) # ρ = π_θ / π_oldeps = 0.2unclipped = ratio * advclipped = np.clip(ratio, 1 - eps, 1 + eps) * advobjective = np.minimum(unclipped, clipped)grad = np.where(unclipped <= clipped, ratio * adv, 0.0) # градиент есть, только если выбрана ветка ρ·Afor a, r, o, g in zip(adv, ratio, objective, grad): print(f"A={a:+.0f} ρ={r:.1f} цель={o:+.2f} d(цель)/d(log π)={g:+.2f}")A=+1 ρ=1.1 цель=+1.10 d(цель)/d(log π)=+1.10A=+1 ρ=1.5 цель=+1.20 d(цель)/d(log π)=+0.00A=+1 ρ=0.5 цель=+0.50 d(цель)/d(log π)=+0.50A=-1 ρ=0.7 цель=-0.80 d(цель)/d(log π)=+0.00A=-1 ρ=1.5 цель=-1.50 d(цель)/d(log π)=-1.50Полный loss: критик и энтропия
Заголовок раздела «Полный loss: критик и энтропия»Актор и критик часто учат одним оптимизатором, поэтому loss для минимизации складывают из трёх частей:
- Минус клиппированная цель — её мы максимизируем.
- Ошибка критика с весом (в статье для Atari , в популярных реализациях 0.5).
- Энтропийный бонусэнтропийный бонусEN entropy bonusДобавка c·H[π(·|s)] к цели — награда за «неуверенность» политики, чтобы она не схлопнулась раньше времени и продолжала исследовать. с весом (обычно 0–0.01). Энтропияэнтропия (информационная)EN (Shannon) entropyH(p) = −Σ p log p — среднее «удивление», мера неопределённости распределения. Максимальна у равномерного распределения. из урока 1.3.3 велика, когда политика не уверена. Награда за неё не даёт политике слишком рано схлопнуться в одно действие и перестать исследовать — роль ε-жадности из урока 6.0.2.
Ещё один стандартный приём — нормировать преимущества по батчу: . Масштаб наград перестаёт влиять на размер шага. Запомните: в GRPO почти та же нормировка, только по группе ответов на один промпт.
Пример. Батч из четырёх действий: , . Варианты , клиппированные , минимум , цель . Критик ошибся на : MSE . Средняя энтропия 1.0. Loss .
Алгоритм
Заголовок раздела «Алгоритм»- Сыграть шагов текущей политикой , запомнить , и .
- Посчитать , преимущества GAE и цели .
- эпох: перемешать батч, для каждого мини-батча нормировать и сделать шаг по .
- Повторить с новым батчем.
В статье PPO для задач MuJoCo: , , мини-батч 64, Adam с шагом , , . Во время обучения смотрят на три числа: среднюю награду, энтропию (не должна падать до нуля слишком рано), KL между старой и новой политикой и clipfrac — долю сэмплов, где сработал клиппинг. Если KL и clipfrac растут, шаг слишком большой.
Как это переносится на языковую модель
Заголовок раздела «Как это переносится на языковую модель»Всё, что выше, переносится на LLM почти дословно:
| RL-понятие | Классика (CartPole) | Языковая модель |
|---|---|---|
| Действие | толкнуть тележку влево или вправо | следующий токен |
| Состояние | 4 числа: положение, скорость, угол | промпт и уже написанные токены |
| Эпизод | пока шест не упал (до 500 шагов) | один ответ до токена конца |
| Награда | +1 за каждый шаг | оценка ответа в конце + KL-штраф на каждом токене |
| , | 0.99, 0.95 | обычно , около 0.95–1 |
| Актор и критик | две маленькие сети | LLM и её копия со скалярной головой |
Формула InstructGPT (Ouyang et al., 2022, §3.5) записана как цель, которую максимизируют:
Теперь вы читаете её целиком: — актор; — награда от reward model за ответ на промпт ; второе слагаемое — штраф за уход от SFT-модели (подробно — в уроках 6.3.1–6.3.2); последнее слагаемое подмешивает обычный претрейн. Осторожно: здесь — вес претрейна, а не дисконт. Оптимизируют эту цель алгоритмом PPO из этого урока: клиппинг, критик, GAE по токенам.
Формула PPO в DeepSeekMath (Shao et al., 2024, формулы 1–2) — тот же , усреднённый по токенам ответа на вопрос : . Авторы прямо пишут, что считается GAE по наградам и обученной функции ценности , а награда токена — оценка reward model минус . И сразу объясняют, что им не нравится: критик — ещё одна модель размером с политику, а учить его точным на каждом токене трудно, когда награда приходит только на последнем. Так появился GRPO:
| PPO (DeepSeekMath, ф. 1–2) | GRPO (ф. 3) | |
|---|---|---|
| Преимущество | GAE по критику , своё у каждого токена | по группе ответов на промпт, одно на все токены |
| Критик | обучается, размером с политику | нет |
| KL к референсу | в награде на каждом токене | отдельным слагаемым в loss |
| Клиппинг | есть | есть |
| Ответов на промпт | обычно один | группа из (в статье 64) |
Иначе говоря, GRPO оставил от PPO отношение вероятностей с клиппингом, а преимущество оценивает без критика — средней наградой группы, то есть выборочной оценкой из урока 6.0.1. Подробно — в уроках 6.3.2 (PPO в RLHF) и 6.4.1 (GRPO).
Практика
Заголовок раздела «Практика»Задание: GAE и loss PPO
Заголовок раздела «Задание: GAE и loss PPO»Реализуйте TD-ошибки, GAE, клиппированную цель, нормировку преимуществ и полный loss PPO. Тесты сверят ответы с примерами урока (робот-курьер, таблица пяти случаев) и проверят, что в клиппированной области градиент равен нулю.
import numpy as np
def td_errors(rewards, values, last_value, gamma):
"""TD-ошибки δ_t = r_t + γ·V(s_{t+1}) − V(s_t) для одной траектории.
rewards — [T], values — [T] (оценки критика V(s_0) … V(s_{T-1})),
last_value — V(s_T) после последнего шага (0, если эпизод закончился).
Ответ — np.ndarray длины T. Подсказка: «следующие» ценности — это values[1:] и last_value.
"""
# TODO: ваш код
...
def gae(rewards, values, last_value, gamma, lam):
"""GAE(λ): A_t = δ_t + γλ·A_{t+1}, считаем с конца траектории (A_T = 0).
Вернуть кортеж (advantages, returns), где returns = advantages + values — цели для критика.
"""
# TODO: ваш код
...
def ppo_clip_objective(logp_new, logp_old, adv, eps=0.2):
"""Клиппированная цель PPO (её МАКСИМИЗИРУЮТ): mean(min(ρ·A, clip(ρ, 1−ε, 1+ε)·A)).
ρ = exp(logp_new − logp_old) — отношение вероятностей новой и старой политики.
Вернуть одно число (float).
"""
# TODO: ваш код
...
def normalize_advantages(adv, eps=1e-8):
"""Нормировка по батчу: (A − mean) / (std + eps)."""
# TODO: ваш код
...
def ppo_loss(logp_new, logp_old, adv, values_pred, returns, entropy, eps=0.2, c_v=0.5, c_e=0.01):
"""Полный loss PPO для МИНИМИЗАЦИИ:
−clip_objective + c_v · mean((V_pred − returns)²) − c_e · mean(entropy)
Вернуть одно число (float).
"""
# TODO: ваш код
...
# Проверьте себя кнопкой «Запустить»: пример из урока (робот-курьер)
r, V = [1.0, 0.0, 2.0], [2.0, 1.5, 1.0]
print("δ =", td_errors(r, V, 0.0, 0.9)) # [0.35, -0.6, 1.0]
for lam in [0.0, 0.5, 0.95, 1.0]:
out = gae(r, V, 0.0, 0.9, lam)
if out is not None:
print(f"λ = {lam}: A = {np.round(out[0], 4)}")
print(ppo_clip_objective(np.log([1.1, 1.5, 0.5, 0.7, 1.5]), np.zeros(5), [1, 1, 1, -1, -1])) # ≈ 0.1
Локально: PPO на CartPole
Заголовок раздела «Локально: PPO на CartPole»Полный PPO на PyTorch в 70 строк: GAE с честной обработкой terminated и truncated, клиппинг, критик, энтропия,
нормировка преимуществ и мониторинг KL и clipfrac. Нужны pip install gymnasium и PyTorch. Гиперпараметры —
из таблицы статьи PPO.
import gymnasium as gymimport numpy as npimport torchimport torch.nn as nn
torch.manual_seed(0)env = gym.make("CartPole-v1")n_obs, n_act = env.observation_space.shape[0], env.action_space.n
actor = nn.Sequential(nn.Linear(n_obs, 64), nn.Tanh(), nn.Linear(64, 64), nn.Tanh(), nn.Linear(64, n_act))critic = nn.Sequential(nn.Linear(n_obs, 64), nn.Tanh(), nn.Linear(64, 64), nn.Tanh(), nn.Linear(64, 1))opt = torch.optim.Adam(list(actor.parameters()) + list(critic.parameters()), lr=3e-4)
T, epochs, mb = 2048, 10, 64 # шагов в батче, эпох на батч, размер мини-батчаgamma, lam, eps, c_v, c_e = 0.99, 0.95, 0.2, 0.5, 0.01
s, _ = env.reset(seed=0)ep_ret, finished = 0.0, []for update in range(1, 26): # 25 обновлений × 2048 шагов ≈ 51 тыс. шагов # ── 1. Сбор батча текущей политикой (она же π_old) ── S, A, R, D, TR, LOGP, V, V_NEXT = [], [], [], [], [], [], [], [] for _ in range(T): st = torch.as_tensor(s, dtype=torch.float32) with torch.no_grad(): dist = torch.distributions.Categorical(logits=actor(st)) a = dist.sample() v = critic(st).item() s2, r, terminated, truncated, _ = env.step(a.item()) with torch.no_grad(): # V(s_{t+1}) нужен, если эпизод оборван по лимиту v_next = critic(torch.as_tensor(s2, dtype=torch.float32)).item() S.append(s); A.append(a.item()); R.append(r); LOGP.append(dist.log_prob(a).item()) D.append(terminated or truncated); TR.append(truncated); V.append(v); V_NEXT.append(v_next) ep_ret += r s = s2 if terminated or truncated: finished.append(ep_ret) ep_ret = 0.0 s, _ = env.reset() # ── 2. GAE: δ_t = r_t + γV(s_{t+1})·[не конец] − V(s_t), A_t = δ_t + γλA_{t+1}·[эпизод не кончился] ── R, V, V_NEXT = np.array(R), np.array(V), np.array(V_NEXT) D, TR = np.array(D), np.array(TR) terminal = D & ~TR delta = R + gamma * V_NEXT * (~terminal) - V adv, running = np.zeros(T), 0.0 for t in reversed(range(T)): running = delta[t] + gamma * lam * running * (not D[t]) adv[t] = running ret = adv + V # цели для критика S = torch.as_tensor(np.array(S), dtype=torch.float32) A, LOGP = torch.as_tensor(A), torch.as_tensor(LOGP, dtype=torch.float32) ADV, RET = torch.as_tensor(adv, dtype=torch.float32), torch.as_tensor(ret, dtype=torch.float32) # ── 3. Несколько эпох по мини-батчам ── kls, clips, ents = [], [], [] for _ in range(epochs): for idx in torch.randperm(T).split(mb): dist = torch.distributions.Categorical(logits=actor(S[idx])) logp = dist.log_prob(A[idx]) ratio = torch.exp(logp - LOGP[idx]) # ρ = π_θ / π_old a_mb = (ADV[idx] - ADV[idx].mean()) / (ADV[idx].std() + 1e-8) # нормировка преимуществ policy_obj = torch.min(ratio * a_mb, torch.clamp(ratio, 1 - eps, 1 + eps) * a_mb).mean() value_loss = ((critic(S[idx]).squeeze(-1) - RET[idx]) ** 2).mean() entropy = dist.entropy().mean() loss = -policy_obj + c_v * value_loss - c_e * entropy opt.zero_grad() loss.backward() nn.utils.clip_grad_norm_(list(actor.parameters()) + list(critic.parameters()), 0.5) opt.step() with torch.no_grad(): kls.append((LOGP[idx] - logp).mean().item()) # оценка KL(π_old ‖ π_θ) clips.append(((ratio - 1).abs() > eps).float().mean().item()) ents.append(entropy.item()) if update % 3 == 1 or update == 25: last = np.mean(finished[-10:]) if finished else 0.0 print(f"обновление {update:2d} шагов {update * T:6d} отдача {last:6.1f} энтропия {np.mean(ents):.3f} " f"KL {np.mean(kls):.4f} clipfrac {np.mean(clips):.3f}")Вывод (PyTorch 2.x, gymnasium 1.x, один поток CPU; на другой версии числа будут немного другими):
обновление 1 шагов 2048 отдача 23.6 энтропия 0.688 KL 0.0084 clipfrac 0.138обновление 4 шагов 8192 отдача 46.8 энтропия 0.616 KL 0.0060 clipfrac 0.059обновление 7 шагов 14336 отдача 183.2 энтропия 0.592 KL 0.0083 clipfrac 0.069обновление 10 шагов 20480 отдача 338.4 энтропия 0.564 KL 0.0068 clipfrac 0.053обновление 13 шагов 26624 отдача 472.6 энтропия 0.540 KL 0.0046 clipfrac 0.072обновление 16 шагов 32768 отдача 500.0 энтропия 0.558 KL 0.0063 clipfrac 0.047обновление 19 шагов 38912 отдача 453.2 энтропия 0.549 KL 0.0023 clipfrac 0.069обновление 22 шагов 45056 отдача 494.7 энтропия 0.529 KL 0.0038 clipfrac 0.083обновление 25 шагов 51200 отдача 500.0 энтропия 0.484 KL 0.0048 clipfrac 0.068Что видно. Отдача выросла с 24 до максимума 500 примерно за 30 тысяч шагов. Энтропия падает плавно — с (монетка) до 0.48: политика становится увереннее, но не схлопывается. KL держится около 0.005, а clipfrac — в районе 5–8%: шаги маленькие, клиппинг срабатывает изредка, как и задумано. На нагруженном 4-ядерном CPU прогон занял около трёх минут. Сохраните средние значения по обновлениям в списки и постройте три графика — награда, энтропия и KL: так выглядят панели мониторинга любого RL-фреймворка, в том числе verl в модуле 6.4.
Проверь себя
Заголовок раздела «Проверь себя»- Градиент политики выводится трюком с логарифмом и не требует модели среды. REINFORCE оценивает его по эпизодам; reward-to-go и baseline снижают шум, а лучший baseline превращает вес действия в преимущество.
- Actor-critic: критик учится регрессией к отдачам, актор — на преимуществах. GAE(λ) — затухающая сумма TD-ошибок ; двигает оценку между TD и Монте-Карло.
- PPO переиспользует батч через отношение вероятностей , клиппингом не даёт уйти далеко и учит всё одним loss: .
- Для LLM: токен — действие, ответ — эпизод, награда в конце плюс KL на токенах. InstructGPT — это PPO с такой наградой; GRPO — PPO без критика, с групповым преимуществом.
Дальше: начинаем путь от базовой модели к ассистенту — что умеет модель после претрейна и из каких этапов состоит пост-трейнинг. Словарь RL из этого модуля вернётся в модулях 6.3 и 6.4.