跳转到内容

第 29 章 生成策略:从分数到采样

29.1 同一个模型,可以接出不同的下文

Section titled “29.1 同一个模型,可以接出不同的下文”

模型读完“The capital of France is”,已经为候选打好分,但应用还需作一次选择:总选最高分,还是偶尔选其他候选?差旅助手也会遇到这个选择,只是标准不同:现行金额答对,比表达多样更重要;虚构小故事则可以欢迎变化,前提是内容仍然连贯。

第 4 章从计数得到概率,第 18 章从模型分数得到下一个 token 的分布。本章先固定分数,只改变选择规则,由此看清生成策略究竟改了什么。随后再看 Mini GPT 的真实记录:选择规则无法补入缺失知识,也不能单独教会模型可靠地遵循指令。

例 29.1:法国首都,一个刻意缩小的候选表。 候选顺序为 Paris、Lyon、red、EOS。EOS 是序列结束 token,选中它就结束本次生成。给定 logits 为 [ln⁡4,ln⁡2,0,0][\ln4,\ln2,0,0],约为 [1.386294,0.693147,0,0][1.386294,0.693147,0,0]。这是教学分数,不是模型实测 logits。Logits 是尚未归一化的数值分数,分数为零不代表概率为零。

取指数得到权重 [4,2,1,1][4,2,1,1],总和为 8,因此概率为 [4/8,2/8,1/8,1/8][4/8,2/8,1/8,1/8]。分母加总了当前全部合格候选的权重,这就是 softmax。程序为避免指数过大,可以先从所有分数中减去最大分数,再取指数;所有权重同时乘了同一个因子,归一化时便会抵消。

贪心解码(greedy decoding) 直接选择最高分,这里是 Paris,不进行随机抽取。本章约定并列时取原始顺序最靠前的候选,所以 red 与 EOS 同分时,red 排在前面。若采用其他并列规则,必须写进运行记录。

若想把分布变平一些,可以先把所有 logits 除以一个正的 温度(temperature) ,再做 softmax。温度为 2 时,权重变成 [2,2,1,1][2,\sqrt2,1,1],因为对数除以 2 后取指数,相当于开平方。分母为 4+2≈5.4142144+\sqrt2\approx5.414214,概率约为 [0.369398,0.261204,0.184699,0.184699][0.369398,0.261204,0.184699,0.184699]。

现在再写一般形式:

pi(τ)=exp⁡(zi/τ)∑j=1Vexp⁡(zj/τ),τ>0.p_i(\tau)=\frac{\exp(z_i/\tau)}{\sum_{j=1}^{V}\exp(z_j/\tau)},\qquad \tau>0.

下标 i 指某个候选,V 是合格候选数量,ziz_i 是该候选的分数,τ\tau 是温度。分母遍历的也是这批候选。温度 1 恢复本例的 4:2:1:1 权重;小于 1 时,相对权重会更集中。本章标量程序把温度 0 单独约定为贪心,不能把 0 直接代入除法。若最高分并列,温度趋近零的极限也不等于确定地取第一个并列项。负温度在这里会被拒绝。

分布变平,也会增加低排名候选的机会。若希望保留一些变化,又不想保留整个尾部,可以再筛选。Top-k 保留概率最高的 k 个候选;Top-p,也称 核采样(nucleus sampling),按概率从高到低,保留累计概率至少达到 p 的最短前缀。并列按原始候选顺序处理。两种方法都必须在筛选后重新归一化。

例 29.2:保留固定个数,还是保留足够概率质量。 温度取 1。Top-k = 2 时,留下 Paris 和 Lyon,原概率之和为 0.5+0.25=0.750.5+0.25=0.75,把保留项都除以 0.75,得到 [2/3,1/3,0,0][2/3,1/3,0,0]。

Top-p = 0.6 时,Paris 单独只有 0.5,还不够;加入 Lyon 后累计到 0.75,就在此停止,得到同样的两候选分布。保留的概率质量可以超过阈值,不会把某个 token 的概率切开以恰好凑数。Top-p = 0.8 时,还需加上 red,累计为 0.875,最终得到 [4/7,2/7,1/7,0][4/7,2/7,1/7,0]。

表 29.1:按原候选顺序列出的推导分布

策略ParisLyonredEOS
贪心约定1000
温度 10.50.250.1250.125
温度 20.3693980.2612040.1846990.184699
温度 1,Top-k 22/31/300
温度 1,Top-p 0.51000
温度 1,Top-p 0.6 或 0.752/31/300
温度 1,Top-p 0.84/72/71/70

阈值恰好为 0.75 时,“至少达到”的规则让筛选停在 Lyon。若程序误写成必须超过 0.75,就会多留 red,改变分布。本实现若同时使用 Top-k、Top-p,先应用温度,再做 Top-k,最后对保留项重新归一化后的分布做 Top-p。这是明确的本地契约,不能默认所有服务都以相同顺序组合这些控制项。

四个权重归一化
  1. 一组数字Paris 4 | Lyon 2 | red 1 | EOS 1
  2. 处理步骤各项除以 8
  3. 一组数字0.5 | 0.25 | 0.125 | 0.125

Paris 的区间到 .5 为止,.60 落在 Lyon。

Top-p = .8
  1. 处理步骤累计 .5 → .75 → .875:停止
  2. 一组数字保留 Paris、Lyon、red;排除 EOS
  3. 处理步骤权重 4+2+1 = 7
  4. 一组数字4/7 | 2/7 | 1/7 | 0

保留质量超过 .8,不拆分 token 概率来凑阈值。

Top-k = 2
  1. 一组数字权重 4、2 → 2/3、1/3
  2. 处理步骤Paris 区间 [0,2/3)
  3. 文本片段抽样 .60 → Paris

同一个给定抽样值,重归一化后选择不同。

图 29.1:筛选改变了概率区间。 本书原创图示 · CC BY-SA 4.0。

图 29.1 说明筛选并非只把几个标签变灰:共同的分母缩小后,保留候选的概率会增加。

29.4 一次抽样选中区间,之后前缀就变了

Section titled “29.4 一次抽样选中区间,之后前缀就变了”

温度 1、不筛选时,按原顺序铺开区间:Paris 占 [0,0.5)[0,0.5),Lyon 占 [0.5,0.75)[0.5,0.75),red 占 [0.75,0.875)[0.75,0.875),EOS 占 [0.875,1)[0.875,1)。从大于等于 0、小于 1 的范围均匀抽取 u;每个区间包含左端,不包含右端。给定 u = 0.74,选 Lyon;0.75 选 red;0.99 选 EOS。恰好为 1 的抽样值不合法。

同一个 u = 0.74,在 Top-k 2 后仍选 Lyon;Top-p 0.8 后也落在 Lyon 的区间,只是这个区间现在从 4/74/7 到 6/76/7。但不同策略不保证同一个 u 选中同一个 token。u = 0.60 时,未筛选分布选 Lyon,Top-k 2 却选 Paris。区间一变,选择也变了。

选中非 EOS token 后,将它的 ID 接到前缀末尾,再运行模型。由于输入已经改变,下次分布通常也会改变。“抽签后放回”适合类比对同一个固定分布反复实验,不能据此声称语言生成每一步都使用相同概率。

实际 Mini GPT 生成器禁止 BOS、PAD,允许 EOS,并在遇到 EOS、输出 token 预算或上下文上限时停止。因达到最大 token 数而停止,不表示答案已经完整。字节 tokenizer 还可能在一个 UTF-8 字符中间停下,因此记录必须保留原字节及解码有效性。若按文本停止串终止,就需规定如何检查解码后的输出;停止串不一定是单个 token,本小型生成器没有实现这种规则。

29.5 每一步选最高分,完整路径仍可能输掉

Section titled “29.5 每一步选最高分,完整路径仍可能输掉”

例 29.3:两步搜索树。 第一步给定 A、B 的概率为 0.6、0.4。接在 A 后,EOS 与 x 都为 0.5;接在 B 后,EOS 为 0.9,x 为 0.1。候选顺序为 A 在 B 前、EOS 在 x 前。完成路径遇 EOS 停止,最多检查两个 token,末尾为 x 的路径标作尚未完成。

表 29.2:按乘法推导的路径联合概率

路径乘法联合概率状态
A,EOS0.6 × 0.50.30完成
A,x0.6 × 0.50.30到检查边界仍未完成
B,EOS0.4 × 0.90.36完成
B,x0.4 × 0.10.04到检查边界仍未完成

贪心先选 A,再按并列规则选 EOS,联合概率为 0.30。宽度为 2 的 束搜索(beam search) 保留第一步的两个前缀,分别展开,便能找到概率为 0.36 的 B、EOS。它只保留有限条部分路径,近似搜索高分序列。束更宽,不证明文本更真实、有用或有创造性;它优化的是指定的模型分数,有限剪枝也可能漏掉最优路径。

路径较长时,可以累加对数概率,避免连乘许多很小的数。原始联合概率往往偏向较短的完整字符串。把对数概率除以长度,会改变这种偏好:按原概率,概率为 0.4 的单 token 路径胜过概率为 0.3 的双 token 路径;但在这个特定长度归一化分数下,ln⁡(0.3)/2>ln⁡(0.4)\ln(0.3)/2>\ln(0.4),次序反过来。不同归一化公式定义了不同目标。GNMT 论文提供了具体任务中的实例;本章公式只是简化说明,并非通用束搜索配方。

29.6 惩罚重复,也可能压低正确的重复

Section titled “29.6 惩罚重复,也可能压低正确的重复”

假设 Paris 在已生成下文中出现两次,每出现一次就从其 logit 减去 0.5。调整后得 ln⁡4−2×0.5≈0.386294\ln4-2\times0.5\approx0.386294,低于 Lyon 的 ln⁡2≈0.693147\ln2\approx0.693147。重复出现的正确城市失去了第一名。这个计数惩罚可写为 zi′=zi−λciz'_i=z_i-\lambda c_i:cic_i 数候选 i 在已生成部分出现的次数,λ\lambda 是每次的惩罚量。其他实现可能按是否出现过,或用乘法规则处理,名称不能互相替代。

惩罚可以减少循环,也可能破坏重复标识符、引用的政策金额,或必须重复前文值的结构化字段。温度和惩罚改变选择偏好,不改变已学权重、来源文档或执行权限。模型若没能使用给定证据,调低温度也不会把 600 元旧规则自动更新为 750 元。

29.7 把固定规则用到真实小模型上

Section titled “29.7 把固定规则用到真实小模型上”

配套实验固定 MG-2 第 600 步权重、tokenizer 和 24 个新 token 预算,运行贪心,以及温度 0.7、1.2 的两种 Top-k 5 采样;每种策略使用种子 7、42、31415。中英文提示在同一个资源文件中预先固定。全部 36 次尝试均已在单线程 CPU、float64 环境运行;版本、逐步 ID、原字节和停止原因保存在 data/part-v/generation-run.json。这些是真实模型输出,与表 29.1 的给定 logits 分开。

结构化任务的英文提示为 Beijing lodging limit: 750. Answer: ,中文为 北京住宿限额750元。答案:,诊断要求是去掉首尾空白后恰好输出 750。创造性任务提示为 The key is red. 和 钥匙是红色的。,标准是续写连贯小场景,并保留红钥匙设定。字符串彼此不同,并不够满足这项标准。

表 29.3:实测结构化输出,种子按 7/42/31415 排列

输入语言与策略种子 7种子 42种子 31415
英文,贪心red.red.red.
英文,0.7/Top-k 5t750on: n: old.red.red.
英文,1.2/Top-k 5t750ol: n: old.ped.tNon: n: old.
中文,贪心 red red red t: red te. Ver: red t: red t red red red t: red te. Ver: red t: red t red red red t: red te. Ver: red t: red t
中文,0.7/Top-k 5 blue key blue er: red red t: red te. Aeuo red red te. red red red t: red te red teu
中文,1.2/Top-k 5 blue key blue er: red red red red te. Answer red red te. red red red t: red keye key.

这 18 次结构化尝试全部未通过。t750on 里夹着数字,不等于给出了正确的纯金额答案。英文各项均因 EOS 停止;中文贪心各次与两种采样的种子 7 达到 token 预算,其余中文采样因 EOS 停止。18 项都能合法解码为 UTF-8,显然仍不是合格中文回答。

创造性任务中,三种策略、三个种子的全部英文输出都是 Answer: red.,随后 EOS;全部中文尝试都立即选择 EOS,下文为空。因此,每种策略在每种语言的三次重复中,都只有一种不同下文,没有任何一项写出要求的小场景。这是一次能力与变化程度均不合格的实验,不能据此推断任何模型都无法通过采样产生变化。它也防止我们只挑一个好看的种子,丢掉其余记录。

种子初始化的是特定随机数生成器。库、精度、内核、候选筛选或抽样顺序不同,都可能改变输出。即使同一环境可以确定复现,也只证明该配置的可复现性,不保证跨平台逐字一致。下一章跟踪两次选择之间的实际计算,看复用与精度怎样成为资源选择。

生成策略通过分数调整、候选筛选、重新归一化、抽样或搜索,以及停止,把 logits 变成选择。每一步都需要明确约定。贪心、采样、束搜索针对不同的局部或序列标准,不能单独保证事实正确、有用的多样性或遵循指令。

  1. 对表 29.1 温度 1、未筛选的分布,分别使用 0.49、0.50、0.75、0.99。给出选择,并解释 0.50 的边界。
  2. 温度 1,Top-p 设为 0.76。保留哪些候选,新概率是多少?为何与 0.75 不同?
  3. 温度改为 0.5,不筛选。推导四个权重和概率,不只说它“更集中”。
  4. 例 29.3 第一步改为 A = 0.8、B = 0.2,比较两条完整路径。束宽为 2 是否总会改变贪心结果?
  5. 某报告说温度 1.2 产生三个不同字符串,所以结构化回答质量提高了。结合表 29.3 诊断这一说法。
  6. 一次运行达到 token 预算,输出也能合法解码为 UTF-8。要判成功,还需做哪两种不同检查?
  1. 依次为 Paris、Lyon、red、EOS。Paris 区间不包含 0.50,Lyon 区间包含它。若两个区间都包含同一边界,选择规则就不明确。
  2. Paris 与 Lyon 合计只有 0.75,因此还需 red。除以 0.875,得到 [4/7,2/7,1/7,0][4/7,2/7,1/7,0]。阈值为 0.75 时,前两个已满足“至少达到”,归一化为 [2/3,1/3,0,0][2/3,1/3,0,0]。
  3. Logits 除以 0.5 相当于加倍,权重变为 [16,4,1,1][16,4,1,1],总和 22,概率为 [8/11,2/11,1/22,1/22][8/11,2/11,1/22,1/22]。第一名获得更多概率,却没有获得新知识。
  4. A、EOS 为 0.8×0.5=0.40.8\times0.5=0.4,B、EOS 为 0.2×0.9=0.180.2\times0.9=0.18。两种搜索都可以选 A、EOS。扩大搜索宽度允许保留其他路径,不要求一定与贪心不同。
  5. 英文温度 1.2 的三项输出都不满足纯金额要求,也没有可靠表达政策答案。不同字符串数量衡量变化,不证明事实或格式质量。应保留全部种子,并分别检查任务标准。
  6. 一是所需回答是否完整,二是内容/格式是否满足任务。UTF-8 合法只检查字节解码,达到预算不保证语义上已经回答完毕。