读完这篇,你能做什么
手算三状态 MDP 的最优价值,运行值迭代与策略更新,并解释任务真正结束、因时间上限截断,以及基线各起什么作用。
学习理由、准备要求与知识点
为什么学它
PPO、GRPO 和 Agent 训练都要明确奖励怎样计算、任务何时结束、动作怎样采样,才能判断学到的是不是想要的行为。
先读这些内容
知识点清单
- 状态与马尔可夫假设
- 策略与环境转移
- 折扣回报
- Bellman期望与最优方程
- 收缩映射和值迭代
- 对数导数技巧
- 状态基线与方差
- 终止和截断的区别
运行前先确认有限状态折扣MDP与单步策略梯度教学;Java 17,Python 3.14与PyTorch 2.9.1+cpu。没有运行完整RLHF、语言模型或GPU训练。
01先弄懂它是什么
有些任务中,当前动作会影响下一步能看到什么、最终得到什么奖励,强化学习研究的就是这种连续决策。例如一次交互可以记成当前状态 s、动作 a、奖励 r 和下一状态 s_next。策略 pi(a|s) 规定在状态 s 下,各动作被选中的概率;环境转移 P(s_next|s,a) 描述做完动作后可能到哪里。策略不能直接改变环境规则,但会影响自己走到哪些状态。
建模时,当前“状态”必须包含预测未来所需的历史信息,这就是马尔可夫假设,并不是说过去不存在。例如 Agent 只看到一条用户消息,却不知道账户余额、当前权限和已经执行过的工具,这条消息就不足以代表完整状态。此时要补充记忆,或按只能看到部分信息的问题来建模;给一个字段取名 state,不会自动满足这些条件。
折扣回报G_t=r_t+gamma×r_(t+1)+gamma平方×r_(t+2)+…,其中gamma在零到一之间控制远期奖励权重。价值V_pi(s)是在状态s遵循策略时的期望回报;Q_pi(s,a)额外固定第一步动作。奖励单位来自任务定义,价值沿用该单位;较高的模型奖励不一定意味着较高的真实业务成功率。
文中这几个词,先认一认
- MDP
- 用状态、可选动作、状态如何变化、奖励和目标来描述连续决策问题的一套模型。
- 策略
- 看到某个状态后,按什么概率选择各个动作的规则;这套规则可以由神经网络表示。
- 优势
- 在同一状态下,比较“先选这个动作、之后继续按策略行动”的预期折扣回报,与“一开始就按该策略选动作”的平均回报,差值就是
Q_pi(s,a)-V_pi(s)。它衡量的是相对这套策略的好坏,不是动作的绝对评分。
02看看它怎么工作
拆开回报的第一项,可得V_pi(s)=sum_a pi(a|s)×[R(s,a)+gamma×sum_s_next P(s_next|s,a)V_pi(s_next)]。这里R是一步奖励的期望,两个求和分别平均动作和环境的不确定性。把动作平均换成最大值,得到最优Bellman算子T。对已知的小MDP反复应用T,就能逐步改进价值估计。
当奖励有界且0≤gamma<1时,两个价值函数经过T后最大绝对差不超过原差的gamma倍,这是收缩性质。它解释了值迭代为何收敛,也给出停止条件:若相邻两轮最大差为delta,上一轮到最优解的误差可界为delta/(1-gamma)。
代码用保守的delta≤epsilon×(1-gamma)返回下一轮结果;gamma越接近一,收敛与误差认证越困难。 本文Java实现将容差内的概率行归一化后迭代;收缩误差推导基于精确算术,浮点舍入不能被这条停止条件自动认证。
真实 Agent 往往不知道环境完整的变化规则,也无法列出所有状态,所以要从实际交互轨迹中学习。对轨迹概率使用 grad p=p×grad log p,可以把期望回报的梯度改写成“对数策略梯度乘回报”的期望。
若 J 从初始状态分布出发、计算完整折扣回合,REINFORCE 可用 sum_t gamma^t×grad log pi(a_t|s_t)×G_t 估计。若换了状态的采样权重,就要一起说明目标如何变化,不能直接省略权重。
减去仅依赖状态的基线b(s)通常不改变策略梯度期望,因为sum_a pi(a|s)×grad log pi(a|s)=grad sum_a pi(a|s)=0。基线能降低方差,但动作相关基线一般需要额外修正;随意减去奖励并不总是无偏。训练时通常把回报或优势当作当前策略更新的固定权重,避免反向传播穿过目标构造而改变推导。
要分清“任务结束”和“这次只观察到这里”。例如一局任务真正终止后,没有后续回报,通常不再加上下一状态的价值估计;但如果只是采样到时间上限,底层任务仍能继续,就可能要用最后状态的估计价值补上尚未观察到的后续回报。
用已有价值估计来帮助更新价值,叫自举,这里不是统计章节的重抽样。即使保留末状态价值,也不能把重置后下一局的优势接到上一局来递推。本篇 CPU 实验只有一步、两个动作,回报就是奖励;多步的时间权重和 GAE 处理留到后文。
先跑通一个最小例子
保存experiment.py,用已安装PyTorch 2.9.1+cpu的解释器运行。实验精确检查单步策略梯度,再从真实采样批次更新两个logits;环境只有动作0奖励0、动作1奖励1。
展开收起代码 · experiment.py
长行可在代码区域内左右滚动,按 Tab 可把焦点移入代码区。
import torch
from torch.distributions import Categorical
torch.manual_seed(32)
torch.set_num_threads(1)
torch.set_default_dtype(torch.float64)
rewards = torch.tensor([0., 1.])
z = torch.zeros(2, requires_grad=True)
p = torch.softmax(z, dim=0)
expected_reward = (p * rewards).sum()
exact = torch.autograd.grad(expected_reward, z)[0]
assert torch.allclose(exact, torch.tensor([-.25, .25]))
for baseline in [0., .5, 7.]:
z = torch.zeros(2, requires_grad=True)
logp = torch.log_softmax(z, dim=0)
# 枚举动作验证估计器期望;权重中的概率不参与本次求导。
loss = -(logp.exp().detach() * (rewards-baseline) * logp).sum()
gradient = torch.autograd.grad(loss, z)[0]
assert torch.allclose(-gradient, exact, atol=1e-12)
logits = torch.nn.Parameter(torch.zeros(2))
optimizer = torch.optim.SGD([logits], lr=.2)
for _ in range(120):
policy = Categorical(logits=logits)
actions = policy.sample((64,)) # 采样索引不需要、也没有普通路径导数。
returns = rewards[actions]
loss = -(policy.log_prob(actions) * (returns-.5).detach()).mean()
optimizer.zero_grad()
loss.backward() # 梯度沿log_prob回到logits。
assert torch.isfinite(logits.grad).all()
optimizer.step()
probability = logits.softmax(0)[1].item()
assert probability > .9
assert Categorical(logits=logits).log_prob(torch.tensor(1)).ndim == 0
terminal_target = 2.
truncated_target = 2. + .9 * 4.
assert terminal_target == 2. and abs(truncated_target-5.6) < 1e-12
print(f"PASS gradient/baseline/sampling/boundary checks; reward1_probability={probability:.6f}")
核对运行结果精确初始奖励梯度为[-0.25,0.25],不同常数基线的期望梯度一致;训练后奖励为1的动作概率超过0.9。仅证明此单步任务的方向与采样更新正确。
正在加载流程图…
查看流程图源码(Mermaid)
flowchart TD
A["定义状态 动作 奖励"] --> B{"是否知道完整转移"}
B -->|"小型已知模型"| C["Bellman更新与误差界"]
B -->|"只能交互采样"| D["策略采样动作"]
D --> E["记录奖励和终止语义"]
E --> F["对数概率乘固定回报"]
F --> G["梯度更新并重新采样"]
G --> D按顺序看,每一步做了什么
- 写清动作影响、奖励单位与状态范围。
- 区分已知转移的规划与未知转移的学习。
- 用小模型手算价值并检查折扣。
- 保存采样动作对应的对数概率。
- 构造固定回报权重,更新后重新采样。
03对照实现代码
PyTorch v2.9.1;策略梯度原论文NIPS 1999 · Categorical.__init__ / sample / log_prob
下面是原创REINFORCE调用片段,使用真实Categorical接口;不是框架源码节选,省略多步回报、优化器和环境管理。
from torch.distributions import Categorical
def policy_objective(logits, actions, returns, baseline):
distribution = Categorical(logits=logits) # 内部将logits归一化为对数概率。
selected = distribution.log_prob(actions) # 只取实际采样动作的对数概率。
advantage = (returns - baseline).detach() # 视作本轮策略更新的固定目标。
return -(selected * advantage).mean() # 最小化负号目标等价于提高期望回报。
固定版本Categorical用logsumexp对输入logits归一化,避免直接指数归一化的部分数值问题;最后一维表示动作类别,其余维度属于批次。传入logits不等于传入概率,混淆二者会改变分布。
sample根据概率使用multinomial生成离散索引;这些索引本身没有普通的可微采样路径。策略梯度使用log_prob回到参数,因此不能把“采样不可微”错误推论为“策略完全无法学习”。
log_prob验证动作后广播批维,并用gather取指定类别。自动广播不保证训练语义正确:若动作与优势形状不一致,可能把不同轨迹交叉配对。进入目标前应明确每一维表示时间、批次还是动作。
教学片段只对已采集动作评价一次目标。真正的多轮复用旧样本需要考虑采样策略与当前策略不一致,PPO通过保存旧概率等机制处理相应问题;不能把这个单步例子直接循环复用为完整PPO。
代码先调用谁,再调用谁
- 策略网络生成每个动作的logits
- Categorical归一化
- sample产生动作并交互
log_prob按采样动作索引取值- 固定回报权重乘对数概率
- backward更新策略参数
04动手写一个例子
带误差停止条件的有限MDP值迭代
给出稠密转移P[S][A][S]、期望奖励R[S][A]和终止标记,求折扣最优价值。概率行需归一化;终止状态价值固定为零;0≤gamma<1,达到迭代上限仍未满足条件时明确失败。
- 输入 1
s0:去s1奖励0或结束奖励1;s1:结束奖励2;gamma=0.9- 输出 1
V(s0)=1.8,V(s1)=2,V(终止)=0
- 输入 2
单状态自循环,奖励1,gamma=0.9- 输出 2
V约为10
每轮从旧价值数组计算所有状态的候选动作值,取最大后写入新数组。这种同步更新便于对应Bellman算子,避免把同一轮部分新值与旧值混用后仍套用未解释的实现分析。
验证转移行非负、有限且和接近一,奖励有限;输入模型的规模是S平方乘A,不能把读取与验证成本忽略。终止状态直接置零,表示未来奖励已在进入终止的那一步计算。 对容差内的概率行,在私有副本上除以行和,避免未经归一化的行和与接近一的折扣相乘后破坏理论收缩前提。
以两轮最大绝对差检验保守误差条件,并给出迭代上限保护。折扣接近一时需要更多轮,不能在预算耗尽后把尚未收敛数组命名为精确最优解。数值溢出同样失败,避免把无穷值通过误差比较误当收敛。 误差界针对精确算术的归一化算子,未包含浮点舍入和输入模型误差;当gamma非常接近一,舍入误差会被放大,严格误差认证需要更高精度或区间算法。
为什么这样写是对的第k轮数组等于从零价值出发应用k次最优Bellman算子得到的值;终止状态始终为零。
每轮每个状态枚举A个动作及S个后继,保存新旧两个S长度数组。稀疏转移可按实际边数优化。 归一化副本保存所有转移概率,因此本实现额外空间包含O(S²A),不能只计算两份价值数组。
保存为 Main.java,运行 javac --release 17 -encoding UTF-8 Main.java,再运行 java Main。程序包含固定输入自测,断言失败时会抛出错误。
展开收起代码 · Main.java · 完整可运行程序
长行可在代码区域内左右滚动,按 Tab 可把焦点移入代码区。
public class Main {
static double[] solve(double[][][] p,double[][] r,boolean[] end,double gamma,double eps,int max) {
if(p==null||r==null||end==null||p.length==0||r.length!=p.length||end.length!=p.length
||!Double.isFinite(gamma)||gamma<0||gamma>=1||!Double.isFinite(eps)||eps<=0||max<=0)
throw new IllegalArgumentException("configuration");
int n=p.length;
double[][][] normalized=new double[n][][]; // 私有副本避免改写调用方的转移模型。
for(int s=0;s<n;s++) {
if(p[s]==null||r[s]==null||p[s].length==0||p[s].length!=r[s].length)throw new IllegalArgumentException("actions");
normalized[s]=new double[p[s].length][n];
for(int a=0;a<p[s].length;a++) {
if(p[s][a]==null||p[s][a].length!=n||!Double.isFinite(r[s][a]))throw new IllegalArgumentException("row");
double sum=0;
for(double q:p[s][a]){if(!Double.isFinite(q)||q<0)throw new IllegalArgumentException("probability");sum+=q;}
if(!Double.isFinite(sum)||Math.abs(sum-1)>1e-12)throw new IllegalArgumentException("normalization");
for(int t=0;t<n;t++) normalized[s][a][t]=p[s][a][t]/sum; // 修正容差内的行和偏差。
}
}
double[] v=new double[n];
for(int iteration=0;iteration<max;iteration++) {
double[] next=new double[n]; double delta=0;
for(int s=0;s<n;s++) {
if(end[s])continue; // 终止价值固定为零,进入终止的奖励已在R里。
double best=Double.NEGATIVE_INFINITY;
for(int a=0;a<p[s].length;a++) {
double q=r[s][a];
for(int t=0;t<n;t++) q+=gamma*normalized[s][a][t]*v[t]; // 本轮只读旧数组。
if(!Double.isFinite(q))throw new IllegalArgumentException("overflow");
best=Math.max(best,q);
}
next[s]=best;delta=Math.max(delta,Math.abs(best-v[s]));
}
v=next;
if(delta<=eps*(1-gamma))return v; // 精确算术下的保守误差条件,不是浮点认证区间。
}
throw new IllegalStateException("iteration budget exhausted");
}
static void near(double a,double b){if(!Double.isFinite(a)||Math.abs(a-b)>1e-6)throw new AssertionError();}
static void bad(Runnable r){try{r.run();}catch(IllegalArgumentException e){return;}throw new AssertionError();}
public static void main(String[] args){
double[][][] p={{{0,1,0},{0,0,1}},{{0,0,1},{0,0,1}},{{0,0,1},{0,0,1}}};
double[][] r={{0,1},{2,0},{0,0}};boolean[] end={false,false,true};
double[] v=solve(p,r,end,.9,1e-8,100);near(v[0],1.8);near(v[1],2);near(v[2],0);
near(solve(p,r,end,0,1e-8,100)[0],1);
double[][][] loop={{{1}}};double[][] reward={{1}};boolean[] nonterminal={false};
near(solve(loop,reward,nonterminal,.9,1e-8,500)[0],10);
double[][][] almost={{{1+5e-13}}};
near(solve(almost,reward,nonterminal,.9,1e-8,500)[0],10);
if(almost[0][0][0]!=1+5e-13)throw new AssertionError("input changed");
near(solve(almost,new double[][]{{0}},nonterminal,1-1e-13,1e-8,2)[0],0);
bad(()->solve(p,r,end,1,1e-8,100));
bad(()->solve(new double[][][]{{{.5}}},reward,nonterminal,.9,1e-8,100));
boolean exhausted=false;
try{solve(loop,reward,nonterminal,.9,1e-8,1);}catch(IllegalStateException e){exhausted=true;}
if(!exhausted)throw new AssertionError();
System.out.println("PASS value, terminal, zero discount, loop, invalid model and budget checks");
}
}这些特殊情况也要试一试
- gamma等于一不满足本文无限期折扣收缩前提,拒绝。
- 终止状态固定为零,不重复计算结束奖励。
- 概率未归一化或非有限数值拒绝。
- 迭代预算用尽不能冒称收敛。
- 容差内的行和偏差在副本归一化,输入保持不变;gamma接近一时不能把浮点停止条件当作严格数值认证。
进阶选读 · 部分可观测与稀疏大状态空间
场景工具返回不完整观测,完整转移矩阵无法枚举。
做法把历史编码或信念状态引入策略,先验证小环境中的可观测性假设,再用采样和函数逼近学习。稀疏已知图可按实际转移边进行备份,并用优先队列传播大残差。
复杂度稀疏一次全量备份约O(E+SA),函数逼近训练成本还取决于网络和轨迹;不能继承稠密小表格的收敛保证。
好处与代价扩大表示能力可处理真实环境,也引入估计误差、分布漂移和稳定性问题。
05项目里怎么用
先写出奖励与成功条件是否一致。例如只奖励工具调用次数,会鼓励无用调用;只奖励最终成功而不计成本,也可能鼓励昂贵搜索。把超时、无权限动作、重复提交与安全约束纳入环境契约,并分别报告各类结果,不能让一个总分掩盖明显故障。
为每条轨迹保存策略版本、动作、对数概率、奖励、终止原因和环境版本。旧策略采集的数据与新策略分布不同,复用时需要明确算法假设;单纯把缓存当成越大越好的训练集,会悄悄改变梯度估计。
评估使用固定且独立的任务集,比较多次运行并记录失败轨迹。训练回报上升可能来自环境漏洞、观察泄漏或奖励尺度变化;应通过反事实与约束检查验证改进,而不是只看一条平滑训练曲线。
容易踩的坑
- 把观测文本直接等同完整状态。
- 混淆奖励、回报与价值。
- 在终止后继续自举,或把时间截断当真终止。
- 对回报目标无意继续求导。
- 无限复用旧样本却不考虑分布差异。
几种做法,怎么选
表格有四列,窄屏可左右滑动查看代价和适用条件。
| 方案 | 优势 | 代价与限制 | 适用条件 |
|---|---|---|---|
| 模型已知的规划 | 小空间可精确枚举并给误差界 | 需要可信转移与可枚举状态 | 教学环境和小型决策模型 |
| 蒙特卡洛策略梯度 | 直接优化随机策略,适用于采样环境 | 轨迹方差较大,需要足够采样 | 可重复交互且回报可计算的任务 |
| 价值估计与actor-critic | 可降低方差并利用中间反馈 | 价值误差和自举可能引入偏差与不稳定 | 有验证机制的较长决策任务 |
06检验是否读懂了
先自己想、自己写,再展开答案核对。场景题是假设的练习情境;遇到还没学过的内容,可以做完基础后再回来。
先用自己的话解释
01为什么仅依赖状态的基线不改变期望梯度?
展开参考答案与推导
给定状态,基线可提出动作求和,剩下sum pi×grad log pi等于grad sum pi,即grad 1=0;动作相关基线不能直接使用这个证明。
02Bellman最大值与策略加权平均分别解决什么问题?
展开参考答案与推导
前者对应最优控制的备份,后者评估一个固定策略。将二者混用会把策略评估悄悄变成改进问题。
03为什么gamma接近一时小残差不一定表示小误差?
展开参考答案与推导
残差误差界含1/(1-gamma),远期影响更难衰减;必须同时报告折扣、容差与迭代上限。
换个情况,还会处理吗
01Agent总奖励上升却频繁无意义调用工具,如何解释?
展开参考答案与推导
先审计奖励是否直接或间接鼓励调用次数,比较按任务成功和成本拆分的指标,再通过限制动作预算的对照实验定位奖励漏洞。
02同一用户消息产生不同行为是否一定是策略随机性?
展开参考答案与推导
也可能存在未纳入状态的历史、权限和外部数据;固定随机种子仍不相同应先检查环境与隐藏状态。
03训练在时间上限处价值突然下跌,检查什么?
展开参考答案与推导
区分terminated和truncated,查看是否错误清零了可继续任务的末状态价值,以及是否把重置后的观测当成原轨迹下一状态。
写代码试一试
01从最优价值提取贪心策略。
- 输入 / 条件
正文三状态MDP,gamma=0.9- 输出 / 预期
s0选择去s1,s1选择奖励2的结束动作
提示 重新计算每个动作R+gamma×PV。
展开参考答案与推导
对非终止状态比较动作值,固定平局规则;终止状态返回无动作标记,不把默认动作当作需要执行的指令。
02验证一个两步回报。
- 输入 / 条件
奖励[1,2],gamma=0.5- 输出 / 预期
G0=2,G1=2
提示 从右向左递推。
展开参考答案与推导
维护future,按future=r+gamma×future更新;在真实结束边界停止跨局累积,不能把下一局奖励接上。
03设计策略梯度符号回归测试。
- 输入 / 条件
两动作等概率,奖励[0,1]- 输出 / 预期
奖励目标梯度[-0.25,0.25]
提示 对softmax的解析导数进行比较。
展开参考答案与推导
先算精确期望奖励并求导,再枚举动作验证log_prob估计器的期望;最小化负目标时符号应反转。
读完之后,独立完成
课后作业:自己做一遍
本篇共 12 道作业,先完成 9 道基础与综合任务,再按前置知识挑战进阶题。其中包含 2 道思维拓展,试着换个条件,看看原来的办法是否还管用。不附参考答案。
手算三状态 MDP 的最优价值,运行值迭代与策略更新,并解释任务真正结束、因时间上限截断,以及基线各起什么作用。
本篇重点加练
状态充分性、收缩前提和回合边界决定价值方程是否适用,需要条件化分析。
- 状态与马尔可夫假设
- 收缩映射和值迭代
- 终止和截断的区别
重点内容会多练几次。先说清楚怎么做,再试试空数据、出错或条件改变时会发生什么。
先自己做,卡住时记下问题,再回来查。问答题写清“为什么、什么时候适用”;动手题留下输入、输出和运行步骤,方便下次重做。
基础必做
- 作业 01原理问答
自建一个只有三个状态、两个动作的决策环境,明确转移、奖励和策略;给出一个省略状态信息后不再满足马尔可夫假设的观测版本。
- 提交内容
- 环境表与观测对照
- 怎样算完成
- 状态与观测区分
- 转移概率合法
练到的知识点状态与马尔可夫假设 · 策略与环境转移
- 作业 02代码推演
对轨迹奖励 [1,-2,4]、折扣 0.8,计算各时刻回报;在自建两状态 MDP 上写策略评估与最优价值的更新式。
- 提交内容
- 手算回报与方程
- 怎样算完成
- 时间下标完整
- 期望和最优运算不混用
练到的知识点折扣回报 · Bellman期望与最优方程
- 作业 03原理问答
两个历史拥有相同当前观察,但剩余任务步数不同。建立有限时限奖励例子,判断仅用观察能否定义同一个状态价值。
- 提交内容
- 历史对照与状态定义
- 怎样算完成
- 剩余时间与终止规则明确
- 状态充分性有具体依据
练到的知识点状态与马尔可夫假设 · 终止和截断的区别
- 作业 04代码推演
对一个自拟两状态折扣 MDP,选两组不同价值向量,手算各经一次 Bellman 更新后的最大坐标差,检验所声明的收缩界。
- 提交内容
- 转移表与一步界限核对
- 怎样算完成
- 转移概率合法
- 折扣和范数定义明确
练到的知识点收缩映射和值迭代
综合应用
- 作业 05编程实践
实现 CPU 值迭代,记录残差、终止条件和提取策略;通过可穷举的小 MDP 独立核对最终策略。
- 提交内容
- 程序及残差日志
- 怎样算完成
- 停止依据可验证
- 计算误差和策略质量分开
练到的知识点Bellman期望与最优方程 · 收缩映射和值迭代
- 作业 06排错实验
在两动作 bandit 上实现 REINFORCE,比较无基线与固定状态基线的梯度样本均值和波动;运行预定的多个种子。
- 提交内容
- CPU 实验与梯度统计
- 怎样算完成
- 基线不依赖当前动作
- 均值和方差分别报告
练到的知识点对数导数技巧 · 状态基线与方差
- 作业 07面试场景
同一任务可因成功、失败或时间上限结束。为价值目标设计三种事件记录及验收案例,说明环境 reset 与学习目标的关系。
- 提交内容
- 终止契约与测试案例
- 怎样算完成
- 真实终止和截断分开
- 重置不隐藏历史边界
练到的知识点状态与马尔可夫假设 · 终止和截断的区别
- 作业 08编程实践
实现 CPU 三状态任务,分别记录自然终止与人为采样截断;对同一可重放轨迹比较两种错误混用方式产生的价值目标。
- 提交内容
- 环境、目标账本及差异
- 怎样算完成
- 环境规则和采样限制分开
- 对照轨迹固定
练到的知识点状态与马尔可夫假设 · 终止和截断的区别
- 作业 09设计评审
观测聚合可能把不同真实状态映为同一标签。设计价值迭代输入审查表,说明数学收敛与对原环境策略有效之间还隔着哪些假设。
- 提交内容
- 聚合模型及有效性审查
- 怎样算完成
- 近似环境与真实环境区分
- 收敛不被当正确建模证据
练到的知识点状态与马尔可夫假设 · 收缩映射和值迭代
进阶挑战 · 掌握前置后选做
- 作业 10设计评审
研究折扣接近一时值迭代停止条件的可靠性,用三个折扣值比较残差和相对参考解误差;先写清参考解来源。
- 提交内容
- 数值实验与误差分析
- 怎样算完成
- 误差参照独立
- 结论限定具体环境
练到的知识点折扣回报 · 收缩映射和值迭代 · 状态基线与方差
思维拓展
先写出你的猜想,再用例子或实验验证。答案可以不同,但要说清依据、适用情况,以及还有什么没弄懂。
- 作业 11思维拓展 · 条件变化
当折扣改成一时,原收缩论证还能直接使用吗?分别构造会终止与可能无限循环的有限环境,研究结论需要怎样补充条件。
- 提交内容
- 两个环境与条件论证
- 怎样算完成
- 无限回报及终止条件明确
- 不把折扣结论无条件外推
练到的知识点收缩映射和值迭代 · 终止和截断的区别
- 作业 12思维拓展 · 跨域迁移
把马尔可夫状态定义迁移到客服对话:当前一句话是否足够预测后续?设计两段观察相同但历史约束不同的对话,并给出可测的状态补充方案。
- 提交内容
- 对话反例与状态验收
- 怎样算完成
- 历史约束来源明确
- 状态补充能对应具体差异
练到的知识点状态与马尔可夫假设 · 终止和截断的区别
完成后,再检验一次
给每题标记“独立完成 / 查阅后完成 / 尚未完成”。查过资料或没做出的题,记下卡在哪里。隔一天换一组输入再试,能解释结果和出错原因,再把这个知识点标为掌握。
继续阅读
先看能帮你完成当前练习的部分。例子跑通后,再读更深入的解释。
- 必读参考文档英文
策略梯度定理原论文 (新标签页)↗
阅读策略参数化与梯度定理的假设;与本篇单步精确枚举实验对照。
- 实践参考文档英文
PyTorch v2.9.1 Categorical源码 (新标签页)↗
沿初始化、sample和
log_prob核对概率及批维语义。 - 实践参考文档英文
Gymnasium Env接口 (新标签页)↗
阅读step返回的terminated与truncated定义,迁移环境时重新核对版本。