diff --git a/assets/home.js b/assets/home.js new file mode 100644 index 0000000..3bf1006 --- /dev/null +++ b/assets/home.js @@ -0,0 +1,14 @@ +document.querySelectorAll('.series-folder').forEach(folder => { + const summary = folder.querySelector('summary'); + if (!summary) return; + summary.addEventListener('click', () => { + window.requestAnimationFrame(() => { + if (folder.open) { + folder.classList.add('is-open'); + } else { + folder.classList.remove('is-open'); + } + }); + }); + if (folder.open) folder.classList.add('is-open'); +}); diff --git a/assets/posts/irl-rlhf-dpo/irlhf_dpo_pipeline.png b/assets/posts/irl-rlhf-dpo/irlhf_dpo_pipeline.png new file mode 100644 index 0000000..cdae630 Binary files /dev/null and b/assets/posts/irl-rlhf-dpo/irlhf_dpo_pipeline.png differ diff --git a/assets/style.css b/assets/style.css index c8c5c81..a89cce4 100644 --- a/assets/style.css +++ b/assets/style.css @@ -78,13 +78,217 @@ main { flex: 1; } 50% { transform: scale(1.035); filter: saturate(1.12); } } .post-list { display: grid; gap: 18px; padding-bottom: 64px; } -.post-list-compact { - gap: 10px; +.post-list:empty { padding: 0; } +.home-feed { + display: grid; + gap: 12px; max-width: 560px; margin: 0 auto; padding-bottom: 56px; } -.post-list:empty { padding: 0; } +.series-folder { + border: 1px solid var(--bg-300); + border-radius: 16px; + background: + linear-gradient(180deg, color-mix(in srgb, var(--primary-100) 55%, var(--bg-100)), var(--bg-100) 42%); + box-shadow: 0 10px 28px color-mix(in srgb, var(--primary-300) 5%, transparent); + overflow: hidden; + transition: border-color .2s ease, box-shadow .2s ease, transform .2s ease; +} +.series-folder[open], +.series-folder.is-open { + border-color: var(--primary-200); + box-shadow: 0 16px 34px color-mix(in srgb, var(--accent-200) 12%, transparent); +} +.series-folder-summary { + list-style: none; + display: grid; + grid-template-columns: auto 1fr auto; + gap: 14px; + align-items: center; + cursor: pointer; + padding: 16px 18px; + user-select: none; +} +.series-folder-summary::-webkit-details-marker { display: none; } +.series-folder-mark { + position: relative; + width: 42px; + height: 34px; + flex-shrink: 0; +} +.series-folder-tab, +.series-folder-body, +.series-folder-stack { + position: absolute; + display: block; + border: 1.5px solid color-mix(in srgb, var(--accent-200) 55%, var(--primary-200)); + background: color-mix(in srgb, var(--primary-100) 70%, var(--bg-100)); +} +.series-folder-tab { + left: 2px; + top: 2px; + width: 18px; + height: 10px; + border-radius: 6px 8px 0 0; + border-bottom: 0; +} +.series-folder-body { + left: 0; + top: 10px; + width: 100%; + height: 22px; + border-radius: 8px; + background: + linear-gradient(180deg, color-mix(in srgb, var(--accent-100) 35%, var(--bg-100)), var(--bg-100)); + box-shadow: inset 0 1px 0 color-mix(in srgb, #fff 55%, transparent); + transition: transform .28s ease; +} +.series-folder-stack { + left: 6px; + top: 16px; + width: calc(100% - 12px); + height: 14px; + border-radius: 5px; + opacity: .55; + transform: translateY(0); + transition: transform .28s ease, opacity .28s ease; +} +.series-folder[open] .series-folder-body, +.series-folder.is-open .series-folder-body { + transform: translateY(-2px) rotate(-2deg); +} +.series-folder[open] .series-folder-stack, +.series-folder.is-open .series-folder-stack { + opacity: .9; + transform: translateY(4px); +} +.series-folder-copy { display: grid; gap: 2px; min-width: 0; } +.series-folder-kicker, +.series-page-kicker { + font-size: 11px; + letter-spacing: .08em; + text-transform: uppercase; + color: var(--accent-200); +} +.series-folder-title { + font: normal 22px/1.35 var(--serif); + letter-spacing: -.02em; + color: var(--text-100); +} +.series-folder-meta { + font-size: 12px; + color: var(--text-200); + font-variant-numeric: tabular-nums; +} +.series-folder-chevron { + width: 10px; + height: 10px; + border-right: 2px solid var(--accent-200); + border-bottom: 2px solid var(--accent-200); + transform: rotate(45deg); + transition: transform .28s ease; + margin-right: 4px; +} +.series-folder[open] .series-folder-chevron, +.series-folder.is-open .series-folder-chevron { + transform: rotate(225deg); +} +.series-folder-panel { + display: grid; + grid-template-rows: 0fr; + transition: grid-template-rows .36s ease; +} +.series-folder[open] .series-folder-panel, +.series-folder.is-open .series-folder-panel { + grid-template-rows: 1fr; +} +.series-folder-panel-inner { + overflow: hidden; + min-height: 0; +} +.series-folder-blurb { + margin: 0; + padding: 0 18px 12px; + color: var(--text-200); + font-size: 13px; + line-height: 1.7; +} +.series-folder-posts { + display: grid; + gap: 8px; + padding: 0 12px 12px; + position: relative; +} +.series-folder-posts::before { + content: ""; + position: absolute; + left: 28px; + top: 4px; + bottom: 18px; + width: 2px; + border-radius: 2px; + background: color-mix(in srgb, var(--accent-100) 70%, var(--primary-200)); +} +.series-folder-posts .post-card-compact { + margin-left: 8px; + display: grid; + grid-template-columns: auto 1fr; + gap: 12px; + align-items: start; + background: color-mix(in srgb, var(--bg-100) 92%, var(--primary-100)); + animation: series-card-in .34s ease both; +} +.series-folder[open] .series-folder-posts .post-card-compact:nth-child(1) { animation-delay: .04s; } +.series-folder[open] .series-folder-posts .post-card-compact:nth-child(2) { animation-delay: .1s; } +.series-folder[open] .series-folder-posts .post-card-compact:nth-child(3) { animation-delay: .16s; } +.series-folder[open] .series-folder-posts .post-card-compact:nth-child(4) { animation-delay: .22s; } +@keyframes series-card-in { + from { opacity: 0; transform: translateY(8px); } + to { opacity: 1; transform: translateY(0); } +} +.series-index { + display: grid; + place-items: center; + width: 28px; + height: 28px; + margin-top: 2px; + border-radius: 999px; + background: var(--primary-100); + color: var(--accent-200); + font-size: 12px; + font-variant-numeric: tabular-nums; + position: relative; + z-index: 1; +} +.compact-copy { min-width: 0; } +.series-folder-link { + display: inline-flex; + align-items: center; + gap: 6px; + margin: 0 18px 16px; + font-size: 13px; + color: var(--accent-200); +} +.series-page-summary { + margin: 12px 0 0; + max-width: 40rem; + color: var(--text-200); + font-size: 15px; + line-height: 1.75; +} +.series-page-list { + display: grid; + gap: 10px; + max-width: 640px; + padding-bottom: 64px; +} +.series-page-list .post-card-compact { + display: grid; + grid-template-columns: auto 1fr; + gap: 14px; + align-items: start; +} .post-card { display: block; padding: 28px 32px 26px; @@ -241,6 +445,12 @@ main { flex: 1; } .post-card:hover { transform: none; } .post-card-compact .card-summary { transition: none; } .geometry-glow { animation: none; } + .series-folder, + .series-folder-body, + .series-folder-stack, + .series-folder-chevron, + .series-folder-panel { transition: none; } + .series-folder-posts .post-card-compact { animation: none; } .prose h2, .prose h3 { transition: none; } .prose h2.heading-flash, .prose h3.heading-flash { animation: none; } diff --git a/blog/active-learning/index.html b/blog/active-learning/index.html index e936f30..ec87d4b 100644 --- a/blog/active-learning/index.html +++ b/blog/active-learning/index.html @@ -150,7 +150,7 @@

6. 两类不确定性

实际使用还需要留意三点。首先,BALD 的质量取决于后验或其近似是否可信;少数偏差相似的模型,并不一定能代表完整的参数不确定性。其次,信息增益不等于测试误差下降,三种方法都不保证选中带来最大性能提升的样本。最后,如果一次选择多个样本,直接取单点分数最高的若干个,可能获得大量重复信息;批量选样还需要考虑样本之间的关系。

这三种方法关注的对象不同:Uncertainty Sampling 看当前预测有多模糊,QBC 看委员会成员有多不一致,BALD 看标签预计能为参数带来多少信息。理解这个差别,比单独记住某个采集公式更有助于判断方法适合什么场景。

参考资料

- + diff --git a/blog/behavior-cloning-plid/index.html b/blog/behavior-cloning-plid/index.html index 948e573..884ac81 100644 --- a/blog/behavior-cloning-plid/index.html +++ b/blog/behavior-cloning-plid/index.html @@ -203,7 +203,7 @@

9. 总结

\text{PLID:}\quad s\sim d_{\pi_m}

这也是从 Behavior Cloning 走向 Distribution Matching 的起点:当专家持续标注成本过高时,下一步是不再逐个纠正动作,而是直接让模型产生与专家相似的行为分布。下一篇笔记讨论 Distribution Matching 与 GAIL。

参考资料

- + diff --git a/blog/distribution-matching-gail/index.html b/blog/distribution-matching-gail/index.html index 121bb4e..aeea5c9 100644 --- a/blog/distribution-matching-gail/index.html +++ b/blog/distribution-matching-gail/index.html @@ -207,8 +207,9 @@

8. 总结

GAIL 用一个二分类器区分专家与模型,再把判别器信号转化为策略奖励。它的关键数学事实是:最优判别器的 log-odds 等于两个分布的 log density ratio;在理想条件下,对抗目标与 JS divergence 相关。

如果说 BC 是“模仿专家在这个状态下做什么”,PLID 是“让专家纠正模型实际遇到的状态”,那么 GAIL 更接近于:

让模型产生整体上无法被判别器与专家区分的行为。

+

这也是通向目标学习的一步:当分布匹配仍不够时,下一篇讨论 IRL、RLHF 与 DPO。

参考资料

- + diff --git a/blog/index.html b/blog/index.html index 0e61917..e70d792 100644 --- a/blog/index.html +++ b/blog/index.html @@ -23,7 +23,7 @@ Musicaldg -

文章

约 10 分钟

Distribution Matching 与 GAIL

从轨迹与状态—动作分布匹配出发,说明 Forward KL 为何可能退化为 BC,以及 GAIL 如何用判别器完成分布匹配。

阅读全文
约 10 分钟

Behavior Cloning 与 PLID

说明 Behavior Cloning 的状态分布偏移,并推导 PLID / DAgger 如何用交互式专家标签修正策略。

阅读全文
约 12 分钟

Active Learning

介绍主动学习的基本流程,比较不确定性采样、QBC 和 BALD 三种选样方法。

阅读全文
+

文章

约 13 分钟

IRL、RLHF 与 DPO

从逆强化学习出发,说明如何从专家行为与人类偏好学习目标,并连接到 RLHF 与 DPO。

阅读全文
约 10 分钟

Distribution Matching 与 GAIL

从轨迹与状态—动作分布匹配出发,说明 Forward KL 为何可能退化为 BC,以及 GAIL 如何用判别器完成分布匹配。

阅读全文
约 10 分钟

Behavior Cloning 与 PLID

说明 Behavior Cloning 的状态分布偏移,并推导 PLID / DAgger 如何用交互式专家标签修正策略。

阅读全文
约 12 分钟

Active Learning

介绍主动学习的基本流程,比较不确定性采样、QBC 和 BALD 三种选样方法。

阅读全文
diff --git a/blog/irl-rlhf-dpo/index.html b/blog/irl-rlhf-dpo/index.html new file mode 100644 index 0000000..ff57a71 --- /dev/null +++ b/blog/irl-rlhf-dpo/index.html @@ -0,0 +1,310 @@ + + + + + + + + + + + + IRL、RLHF 与 DPO · Musicaldg + + + + + + + + +
+
+ Musicaldg + +
+
← 全部文章

IRL、RLHF 与 DPO

目录

Behavior Cloning、PLID 和 GAIL 主要学习专家如何行动。若希望模型在新环境中仍能做出合理决策,就需要进一步理解专家行为背后的目标。本文从 Inverse Reinforcement Learning 出发,说明如何从专家行为推断奖励,并连接到 RLHF 与 DPO。

+

系列前文:Behavior Cloning 与 PLID、Distribution Matching 与 GAIL。

+

IRL、RLHF 与 DPO 如何逐步改变监督信号

+

1. 问题转向

+

前两篇介绍了三种直接学习行为的方式:

+
  • Behavior Cloning 在专家访问过的状态上拟合动作;
  • PLID 让当前策略探索,再由专家标注模型实际遇到的状态;
  • GAIL 通过判别器,让模型产生难以与专家区分的状态—动作分布。
+

它们都主要回答:

+

专家在这个状态下做了什么?

+

但在环境变化、任务目标变化或专家行为存在多种合理解释时,直接复制动作可能不够。我们可能更希望理解:

+

专家为什么做这个选择?它在优化什么目标?

+

这就是 Inverse Reinforcement Learning(逆强化学习,IRL)的出发点。

+

普通强化学习的方向是:

+
R\longrightarrow\pi^*
+

给定奖励函数 R,求在该奖励下表现最好的策略 \pi^*。

+

IRL 则试图反过来:

+
\pi_E\longrightarrow\hat R_\phi\longrightarrow\hat\pi
+

先观察专家策略 \pi_E,推断一个能够解释专家行为的奖励函数 R_\phi,再在这个奖励下重新优化策略。

+

需要先强调:IRL 找到的通常是一个可以解释专家行为的奖励函数,不一定是专家真实的心理动机。

+

2. 方法对照

+

不同方法的已知信息与学习对象如下:

+
  • RL:已知奖励函数;学习策略;如何最大化已知目标?
  • BC / PLID:已知专家状态—动作;学习策略;如何直接复制专家行为?
  • GAIL:已知专家轨迹;学习策略;如何匹配行为分布?
  • IRL:已知专家行为,奖励未知;学习奖励函数,再学习策略;专家行为背后的目标是什么?
  • RLHF:已知人类偏好比较;学习奖励模型,再优化策略;哪个行为更符合人类偏好?
  • DPO:已知人类偏好比较;学习直接优化策略;能否绕过显式奖励模型?
+

这张表也说明了第三篇的主线:监督信号逐渐从具体动作变得更加抽象。

+

3. IRL 形式化

+

3.1 参数化奖励

+

假设奖励函数未知,我们用带参数的函数表示它:

+
R_\phi(s)
+

其中 \phi 是奖励函数的参数。给定策略 \pi_\theta,其期望折扣回报为:

+
J(\theta,\phi) += +\mathbb E_{\tau\sim p_{\pi_\theta}} +\left[ +\sum_{t=0}^{T-1} +\gamma^t R_\phi(s_t) +\right]
+

改变 \theta 会改变模型访问的状态;改变 \phi 会改变每个状态的价值。因此 IRL 中的策略和奖励参数通常通过交替过程共同出现。

+

3.2 线性奖励

+

为了让问题可分析,常假设奖励由状态特征线性组合而成:

+
R_\phi(s) += +\phi^\top\psi(s)
+

其中:

+
  • \psi(s)\in\mathbb R^d 是状态特征向量;
  • \phi\in\mathbb R^d 是每个特征的奖励权重。
+

例如在导航任务中,特征可以表示:

+
  • 距离目标的远近;
  • 与障碍物的距离;
  • 速度或能耗;
  • 是否发生碰撞。
+

线性假设不是说真实奖励一定线性,而是将问题限制在一个可解释、可优化的函数族中。

+

4. 特征期望匹配

+

4.1 累计特征

+

定义策略 \pi 的累计特征期望:

+
\mu_\pi += +\mathbb E_{\tau\sim p_\pi} +\left[ +\sum_{t=0}^{T-1} +\gamma^t\psi(s_t) +\right]
+

在线性奖励下,策略的期望回报可以写成:

+
J(\pi,\phi) += +\phi^\top\mu_\pi
+

推导如下:

+
\begin{aligned} +J(\pi,\phi) +&= +\mathbb E_{\tau\sim p_\pi} +\left[ +\sum_{t=0}^{T-1} +\gamma^t\phi^\top\psi(s_t) +\right]\\ +&= +\phi^\top +\mathbb E_{\tau\sim p_\pi} +\left[ +\sum_{t=0}^{T-1} +\gamma^t\psi(s_t) +\right]\\ +&= +\phi^\top\mu_\pi +\end{aligned}
+

这里使用了内积的线性性以及期望与线性变换可以交换。

+

4.2 匹配的作用

+

设专家的累计特征期望为 \mu_E,模型的累计特征期望为 \mu_\pi。在同一个奖励函数下,二者的回报差为:

+
\left| +J(\pi_E,\phi)-J(\pi,\phi) +\right| += +\left| +\phi^\top(\mu_E-\mu_\pi) +\right|
+

根据 Cauchy–Schwarz 不等式:

+
\left| +\phi^\top(\mu_E-\mu_\pi) +\right| +\leq +\|\phi\|_2 +\|\mu_E-\mu_\pi\|_2
+

因此,当模型和专家的累计特征期望接近时,在满足参数约束的一族线性奖励函数下,它们的表现差异也会受到控制。

+

这就是 Feature Expectation Matching(特征期望匹配)的核心直觉。

+

4.3 真实奖励

+

特征期望匹配并不能保证找到专家真实的奖励函数。它只说明:在选定特征和约束范围内,模型的行为统计与专家相近。

+

如果特征没有表达“安全”这一维度,即使模型和专家在已有特征上匹配,模型也可能在安全性上表现很差。这是特征设计带来的限制。

+

5. Maximum Entropy IRL

+

5.1 多种合理行为

+

现实中的专家并不一定每次都采取完全相同的动作。即使面对同一个任务,也可能存在多条都合理的路线。

+

如果我们把专家行为强行解释成唯一最优轨迹,就可能把偶然选择误认为必然目标。Maximum Entropy IRL 的思路是:在能够解释专家数据的前提下,选择额外假设最少的行为分布。

+

一种常见形式是定义轨迹分布:

+
p_\phi(\tau) += +\frac{1}{Z(\phi)} +\exp +\left( +\sum_{t=0}^{T-1} +R_\phi(s_t) +\right)
+

其中 Z(\phi) 是 partition function,用来保证所有轨迹概率之和为 1:

+
Z(\phi) += +\sum_\tau +\exp +\left( +\sum_{t=0}^{T-1} +R_\phi(s_t) +\right)
+

奖励高的轨迹概率更大,但其他轨迹仍然可能出现。

+

5.2 奖励梯度

+

给定专家轨迹数据,最大化其对数似然:

+
\mathcal L(\phi) += +\mathbb E_{\tau\sim p_E} +\left[ +\log p_\phi(\tau) +\right]
+

对参数 \phi 求梯度,得到“专家特征期望减去模型特征期望”的结构:

+
\nabla_\phi\mathcal L += +\mu_E +- +\mathbb E_{\tau\sim p_\phi} +\left[ +\mu_\tau +\right]
+

这里 \mu_\tau 表示单条轨迹的累计特征向量。

+

这条公式的直觉是:

+
  • 如果模型产生的某个特征少于专家,就提高该特征对应的奖励;
  • 如果模型产生的某个特征多于专家,就降低对应奖励;
  • 训练通过比较专家与模型的行为统计量来更新奖励函数。
+

由于模型特征期望通常需要从当前策略 rollout 中估计,IRL 往往包含“更新奖励—用 RL 优化策略—重新比较行为”的循环。

+

5.3 奖励歧义

+

奖励函数存在不可辨识性。一个极端例子是:

+
R(s,a)=0
+

在这个奖励下,所有策略的回报都相同,因此专家策略也可以被视为最优策略。但这个奖励没有解释专家究竟偏好什么。

+

因此,IRL 的目标不是机械地寻找任何一个能让专家成为最优的奖励函数,而是通过函数族限制、正则化、最大熵假设或额外偏好数据,寻找更有用的解释。

+

6. RLHF

+

6.1 偏好比较

+

在许多任务中,人类很难给一个行为指定稳定的绝对奖励,但比较两个行为的相对优劣要容易得多。

+

例如,对于同一个问题,模型生成两个回答。人类可能很难判断它们应该分别得到 8.1 分还是 8.6 分,但通常可以判断哪个回答更好。

+

RLHF(Reinforcement Learning from Human Feedback)的关键变化是:

+

不要求人类直接写出奖励函数,而是从人类对行为的偏好比较中学习奖励模型。

+

6.2 Bradley–Terry

+

设 x 是 prompt,y^+ 是人类偏好的回答,y^- 是较不受偏好的回答。偏好数据写成:

+
\mathcal D_\pm += +\left\{ +(x_n,y_n^+,y_n^-) +\right\}_{n=1}^{N}
+

奖励模型记为 r_\phi(x,y)。Bradley–Terry 模型假设:

+
P(y^+\succ y^-\mid x) += +\sigma +\left( + r_\phi(x,y^+)-r_\phi(x,y^-) +\right)
+

其中 \sigma 是 sigmoid 函数。

+

如果偏好回答的奖励比另一回答高很多,模型预测人类选择它的概率就更高。

+

于是可以用二元交叉熵训练 Reward Model:

+
\mathcal L_{\mathrm{RM}}(\phi) += +-\mathbb E_{(x,y^+,y^-)} +\left[ +\log +\sigma +\left( + r_\phi(x,y^+)-r_\phi(x,y^-) +\right) +\right]
+

奖励模型不需要让奖励值具有绝对意义。对所有回答的奖励同时加上一个常数,偏好概率不会改变,因为真正起作用的是奖励差:

+
\bigl(r(x,y^+)+c\bigr) +- +\bigl(r(x,y^-)+c\bigr) += + r(x,y^+)-r(x,y^-)
+

6.3 RLHF 流程

+

经典 RLHF 通常可以分为三步:

+
  1. 用监督微调得到初始策略 \pi_0;
  2. 让模型生成候选回答,由人类进行偏好比较,训练 Reward Model;
  3. 使用 RL 优化策略,使其获得更高奖励,同时不要偏离 reference policy 太远。
+

因此,RLHF 仍然保留了 IRL 的两阶段结构:

+
\text{行为偏好} +\longrightarrow +\text{奖励模型} +\longrightarrow +\text{策略优化}
+

它与 IRL 的区别主要在于监督形式不同:IRL 通常观察专家行为,RLHF 则直接获得人类对行为的相对偏好。

+

7. DPO

+

7.1 KL 正则化

+

经典 RLHF 的策略优化目标可以写成:

+
\max_{\pi_\theta} +\mathbb E_{y\sim\pi_\theta(\cdot\mid x)} +\left[ + r(x,y) +\right] +- +\beta +D_{\mathrm{KL}} +\left( + \pi_\theta(\cdot\mid x) +\|\pi_0(\cdot\mid x) +\right)
+

第一项鼓励模型生成高奖励回答,第二项约束当前策略不要偏离 reference policy \pi_0 太远。

+

参数 \beta>0 控制偏离惩罚:\beta 越大,策略越接近 reference policy。

+

7.2 最优策略

+

对于固定的 prompt x,KL 正则化目标的最优策略具有如下形式:

+
\pi^*(y\mid x) += +\frac{1}{Z(x)} +\pi_0(y\mid x) +\exp +\left( +\frac{r(x,y)}{\beta} +\right)
+

其中 Z(x) 是归一化因子。

+

整理可得:

+
r(x,y) += +\beta +\log +\frac{\pi^*(y\mid x)}{\pi_0(y\mid x)} ++ +\beta\log Z(x)
+

这意味着,在 KL 正则化 RL 的最优解下,奖励可以用最优策略相对于 reference policy 的 log-probability ratio 表示。

+

7.3 偏好代入

+

对一对回答 y^+ 和 y^-,奖励差中的归一化项会抵消:

+
\begin{aligned} +&r(x,y^+)-r(x,y^-)\\ +&= +\beta +\left[ +\log\frac{\pi^*(y^+\mid x)}{\pi_0(y^+\mid x)} +- +\log\frac{\pi^*(y^-\mid x)}{\pi_0(y^-\mid x)} +\right] +\end{aligned}
+

将未知的最优策略 \pi^* 用当前策略 \pi_\theta 近似,再代入 Bradley–Terry 偏好模型,就得到 DPO 的直接偏好优化目标:

+
\begin{aligned} +\mathcal L_{\mathrm{DPO}}(\theta) +=-\mathbb E_{(x,y^+,y^-)} +\Bigg[ +\log\sigma\Bigg( +\beta +\Big[ +&\log\frac{\pi_\theta(y^+\mid x)}{\pi_0(y^+\mid x)}\\ +-&\log\frac{\pi_\theta(y^-\mid x)}{\pi_0(y^-\mid x)} +\Big] +\Bigg) +\Bigg] +\end{aligned}
+

DPO 的核心含义是:

+
  • 提高偏好回答相对于 reference policy 的概率;
  • 降低非偏好回答相对于 reference policy 的概率;
  • 用偏好数据直接训练策略,而不是先单独训练 Reward Model,再使用 PPO 等 RL 算法优化策略。
+

7.4 边界

+

DPO 绕过的是显式的 Reward Model 和策略阶段的在线 RL 优化流程,但它并没有消除所有问题:

+
  • 偏好数据仍然可能有噪声和标注偏差;
  • reference policy 会影响优化结果;
  • 离线偏好数据可能无法覆盖模型部署时的状态;
  • 模型可能学习标注者偏好的表面模式,而不是真正的任务质量;
  • 长回答与短回答之间可能存在长度偏差。
+

因此,DPO 不是“无需奖励、无需假设”的方法,而是将奖励与参考策略的关系隐含进了直接偏好优化目标。

+

8. 系列串联

+

现在可以把本系列的三篇文章放在同一张图中理解:

+

监督信号从动作到偏好

+

监督信号从动作标签逐步转向行为目标与相对偏好。

+

三篇文章的分工是:

+
  1. Behavior Cloning 到 PLID:为什么专家状态分布与模型状态分布不同;
  2. Distribution Matching 到 GAIL:如何让模型整体行为接近专家分布;
  3. IRL、RLHF 与 DPO:当行为背后的目标未知时,如何从行为或偏好学习目标。
+

9. 总结

+

IRL 把模仿学习的问题从“专家做了什么”推进到“专家可能在优化什么”。在线性奖励和特征期望匹配的设定下,专家与模型的行为差异可以通过累计特征统计量来分析;Maximum Entropy IRL 则允许专家存在多种合理行为,并通过专家与模型的特征期望差异更新奖励参数。

+

RLHF 改变了监督信号:人类不必直接给出绝对奖励,只需要比较两个行为哪个更好。Reward Model 将这些相对偏好转化为可优化的奖励。

+

DPO 则进一步利用 KL 正则化 RL 的解析关系,把奖励差表示为当前策略与 reference policy 的 log-probability ratio,从而直接用偏好数据更新策略。

+

因此,第三篇的主线可以概括为:

+

从复制专家行为,到推断行为目标,再到直接利用人类偏好优化策略。

+

参考资料

+
+ +
+ + diff --git a/content/posts/active-learning.md b/content/posts/active-learning.md index d82f80a..d1642e3 100644 --- a/content/posts/active-learning.md +++ b/content/posts/active-learning.md @@ -278,4 +278,4 @@ $$ - [课程讲义](https://github.com/enalisnick/enalisnick.github.io/blob/master/ML_with_Humans_Course_Notes.pdf) - [BALD 论文](https://arxiv.org/abs/1112.5745) -- 系列后续:[Behavior Cloning 与 PLID](/blog/behavior-cloning-plid/)、[Distribution Matching 与 GAIL](/blog/distribution-matching-gail/) +- 系列后续:[Imitation Learning](/series/imitation-learning/) diff --git a/content/posts/behavior-cloning-plid.md b/content/posts/behavior-cloning-plid.md index 1a64264..1b57972 100644 --- a/content/posts/behavior-cloning-plid.md +++ b/content/posts/behavior-cloning-plid.md @@ -345,6 +345,6 @@ $$ ## 参考资料 - [课程讲义](https://github.com/enalisnick/enalisnick.github.io/blob/master/ML_with_Humans_Course_Notes.pdf) -- 系列上一篇:[Active Learning](/blog/active-learning/) +- 系列:[Imitation Learning](/series/imitation-learning/) - 系列下一篇:[Distribution Matching 与 GAIL](/blog/distribution-matching-gail/) diff --git a/content/posts/distribution-matching-gail.md b/content/posts/distribution-matching-gail.md index 733eafe..a6e6fa3 100644 --- a/content/posts/distribution-matching-gail.md +++ b/content/posts/distribution-matching-gail.md @@ -335,8 +335,12 @@ GAIL 用一个二分类器区分专家与模型,再把判别器信号转化为 > 让模型产生整体上无法被判别器与专家区分的行为。 +这也是通向目标学习的一步:当分布匹配仍不够时,下一篇讨论 [IRL、RLHF 与 DPO](/blog/irl-rlhf-dpo/)。 + ## 参考资料 - [课程讲义](https://github.com/enalisnick/enalisnick.github.io/blob/master/ML_with_Humans_Course_Notes.pdf) +- 系列:[Imitation Learning](/series/imitation-learning/) - 系列上一篇:[Behavior Cloning 与 PLID](/blog/behavior-cloning-plid/) +- 系列下一篇:[IRL、RLHF 与 DPO](/blog/irl-rlhf-dpo/) diff --git a/content/posts/irl-rlhf-dpo.md b/content/posts/irl-rlhf-dpo.md new file mode 100644 index 0000000..35da83a --- /dev/null +++ b/content/posts/irl-rlhf-dpo.md @@ -0,0 +1,503 @@ +--- +title: IRL、RLHF 与 DPO +date: 2026-11-03 +summary: 从逆强化学习出发,说明如何从专家行为与人类偏好学习目标,并连接到 RLHF 与 DPO。 +draft: false +--- + +Behavior Cloning、PLID 和 GAIL 主要学习专家如何行动。若希望模型在新环境中仍能做出合理决策,就需要进一步理解专家行为背后的目标。本文从 Inverse Reinforcement Learning 出发,说明如何从专家行为推断奖励,并连接到 RLHF 与 DPO。 + +系列前文:[Behavior Cloning 与 PLID](/blog/behavior-cloning-plid/)、[Distribution Matching 与 GAIL](/blog/distribution-matching-gail/)。 + +> IRL、RLHF 与 DPO 如何逐步改变监督信号 + +## 1. 问题转向 + +前两篇介绍了三种直接学习行为的方式: + +- Behavior Cloning 在专家访问过的状态上拟合动作; +- PLID 让当前策略探索,再由专家标注模型实际遇到的状态; +- GAIL 通过判别器,让模型产生难以与专家区分的状态—动作分布。 + +它们都主要回答: + +> 专家在这个状态下做了什么? + +但在环境变化、任务目标变化或专家行为存在多种合理解释时,直接复制动作可能不够。我们可能更希望理解: + +> 专家为什么做这个选择?它在优化什么目标? + +这就是 Inverse Reinforcement Learning(逆强化学习,IRL)的出发点。 + +普通强化学习的方向是: + +$$ +R\longrightarrow\pi^* +$$ + +给定奖励函数 $R$,求在该奖励下表现最好的策略 $\pi^*$。 + +IRL 则试图反过来: + +$$ +\pi_E\longrightarrow\hat R_\phi\longrightarrow\hat\pi +$$ + +先观察专家策略 $\pi_E$,推断一个能够解释专家行为的奖励函数 $R_\phi$,再在这个奖励下重新优化策略。 + +需要先强调:IRL 找到的通常是一个**可以解释专家行为的奖励函数**,不一定是专家真实的心理动机。 + +## 2. 方法对照 + +不同方法的已知信息与学习对象如下: + +- **RL**:已知奖励函数;学习策略;如何最大化已知目标? +- **BC / PLID**:已知专家状态—动作;学习策略;如何直接复制专家行为? +- **GAIL**:已知专家轨迹;学习策略;如何匹配行为分布? +- **IRL**:已知专家行为,奖励未知;学习奖励函数,再学习策略;专家行为背后的目标是什么? +- **RLHF**:已知人类偏好比较;学习奖励模型,再优化策略;哪个行为更符合人类偏好? +- **DPO**:已知人类偏好比较;学习直接优化策略;能否绕过显式奖励模型? + +这张表也说明了第三篇的主线:监督信号逐渐从具体动作变得更加抽象。 + +## 3. IRL 形式化 + +### 3.1 参数化奖励 + +假设奖励函数未知,我们用带参数的函数表示它: + +$$ +R_\phi(s) +$$ + +其中 $\phi$ 是奖励函数的参数。给定策略 $\pi_\theta$,其期望折扣回报为: + +$$ +J(\theta,\phi) += +\mathbb E_{\tau\sim p_{\pi_\theta}} +\left[ +\sum_{t=0}^{T-1} +\gamma^t R_\phi(s_t) +\right] +$$ + +改变 $\theta$ 会改变模型访问的状态;改变 $\phi$ 会改变每个状态的价值。因此 IRL 中的策略和奖励参数通常通过交替过程共同出现。 + +### 3.2 线性奖励 + +为了让问题可分析,常假设奖励由状态特征线性组合而成: + +$$ +R_\phi(s) += +\phi^\top\psi(s) +$$ + +其中: + +- $\psi(s)\in\mathbb R^d$ 是状态特征向量; +- $\phi\in\mathbb R^d$ 是每个特征的奖励权重。 + +例如在导航任务中,特征可以表示: + +- 距离目标的远近; +- 与障碍物的距离; +- 速度或能耗; +- 是否发生碰撞。 + +线性假设不是说真实奖励一定线性,而是将问题限制在一个可解释、可优化的函数族中。 + +## 4. 特征期望匹配 + +### 4.1 累计特征 + +定义策略 $\pi$ 的累计特征期望: + +$$ +\mu_\pi += +\mathbb E_{\tau\sim p_\pi} +\left[ +\sum_{t=0}^{T-1} +\gamma^t\psi(s_t) +\right] +$$ + +在线性奖励下,策略的期望回报可以写成: + +$$ +J(\pi,\phi) += +\phi^\top\mu_\pi +$$ + +推导如下: + +$$ +\begin{aligned} +J(\pi,\phi) +&= +\mathbb E_{\tau\sim p_\pi} +\left[ +\sum_{t=0}^{T-1} +\gamma^t\phi^\top\psi(s_t) +\right]\\ +&= +\phi^\top +\mathbb E_{\tau\sim p_\pi} +\left[ +\sum_{t=0}^{T-1} +\gamma^t\psi(s_t) +\right]\\ +&= +\phi^\top\mu_\pi +\end{aligned} +$$ + +这里使用了内积的线性性以及期望与线性变换可以交换。 + +### 4.2 匹配的作用 + +设专家的累计特征期望为 $\mu_E$,模型的累计特征期望为 $\mu_\pi$。在同一个奖励函数下,二者的回报差为: + +$$ +\left| +J(\pi_E,\phi)-J(\pi,\phi) +\right| += +\left| +\phi^\top(\mu_E-\mu_\pi) +\right| +$$ + +根据 Cauchy–Schwarz 不等式: + +$$ +\left| +\phi^\top(\mu_E-\mu_\pi) +\right| +\leq +\|\phi\|_2 +\|\mu_E-\mu_\pi\|_2 +$$ + +因此,当模型和专家的累计特征期望接近时,在满足参数约束的一族线性奖励函数下,它们的表现差异也会受到控制。 + +这就是 Feature Expectation Matching(特征期望匹配)的核心直觉。 + +### 4.3 真实奖励 + +特征期望匹配并不能保证找到专家真实的奖励函数。它只说明:在选定特征和约束范围内,模型的行为统计与专家相近。 + +如果特征没有表达“安全”这一维度,即使模型和专家在已有特征上匹配,模型也可能在安全性上表现很差。这是特征设计带来的限制。 + +## 5. Maximum Entropy IRL + +### 5.1 多种合理行为 + +现实中的专家并不一定每次都采取完全相同的动作。即使面对同一个任务,也可能存在多条都合理的路线。 + +如果我们把专家行为强行解释成唯一最优轨迹,就可能把偶然选择误认为必然目标。Maximum Entropy IRL 的思路是:在能够解释专家数据的前提下,选择额外假设最少的行为分布。 + +一种常见形式是定义轨迹分布: + +$$ +p_\phi(\tau) += +\frac{1}{Z(\phi)} +\exp +\left( +\sum_{t=0}^{T-1} +R_\phi(s_t) +\right) +$$ + +其中 $Z(\phi)$ 是 partition function,用来保证所有轨迹概率之和为 1: + +$$ +Z(\phi) += +\sum_\tau +\exp +\left( +\sum_{t=0}^{T-1} +R_\phi(s_t) +\right) +$$ + +奖励高的轨迹概率更大,但其他轨迹仍然可能出现。 + +### 5.2 奖励梯度 + +给定专家轨迹数据,最大化其对数似然: + +$$ +\mathcal L(\phi) += +\mathbb E_{\tau\sim p_E} +\left[ +\log p_\phi(\tau) +\right] +$$ + +对参数 $\phi$ 求梯度,得到“专家特征期望减去模型特征期望”的结构: + +$$ +\nabla_\phi\mathcal L += +\mu_E +- +\mathbb E_{\tau\sim p_\phi} +\left[ +\mu_\tau +\right] +$$ + +这里 $\mu_\tau$ 表示单条轨迹的累计特征向量。 + +这条公式的直觉是: + +- 如果模型产生的某个特征少于专家,就提高该特征对应的奖励; +- 如果模型产生的某个特征多于专家,就降低对应奖励; +- 训练通过比较专家与模型的行为统计量来更新奖励函数。 + +由于模型特征期望通常需要从当前策略 rollout 中估计,IRL 往往包含“更新奖励—用 RL 优化策略—重新比较行为”的循环。 + +### 5.3 奖励歧义 + +奖励函数存在不可辨识性。一个极端例子是: + +$$ +R(s,a)=0 +$$ + +在这个奖励下,所有策略的回报都相同,因此专家策略也可以被视为最优策略。但这个奖励没有解释专家究竟偏好什么。 + +因此,IRL 的目标不是机械地寻找任何一个能让专家成为最优的奖励函数,而是通过函数族限制、正则化、最大熵假设或额外偏好数据,寻找更有用的解释。 + +## 6. RLHF + +### 6.1 偏好比较 + +在许多任务中,人类很难给一个行为指定稳定的绝对奖励,但比较两个行为的相对优劣要容易得多。 + +例如,对于同一个问题,模型生成两个回答。人类可能很难判断它们应该分别得到 8.1 分还是 8.6 分,但通常可以判断哪个回答更好。 + +RLHF(Reinforcement Learning from Human Feedback)的关键变化是: + +> 不要求人类直接写出奖励函数,而是从人类对行为的偏好比较中学习奖励模型。 + +### 6.2 Bradley–Terry + +设 $x$ 是 prompt,$y^+$ 是人类偏好的回答,$y^-$ 是较不受偏好的回答。偏好数据写成: + +$$ +\mathcal D_\pm += +\left\{ +(x_n,y_n^+,y_n^-) +\right\}_{n=1}^{N} +$$ + +奖励模型记为 $r_\phi(x,y)$。Bradley–Terry 模型假设: + +$$ +P(y^+\succ y^-\mid x) += +\sigma +\left( + r_\phi(x,y^+)-r_\phi(x,y^-) +\right) +$$ + +其中 $\sigma$ 是 sigmoid 函数。 + +如果偏好回答的奖励比另一回答高很多,模型预测人类选择它的概率就更高。 + +于是可以用二元交叉熵训练 Reward Model: + +$$ +\mathcal L_{\mathrm{RM}}(\phi) += +-\mathbb E_{(x,y^+,y^-)} +\left[ +\log +\sigma +\left( + r_\phi(x,y^+)-r_\phi(x,y^-) +\right) +\right] +$$ + +奖励模型不需要让奖励值具有绝对意义。对所有回答的奖励同时加上一个常数,偏好概率不会改变,因为真正起作用的是奖励差: + +$$ +\bigl(r(x,y^+)+c\bigr) +- +\bigl(r(x,y^-)+c\bigr) += + r(x,y^+)-r(x,y^-) +$$ + +### 6.3 RLHF 流程 + +经典 RLHF 通常可以分为三步: + +1. 用监督微调得到初始策略 $\pi_0$; +2. 让模型生成候选回答,由人类进行偏好比较,训练 Reward Model; +3. 使用 RL 优化策略,使其获得更高奖励,同时不要偏离 reference policy 太远。 + +因此,RLHF 仍然保留了 IRL 的两阶段结构: + +$$ +\text{行为偏好} +\longrightarrow +\text{奖励模型} +\longrightarrow +\text{策略优化} +$$ + +它与 IRL 的区别主要在于监督形式不同:IRL 通常观察专家行为,RLHF 则直接获得人类对行为的相对偏好。 + +## 7. DPO + +### 7.1 KL 正则化 + +经典 RLHF 的策略优化目标可以写成: + +$$ +\max_{\pi_\theta} +\mathbb E_{y\sim\pi_\theta(\cdot\mid x)} +\left[ + r(x,y) +\right] +- +\beta +D_{\mathrm{KL}} +\left( + \pi_\theta(\cdot\mid x) +\|\pi_0(\cdot\mid x) +\right) +$$ + +第一项鼓励模型生成高奖励回答,第二项约束当前策略不要偏离 reference policy $\pi_0$ 太远。 + +参数 $\beta>0$ 控制偏离惩罚:$\beta$ 越大,策略越接近 reference policy。 + +### 7.2 最优策略 + +对于固定的 prompt $x$,KL 正则化目标的最优策略具有如下形式: + +$$ +\pi^*(y\mid x) += +\frac{1}{Z(x)} +\pi_0(y\mid x) +\exp +\left( +\frac{r(x,y)}{\beta} +\right) +$$ + +其中 $Z(x)$ 是归一化因子。 + +整理可得: + +$$ +r(x,y) += +\beta +\log +\frac{\pi^*(y\mid x)}{\pi_0(y\mid x)} ++ +\beta\log Z(x) +$$ + +这意味着,在 KL 正则化 RL 的最优解下,奖励可以用最优策略相对于 reference policy 的 log-probability ratio 表示。 + +### 7.3 偏好代入 + +对一对回答 $y^+$ 和 $y^-$,奖励差中的归一化项会抵消: + +$$ +\begin{aligned} +&r(x,y^+)-r(x,y^-)\\ +&= +\beta +\left[ +\log\frac{\pi^*(y^+\mid x)}{\pi_0(y^+\mid x)} +- +\log\frac{\pi^*(y^-\mid x)}{\pi_0(y^-\mid x)} +\right] +\end{aligned} +$$ + +将未知的最优策略 $\pi^*$ 用当前策略 $\pi_\theta$ 近似,再代入 Bradley–Terry 偏好模型,就得到 DPO 的直接偏好优化目标: + +$$ +\begin{aligned} +\mathcal L_{\mathrm{DPO}}(\theta) +=-\mathbb E_{(x,y^+,y^-)} +\Bigg[ +\log\sigma\Bigg( +\beta +\Big[ +&\log\frac{\pi_\theta(y^+\mid x)}{\pi_0(y^+\mid x)}\\ +-&\log\frac{\pi_\theta(y^-\mid x)}{\pi_0(y^-\mid x)} +\Big] +\Bigg) +\Bigg] +\end{aligned} +$$ + +DPO 的核心含义是: + +- 提高偏好回答相对于 reference policy 的概率; +- 降低非偏好回答相对于 reference policy 的概率; +- 用偏好数据直接训练策略,而不是先单独训练 Reward Model,再使用 PPO 等 RL 算法优化策略。 + +### 7.4 边界 + +DPO 绕过的是显式的 Reward Model 和策略阶段的在线 RL 优化流程,但它并没有消除所有问题: + +- 偏好数据仍然可能有噪声和标注偏差; +- reference policy 会影响优化结果; +- 离线偏好数据可能无法覆盖模型部署时的状态; +- 模型可能学习标注者偏好的表面模式,而不是真正的任务质量; +- 长回答与短回答之间可能存在长度偏差。 + +因此,DPO 不是“无需奖励、无需假设”的方法,而是将奖励与参考策略的关系隐含进了直接偏好优化目标。 + +## 8. 系列串联 + +现在可以把本系列的三篇文章放在同一张图中理解: + +![监督信号从动作到偏好](/assets/posts/irl-rlhf-dpo/irlhf_dpo_pipeline.png) + +*监督信号从动作标签逐步转向行为目标与相对偏好。* + +三篇文章的分工是: + +1. **Behavior Cloning 到 PLID**:为什么专家状态分布与模型状态分布不同; +2. **Distribution Matching 到 GAIL**:如何让模型整体行为接近专家分布; +3. **IRL、RLHF 与 DPO**:当行为背后的目标未知时,如何从行为或偏好学习目标。 + +## 9. 总结 + +IRL 把模仿学习的问题从“专家做了什么”推进到“专家可能在优化什么”。在线性奖励和特征期望匹配的设定下,专家与模型的行为差异可以通过累计特征统计量来分析;Maximum Entropy IRL 则允许专家存在多种合理行为,并通过专家与模型的特征期望差异更新奖励参数。 + +RLHF 改变了监督信号:人类不必直接给出绝对奖励,只需要比较两个行为哪个更好。Reward Model 将这些相对偏好转化为可优化的奖励。 + +DPO 则进一步利用 KL 正则化 RL 的解析关系,把奖励差表示为当前策略与 reference policy 的 log-probability ratio,从而直接用偏好数据更新策略。 + +因此,第三篇的主线可以概括为: + +> 从复制专家行为,到推断行为目标,再到直接利用人类偏好优化策略。 + +## 参考资料 + +- [课程讲义](https://github.com/enalisnick/enalisnick.github.io/blob/master/ML_with_Humans_Course_Notes.pdf) +- 系列:[Imitation Learning](/series/imitation-learning/) +- 系列第一篇:[Behavior Cloning 与 PLID](/blog/behavior-cloning-plid/) +- 系列第二篇:[Distribution Matching 与 GAIL](/blog/distribution-matching-gail/) diff --git a/content/series.json b/content/series.json new file mode 100644 index 0000000..8dbac03 --- /dev/null +++ b/content/series.json @@ -0,0 +1,12 @@ +[ + { + "id": "imitation-learning", + "title": "Imitation Learning", + "summary": "从行为克隆到偏好优化,理解模仿学习中监督信号如何逐步抽象。", + "posts": [ + "behavior-cloning-plid", + "distribution-matching-gail", + "irl-rlhf-dpo" + ] + } +] diff --git a/feed.xml b/feed.xml index b659527..a2f3278 100644 --- a/feed.xml +++ b/feed.xml @@ -1,2 +1,2 @@ -Musicaldghttps://musicaldg.github.ioMusicaldg 的机器学习笔记。zh-CNDistribution Matching 与 GAILhttps://musicaldg.github.io/blog/distribution-matching-gail/https://musicaldg.github.io/blog/distribution-matching-gail/从轨迹与状态—动作分布匹配出发,说明 Forward KL 为何可能退化为 BC,以及 GAIL 如何用判别器完成分布匹配。Mon, 02 Nov 2026 00:00:00 GMTBehavior Cloning 与 PLIDhttps://musicaldg.github.io/blog/behavior-cloning-plid/https://musicaldg.github.io/blog/behavior-cloning-plid/说明 Behavior Cloning 的状态分布偏移,并推导 PLID / DAgger 如何用交互式专家标签修正策略。Tue, 20 Oct 2026 00:00:00 GMTActive Learninghttps://musicaldg.github.io/blog/active-learning/https://musicaldg.github.io/blog/active-learning/介绍主动学习的基本流程,比较不确定性采样、QBC 和 BALD 三种选样方法。Tue, 29 Sep 2026 00:00:00 GMT +Musicaldghttps://musicaldg.github.ioMusicaldg 的机器学习笔记。zh-CNIRL、RLHF 与 DPOhttps://musicaldg.github.io/blog/irl-rlhf-dpo/https://musicaldg.github.io/blog/irl-rlhf-dpo/从逆强化学习出发,说明如何从专家行为与人类偏好学习目标,并连接到 RLHF 与 DPO。Tue, 03 Nov 2026 00:00:00 GMTDistribution Matching 与 GAILhttps://musicaldg.github.io/blog/distribution-matching-gail/https://musicaldg.github.io/blog/distribution-matching-gail/从轨迹与状态—动作分布匹配出发,说明 Forward KL 为何可能退化为 BC,以及 GAIL 如何用判别器完成分布匹配。Mon, 02 Nov 2026 00:00:00 GMTBehavior Cloning 与 PLIDhttps://musicaldg.github.io/blog/behavior-cloning-plid/https://musicaldg.github.io/blog/behavior-cloning-plid/说明 Behavior Cloning 的状态分布偏移,并推导 PLID / DAgger 如何用交互式专家标签修正策略。Tue, 20 Oct 2026 00:00:00 GMTActive Learninghttps://musicaldg.github.io/blog/active-learning/https://musicaldg.github.io/blog/active-learning/介绍主动学习的基本流程,比较不确定性采样、QBC 和 BALD 三种选样方法。Tue, 29 Sep 2026 00:00:00 GMT diff --git a/generated-files.json b/generated-files.json index c157bc2..8aaa90d 100644 --- a/generated-files.json +++ b/generated-files.json @@ -2,6 +2,8 @@ "index.html", "blog/index.html", "404.html", + "series/imitation-learning/index.html", + "blog/irl-rlhf-dpo/index.html", "blog/distribution-matching-gail/index.html", "blog/behavior-cloning-plid/index.html", "blog/active-learning/index.html", diff --git a/index.html b/index.html index b09ebe7..baed61e 100644 --- a/index.html +++ b/index.html @@ -14,7 +14,7 @@ - + @@ -28,8 +28,8 @@ -
-

Distribution Matching 与 GAIL

从轨迹与状态—动作分布匹配出发,说明 Forward KL 为何可能退化为 BC,以及 GAIL 如何用判别器完成分布匹配。

Behavior Cloning 与 PLID

说明 Behavior Cloning 的状态分布偏移,并推导 PLID / DAgger 如何用交互式专家标签修正策略。

Active Learning

介绍主动学习的基本流程,比较不确定性采样、QBC 和 BALD 三种选样方法。

+
+
系列Imitation Learning3 篇 · 2026-10-20 — 2026-11-03

Active Learning

介绍主动学习的基本流程,比较不确定性采样、QBC 和 BALD 三种选样方法。

diff --git a/scripts/build.py b/scripts/build.py index bd0b7a6..b744ab8 100644 --- a/scripts/build.py +++ b/scripts/build.py @@ -154,10 +154,46 @@ def read_posts(): return sorted(posts, key=lambda x: (x['date'], x['slug']), reverse=True) +def read_series(posts_by_slug): + path = ROOT / 'content/series.json' + if not path.exists(): + return [] + catalog = json.loads(path.read_text(encoding='utf-8')) + series_list = [] + for entry in catalog: + for key in ('id', 'title', 'summary', 'posts'): + if not entry.get(key): + raise ValueError(f'series.json: 缺少 {key}') + if not re.fullmatch(r'[a-z0-9]+(?:-[a-z0-9]+)*', entry['id']): + raise ValueError(f'series.json: id 请使用小写英文、数字和连字符') + members = [] + for slug in entry['posts']: + post = posts_by_slug.get(slug) + if not post: + raise ValueError(f'series.json: 找不到文章 {slug}') + members.append(post) + if not members: + raise ValueError(f'series.json: {entry["id"]} 没有文章') + series_list.append({ + 'id': entry['id'], + 'title': entry['title'], + 'summary': entry['summary'], + 'posts': members, + 'count': len(members), + 'start': min(p['date'] for p in members), + 'end': max(p['date'] for p in members), + }) + return series_list + + def build(): config = json.loads((ROOT / 'site.json').read_text(encoding='utf-8')) layout = Template((ROOT / 'templates/layout.html').read_text(encoding='utf-8')) posts = read_posts() + posts_by_slug = {p['slug']: p for p in posts} + series_list = read_series(posts_by_slug) + series_slugs = {slug for series in series_list for slug in (p['slug'] for p in series['posts'])} + standalone = [p for p in posts if p['slug'] not in series_slugs] previous = json.loads((ROOT / 'generated-files.json').read_text()) if (ROOT / 'generated-files.json').exists() else [] generated = [] @@ -167,27 +203,63 @@ def write(path, content): target.write_text(content.rstrip() + '\n', encoding='utf-8') generated.append(path) - def page(path, title, description, body, current='', og_type='website'): + def page(path, title, description, body, current='', og_type='website', extra_assets=''): url_path = '/' if path == 'index.html' else '/' + path.removesuffix('index.html') - write(path, layout.substitute(name=esc(config['name']), github=esc(config['github']), year=dt.date.today().year, title=esc(title), description=esc(description), canonical=esc(config['url'] + url_path), body=body, home_current='aria-current="page"' if current == 'home' else '', blog_current='aria-current="page"' if current == 'blog' else '', og_type=og_type, page_class='article-page' if og_type == 'article' else '', article_assets='' if og_type == 'article' else '')) + article_assets = '' if og_type == 'article' else '' + write(path, layout.substitute(name=esc(config['name']), github=esc(config['github']), year=dt.date.today().year, title=esc(title), description=esc(description), canonical=esc(config['url'] + url_path), body=body, home_current='aria-current="page"' if current == 'home' else '', blog_current='aria-current="page"' if current == 'blog' else '', og_type=og_type, page_class='article-page' if og_type == 'article' else '', article_assets=article_assets + extra_assets)) def blog_rows(selected): return ''.join(f'
约 {p["minutes"]} 分钟

{esc(p["title"])}

{esc(p["summary"])}

阅读全文
' for p in selected) or EMPTY - def home_rows(selected): - return ''.join( - f'' - f'' - f'

{esc(p["title"])}

' - f'

{esc(p["summary"])}

' + def compact_card(post, index=None): + index_html = f'{index:02d}' if index is not None else '' + return ( + f'
' + f'{index_html}' + f'
' + f'

{esc(post["title"])}

' + f'

{esc(post["summary"])}

' f'
' - for p in selected - ) or EMPTY + ) + + def series_folder(series, open_by_default=False): + span = series['start'] if series['start'] == series['end'] else f'{series["start"]} — {series["end"]}' + cards = ''.join(compact_card(post, index=i) for i, post in enumerate(series['posts'], 1)) + open_attr = ' open' if open_by_default else '' + return ( + f'
' + f'' + f'' + f'系列' + f'{esc(series["title"])}' + f'{series["count"]} 篇 · {span}' + f'' + f'' + f'
' + f'

{esc(series["summary"])}

' + f'
{cards}
' + f'打开系列页 ' + f'
' + ) + + def home_feed(): + parts = [series_folder(series) for series in series_list] + parts.extend(compact_card(post) for post in standalone[:4]) + return ''.join(parts) or EMPTY - home = Template((ROOT / 'templates/home.html').read_text(encoding='utf-8')).substitute(posts=home_rows(posts[:5])) - page('index.html', config['name'], config['description'], home, 'home') + home = Template((ROOT / 'templates/home.html').read_text(encoding='utf-8')).substitute(feed=home_feed()) + page('index.html', config['name'], config['description'], home, 'home', extra_assets='') page('blog/index.html', '文章 · ' + config['name'], '机器学习笔记。', '

文章

' + blog_rows(posts) + '
', 'blog') page('404.html', '页面未找到 · ' + config['name'], '页面未找到', '

404

页面未找到

回到首页 ↗
') + for series in series_list: + cards = ''.join(compact_card(post, index=i) for i, post in enumerate(series['posts'], 1)) + body = ( + f'
← 首页' + f'

系列

{esc(series["title"])}

' + f'

{esc(series["summary"])}

' + f'
{cards}
' + ) + page(f'series/{series["id"]}/index.html', series['title'] + ' · ' + config['name'], series['summary'], body, 'home') for post in posts: toc = '' body = f'
← 全部文章

{esc(post["title"])}

目录{toc}
{post["body"]}
' @@ -209,7 +281,7 @@ def home_rows(selected): write('sitemap.xml', ET.tostring(sitemap, encoding='utf-8', xml_declaration=True).decode('utf-8')) write('robots.txt', 'User-agent: *\nAllow: /\nSitemap: ' + config['url'] + '/sitemap.xml') for obsolete in set(previous) - set(generated): - if obsolete.startswith('blog/') and obsolete.endswith('/index.html'): + if obsolete.endswith('/index.html') and (obsolete.startswith('blog/') or obsolete.startswith('series/')): target = ROOT / obsolete if target.exists(): target.unlink() diff --git a/series/imitation-learning/index.html b/series/imitation-learning/index.html new file mode 100644 index 0000000..9e4c101 --- /dev/null +++ b/series/imitation-learning/index.html @@ -0,0 +1,30 @@ + + + + + + + + + + + + Imitation Learning · Musicaldg + + + + + + + + +
+
+ Musicaldg + +
+
← 首页

系列

Imitation Learning

从行为克隆到偏好优化,理解模仿学习中监督信号如何逐步抽象。

01

Behavior Cloning 与 PLID

说明 Behavior Cloning 的状态分布偏移,并推导 PLID / DAgger 如何用交互式专家标签修正策略。

02

Distribution Matching 与 GAIL

从轨迹与状态—动作分布匹配出发,说明 Forward KL 为何可能退化为 BC,以及 GAIL 如何用判别器完成分布匹配。

03

IRL、RLHF 与 DPO

从逆强化学习出发,说明如何从专家行为与人类偏好学习目标,并连接到 RLHF 与 DPO。

+
© 2026 MusicaldgRSS
+
+ + diff --git a/sitemap.xml b/sitemap.xml index ac5e410..053215e 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -1,2 +1,2 @@ -https://musicaldg.github.io/https://musicaldg.github.io/blog/https://musicaldg.github.io/blog/distribution-matching-gail/https://musicaldg.github.io/blog/behavior-cloning-plid/https://musicaldg.github.io/blog/active-learning/ +https://musicaldg.github.io/https://musicaldg.github.io/blog/https://musicaldg.github.io/series/imitation-learning/https://musicaldg.github.io/blog/irl-rlhf-dpo/https://musicaldg.github.io/blog/distribution-matching-gail/https://musicaldg.github.io/blog/behavior-cloning-plid/https://musicaldg.github.io/blog/active-learning/ diff --git a/templates/home.html b/templates/home.html index 33ad83e..47c326f 100644 --- a/templates/home.html +++ b/templates/home.html @@ -3,6 +3,6 @@ -
-$posts +
+$feed