本课程到底做成什么
本课程把强化学习的全部关键环节接成一台可以下载、运行、检查和反驳的实验台。读者需要会 Python 函数、列表、有限求和、对数和基本求导;涉及条件概率、方差、策略梯度、组基线与相对熵时,讲义会在使用前推导。微型 Transformer 的注意力和反向传播作为前置课程的导入结果,项目仍提供完整源代码。终点是能说明一次更新为什么成立、验证什么、在哪些任务上失败,而不是把几行调用写成“大模型推理训练”。
全书采用同一原创算术协议。输入 ,其中两个数各在零到四之间,共二十五道题。输出轨迹 :先写整数和 ,再写这个和的两倍对十取余 ,最后写终止词元 。取余指除以十后的非负余数,例如十二除以十余二。第一步不是自然语言解释,而是可验证的中间状态;第二步须与它一致。两步做对也不能证明网络在人类意义上依次采用了这条算法。
把对象与编码分开
数学上的数字、模型中的整数编号与显示字符是三件事。本项目恰好把十个数字的编号设为零至九,但加号编号十、等号十一、起始 BOS 十二、终止 EOS 十三。任务 被序列化为编号 [12,2,10,2,11],正确响应为 [4,8,13]。词表大小十四并不表示每一步都允许十四个动作;训练和采样共同采用明确的语法约束,前两步只允许十个数字,第三步强制终止。
因此给定输入的随机样本空间是全部一百条两位数字轨迹,每条最后都接同一个 EOS。事件是这些轨迹的任意子集。策略给每条轨迹一个非负概率,所有概率相加为一。输入任务的训练分布是二十道训练题上的均匀分布,测试分布单独定义;不能把二者混成同一个未说明的“数据分布”。本文所有对数均为自然对数,概率比对应的单位为纳特,奖励没有物理单位。
模型输出的原始十四维 logits 是尚未归一化的实数。取前十维再做 softmax 得到当前受限动作分布;这等价于把其他动作的打分设为负无穷后归一化。不能先在十四个动作上取概率、删掉四项后直接当作新概率,那样总和小于一。这里的支持限制本来就排除了自由格式失败,报告必须说清“受限语法内的正确率”,不能宣传成自由文本输出可靠性。
奖励是任务合同,而不是好看的数字
验证器是一个确定性函数,接收任务和完整响应,返回奖励零或一以及失败原因。用指示函数 表示条件C成立为一、否则为零。先检查任务类型、长度和取值域,再检查响应恰为三个真正的整数。Python 中布尔值属于整数的子类,所以必须用严格类型检查拒绝 True 冒充数字。随后检查前两位在零到九、最后一位恰为 EOS,最后按次序检查中间和与最终余数。任何多余内容、少一步或不合法编号均失败。
固定这个顺序能把格式、中间步骤、最终步骤三种失败区分开,但诊断标签不是额外奖励。给格式正确加零点二、给中间正确再加零点三,是另一套塑形奖励,可能有用,也可能诱导只写易得分步骤。我们先使用严格全通过奖励,把“任务成功”作为唯一训练反馈;后面的对照才讨论如何改变目标。训练中不允许验证失败后修补答案再记成功,修补器本身需要单独计预算。
算例一:一条正确轨迹的全部检查
输入 时,中间和为七,两倍十四对十余四,所以响应应为 [7,4,13]。检查长度三、每个元素类型 int、两位数字合法、末位终止合法,再检查七等于三加四,四等于十四取余,奖励一。如果网络输出 [7,14,13],计算两倍的意图或许正确,但数字十四不在动作支持内且没有取余,应记格式失败,不能根据主观理解给满分。
同一道题输出 [4,8,13],第二步确实是第一步的两倍取余,却把输入和算错;奖励仍为零。这说明“内部自洽”和“完成原任务”不是同一个条件。输出 [7,4] 则缺少终止标记;输出 [7,4,13,13] 多了标记。我们宁愿在合同中提前定义这些边界,也不在结果出现后临时修改规则,借此保住看起来不错的曲线。
算例二:均匀策略提供阳性与阴性对照
若两步各自独立且均匀选十个数字,任一轨迹概率都是百分之一。每题只有一条通过严格验证的轨迹,所以单次成功概率是百分之一,而不是十分之一。第一步正确概率十分之一,在此条件下第二步正确仍为十分之一,连乘得百分之一。如果只看最终余数,有时错误中间和也会碰巧给出同样余数;严格奖励刻意不把这种捷径计成功。
模型采样一组八条独立轨迹时,完全没成功的概率是 ,约百分之九十二点二七;至少一条成功约百分之七点七三。这解释为什么从随机策略开始,许多组的奖励全零。全零组在仅有终局奖励的组中心化估计中没有学习信号,并不证明程序坏掉。项目先用少量监督示范提供探索起点,再明确把监督收益和后续强化学习收益拆开报告。
数据划分故意保留一个难以粉饰的缺口
项目把所有和等于四的五个输入留作测试:零加四、一加三、二加二、三加一、四加零。训练集合包含其余二十题。这不是从同分布随机抽样得到的五题,而是未见中间结果的组合外推压力测试。若测试失败,我们只能说本实验没有学会这组外推;不能由此证明所有强化学习都无法推理。反过来,训练成功也不足以声称掌握普遍加法,因为有限输入完全可能被参数记住。
拆分文件由代码中的常量和数据摘要锁定。题目、协议、奖励与序列化一起进入 SHA-256 摘要,加载检查点时重新核对,避免拿新规则解释旧权重。摘要能发现字节变化,不能证明数据没有任何统计关联;训练和测试共享加法结构本来就是设计的一部分。我们不再把测试题混入监督示范,也不根据测试表现选择训练步数,固定预算在第五到八章完整记录。
从本章走向后续更新
本章只定义环境,不允许把奖励的存在当作学习已经发生。第二章先在三个有限动作上推导精确策略梯度,第三章证明组基线什么时候保持正确,第四章加入参考分布约束,第五章把完整轨迹概率接到真实解码器,第六章才采样并更新全部参数。第七章比较训练收益、测试退化和额外采样预算,第八章重建整个证据链。每一步依赖前面的同一合同,不能到评价时偷换成功标准。
第一次动手应先运行 tests.py 的验证器正例和攻击反例,再观察随机策略的一百路径枚举。正例全部通过但攻击也通过,是验证器过宽;攻击全部拒绝但正例也拒绝,是验证器失效。两种情况都会让奖励曲线失去解释。实际软件的资源边界也明确:本协议只处理固定长度的小整数序列,没有 eval、任意代码执行或长表达式求值,验证成本因此是常数规模;它不是通用数学证明检查器。
from run import verify, target
assert verify((3,4), target((3,4)))["reward"] == 1
assert verify((3,4), [4,8,13])["reason"] == "intermediate"
assert verify((2,2), [4,8,True])["reward"] == 0
print("contract checks pass")TRY IT YOURSELF
练习一:概率从哪里来
均匀策略独立采两位数字,为什么正确率不是十分之一?
提示 1
提示 2
对照参考解答
TRY IT YOURSELF
练习二:设计奖励攻击
只检查最终数字v等于正确余数,会接受哪条不合格轨迹?以(2,2)为例。
提示 1
提示 2
对照参考解答
TRY IT YOURSELF
练习三:划分性质
测试为什么不能叫二十五题总体的无偏随机估计?