先把要优化的数写出来
本章暂时不用神经网络,先只看三个动作组成的有限策略。参数向量 是三个实数打分,概率由 softmax 归一化;奖励固定为第零动作一分,其余零分。期望奖励 是概率乘奖励的和,等于第零动作概率。这里的期望是重复按同一概率分布抽动作得到的平均,不是把三个奖励直接等权平均。输入固定时,这已经包含本项目策略学习最核心的难点:采样分布本身依赖要更新的参数。
读者已知指数导数和商的求导法则。令归一化常数 ,则 。对第k个打分求导,分子给指示项,分母给指数项,整理为 。除以正概率,得到对数概率导数。它叫 score,表示这个已抽动作的对数概率对参数的局部敏感度,不是奖励分数。
概率归一化导出零均值score
把每个动作的 score 按该动作概率加权,得到概率导数之和。有限和可以逐项求导,而所有概率之和恒为一,它的导数为零。这是后面基线和KL推导的支点。条件是当前参数附近支持不随参数突变、各项可导;当前十数字softmax始终严格正,满足条件。不能在参数控制“是否允许这个动作”的硬门槛处,无条件沿用同一个导数公式。
对 求导,奖励在本章固定,不对参数求导。用概率导数等于概率乘对数概率导数,得到策略梯度是奖励乘 score 的期望。这是有限样本空间中的精确恒等式,不需要先令样本数趋于无穷。实际采样得到的单条 只是这个期望的随机估计,可能方向很差;精确恒等式与有限样本估计必须分开。
算例一:三动作的梯度可以算到底
先取三个打分全零,于是每个动作概率三分之一,期望奖励三分之一。对第零打分的梯度为 ;对另两个打分为 。三项和为零,符合给所有打分加同一常数不会改变softmax的平移对称性。沿这个梯度走足够小的正步,会提高正确动作相对打分;不是三个打分一起无限升高。
抽到正确动作时,单样本梯度为 [2/3,-1/3,-1/3],概率三分之一;抽到错误动作时奖励零,单样本梯度为零,合起来得到 [2/9,-1/9,-1/9]。不能把抽到错误时的零梯度解释为“错误动作不必减少”,正确动作被提升时归一化已经挤压其他概率。加入基线后,错误动作也能给非零样本梯度,但总体期望仍相同,第三章会精确证明。
再取非对称打分 [0.3,-0.2,0.1],项目 lab.py 输出实际概率、解析梯度和中心有限差分。中心差分把第k打分分别加减一个小量h,重新计算J,差除以2h。函数光滑且h适中时,截断误差是二阶量;h太小又会被浮点抵消误差主导。项目用h等于十的负五次方并检查误差,而不是笼统说“数值求导就是精确真值”。
从动作换成完整轨迹
现在回到输入x和二步响应y,用 表示网络全部可训练参数。自回归定义说,第一步的概率由输入决定,第二步还条件于已经写出的第一步,完整概率是二者乘积。取对数把乘积变成和,再对共享参数求导,得到两个位置score相加。一次成功的终局奖励乘整个和,意味着前后动作都承担信用;并不是只更新最后一个数字的输出头。两步都经过同一Transformer,参数梯度还通过中间隐状态传播。
提示部分不是策略抽出的响应,不把提示词元概率加进响应似然。结束动作在本协议中强制,概率一、对数零、梯度零,也不该额外混进十四类softmax得一个伪造的负对数项。若换自由文本协议,EOS会变成真正随机动作,必须重新定义样本空间、截断规则和似然。本项目故意固定二步来把这些边界看清楚,不把固定长度结论冒充任意长文本。
算例二:两条路径共享前缀时怎样算
设某输入下第一步写四的概率0.2,给定四后第二步写八的概率0.3,则路径[4,8,EOS]概率0.06,对数是log0.2加log0.3。若最后验证通过,奖励一,策略梯度样本是第一步score与第二步score之和。如果只用第二步log0.3反向传播,就没有直接的第一步选择信用,目标不再是完整成功路径概率;这也是 project 中 path_logps 必须把两个位置相加的原因。
另一条[4,7,EOS]共享第一步,第二步不同且失败。两条路径的局部梯度对共享参数并不互不相干,因为相同输入和前缀经过相同计算图。采样后把响应编号当作固定数据重新前向是合法的score估计;不要尝试对离散multinomial的输出编号求普通导数。我们求的是抽中该编号的概率导数,已经通过期望恒等式处理了抽样带来的参数依赖。
代码中的负号、平均与更新顺序
优化器通常最小化损失,所以最大化奖励的样本目标前加负号。一批独立样本的损失为负的奖励乘对数概率之平均,反向传播后执行梯度下降,等价于奖励目标的梯度上升。若用和而不是平均,在同样学习率下会把更新尺度乘批量;不能改变批量却仍把实验称为完全相同的优化设置。梯度裁剪只限制实际步前的梯度范数,可能改变方向尺度,不属于原始无偏估计定理的一部分。
训练循环必须先清空上一批梯度、计算当前图、反向传播、检查有限值、再裁剪和更新。PyTorch默认累加梯度;忘记清空会混入旧批次。奖励、基线和参考概率在估计器中按规定停止梯度,第四章解释为什么;模型当前的log概率保留梯度。detach不是让模型“不学习”,而是避免把估计器权重误当成另一条可微损失路径。
独立核对与不能偷换的结论
项目提供三路核对:stdlib三个动作解析与中心差分;完整一百路径求和的直接自动微分;同一枚举下把概率权重和回报停止梯度后只保留score路径。后两路相等不是样本准确率测试,而是目标梯度的代数实现检查。tests.py 还检查三动作梯度和为零、受限轨迹概率归一以及因果前缀不受未来词元改变。
通过这些检查仅证明指定函数的局部梯度实现一致。它不保证有限步优化全局最好,也不保证训练题上的提升能迁移到未见输入。非凸模型、有限步长、裁剪、Adam状态和采样方差都介入实际轨迹。因此项目保留初始化种子、监督步数、RL步数和每阶段梯度账本;第七章用冻结检查点测真实结果,而不是用“梯度正确”替代“模型学会”。
from lab import finite
r=finite([.3,-.2,.1])
assert r["max_error"] < 1e-9
assert abs(sum(r["gradient"])) < 1e-12
print(r)TRY IT YOURSELF
练习一:从商法则重建score
对p_i=exp(z_i)/sum_j exp(z_j)求z_k导数,并给出log p_i导数。
提示 1
提示 2
对照参考解答
TRY IT YOURSELF
练习二:反向传播缺了一步
路径概率0.2×0.3,只用log0.3乘奖励训练,漏了什么?
提示 1
提示 2
对照参考解答
TRY IT YOURSELF
练习三:有限差分的边界
把中心差分h从1e-5不断减小到1e-16,误差是否必然减小?