GRPO алгоритм DeepSeekMath: замена PPO для RL-обучения LLM | Полный разбор | AiManual
AiManual Logo Ai / Manual.
01 Янв 2026 Гайд

GRPO: как DeepSeekMath выкинул критика из RL и получил суперэффективный алгоритм

Глубокий разбор Group Relative Policy Optimization (GRPO) — революционного алгоритма RL-обучения из DeepSeekMath. Как работает, чем лучше PPO, и как экономит 70

PPO устарел. И вот почему это больно

Представь: ты тренируешь языковую модель решать математические задачи. Нужно RL-обучение. Берёшь PPO — стандарт де-факто. И тут начинается ад. Два гигантских нейрона: политика и критик. Каждый — сотни миллиардов параметров. Память заканчивается через 20 минут. График загрузки GPU напоминает кардиограмму инфарктника.

Команда DeepSeekMath посмотрела на эту конструкцию и спросила: "А зачем нам вообще отдельный критик?" Так родился GRPO — Group Relative Policy Optimization. Алгоритм, который выкидывает половину проблемы и работает в разы эффективнее.

Главная боль PPO: Критик — это отдельная модель, которую нужно обучать параллельно с политикой. Она оценивает "ценность" состояний, но занимает столько же памяти, сколько основная модель. Для Llama 70B это примерно 140GB GPU RAM только для двух моделей. Безумие.

Суть GRPO: сравнивай ответы, а не оценивай абсолютно

Вот ключевой инсайт GRPO. Вместо того чтобы обучать критика предсказывать "насколько хорош этот ответ", алгоритм говорит: "Давайте просто сравним несколько ответов между собой".

Работает это так:

  1. Для одного промпта генерируешь N разных ответов (обычно 4-8)
  2. Получаешь реварды для каждого ответа (например, от другой модели или по метрике)
  3. Сортируешь ответы по ревардам
  4. Используешь относительные ранги вместо абсолютных значений
💡
Аналогия: Представь, что ты судья на конкурсе. Вместо того чтобы выставлять каждой участнице оценку от 1 до 10 (как PPO-критик), ты просто ранжируешь их: 1-е место, 2-е, 3-е. Такой подход требует меньше информации, но для обучения политики — вполне достаточно.

Математика без магии: как выглядит loss-функция

Вот где начинается настоящая красота. Формула GRPO настолько проста, что сначала не верится, что она работает:

import torch
import torch.nn.functional as F

def grpo_loss(log_probs, rewards):
    """
    log_probs: тензор размерности [batch_size, n_responses]
    rewards: тензор размерности [batch_size, n_responses]
    """
    # Нормализуем реварды в пределах группы
    normalized_rewards = (rewards - rewards.mean(dim=-1, keepdim=True)) \
                         / (rewards.std(dim=-1, keepdim=True) + 1e-8)
    
    # Превращаем в вероятности через softmax
    weights = F.softmax(normalized_rewards, dim=-1)
    
    # Взвешенная сумма логарифмических вероятностей
    loss = -(weights * log_probs).sum(dim=-1).mean()
    
    return loss

Видишь? Никакого отдельного критика. Никаких сложных value-функций. Просто сравниваем ответы внутри группы и усиливаем те, что оказались лучше.

1 Почему это работает для reasoning-задач

Математические задачи — идеальный кейс для GRPO. Почему? Потому что здесь есть чёткие критерии: ответ либо правильный, либо нет. Или почти правильный. Не нужно тонких нюансов "насколько хорош этот поэтический образ".

Когда модель решает уравнение, можно:

  • Проверить конечный ответ
  • Оценить промежуточные шаги
  • Даже посчитать "похожесть" на правильное решение

Это даёт чёткие реварды. А раз реварды чёткие — можно сравнивать ответы между собой. И не нужен критик, который пытается предсказать абсолютное значение.

PPO vs GRPO: битва на конкретных цифрах

Параметр PPO GRPO Выигрыш
Моделей для обучения 2 (политика + критик) 1 (только политика) 50% памяти
Градиентных шагов 2 (отдельно для политики и критика) 1 2x скорость
Стабильность Низкая (две модели могут расходиться) Высокая (нет расхождения) Меньше debugging
Качество на GSM8K ~75% ~82% (в DeepSeekMath) +7% абсолютных

Цифры не врут. GRPO не просто экономит ресурсы — он даёт лучшие результаты. В DeepSeekMath-R1 модель достигла 84.8% на GSM8K. И это без танцев с бубнами вокруг критика.

Как НЕ надо реализовывать GRPO: частые ошибки

Смотри, вот типичная ошибка новичков:

# ❌ НЕПРАВИЛЬНО: забываем нормализацию
# Это сломается, если реварды в разных группах имеют разный масштаб
def broken_grpo_loss(log_probs, rewards):
    weights = F.softmax(rewards, dim=-1)  # Опасность!
    loss = -(weights * log_probs).sum(dim=-1).mean()
    return loss

Почему это плохо? Представь: в одной группе реварды [0.9, 0.8, 0.7], а в другой [90, 80, 70]. Softmax превратит вторую группу в почти one-hot вектор. Обучение станет нестабильным.

Важно: Всегда нормализуй реварды внутри группы (вычитай среднее, дели на стандартное отклонение). Иначе алгоритм будет сравнивать несравнимое.

2 Размер группы — золотая середина

Ещё одна ошибка — неправильный выбор N (количество ответов на промпт).

  • N=2: Слишком мало. Сравнение почти бесполезно
  • N=4-8: Идеально. Есть что сравнивать, но не слишком дорого
  • N=16+: Бессмысленно тратишь compute. Убывающая отдача

DeepSeekMath использует N=4 для большинства экспериментов. Этого достаточно, чтобы получить надёжный сигнал, но не сжечь бюджет на генерацию.

GRPO в конвейере: от сырой модели до reasoning-монстра

Вот как выглядит полный пайплайн обучения с GRPO:

# Упрощенный псевдокод полного конвейера
def train_grpo_pipeline(model, dataset, num_epochs=3):
    optimizer = torch.optim.AdamW(model.parameters(), lr=5e-6)
    
    for epoch in range(num_epochs):
        for batch in dataset:
            # 1. Генерация нескольких ответов на каждый промпт
            all_responses = []
            all_log_probs = []
            
            for _ in range(4):  # N=4
                responses, log_probs = model.generate(batch["prompt"])
                all_responses.append(responses)
                all_log_probs.append(log_probs)
            
            # 2. Оценка ревардов (например, другой моделью)
            rewards = evaluate_responses(all_responses, batch["reference"])
            
            # 3. Вычисление GRPO loss
            loss = grpo_loss(torch.stack(all_log_probs, dim=1), rewards)
            
            # 4. Обратное распространение
            optimizer.zero_grad()
            loss.backward()
            torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0)
            optimizer.step()
            
    return model

Заметь: в этом пайплайне нет шага "обновить критика". Нет шага "синхронизировать политику и критика". Нет градиентов для value-функции. Всё упрощается до неприличия.

Когда GRPO не работает (и нужно возвращаться к PPO)

GRPO — не серебряная пуля. Есть сценарии, где PPO всё ещё лучше:

  1. Субъективные задачи: Поэзия, креативное письмо, юмор. Здесь нет чётких "правильных" ответов, только предпочтения. Критик, обученный на человеческих оценках, может улавливать тонкие нюансы.
  2. Очень маленькие группы: Если можешь генерировать только 1-2 ответа на промпт (ограничения по времени/ресурсам), относительное сравнение теряет смысл.
  3. Задачи с долгосрочными последствиями: В диалоговых системах, где нужно учитывать контекст нескольких ходов назад, value-функция критика помогает планировать.

Но для reasoning, математики, кодинга — GRPO бьёт PPO по всем фронтам. Особенно если посмотреть на статью про KEF vs OpenAI o3, где как раз сравнивают подходы к прокачке reasoning.

GRPO vs DPO: родственники или конкуренты?

На первый взгляд, GRPO похож на DPO (Direct Preference Optimization). Оба избавляются от отдельного критика. Но есть ключевые различия:

Аспект DPO GRPO
Данные Парные предпочтения (A лучше B) Множественные ответы с ревардами
Цель Выравнивание с человеческими ценностями Максимизация объективных метрик
Сложность Нужны размеченные данные предпочтений Нужна функция оценки (ревард)

По сути, DPO — для alignment ("будь полезным, честным, безвредным"), а GRPO — для capability ("решай математику лучше"). Они решают разные задачи, но оба показывают: можно обойтись без громоздкого RLHF с отдельным критиком.

Практический совет: с чего начать внедрение GRPO

Хочешь попробовать GRPO на своей модели? Вот минимальный рабочий план:

1 Подготовка данных

Собери датасет с чёткими правильными ответами. Для математики — GSM8K, MATH. Для кодинга — HumanEval, MBPP. Важно: у тебя должна быть функция, которая для любого ответа выдаёт числовой ревард.

Если не знаешь, где брать данные — посмотри статью про источники данных для fine-tuning.

2. Выбери функцию реварда

Варианты:

  • Exact match: 1 если ответ совпадает с эталоном, 0 если нет
  • Вероятность от другой модели: GPT-4 оценивает, насколько ответ правильный
  • Собственный классификатор: Небольшая модель, обученная отличать правильные решения от неправильных

3. Начни с маленькой модели

Не лезь сразу на Llama 70B. Возьми Qwen 1.5B или Llama 3.2 3B. Обучи на 1000 примеров. Посмотри, сходится ли loss. Если статья про "несущие" нейроны в Llama 3.2 3B показала что-то — примени эти знания.

4. Мониторь разнообразие ответов

Самая опасная вещь в GRPO — коллапс разнообразия. Если модель начнёт генерировать почти одинаковые ответы, сравнение теряет смысл. Добавь энтропийную регуляризацию:

def grpo_loss_with_entropy(log_probs, rewards, beta=0.01):
    normalized_rewards = (rewards - rewards.mean(dim=-1, keepdim=True)) \
                         / (rewards.std(dim=-1, keepdim=True) + 1e-8)
    weights = F.softmax(normalized_rewards, dim=-1)
    
    policy_loss = -(weights * log_probs).sum(dim=-1).mean()
    
    # Энтропийная регуляризация
    entropy = -(F.softmax(log_probs, dim=-1) * F.log_softmax(log_probs, dim=-1)).sum(dim=-1).mean()
    
    total_loss = policy_loss - beta * entropy
    return total_loss

Что дальше? Эволюция GRPO и будущее RL для LLM

GRPO — не конечная точка. Уже видны направления развития:

  1. GRPO + RAG: Использовать RAG-системы для получения ревардов. Модель генерирует ответ, RAG ищет похожие правильные решения, оценивает схожесть.
  2. Мультимодальный GRPO: Не только текст, но и код, диаграммы, математические обозначения. Особенно актуально с ростом мультимодальных моделей.
  3. GRPO для небольших моделей: Если Grokkit прав и маленькие модели могут заменить большие — GRPO станет стандартом для их обучения.

Самый интересный вопрос: а что, если применить GRPO не только к финальному ответу, но и к промежуточным шагам reasoning? За каждый логический шаг — отдельный ревард. Получится что-то вроде hierarchical GRPO. В DeepSeekMath-R1 уже есть намёки на это.

Прогноз: Через год 80% reasoning-моделей будут использовать GRPO или его производные. PPO останется только для alignment-задач, где нужны тонкие человеческие предпочтения. А для всего, что можно измерить объективно — будет царствовать групповое относительное сравнение.

Попробуй. Начни с маленького эксперимента. Удивишься, насколько проще стало обучать модели решать задачи. Без критика, без синхронизации, без половины головной боли. Просто генерируй, сравнивай, усиливаем лучшее. Вот и весь секрет.