VKВлад КуликовОткрытые лекции
RL для LLM8 / 13

Модуль 8. RLHF и прямые методы оптимизации предпочтений

Сначала попробуйте решить упражнение. Ответы, подробные решения и проектные ориентиры раскрываются отдельно и сохраняют своё состояние при переключении RU/EN.

Скачать файлы курса (.zip) 382,1 КБ

Архив содержит файлы на обоих языках и вспомогательные материалы с сохранением структуры каталогов.

Четыре роли и физическая реализация

В отчёте написано: «Для RLHF всегда нужно одновременно держать в памяти четыре полные LLM: политику, базу, модель награды и критик».

  1. Разделите логические роли и физические копии параметров.

  2. Для каждой роли укажите, что она вычисляет и обновляется ли она.

  3. Назовите минимум четыре способа уменьшить память, не меняя математической роли компонента.

  4. Объясните, какая вычислительная цена RLHF остаётся после таких оптимизаций.

Показать ответ и решение

Политика генерирует ответы и обновляется. База задаёт KL-якорь и заморожена. Модель награды оценивает ответы и обычно заморожена на стадии оптимизации политики. Критик оценивает ожидаемую будущую награду и обучается вместе с RL-контуром.

Это четыре роли, а не четыре обязательные независимые копии. Память уменьшают общей основой политики и головы ценности, LoRA, квантованием замороженных компонентов, кэшированием логарифмов вероятностей базы, выгрузкой на CPU, разнесением ролей между процессами и меньшими моделью награды и критиком. Остаются генерация, прямые проходы базы и модели награды, оценивание ценности, хранение роллаутов и обратный проход политики.

Ограничение KL и штраф KL

Сравните

max⁡π  Eπ[r]приDKL(π∥πref)≤δ\max_\pi\;\mathbb E_\pi[r] \quad\text{при}\quad D_{\mathrm{KL}}(\pi\|\pi_{\mathrm{ref}})\le\delta

и

max⁡π  Eπ[r]−βDKL(π∥πref).\max_\pi\;\mathbb E_\pi[r] - \beta D_{\mathrm{KL}}(\pi\|\pi_{\mathrm{ref}}).

Почему они связаны, но выбранное β\beta в нейросетевом обучении не задаёт заранее точный фактический KL? Что KL-регуляризация гарантирует в идеализированной задаче и чего она не гарантирует относительно модели награды и сохранения способностей LLM?

Показать ответ и решение

Штрафованная задача является лагранжевой формой ограниченной. В идеальной выпуклой постановке активному ограничению соответствует множитель β\beta. В нейросетевом обучении параметризация невыпукла, оценки стохастичны, а оптимизация конечна, поэтому выбранный β\beta не задаёт точный фактический KL.

В точной задаче KL устанавливает цену ухода от базы и сохраняет её носитель. Он не доказывает правильность модели награды, не исключает эксплуатацию её ошибок и не гарантирует сохранение каждой способности LLM.

Сэмплированное отношение и точный KL

Для выбранного токена получено

log⁡πθ(a∣s)−log⁡πref(a∣s)=−0.7.\log\pi_\theta(a\mid s)-\log\pi_{\mathrm{ref}}(a\mid s)=-0.7.

Разработчик заключил: «KL на этом токене отрицателен». Исправьте вывод. Различите один сэмплированный логарифм отношения, его ожидание по текущей политике, точный категориальный KL и сумму токеновых вкладов для одного ответа. Почему маска ответа и фактическая политика декодирования входят в контракт вычисления?

Показать ответ и решение

Число −0.7-0.7 — одно значение

log⁡πθ(a∣s)πref(a∣s),\log\frac{\pi_\theta(a\mid s)}{\pi_{\mathrm{ref}}(a\mid s)},

которое может быть отрицательным. Его ожидание по a∼πθa\sim\pi_\theta равно

DKL(πθ∥πref)≥0.D_{\mathrm{KL}}(\pi_\theta\|\pi_{\mathrm{ref}})\ge0.

Точный категориальный KL суммирует по всему словарю. Последовательностный вклад складывает сэмплированные логарифмы отношений вдоль одного ответа и тоже может быть отрицательным. Маска определяет действия политики, а фактическое декодирование задаёт правильное распределение поведения после температуры, ограничения числа наиболее вероятных токенов, отсечения по накопленной массе и запретов токенов.

Что требуется для вывода DPO

Перечислите предположения, связывающие KL-регуляризованный оптимум, неявную награду и DPO-потерю. Обсудите пары к одному запросу, модель Брэдли—Терри, фиксированную базу, носитель, качество пар и различие между оптимизацией функции потерь и доказанной правильностью предпочтений.

Показать ответ и решение

Нужны пары к одному запросу, BT-правдоподобие, точный KL-регуляризованный оптимум, фиксированная база и общий носитель. Два ответа должны проходить одинаковую токенизацию, шаблон и обрезку; метки должны отражать нужную рубрику.

Если BT неточна, DPO остаётся определённой классификационной потерей, но интерпретация как точного восстановления неявной награды становится приближённой. Ошибочные пары не делают градиент неопределённым — они направляют его к ошибочной цели.

DPO и классический офлайн-RL

Команда описала DPO как «классический офлайн-RL в точности, только для текста». Сопоставьте методы по единице данных, наличию переходов (s,a,r,s′)(s,a,r,s'), явной Q-функции, бутстрэппингу Беллмана, роли базы и риску слабого покрытия. Сформулируйте более точное отношение между семействами.

Показать ответ и решение

DPO получает запрос и пару полных ответов. Классический офлайн-RL обычно получает переходы или траектории с наградами. DPO не требует явной Q-функции, уравнений Беллмана и бутстрэппинга; база входит непосредственно в логарифмические отношения.

Общее — фиксированные данные и риск слабого покрытия. Но в офлайн-RL ошибка может усиливаться максимизацией и бутстрэппингом, а DPO эксплуатирует ограниченность пар, стиль, длину и неразмеченные альтернативы. Поэтому DPO — прямой метод оптимизации политики по фиксированным предпочтениям, родственный офлайн-обучению, но не тождественный классическому офлайн-RL.

Рост зазора без роста вероятности победителя

В DPO относительный зазор между предпочтённым и отклонённым ответами растёт. Следует ли отсюда рост вероятности предпочтённого ответа? Постройте объяснение с третьим, не размеченным ответом. Укажите минимум четыре диагностические величины, которые нужно смотреть вместе с потерей.

Показать ответ и решение

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

Аудит данных, длины и шаблона диалога

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

Показать ответ и решение

Здесь есть корреляция длины с меткой, асимметричная обрезка и устаревший кэш базы. Нужно сохранять исходный текст, токены, маски, длины до/после обрезки, причину остановки, токенизатор, шаблон, версии политики и базы, параметры декодирования, происхождение пары и версию предобработки.

Деление на длину меняет целевую функцию. Оно может ослабить одно смещение, но создать предпочтение коротких ответов и не исправляет кэш, обрезку или плохую разметку.

Выбор метода по контракту данных

Для каждого сценария выберите DPO, IPO, SimPO, KTO, ORPO, PPO/RLOO либо RLVR. Допускается «сначала изменить данные».

  1. Есть качественные пары и память для замороженной базы.

  2. Есть только отдельные метки «желательно/нежелательно».

  3. Нужен одноэтапный режим без отдельной базы во время обучения.

  4. DPO продолжает раздувать зазоры после остановки роста качества.

  5. Награда программно проверяется, нужны свежие ответы текущей политики.

  6. Длины сильно различаются, команда хочет явную нормировку последовательностной оценки.

Для каждого выбора назовите главное предположение и одну обязательную метрику.

Показать ответ и решение
  1. DPO — качественные пары и доступная база; смотреть выбранные/отклонённые логарифмы отдельно.

  2. KTO — отдельные желательные и нежелательные примеры; контролировать баланс и семантику меток.

  3. ORPO — одноэтапная SFT+парная цель без отдельной базы; смотреть NLL и парную часть.

  4. IPO, cDPO или ранняя остановка — конечная маржа/шум; нужна независимая метрика качества.

  5. RLVR с PPO-, RLOO- или GRPO-подобным обновлением — проверяемая награда и свежие ответы; смотреть награду, KL и энтропию.

  6. SimPO — явная нормировка по длине; проверять качество по длиновым срезам.

Скаляризация или явное ограничение

Команда объединяет полезность и риск в одну оценку R−αCR-\alpha C и заявляет: «Достаточно подобрать α\alpha, поэтому отдельное ограничение безопасности не нужно».

  1. Сравните фиксированную скаляризацию с задачей max⁡E[R]\max\mathbb E[R] при E[C]≤d\mathbb E[C]\le d.

  2. Объясните роль двойственной переменной λ\lambda и почему её адаптация отличается от заранее выбранного α\alpha.

  3. Почему модель награды и модель стоимости следует обучать, журналировать и проверять отдельно?

  4. Почему ограничение на среднюю стоимость не гарантирует безопасность каждого запроса?

  5. Назовите минимум три дополнительных механизма для критических действий и объясните, почему контроль выпуска в Модуле 13 остаётся необходимым.

Показать ответ и решение

Фиксированная сумма R−αCR-\alpha C заранее задаёт цену риска. Если масштаб CC изменился или фактическая частота нарушений оказалась выше ожидаемой, сама цель не требует вернуть стоимость к заданному бюджету. Ограниченная задача формулирует проверяемое условие E[C]≤d\mathbb E[C]\le d, а двойственная переменная играет роль адаптивной цены нарушения:

λ←[λ+ηλ(E^[C]−d)]+.\lambda\leftarrow[\lambda+\eta_\lambda(\widehat{\mathbb E}[C]-d)]_+.

При превышении бюджета λ\lambda растёт и усиливает штраф; при запасе по ограничению он уменьшается, но остаётся неотрицательным. Это не делает метод безошибочным: качество зависит от измерения стоимости и от оптимизации политики.

Награда и стоимость отвечают на разные вопросы и могут иметь разные данные, ошибки и пороги. Сведение CC к −R-R позволяет высокой полезности компенсировать критический риск. Отдельные модели и журналы позволяют увидеть такой обмен.

Ограничение на среднее допускает редкие, но тяжёлые нарушения. Для критических действий нужны, например, жёсткое запрещение части действий, безопасный набор инструментов, изоляция среды, отказ или аварийное прерывание, а также сценарные и поэлементные проверки. Поэтому независимый контроль выпуска из Модуля 13 остаётся обязательным.

Точный KL-регуляризованный оптимум

Даны

πref=(0.5,0.3,0.2),r=(0,1,−0.5),β=1.\pi_{\mathrm{ref}}=(0.5,0.3,0.2), \qquad r=(0,1,-0.5), \qquad \beta=1.

Вычислите ненормированные веса wi=πref,iexp⁡(ri/β)w_i=\pi_{\mathrm{ref},i}\exp(r_i/\beta), нормированную π∗\pi^*, ожидаемую награду, KL к базе и регуляризованную цель. Сравните с самой базой.

Показать ответ и решение
w=(0.5e0,0.3e1,0.2e−0.5)≈(0.500000,0.815485,0.121306).w=(0.5e^0,0.3e^1,0.2e^{-0.5}) \approx(0.500000,0.815485,0.121306).

После нормировки

π∗≈(0.347998,0.567574,0.084429).\pi^*\approx(0.347998,0.567574,0.084429).

Далее

Eπ∗[r]≈0.525359,DKL(π∗∥πref)≈0.162947,\mathbb E_{\pi^*}[r]\approx0.525359, \qquad D_{\mathrm{KL}}(\pi^*\|\pi_{\mathrm{ref}})\approx0.162947,

а регуляризованная цель равна примерно 0.3624120.362412. Для базы цель равна 0.3−0.5⋅0.2=0.20.3-0.5\cdot0.2=0.2, поскольку её KL к себе нулевой.

Сдвиг награды и носитель базы

Докажите для

π∗(y)∝πref(y)exp⁡(r(y)/β)\pi^*(y)\propto\pi_{\mathrm{ref}}(y)\exp(r(y)/\beta)

два свойства: общий сдвиг всех наград не меняет π∗\pi^*; нулевая вероятность базы остаётся нулевой при конечной награде. Свяжите свойства с неидентифицируемостью уровня награды и условием носителя.

Показать ответ и решение

Для r′(y)=r(y)+cr'(y)=r(y)+c:

π′(y)∝ec/βπref(y)er(y)/β.\pi'(y)\propto e^{c/\beta}\pi_{\mathrm{ref}}(y)e^{r(y)/\beta}.

Общий множитель сокращается при нормировке. Если πref(y)=0\pi_{\mathrm{ref}}(y)=0, ненормированный вес равен нулю при конечной награде. Первое свойство отражает неидентифицируемость абсолютного уровня награды, второе — ограничение носителя прямым KL.

От неявной награды к DPO

Из

r(x,y)=βlog⁡π∗(y∣x)πref(y∣x)+βlog⁡Z(x)r(x,y) = \beta\log\frac{\pi^*(y\mid x)}{\pi_{\mathrm{ref}}(y\mid x)} + \beta\log Z(x)

выведите DPO-логит для пары и покажите сокращение log⁡Z(x)\log Z(x). Получите потерю −log⁡σ(z)-\log\sigma(z).

Показать ответ и решение

В BT входит разность наград. Две добавки βlog⁡Z(x)\beta\log Z(x) сокращаются, поэтому

z=β[log⁡πθ(y+∣x)πref(y+∣x)−log⁡πθ(y−∣x)πref(y−∣x)].z=\beta\left[ \log\frac{\pi_\theta(y^+\mid x)}{\pi_{\mathrm{ref}}(y^+\mid x)} - \log\frac{\pi_\theta(y^-\mid x)}{\pi_{\mathrm{ref}}(y^-\mid x)} \right].

Отрицательный логарифм вероятности наблюдаемого выбора:

LDPO=−log⁡σ(z)=softplus⁡(−z).\mathcal L_{\mathrm{DPO}}=-\log\sigma(z)=\operatorname{softplus}(-z).

Потеря и градиентный вес DPO

Даны

log⁡πθ(y+∣x)=−2.0,log⁡πθ(y−∣x)=−3.0,\log\pi_\theta(y^+\mid x)=-2.0, \quad \log\pi_\theta(y^-\mid x)=-3.0, log⁡πref(y+∣x)=−2.2,log⁡πref(y−∣x)=−2.4,\log\pi_{\mathrm{ref}}(y^+\mid x)=-2.2, \quad \log\pi_{\mathrm{ref}}(y^-\mid x)=-2.4,

и β=0.5\beta=0.5. Вычислите два логарифма отношений, зазор hh, логит zz, потерю softplus⁡(−z)\operatorname{softplus}(-z) и вес βσ(−z)\beta\sigma(-z). Что происходит с весом при большом положительном зазоре?

Показать ответ и решение

Выбранное отношение: −2.0−(−2.2)=0.2-2.0-(-2.2)=0.2. Отклонённое: −3.0−(−2.4)=−0.6-3.0-(-2.4)=-0.6. Поэтому

h=0.8,z=0.4.h=0.8, \qquad z=0.4. L=softplus⁡(−0.4)≈0.513015,\mathcal L=\operatorname{softplus}(-0.4)\approx0.513015, βσ(−z)≈0.200656.\beta\sigma(-z)\approx0.200656.

При большом положительном зазоре вес стремится к нулю.

Конечная цель: cDPO и IPO

  1. Для z=2z=2 и ε=0.1\varepsilon=0.1 вычислите
(1−ε)softplus⁡(−z)+εsoftplus⁡(z).(1-\varepsilon)\operatorname{softplus}(-z) + \varepsilon\operatorname{softplus}(z).
  1. Для IPO с τ=0.25\tau=0.25 найдите h∗=1/(2τ)h^*=1/(2\tau) и потери (h−h∗)2(h-h^*)^2 при h=1h=1, 22, 44.

Объясните смысл конечного оптимума IPO.

Показать ответ и решение
softplus⁡(−2)≈0.126928,softplus⁡(2)≈2.126928.\operatorname{softplus}(-2)\approx0.126928, \qquad \operatorname{softplus}(2)\approx2.126928.

Следовательно,

LcDPO≈0.9⋅0.126928+0.1⋅2.126928=0.326928.\mathcal L_{\mathrm{cDPO}}\approx0.9\cdot0.126928+0.1\cdot2.126928=0.326928.

Для τ=0.25\tau=0.25 цель h∗=2h^*=2. Потери при h=1,2,4h=1,2,4 равны 1,0,41,0,4. IPO штрафует и недостаточный, и чрезмерный зазор, тогда как обычная DPO-потеря продолжает уменьшаться при его росте.

Точный пример смещения правдоподобия

Три ответа имеют логиты

z(t)=(−t,−3t,4t).z(t)=(-t,-3t,4t).

Первый предпочтён, второй отклонён, третий не наблюдается. Покажите, что log⁡p1−log⁡p2=2t\log p_1-\log p_2=2t, вычислите вероятности при t=0t=0, 0.50.5, 11 и объясните падение p1p_1 при росте парного зазора. Какой сигнал остановки обнаружит режим?

Показать ответ и решение

Нормировочная константа softmax сокращается:

log⁡p1−log⁡p2=(−t)−(−3t)=2t.\log p_1-\log p_2=(-t)-(-3t)=2t.
ttp1p_1p2p_2p3p_3
00.3333330.3333330.333333
0.50.0737990.0271490.899052
10.0066870.0009050.992408

Третий логит забирает массу, хотя первый падает медленнее второго. Сигнал — рост маржи при падении выбранного логарифма вероятности, дополненный независимой оценкой генераций.

Два действия и бюджет стоимости

Безопасное действие имеет награду 0.60.6 и стоимость 00, рискованное — награду 1.01.0 и стоимость 11. Политика выбирает рискованное действие с вероятностью qq.

  1. Запишите E[R]\mathbb E[R] и E[C]\mathbb E[C].

  2. Найдите оптимальное q∗q^* при ограничении E[C]≤0.25\mathbb E[C]\le0.25 и соответствующую ожидаемую награду.

  3. Запишите

L(q,λ)=0.6+0.4q−λ(q−0.25).\mathcal L(q,\lambda) = 0.6+0.4q-\lambda(q-0.25).

Какой q∈[0,1]q\in[0,1] максимизирует L\mathcal L при фиксированных λ<0.4\lambda<0.4, λ>0.4\lambda>0.4 и λ=0.4\lambda=0.4?

  1. Выполните один двойственный шаг из λ=0.2\lambda=0.2 с оценкой стоимости 0.60.6, бюджетом 0.250.25 и скоростью 0.50.5.

  2. Объясните, почему средний бюджет и жёсткий запрет рискованного действия отвечают на разные требования.

Показать ответ и решение

Для смеси

E[C]=q,E[R]=(1−q)0.6+q⋅1.0=0.6+0.4q.\mathbb E[C]=q, \qquad \mathbb E[R]=(1-q)0.6+q\cdot1.0=0.6+0.4q.

Награда растёт по qq, а ограничение даёт q≤0.25q\le0.25. Поэтому

q∗=0.25,E[R]=0.6+0.4⋅0.25=0.7.q^*=0.25, \qquad \mathbb E[R]=0.6+0.4\cdot0.25=0.7.

Лагранжева функция линейна по qq:

L(q,λ)=0.6+0.25λ+(0.4−λ)q.\mathcal L(q,\lambda)=0.6+0.25\lambda+(0.4-\lambda)q.

Следовательно, при λ<0.4\lambda<0.4 максимум достигается в q=1q=1, при λ>0.4\lambda>0.4 — в q=0q=0, а при λ=0.4\lambda=0.4 любое q∈[0,1]q\in[0,1] даёт одинаковое значение. В седловой точке ограничение и двойственная цена совместно удерживают qq на границе допустимого множества.

Один двойственный шаг:

λ′=[0.2+0.5(0.6−0.25)]+=0.375.\lambda' = [0.2+0.5(0.6-0.25)]_+ =0.375.

Средний бюджет допускает рискованное действие с ограниченной частотой. Жёсткий запрет задаёт q=0q=0 для соответствующего класса состояний. Это разные требования и разные допустимые множества политик.

Оптимальная политика и граница награда–KL

Реализуйте устойчивую функцию:

Python
import numpy as np


def optimal_kl_policy(reference: np.ndarray, rewards: np.ndarray, beta: float) -> np.ndarray:
    """Return argmax E_pi[r] - beta * KL(pi || reference)."""
    ...

Проверьте β>0\beta>0, носитель базы и устойчивую нормировку. Затем постройте таблицу награды и KL по сетке β\beta.

Открытые проверки:

Python
p = optimal_kl_policy([1/3, 1/3, 1/3], [1.0, 0.0, -1.0], 1.0)
np.testing.assert_allclose(p, [0.66524096, 0.24472847, 0.09003057], rtol=1e-7)
Показать ответ и решение
Python
import numpy as np


def optimal_kl_policy(reference, rewards, beta):
    reference = np.asarray(reference, dtype=np.float64)
    rewards = np.asarray(rewards, dtype=np.float64)
    if reference.ndim != 1 or rewards.shape != reference.shape:
        raise ValueError("aligned vectors required")
    if beta <= 0 or not np.isfinite(beta):
        raise ValueError("beta must be finite and positive")
    if np.any(reference < 0) or not np.isclose(reference.sum(), 1.0):
        raise ValueError("reference must be a distribution")
    support = reference > 0
    logits = np.full_like(reference, -np.inf)
    logits[support] = np.log(reference[support]) + rewards[support] / beta
    maximum = np.max(logits[support])
    weights = np.zeros_like(reference)
    weights[support] = np.exp(logits[support] - maximum)
    return weights / weights.sum()

Для сетки β\beta вычисляются policy @ rewards и категориальный KL. В учебном примере при уменьшении β\beta обе величины растут.

Токеновый KL-шейпинг

Реализуйте функцию, добавляющую −β(log⁡πt−log⁡πref,t)-\beta(\log\pi_t-\log\pi_{\mathrm{ref},t}) к активным токенам и итоговую награду к последнему активному токену.

Python
import numpy as np


def shape_token_rewards(policy_logprobs, reference_logprobs, terminal_reward, beta, mask):
    ...

Проверьте тождество для суммы и обработайте пустую маску как ошибку.

Открытые проверки:

Python
policy = np.array([-0.5, -0.7])
reference = np.array([-0.4, -0.9])
shaped = shape_token_rewards(policy, reference, terminal_reward=1.0, beta=0.5, mask=np.ones_like(policy))
assert shaped.shape == (2,)
assert abs(float(shaped[0]) - (-0.5 * (-0.5 - -0.4))) < 1e-12
assert abs(float(shaped.sum()) - (1.0 - 0.5 * float((policy - reference).sum()))) < 1e-12
Показать ответ и решение
Python
import numpy as np


def shape_token_rewards(policy_logprobs, reference_logprobs, terminal_reward, beta, mask):
    p = np.asarray(policy_logprobs, dtype=np.float64)
    q = np.asarray(reference_logprobs, dtype=np.float64)
    mask = np.asarray(mask, dtype=np.float64)
    if p.ndim != 1 or q.shape != p.shape or mask.shape != p.shape:
        raise ValueError("aligned vectors required")
    if np.any((mask != 0) & (mask != 1)) or mask.sum() == 0:
        raise ValueError("mask must be non-empty and binary")
    rewards = -beta * (p - q) * mask
    rewards[np.flatnonzero(mask)[-1]] += terminal_reward
    return rewards

Проверка:

Python
out = shape_token_rewards([-0.2, -1.0, -2.0], [-0.2, -1.3, -1.8], 1.5, 0.2, [0, 1, 1])
assert np.isclose(out.sum(), 1.5 - 0.2 * (0.3 - 0.2))

Пакетная диагностика DPO

Реализуйте функцию, возвращающую среднюю потерю, точность пар, зазор, выбранный и отклонённый логарифмы вероятностей, неявные награды и градиентный вес.

Python
import numpy as np


def summarize_pairs(pc, pr, rc, rr, beta) -> dict[str, float]:
    ...

Добавьте тест, где точность пар растёт, а средняя вероятность предпочтённого ответа падает.

Открытые проверки:

Python
report = summarize_pairs([-2.0, -1.0], [-3.0, -1.5], [-2.5, -1.2], [-2.6, -1.4], 0.1)
assert abs(report["pair_accuracy"] - 1.0) < 1e-12
assert abs(report["mean_margin"] - 0.6) < 1e-12
assert abs(report["mean_chosen_logp"] - (-1.5)) < 1e-12
assert abs(report["mean_loss"] - 0.6637095) < 1e-6
Показать ответ и решение
Python
import numpy as np


def softplus(x):
    x = np.asarray(x, dtype=np.float64)
    return np.maximum(x, 0.0) + np.log1p(np.exp(-np.abs(x)))


def summarize_pairs(pc, pr, rc, rr, beta):
    pc, pr, rc, rr = [np.asarray(x, dtype=np.float64) for x in (pc, pr, rc, rr)]
    if not (pc.shape == pr.shape == rc.shape == rr.shape):
        raise ValueError("shared shape required")
    chosen_ratio = pc - rc
    rejected_ratio = pr - rr
    margin = chosen_ratio - rejected_ratio
    z = beta * margin
    return {
        "mean_loss": float(np.mean(softplus(-z))),
        "pair_accuracy": float(np.mean(margin > 0)),
        "mean_margin": float(np.mean(margin)),
        "mean_chosen_logp": float(np.mean(pc)),
        "mean_rejected_logp": float(np.mean(pr)),
        "mean_implicit_chosen_reward": float(np.mean(beta * chosen_ratio)),
        "mean_implicit_rejected_reward": float(np.mean(beta * rejected_ratio)),
        "mean_gradient_weight": float(np.mean(beta / (1.0 + np.exp(z)))),
    }

Логиты (−t,−3t,4t)(-t,-3t,4t) дают тест, где маржа растёт, а выбранный logp падает.

cDPO и IPO

Реализуйте векторизованные функции:

Python
import numpy as np


def conservative_dpo_loss(margin, beta, label_smoothing):
    ...


def ipo_loss(margin, tau):
    ...

Проверьте совпадение cDPO с DPO при нулевом сглаживании и минимум IPO при 1/(2τ)1/(2\tau).

Открытые проверки:

Python
margins = np.array([-1.0, 0.0, 2.0])
beta = 0.3
conservative = conservative_dpo_loss(margins, beta, label_smoothing=0.0)
ordinary_dpo = np.logaddexp(0.0, -beta * margins)
np.testing.assert_allclose(conservative, ordinary_dpo)
assert abs(float(ipo_loss(np.array([2.0]), tau=0.25)[0])) < 1e-12
Показать ответ и решение
Python
import numpy as np


def softplus(x):
    x = np.asarray(x, dtype=np.float64)
    return np.maximum(x, 0.0) + np.log1p(np.exp(-np.abs(x)))


def conservative_dpo_loss(margin, beta, label_smoothing):
    eps = float(label_smoothing)
    if beta <= 0 or not 0 <= eps < 0.5:
        raise ValueError("invalid beta or smoothing")
    z = beta * np.asarray(margin, dtype=np.float64)
    return (1.0 - eps) * softplus(-z) + eps * softplus(z)


def ipo_loss(margin, tau):
    if tau <= 0:
        raise ValueError("tau must be positive")
    margin = np.asarray(margin, dtype=np.float64)
    return (margin - 1.0 / (2.0 * tau)) ** 2

SimPO и ORPO

Реализуйте SimPO-оценку на средней логарифмической вероятности, SimPO-потерю, устойчивый логарифм шансов из logp и полную ORPO-цель.

Python

def simpo_reward(sequence_logp: float, length: int, beta: float) -> float:
    ...


def orpo_total_loss(chosen_mean_nll, chosen_logp, rejected_logp, lam) -> float:
    ...

Объясните, почему одинаковые числа гиперпараметров разных методов не означают одинаковый смысл обновления.

Открытые проверки:

Python
assert abs(simpo_reward(-4.0, 2, 1.0) - (-2.0)) < 1e-12
assert abs(simpo_reward(-4.0, 4, 1.0) - (-1.0)) < 1e-12
assert abs(simpo_reward(-4.0, 2, 2.0) - (-4.0)) < 1e-12
Показать ответ и решение
Python
import math


def softplus(x):
    return max(x, 0.0) + math.log1p(math.exp(-abs(x)))


def simpo_reward(sequence_logp, length, beta):
    if length <= 0 or beta <= 0:
        raise ValueError("positive length and beta required")
    return beta * sequence_logp / length


def log_odds_from_logprob(logp):
    if not math.isfinite(logp) or logp >= 0:
        raise ValueError("logp must be finite and negative")
    p = math.exp(logp)
    return logp - math.log1p(-p)


def orpo_total_loss(chosen_mean_nll, chosen_logp, rejected_logp, lam):
    if chosen_mean_nll < 0 or lam < 0:
        raise ValueError("non-negative inputs required")
    ratio = log_odds_from_logprob(chosen_logp) - log_odds_from_logprob(rejected_logp)
    return chosen_mean_nll + lam * softplus(-ratio)

Параметры разных методов входят в разные формулы; одинаковое численное значение не означает одинакового градиента.

Эксперимент со смещением правдоподобия

Реализуйте:

Python
import numpy as np


def likelihood_displacement_curve(ts: np.ndarray) -> dict[str, np.ndarray]:
    """Softmax probabilities for logits [-t, -3t, 4t]."""
    ...

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

Открытые проверки:

Python
ts = np.array([0.0, 0.2, 1.0, 3.0])
curve = likelihood_displacement_curve(ts)
np.testing.assert_allclose(
    np.log(curve["chosen"]) - np.log(curve["rejected"]),
    2.0 * ts,
    atol=1e-12,
)
assert displacement_alert(curve)
Показать ответ и решение
Python
import numpy as np


def likelihood_displacement_curve(ts):
    ts = np.asarray(ts, dtype=np.float64)
    logits = np.stack([-ts, -3.0 * ts, 4.0 * ts], axis=1)
    logits -= logits.max(axis=1, keepdims=True)
    p = np.exp(logits)
    p /= p.sum(axis=1, keepdims=True)
    return {"t": ts, "chosen": p[:, 0], "rejected": p[:, 1], "other": p[:, 2], "log_margin": 2.0 * ts}


def displacement_alert(curve):
    return bool(
        np.all(np.diff(curve["log_margin"]) > 0)
        and np.mean(np.diff(np.log(curve["chosen"]))) < 0
    )

Сигнал видит геометрию вероятностей, но не содержание третьего ответа. Поэтому он является диагностикой, а не доказательством снижения качества.

Ограниченная цель и двойственное обновление

Реализуйте:

Python
import numpy as np


def dual_ascent_step(multipliers, expected_costs, limits, step_size):
    """Return projected dual ascent: [lambda + eta * (cost - limit)]_+."""
    ...


def two_action_constrained_optimum(
    safe_reward,
    risky_reward,
    safe_cost,
    risky_cost,
    cost_limit,
):
    """Optimal risky-action probability for a two-action linear mixture."""
    ...

Проверьте учебный пример q∗=0.25q^*=0.25, обработайте недопустимый бюджет и покажите, что множитель растёт при нарушении и уменьшается без нарушения. Затем объясните, почему корректная численная реализация двойственного шага ещё не доказывает корректность модели стоимости.

Открытые проверки:

Python
updated = dual_ascent_step([0.2, 0.1], [0.6, 0.0], [0.25, 0.2], 0.5)
np.testing.assert_allclose(updated, [0.375, 0.0])
Показать ответ и решение
Python
import numpy as np


def dual_ascent_step(multipliers, expected_costs, limits, step_size):
    lam = np.asarray(multipliers, dtype=np.float64)
    costs = np.asarray(expected_costs, dtype=np.float64)
    bounds = np.asarray(limits, dtype=np.float64)
    if lam.shape != costs.shape or lam.shape != bounds.shape:
        raise ValueError("all arrays must have the same shape")
    if np.any(lam < 0) or not np.all(np.isfinite(lam)):
        raise ValueError("multipliers must be finite and non-negative")
    if step_size <= 0 or not np.isfinite(step_size):
        raise ValueError("step_size must be finite and positive")
    return np.maximum(0.0, lam + step_size * (costs - bounds))


def two_action_constrained_optimum(
    safe_reward,
    risky_reward,
    safe_cost,
    risky_cost,
    cost_limit,
):
    values = np.asarray(
        [safe_reward, risky_reward, safe_cost, risky_cost, cost_limit],
        dtype=np.float64,
    )
    if not np.all(np.isfinite(values)):
        raise ValueError("all inputs must be finite")
    if risky_cost <= safe_cost:
        raise ValueError("the teaching contract requires risky_cost > safe_cost")
    if cost_limit < safe_cost:
        raise ValueError("the cost budget is infeasible even for the safe action")
    q_max = np.clip(
        (cost_limit - safe_cost) / (risky_cost - safe_cost),
        0.0,
        1.0,
    )
    return float(q_max if risky_reward > safe_reward else 0.0)

Для учебных чисел функция возвращает 0.250.25. При нарушении, например C=0.6>d=0.25C=0.6>d=0.25, множитель увеличивается; при C<dC<d уменьшается до нуля с проекцией на неотрицательную полуось.

Проверка кода подтверждает только алгебру обновления. Она не проверяет, что CC измеряет нужный риск, что данные покрывают будущие запросы или что ограничение на среднее достаточно для критического сценария.