生成的目标
记某个生成的结果集为 $S$, 用户会对其打分为 $A(S) \in \mathbb{R}$, 将其归一化处理后可以得到一个概率分布, 记作 $q_*$, 显然有 $q_*(S) \propto A(S)$. 设 $\mathrm{d} (p, q) \in \mathbb{R}$ 是某评价两分布接近程度的函数, $g$ 是生成器采样得到结果的分布, 我们不妨假定用户希望最小化 $\mathrm{d} (q_*, g)$. 但往往 $q_*$ 是几乎不可知的, 于是我们接下来考虑如何在不知道 $q_*$ 的情况下最小化 $\mathrm{d} (q_*, g)$.
直觉上, 对于一个训练好的语言模型, 我们认为它只需要针对一个输入, 从模型的输出分布中选择一个即可, 但事实并非如此. 一般生成使用的都是自回归模型, 每次根据上下文生成一个 token, 并将该 token 加入上下文中, 如此反复. 以下是几种生成的方式:
-
最大化: 考虑每次生成一个结果 $S$, 使 $v(S)$ 最大化, 其中 $v$ 是某个近似估计当前输出与 $q_*$ 拟合程度的函数.
-
采样: 每次从一个分布 $p_θ(\cdot | y_{:i−1})$ 中采样, 然后将其附加到上下文中.
-
从指定的目标分布中采样: 采样到某个结果的概率正比于其与分布 $q_*$ 的拟合程度.
生成算法
MAP Decoding Algorithm
最简单的 MAP 解码就是贪心地选择使当前 $p_\theta(y|x)$ 最大的 $y$, 但显然其不一定取到整个序列的最优解.
对 MAP 解码的一个优化是, 考虑保留排名前 $k$ 的结果分别加入上下文中用于下次迭代.
当然, MAP 解码有一些缺陷, 在实践中发现其倾向于产生较短的结果, 对于此, 可以通过将序列的对数概率除以其长度缓解, 但并不足以完全解决. 同时, 由于贪心算法本身的特性, 序列的生成也可能陷入循环. 而在误差方面, 由于最终结果空间中每条路径的概率都非常小, 一些偶然误差就会影响非常大, 结果就容易退化. 在一些情况下, 假设各个 token 的概率相近, 每次取概率最大的 token 可能导致最终结果路径偏离典型集非常远.
尽管 MAP 解码有许多缺点, 其在翻译等输入输出问题上表现得仍然很好, 原因可能是其结构无意中符合了人的思维模式. 另一方面, MAP 解码会极大地限制输出的多样性, 而保留排名前 $k$ 的结果又会导致极大的计算资源开销, 所以我们需要更高效从模型中进行采样的算法.
采样和适配器
MAP 解码的一个替代方法是不进行任何贪心操作, 直接从 $y \sim y_\theta(y|x)$ 中采样, 各项分布正比于对数概率, 这被称为祖先采样.
祖先采样避免了许多 MAP 解码的退化行为, 比如重复陷阱, 并为语言模型的生成引入了更丰富的多样性. 当然, 祖先采样也有一些缺陷, 比如可能会过度采样不太可能的 token. 对于此, 可以通过启发式方法在每个时间步骤选择一个阈值, 仅考虑采样概率高于该阈值的 token. 有些时候我们希望获得比祖先采样更高的多样性, 可以考虑在贪心采样和均匀采样之间进行插值.
考虑用一个式子拟合以上方法
将 $\tau$ 设为 $\to 0$ 即为贪心解码, 设 $\tau$ 为 $1$ 即为祖先采样, 设 $\tau > 1$ 即接近于均匀采样.
控制生成
考虑将生成概率复合上一个调节序列 $c(y)$, 即
以下是基于 $c(y)$ 结构的三个例子.
分类器: 设 $c(y) = p(a|x, y)$, 它预测 $y$ 包含一个属性 $a$ 的概率, 比如某种风格. 目标从以下分布中采样
其中 $\beta$ 是一个超参数, 越大则给分类器分配更高的权重.
提示器: 设 $c(y) = [y \in Y_x^*]$, 它确保生成的结果包含 $Y_x^*$ 中的某个期望关键字, 例如 $Y_x^*$ 是推理问题中的正确解决方案集合. 目标从以下分布中采样
奖励: 一个重要的情况是, 当 $c(y)$ 被奖励函数 $r(x, y) \to \mathbb{R}$ 控制时, 目标从以下分布中采样