Глава 8: Модельно-основанный Offline RL (MOPO, MOReL)

«Если нельзя провести новые эксперименты — постройте симулятор из имеющихся данных и экспериментируйте внутри него. Но помните: симулятор лжёт там, где вы никогда не бывали.»


За пределами модельно-свободных методов

Главы 2–6 атаковали offline RL с одной стороны: модифицировать функцию ценности так, чтобы она была пессимистична относительно действий, отсутствующих в датасете. CQL занижает Q-значения для OOD-действий. IQL полностью избегает запросов к OOD-действиям.

Оба метода разделяют фундаментальное ограничение: они могут использовать только переходы, собранные поведенческой политикой. Если критически важные области пространства состояние-действие просто отсутствуют в датасете, модельно-свободные методы не имеют откуда учиться.

Модельно-основанный offline RL предлагает иной подход: обучить динамику системы, а затем генерировать синтетические переходы «в уме». Вместо того чтобы ограничиваться существующими данными, строится мысленная модель и воображается, что произойдёт при новых действиях.

Это мощно — но опасно. Модель ошибается там, где данных мало, и политика, эксплуатирующая ошибки модели, провалится так же катастрофически, как и та, что эксплуатирует ошибки Q-функции. Два алгоритма этой главы решают проблему по-разному:

Одна цель, разная геометрия пессимизма.


Часть I: MOPO

Идея

Model-Based Offline Policy Optimization (MOPO) работает в три фазы:

  1. Обучить модель динамики $\hat{T}(s' | s, a)$ из офлайн-датасета с помощью ансамбля нейронных сетей. Каждая модель ансамбля делает немного разные предсказания. Где они согласны — модель уверена. Где расходятся — неопределённость высокая.

  2. Генерировать синтетические ролл-ауты, ветвясь от реальных состояний. Стартуем из реального состояния $s \in \mathcal{D}$, выбираем действие, предсказываем $s'$ моделью, повторяем $h$ шагов. На каждом шаге штрафуем награду на неопределённость модели:

$$\tilde{r}(s, a) = \hat{r}(s, a) - \lambda \cdot u(s, a)$$

  1. Обучить стандартный RL-алгоритм (SAC) на объединённых реальных + синтетических данных. Штраф гарантирует, что агент избегает ненадёжных регионов.

Результат: эффективный датасет в 10–100 раз больше исходного со встроенной безопасностью через штраф за неопределённость.

Формализация

Ансамбль динамики

Обучаем ансамбль из $N$ вероятностных моделей $\{\hat{T}_i\}_{i=1}^N$, каждая возвращает гауссиан над следующими состояниями:

$$\hat{T}_i(s' | s, a) = \mathcal{N}\left(s + \mu_{\theta_i}(s, a), \; \sigma^2_{\theta_i}(s, a)\right)$$

Ключевые решения:

Оценка неопределённости

Для данной пары $(s, a)$ каждая модель предсказывает среднее $\hat{s}'_i$. Эпистемическая неопределённость — «насколько модели расходятся?»:

$$u(s, a) = \left\| \text{Std}_{i=1}^N \left[ \hat{s}'_i \right] \right\|_2$$

Это стандартное отклонение предсказаний по ансамблю, свёрнутое в скаляр через L2-норму.

Почему расхождение ансамбля работает: если все модели видели похожие данные рядом с $(s, a)$, они сходятся к похожим предсказаниям — малое $u$. Если данных мало, bootstrap приводит к тому, что каждая модель выучивает разные паразитные паттерны — большое $u$. Это ключевой механизм: неопределённость высокая именно там, где данных нет.

Цель MOPO

MOPO строит пессимистическое MDP $\tilde{\mathcal{M}}$ со штрафными наградами и оптимизирует политику в нём:

$$\tilde{r}(s, a) = \hat{r}(s, a) - \lambda \cdot u(s, a)$$

$$\pi^* = \arg\max_\pi \; \mathbb{E}_{\tilde{\mathcal{M}}} \left[ \sum_t \gamma^t \tilde{r}(s_t, a_t) \right]$$

Теоретическая гарантия из Yu et al. (2020):

$$J(\pi) \geq \hat{J}_{\tilde{\mathcal{M}}}(\pi) - C \cdot \mathbb{E}_{s \sim d^\pi} \left[ \max_a u(s, a) \right]$$

где $J(\pi)$ — истинная отдача, $\hat{J}_{\tilde{\mathcal{M}}}(\pi)$ — отдача в пессимистической модели. Граница говорит: оптимизация в штрафной модели даёт нижнюю оценку реальной производительности, с зазором пропорциональным остаточной ошибке модели. Замечание: в оригинальной статье MOPO $u(s,a)$ — максимум по ансамблю нормы обученного (алеаторного) std; здесь используется разброс предсказаний ансамбля (std средних) — распространённый вариант реализации, близкий к USAD в MOReL.

Ветвящиеся ролл-ауты

Вместо того чтобы разворачивать полные эпизоды с нуля, MOPO использует ветвящиеся ролл-ауты:

  1. Сэмплируем начальное состояние $s_0$ из реального датасета $\mathcal{D}$.
  2. Разворачиваем на $h$ шагов с моделью и текущей политикой.
  3. Каждый синтетический переход $(s_t, a_t, \tilde{r}_t, s_{t+1})$ добавляется в синтетический буфер.

Старт из реальных состояний гарантирует, что ролл-аут начинается в хорошо смоделированном регионе. Короткий горизонт $h$ ограничивает накопление ошибок. Штрафная награда препятствует посещению плохо смоделированных регионов внутри ролл-аута.

Реализация

📄 Полный код: mopo.py

Вероятностная модель динамики

class ProbabilisticDynamicsNet(nn.Module):
    """
    (s, a) -> (mean, log_var) для s'.
    Предсказывает остатки: s'_pred ~ N(s + mean(s,a), exp(log_var(s,a)))
    Обучается через NLL, а не MSE — сеть сама учится своей неопределённости.
    """
    def __init__(self, state_dim, action_dim, hidden_dim=256):
        super().__init__()
        self.trunk = nn.Sequential(
            nn.Linear(state_dim + action_dim, hidden_dim), nn.SiLU(),
            nn.Linear(hidden_dim, hidden_dim), nn.SiLU(),
            nn.Linear(hidden_dim, hidden_dim), nn.SiLU(),
        )
        self.mean_head    = nn.Linear(hidden_dim, state_dim)
        self.log_var_head = nn.Linear(hidden_dim, state_dim)
        self.min_log_var  = nn.Parameter(-10.0 * torch.ones(state_dim))
        self.max_log_var  = nn.Parameter(0.5  * torch.ones(state_dim))

Активация SiLU (swish) превосходит ReLU для моделей динамики — более гладкие градиенты помогают аппроксимировать плавные физические переходы.

NLL-обучение

    def nll_loss(self, state, action, next_state):
        mean, log_var = self.forward(state, action)
        residual = next_state - state
        var      = log_var.exp()
        # NLL = 0.5 * [ log_var + (residual - mean)² / var ]
        nll      = 0.5 * (log_var + (residual - mean).pow(2) / var)
        loss     = nll.sum(-1).mean()
        bound_reg = 0.01 * (self.max_log_var.sum() - self.min_log_var.sum())
        return loss + bound_reg

Обучение через NLL, а не MSE критично. MSE обучает только среднее, оставляя дисперсию неконтролируемой. NLL совместно обучает среднее (минимизация ошибки предсказания) и дисперсию (калибровка уверенности) — делая обученное $\sigma^2$ значимым как прокси неопределённости.

Синтетические ролл-ауты со штрафом за неопределённость

    def generate_synthetic_data(self, real_states):
        state = real_states[random_idx]

        for step in range(self.rollout_horizon):
            action, _   = self.policy.sample(state)
            next_state, uncertainty = self.ensemble.predict_with_uncertainty(
                state, action)
            reward = self._model_reward(state, action, next_state)

            # Ключевая строка: штрафуем награду на эпистемическую неопределённость
            penalized_reward = reward - self.lam * uncertainty
            state = next_state

Одно вычитание reward - self.lam * uncertainty — это то, что превращает наивный MBRL (опасный) в MOPO (безопасный).


Часть II: MOReL

Иная геометрия пессимизма

MOPO использует непрерывный штраф: чем дальше от данных, тем больше вычитается из награды. Политика всё равно может заходить в неопределённые регионы — они просто кажутся менее привлекательными.

MOReL использует дискретный подход: разделяет пространство состояние-действие на «известные» и «неизвестные» регионы и применяет жёсткий штраф $\kappa$ в неизвестном регионе. Это создаёт резкую границу, а не градиент.

Model-Based Offline Reinforcement Learning (MOReL) — Kidambi et al., NeurIPS 2020 — строит Пессимистическое MDP (P-MDP) непосредственно из офлайн-данных с встроенным поглощающим состоянием отказа для OOD-переходов.

Построение P-MDP

Пусть $\mathcal{D}$ — офлайн-датасет. MOReL определяет порог $\epsilon$ на неопределённость предсказания и разделяет пространство:

$$\text{KNOWN} = \{(s,a) : u(s,a) \leq \epsilon\}$$

$$\text{UNKNOWN} = \{(s,a) : u(s,a) > \epsilon\}$$

Пессимистическое MDP $\tilde{\mathcal{M}} = (\mathcal{S} \cup \{s_\perp\}, \mathcal{A}, \tilde{T}, \tilde{r}, \gamma)$:

$$\tilde{T}(s' | s, a) = \begin{cases} \hat{T}(s' | s, a) & \text{если } (s,a) \in \text{KNOWN} \\ \delta(s_\perp) & \text{если } (s,a) \in \text{UNKNOWN} \end{cases}$$

$$\tilde{r}(s, a) = \begin{cases} \hat{r}(s, a) & \text{если } s \neq s_\perp \\ -\kappa & \text{если } s = s_\perp \end{cases}$$

где $s_\perp$ — поглощающее состояние отказа, а $\kappa > 0$ — большой штраф. Попав в неизвестный регион, агент переходит в $s_\perp$ и получает $-\kappa$ на каждом последующем шаге — сильнейший стимул избегать неизвестного.

Теоретическая гарантия

Теорема (Kidambi et al., 2020). Пусть $\hat{\pi}$ — оптимальная политика в P-MDP $\tilde{\mathcal{M}}$. Тогда:

$$J^*(\pi) - J(\hat{\pi}) \leq \frac{2\gamma \kappa}{(1-\gamma)^2} \cdot \Pr_{d^{\hat{\pi}}}[\text{UNKNOWN}]$$

Граница говорит: зазор между оптимальной политикой и тем, что находит MOReL, ограничен вероятностью попадания политики MOReL в неизвестный регион, взвешенной на штраф. Это более сильная гарантия, чем у MOPO: она не зависит от распределения и не требует предположений о распределении ошибок динамики.

Реализация

📄 Полный код: morel.py

MOReL использует ту же архитектуру ансамбля что и MOPO (ProbabilisticDynamicsNet, DynamicsEnsemble). Специфичные для MOReL дополнения:

Шаг 1 — Калибровка epsilon по данным in-distribution:

# После обучения ансамбля — установить epsilon на 80-м перцентиле
# неопределённости на реальных переходах из датасета.
epsilon = ensemble.calibrate_epsilon(dataset, percentile=80.0)

Шаг 2 — Ролл-ауты в P-MDP с жёстким HALT:

# Внутри MOReLAgent.generate_synthetic_data():
for step in range(self.rollout_horizon):
    action, _ = self.policy.sample(state[active])
    next_state, uncertainty = self.ensemble.predict_with_uncertainty(
        state[active], action)

    # Жёсткая граница: если OOD — завершить с штрафом
    ood = uncertainty > self.epsilon

    reward = torch.where(
        ood,
        -self.kappa * torch.ones(ood.shape[0], device=device),
        self._model_reward(state[active], action, next_state)
    )
    done = ood.float()

    # Поглощающее состояние: остановленные ролл-ауты остаются на месте
    next_state_out = torch.where(
        ood.unsqueeze(-1), state[active], next_state)

    # Деактивировать остановленные ролл-ауты
    active[active.nonzero(as_tuple=True)[0][ood]] = False

Ключевое отличие от MOPO: вместо вычитания непрерывного штрафа OOD-переходы немедленно завершаются с done=True и наградой $-\kappa$. Q-функция видит нулевое будущее вознаграждение после таких переходов.

Выбор $\epsilon$

$\epsilon$ Эффект
Очень малый Крошечный известный регион — агент ограничен рядом с поведенческой политикой (≈ BC)
Умеренный (по умолчанию) Включает хорошо смоделированные экстраполяции
Очень большой Всё пространство «известно» — возврат к неограниченному MBRL

Практика: устанавливайте $\epsilon$ на уровне 70–80-го перцентиля неопределённости на данных in-distribution.

# Калибровка epsilon по данным in-distribution
with torch.no_grad():
    s_cal = torch.FloatTensor(dataset['states'][:2000]).to(device)
    a_cal = torch.FloatTensor(dataset['actions'][:2000]).to(device)
    _, u_cal = ensemble.predict_with_uncertainty(s_cal, a_cal)
epsilon = torch.quantile(u_cal, 0.80).item()
print(f"Откалиброванный epsilon = {epsilon:.4f}")

MOPO vs MOReL vs модельно-свободные

CQL IQL MOPO MOReL
Использует модель Нет Нет Да Да
Обработка OOD Занижает Q Никогда не запрашивает OOD Непрерывный штраф $-\lambda u$ Жёсткая граница + $-\kappa$
Аугментация данных Нет Нет Да Да
Геометрия пессимизма Мягкая (штраф Q) Структурная (V-сеть) Мягкая (штраф награды) Жёсткая (поглощающее состояние)
Теоретическая гарантия Нижняя оценка Q Через V Нижняя оценка $J(\pi)$ PAC-оценка без предположений на распределение
Гиперпараметры $\alpha$ $\tau, \beta$ $\lambda, h, N$ $\epsilon, \kappa, h, N$
Лучше всего для Плотные датасеты Стабильное обучение Разреженные, гладкая динамика Жёсткие требования безопасности

Гайд по гиперпараметрам

MOPO: $\lambda$ (вес штрафа за неопределённость)

$\lambda$ Поведение
$\lambda = 0$ Нет штрафа — полное доверие модели (опасно)
$\lambda = 0.5$ Лёгкий штраф — для высококачественных моделей
$\lambda = 1.0$ По умолчанию — разумный пессимизм
$\lambda = 3.0$+ Сильный штраф — для зашумлённых данных
$\lambda \to \infty$ Возврат к модельно-свободному на реальных данных

Оба: $h$ (горизонт ролл-аута)

Правило большого пальца: если модель имеет ошибку $\epsilon_1$ за шаг, за $h$ шагов накапливается примерно $h \cdot \epsilon_1$. Устанавливайте $h$ так, чтобы $h \cdot \epsilon_1 < 0.1$.

Оба: $N$ (размер ансамбля)


Практические советы

Нормализуйте всё. Состояния, действия, награды — всё нормализуется до обучения модели динамики. Входные данные в $[-1, 1]$ или $[0, 1]$ критически важны для сходимости.

Остаточное предсказание обязательно. Всегда предсказывайте $\Delta s = s' - s$. Для медленно изменяющихся систем (большинство промышленных процессов) остаток на порядки меньше абсолютного состояния.

Мониторьте расхождение ансамбля. Отношение u(OOD) / u(in-distribution) должно быть >> 1. Если близко к 1 — ансамбль недостаточно разнообразен.

Периодически перегенерируйте синтетические данные. По мере улучшения политики она посещает другие регионы. Перегенерируйте каждые 5–10 эпох SAC.

Для промышленных приложений: если у вас есть физический симулятор (хотя бы приближённый), обучайте нейронный ансамбль на остатках между физической моделью и реальными данными. Этот гибридный подход часто требует значительно меньше офлайн-данных. Глава 9 развивает эту идею в полноценную методологию.


Ограничения

Ошибки модели накапливаются. На $h$ шагах однощаговые ошибки суммируются. Штраф MOPO или жёсткая граница MOReL снижают риск, но очень длинные горизонты остаются проблематичными.

Высокоразмерные наблюдения. Обучение $T(s' | s, a)$ по пикселям требует значительно больше данных, чем по компактным представлениям состояния.

Вычислительные затраты масштабируются с размером ансамбля. Обучение и инференс требуют $N \times$ вычислений по сравнению с одной моделью.

Модель вознаграждения. В нашей реализации функция вознаграждения известна аналитически. На практике награды тоже могут потребовать обучения — ещё один источник ошибок.

Разнообразие ансамбля хрупко. Если все модели сходятся к одному решению, оценки неопределённости обрушиваются до нуля — штраф MOPO и граница MOReL становятся бесполезными.


Итоги

Свойство MOPO MOReL
Необходимые данные Переходы $(s, a, r, s')$ Переходы $(s, a, r, s')$
Ключевой механизм Неопределённость ансамбля как мягкий штраф награды Жёсткое разделение known/unknown через порог $\epsilon$
Пессимизм Непрерывный: $\tilde{r} = r - \lambda u$ Дискретный: поглощающее состояние за $\epsilon$
Теоретическая гарантия Нижняя оценка $J(\pi)$ PAC-оценка без предположений на распределение
Лучше для Максимизация производительности, гладкая динамика Жёсткие требования безопасности, нужны формальные гарантии

Оба алгоритма представляют качественный сдвиг от модельно-свободного offline RL: вместо ограничения политики рядом с данными мы расширяем данные на большую область пространства состояние-действие. Ансамбль обеспечивает безопасность этого расширения — агент доверяет модели только там, где она надёжна.

Следующий вопрос: можно ли делать лучше, чем обучать динамику с нуля? Если мы знаем физику системы — законы сохранения, дифференциальные уравнения, свойства материала — мы можем встроить эти знания прямо в модель и резко сократить объём необходимых данных. Это тема Главы 9: Physics-Informed Offline RL.


Литература