简介:《强化学习的数学原理》是西湖大学赵世钰教授撰写的英文专著,面向具备线性代数、概率论与优化基础的研究生及算法工程师,系统解决强化学习理论理解不深、公式推导不清、算法本质难把握等核心痛点。全书从网格世界等直观示例切入,严格推导贝尔曼方程、值迭代、策略梯度、Actor-Critic等关键方法,并在附录中严谨论证序列收敛性,兼顾数学严谨性与教学可读性。资源为单文件PDF(18.9MB),内容完整覆盖10章主体+附录,含大量图示、矩阵向量形式表达、闭式解与迭代解对比、Q&A总结等特色设计,便于精读推演与课堂讲授参考。目前已有845人学习下载,适合希望夯实RL数学根基、深入理解算法收敛性与设计逻辑的进阶学习者。
1. 强化学习的数学原理:不是“调参玄学”,而是你手里的“决策说明书”
你有没有试过教一个完全没接触过编程的朋友写个自动走迷宫的小程序?他可能很快能画出格子、标出起点终点,但一问“那机器人怎么知道该往左还是往右走”,他就卡住了——不是不会写if语句,而是根本不知道“凭什么往右走比往左走更值得”这件事该怎么量化、怎么算、怎么一步步推出来。
这正是绝大多数人第一次听说“强化学习”时的真实状态:它听起来像魔法——AI自己试错、自己变强;可一旦想动手,就发现满屏是“策略”“回报”“贝尔曼方程”“值函数”……像一本没给目录、没标页码、还夹着十几张手写批注的旧讲义。更让人发怵的是,网上教程要么直接甩出 PyTorch 代码让你抄,结果报错三行、调试五小时;要么堆砌定义:“强化学习是智能体与环境交互以最大化累积奖励的过程”——读完等于没读。
其实,它真没那么玄。它本质上是一套给“做决定”这件事建数学模型的方法论:就像你每次点外卖前会下意识比较“贵不贵、快不快、好不好吃”,强化学习就是把这种日常权衡,翻译成可计算、可迭代、可证明的数学语言。而赵世钰老师这本《强化学习的数学原理》,就是目前中文世界里唯一一本从零开始、不跳步、不预设“你已经懂了概率和线代”的英文入门书——它不教你调参技巧,但它会带你亲手推导:为什么一个格子的“价值”必须等于它下一步所有可能动作的加权平均?为什么“先试错再总结”的蒙特卡洛方法,和“边走边估”的时间差分法,本质都是在解同一个方程的不同近似?它不承诺你三天写出 AlphaGo,但它保证:当你合上第 4 章,你会清楚地知道“值迭代”每一步在算什么、为什么这么算、算错了怎么看出来。
这本书适合谁?不是已经跑通 DQN 的熟手,而是那个对着reward = r + gamma * V(s')发呆、想问“这个gamma是谁定的?为什么不能是 1.2?”的你;是那个下载了 RL 库却不敢删掉示例代码里一行注释的新手;是那个希望真正“看懂”而不是“用熟”的学习者。它不要求你背公式,但要求你愿意跟着书里那个小网格世界,一笔一划算出第一个状态值——而这,恰恰是绕开所有“玄学感”的唯一入口。
2. 先搞懂一个概念:强化学习不是“AI自学”,而是“给决策装上数学导航仪”
很多人误以为强化学习(Reinforcement Learning, RL)是让机器“像人一样试错成长”。这说法没错,但漏掉了最关键的部分:试错本身不产生智能,对试错结果进行结构化归因和数学建模,才产生智能。就像婴儿乱拍玩具也能偶然响铃,但只有当他开始建立“拍A响、拍B不响”的因果联想,并据此调整下一次动作,才叫学习。强化学习的全部意义,就在于把这种联想过程,变成一套可写、可算、可验证的数学流程。
这本书第一章就用一个极简的“网格世界”(grid world)把这事掰开了讲。我们不急着写代码,先一起在纸上画:
S □ □ □ □ G □ □ □S是起点(Start),G是目标(Goal),□是空地;- 智能体每次只能上下左右移动一格(动作:up/down/left/right);
- 每次移动消耗 -1 分(惩罚),到达
G得 +10 分(奖励); - 碰墙或越界,位置不变,同样扣 -1 分。
现在问题来了:如果智能体当前在(0,0)(左上角 S),它该选哪个动作?直觉说“往右”,但“直觉”没法写进程序。我们需要一个数学量来回答这个问题——这就是State Value(状态值),记作V(s)。
2.1 状态值V(s):不是“这个格子多好”,而是“从这里出发,未来能捞到多少分”的期望值
注意关键词:“从这里出发” + “未来” + “期望值”。它不关心此刻脚下有没有金币,只关心“如果我从这里开始,严格按某个固定规则(即策略 policy)行动,长期下来平均能得多少分”。
举个具体例子。假设我们定一个最傻的策略:永远随机选一个方向走(均匀随机)。那么从起点(0,0)出发,它的V(s)怎么算?
- 第一步:四个方向各 1/4 概率。往右到
(0,1),得 -1 分;往下到(1,0),得 -1 分;往上/左碰墙,位置不变,也得 -1 分。 - 所以第一步必然扣 1 分,之后呢?就要看
(0,1)和(1,0)这两个新位置的V值了。
你看,V(s)的定义天然形成了一个“套娃”:V(s)依赖于它下一步所有可能到达的状态的V值。这个关系,就是全书最核心的数学工具——贝尔曼方程(Bellman Equation)的雏形。
提示:别被名字吓住。“贝尔曼”只是提出者的名字,方程本身非常朴素:一个状态的价值 = 当前动作的即时奖励 + 下一个状态价值的折扣加权平均。它不是天降神谕,而是对“长期收益”这个概念最自然的数学翻译。
2.2 动作(Action)和策略(Policy):决策的“操作系统”和“运行指令”
在网格世界里,“动作”很直观:上/下/左/右。但现实中,动作空间可以极大(比如机械臂有 7 个关节,每个关节有连续角度)。所以书中强调:动作是智能体能执行的最小可控单元,它必须明确、可执行、有确定后果。
而“策略”(policy),就是智能体的“决策操作系统”。它不是一个固定路线(比如“先右→再右→再下”),而是一个映射规则:对每一个可能的状态s,给出一个动作选择的概率分布π(a|s)。
- 如果
π(right|S) = 1.0,表示在起点一定往右——这是确定性策略; - 如果
π(up|S) = π(down|S) = π(left|S) = π(right|S) = 0.25,就是前面说的随机策略。
关键点来了:没有策略,就没有状态值。同一个格子(1,1),在“永远往右”策略下的V值,和在“永远往下”策略下的V值,可能天差地别。V(s)永远是相对于某个特定策略π定义的,记作V^π(s)。这点初学者极易忽略,导致后面读贝尔曼方程时一头雾水。
2.3 奖励(Reward)和回报(Return):为什么不能只看“眼前一分”?
继续用网格世界。假设智能体走到(1,2)(G 正上方),此时:
- 往下走一步到 G,立刻得 +10 分;
- 往右走一步碰墙,扣 -1 分,还在原地。
直觉选“往下”。但如果奖励设计不同呢?比如:
- 到达 G 只给 +1 分(不是 +10),
- 但每多走一步额外奖励 +0.5 分(鼓励探索)。
这时,“立刻冲向 G”可能反而不如“绕一圈再进去”得分高。这就是回报(Return)的意义:它不是单次奖励r,而是从当前时刻起,未来所有奖励的加权和,常用符号G_t表示:
G_t = r_{t+1} + γ * r_{t+2} + γ² * r_{t+3} + ...其中γ(gamma)是折扣因子,取值在[0,1)之间。γ=0表示只看下一步(短视);γ=0.99表示非常看重长远(但计算更复杂)。它解决了两个现实问题:
- 数学收敛性:无限步奖励和可能发散,
γ<1保证G_t有确定上限; - 行为合理性:人也会觉得“明年的一百块”不如“今天的一百块”值钱,
γ就是这个“心理折价率”。
注意:
γ不是超参数调出来的,它是问题定义的一部分。你设计任务时,就得想清楚:“我希望智能体更看重即时效果,还是长期布局?”——这直接决定了γ的合理取值范围。
2.4 马尔可夫决策过程(MDP):所有故事发生的“舞台说明书”
前面提到的状态、动作、奖励、策略,它们不是孤立存在的。它们共同构成一个严谨的数学框架——马尔可夫决策过程(Markov Decision Process, MDP)。书里把它比作“舞台说明书”,非常贴切:
- 状态集合 S:所有可能的“舞台布景”(如网格中所有坐标);
- 动作集合 A:所有可用的“演员动作”(上下左右);
- 状态转移概率 P(s'|s,a):告诉导演,“当演员在布景
s做动作a时,下一幕布景s'出现的概率是多少”(比如在(0,0)往右,100% 到(0,1);往上,100% 碰墙留在(0,0)); - 奖励函数 R(s,a,s'):告诉编剧,“这场戏从
s开始,演员做a,转到s',观众打几分”(通常简化为R(s,a)或R(s)); - 折扣因子 γ:整部剧的“时间权重设定”。
MDP 的核心假设是马尔可夫性(Markov Property):下一个状态s'的概率,只取决于当前状态s和当前动作a,与之前所有历史无关。换句话说,这个“舞台”没有记忆。你不需要知道智能体是怎么走到(1,1)的(是从左来?从上来?绕了三圈?),只要知道它此刻在(1,1),就能预测它下一步去哪。这个看似简单的假设,是整个强化学习理论能成立的基石——没有它,状态值就无法仅用s来定义,贝尔曼方程也就无从谈起。
2.5 常见问题排查:新手最容易卡在这 4 个“思维断点”上
刚接触这些概念时,不是代码报错,而是脑子“报错”。以下是我在带新人时,高频出现的 4 个思维断点,附上现象、原因和解法:
现象 1:死磕“策略”定义,总想给每个状态写死一个动作
原因:混淆了“策略”(policy)和“最优动作序列”(optimal path)。策略是概率分布,不是路径规划。初学者常误以为“学 RL 就是找一条最短路径”,但 RL 解决的是在不确定环境中,面对未知转移概率时,如何做出鲁棒决策。路径是确定性世界的解,策略是不确定性世界的解。
解决:立刻回到网格世界,手动计算两个不同策略(如“随机” vs “右优先”)下同一个状态的V^π(s),亲眼看到数值差异。数值不同,说明策略真的在影响价值——它不是虚的概念。
现象 2:看到V(s) = E[ G_t | s_t = s ]就懵,不理解E[·]和G_t的关系
原因:“期望值E”被当成统计学黑箱。其实这里E就是“加权平均”:把智能体从s出发所有可能的未来轨迹(trajectory)列出来,每条轨迹有一个发生概率和一个总回报G_t,V(s)就是所有G_t按其概率加权后的平均值。
解决:用纸笔穷举小网格的全部可能轨迹(比如 3 步内能到 G 的所有走法),算出每条的G_t和概率,手动加权求和。算一遍,E就从符号变成数字。
现象 3:认为“奖励函数 R 是环境给的,我不能改”
原因:把奖励函数当成物理定律。实际上,奖励函数是你作为任务设计者写的‘价值观说明书’。你想让机器人快,就给时间惩罚;想让它省电,就加能耗惩罚;想让它避开障碍,就给碰撞负奖励。RL 不解决“什么是好”,它解决“在你定义的好之下,如何达成”。
解决:修改网格世界的奖励:把到达 G 的奖励从 +10 改成 +1,把每步移动惩罚从 -1 改成 -0.1。重新估算V(s),观察策略如何从“激进冲线”变成“谨慎探索”。你会立刻明白:奖励函数不是输入,而是你的设计意图接口。
现象 4:纠结“马尔可夫性是否真实”,怀疑“现实世界哪有无记忆的环境”
原因:把数学假设等同于物理事实。马尔可夫性不是说世界没历史,而是说你可以把所有需要的历史信息,都编码进当前状态s中。比如,如果机器人需要记住“刚才是否开过门”,就把door_open: True/False加进状态向量。状态设计得好,马尔可夫性就成立。
解决:构造一个非马尔可夫小例子:智能体在(0,0),如果上一步是从(0,1)来的,往右能到(0,1);如果上一步是从(1,0)来的,往右会碰墙。此时单纯用坐标(0,0)描述状态就不够,必须扩展为(0,0,from_right)或(0,0,from_down)。这个练习会让你彻底理解:状态设计,是建模的第一步,也是最关键的一步。
3. 第一步怎么迈:用纸笔算出第一个状态值,亲手验证贝尔曼方程
很多新手以为学数学原理,就得先啃定理证明。但赵世钰老师的写法非常务实:所有理论,都锚定在一个可计算、可验证的具体例子上——就是那个 3x3 网格世界。第 2 章的核心任务,就是带着你,用最原始的纸笔,算出V^π(s),并亲手验证它满足贝尔曼方程。这不是为了怀旧,而是因为——当你亲手算出第一个V(s),你就拿到了打开 RL 黑匣子的第一把钥匙。
我们延续上一章的设定:
- 网格:3x3,S 在
(0,0),G 在(1,2); - 动作:up/down/left/right;
- 奖励:每步移动
-1,到达 G 得+10,碰墙-1且位置不变; - 策略
π:确定性策略——在每个非目标格子,总是选择离 G 曼哈顿距离最小的方向(即贪心策略)。例如:(0,0):到 G 距离是|0-1|+|0-2|=3,右到(0,1)距离2,下到(1,0)距离3,所以选right;(0,1):右到(0,2)距离1,下到(1,1)距离1,任选其一(我们定为right);(0,2):下到 G,距离0,所以选down。
目标:计算V^π(S) = V^π(0,0)。
3.1 为什么不能直接“走一遍”?——回报G_t是随机变量
直觉想:“按策略走一遍:(0,0)→(0,1)→(0,2)→(1,2),三步,奖励(-1)+(-1)+(+10)=+8,所以V=8?” 错!因为V(s)是期望回报,不是某一次轨迹的回报。在这个策略下,从(0,0)出发,确实大概率走上面那条路,但也存在小概率“失误”:比如在(0,1)本该右,但策略是确定性的,所以没失误?等等——确定性策略下,轨迹是唯一的?不,还有碰墙!
关键细节:在(0,0)选right,100% 到(0,1);但在(0,1)选right,100% 到(0,2);在(0,2)选down,100% 到(1,2)=G。看起来是确定轨迹?但别忘了:碰墙是随机事件吗?不,它是确定的物理反馈。在这个设定下,只要策略确定、环境确定,轨迹就唯一。所以G_t是确定值,V(s)就等于这个确定值?对!但这是特例。一旦策略引入随机性(比如ε-greedy),或环境有随机性(比如风把智能体吹偏),G_t就变成随机变量,V(s)必须用期望值定义。本书刻意从确定性案例起步,是为了让你先抓住“价值”的主干,再添枝叶。
所以,本例中V^π(0,0) = (-1) + (-1) + (+10) = 8。但这只是答案,不是过程。贝尔曼方程要我们验证:这个8,是否等于“当前奖励 + 下一状态价值的折扣加权平均”?
3.2 贝尔曼方程的纸笔验证:从V(0,0)开始,一层层剥洋葱
贝尔曼方程对状态值的定义是:
V^π(s) = Σ_a π(a|s) * Σ_s' P(s'|s,a) * [ R(s,a,s') + γ * V^π(s') ]对我们这个确定性策略π和确定性环境,π(a|s)和P(s'|s,a)都是 0 或 1,公式大幅简化:
V^π(s) = R(s, a_π(s), s') + γ * V^π(s')其中a_π(s)是策略π在s下选择的动作,s'是执行该动作后到达的状态。
现在,我们从终点G=(1,2)开始倒推(这是动态规划的思想):
Step 1:
V^π(G)是多少?
到达 G 后,episode 结束,不再有后续动作和奖励。所以V^π(G) = 0(标准约定:终止状态价值为 0)。注意:不是
+10!+10是到达 G 时获得的奖励,它计入R(s,a,s'),不是V(s')。V(s')是“从s'开始的未来期望回报”,s'=G时未来为 0。Step 2:计算
V^π(0,2)(G 正上方)
策略:down→s' = G = (1,2)
奖励:R((0,2), down, (1,2)) = +10(到达 G 的奖励)
所以:V^π(0,2) = +10 + γ * V^π(G) = 10 + γ * 0 = 10
(这里γ暂取1.0简化,实际常用0.9,但原理相同)Step 3:计算
V^π(0,1)(中间上排)
策略:right→s' = (0,2)
奖励:R((0,1), right, (0,2)) = -1(普通移动)
所以:V^π(0,1) = -1 + γ * V^π(0,2) = -1 + γ * 10
若γ=1,则V^π(0,1) = 9Step 4:计算
V^π(0,0)(起点)
策略:right→s' = (0,1)
奖励:R((0,0), right, (0,1)) = -1
所以:V^π(0,0) = -1 + γ * V^π(0,1) = -1 + γ * (-1 + γ * 10) = -1 -γ + 10γ²
若γ=1,则V^π(0,0) = -1 -1 + 10 = 8—— 和我们直接走一遍得到的结果一致!
恭喜,你刚刚亲手验证了贝尔曼方程。这个过程揭示了V^π(s)的本质:它不是一个孤立的数,而是整个状态网络的自洽解。每个V(s)都由它的后继状态V(s')决定,所有V(s)必须同时满足这套方程。这就是为什么第 2 章花大量篇幅讲“如何解贝尔曼方程”——因为V^π(s)是 RL 的基石,而贝尔曼方程是它的定义式。
3.3 从“算一个值”到“解一个系统”:矩阵形式与迭代法初探
上面是小网格的手动推导。但现实问题中,状态数可能是百万级。我们不可能一个个手算。这时,贝尔曼方程的矩阵-向量形式就显出威力了。
把所有状态的V^π值排成一个列向量v(维度 = 状态数),把所有R(s,a,s')和P(s'|s,a)整合成矩阵,方程就变成:
v = r^π + γ * P^π * v其中r^π是策略π下的期望即时奖励向量,P^π是策略π下的状态转移矩阵。移项得:
(I - γ * P^π) * v = r^π这就成了一个标准的线性方程组A*v = b。解法有两种:
- 闭式解(Closed-form):
v = (I - γ * P^π)^(-1) * r^π。数学上漂亮,但矩阵求逆计算量大,且I - γ * P^π必须可逆(γ太大会导致不可逆)。 - 迭代法(Iterative solution):从任意初始
v₀(比如全 0)开始,反复应用v_{k+1} = r^π + γ * P^π * v_k,直到v_k收敛。这就是著名的**策略评估(Policy Evaluation)**算法。
提示:迭代法不是“偷懒”,而是 RL 的灵魂。它模拟了智能体“边体验、边更新认知”的过程。每一次
v_{k+1},都是基于当前对世界的认知v_k,对价值的一次修正。收敛时,v就是那个自洽的、满足所有贝尔曼方程的解。
3.4 动作值Q(s,a):比状态值更“接地气”的决策助手
状态值V^π(s)告诉你“从这里出发,按策略π走,能得多少分”。但它不告诉你“如果我现在不按π走,临时换个动作,会怎样?”——这正是动作值Q^π(s,a)的用武之地:
Q^π(s,a) = E[ r_{t+1} + γ * r_{t+2} + γ² * r_{t+3} + ... | s_t = s, a_t = a ]即:在状态s执行动作a后,再严格按策略π行动,能得到的期望回报。
它和V^π(s)的关系是:
V^π(s) = Σ_a π(a|s) * Q^π(s,a)——状态值,就是该状态下所有可能动作的Q值,按策略概率加权的平均。
而Q^π(s,a)自身也满足贝尔曼方程:
Q^π(s,a) = Σ_s' P(s'|s,a) * [ R(s,a,s') + γ * Σ_{a'} π(a'|s') * Q^π(s',a') ]这个方程的意义在于:它把“评价一个动作好坏”的任务,分解为“看这个动作带来的即时奖励 + 它引向的下一个状态中,按策略π能拿到的最好Q值的平均”。这为后续的“策略改进”(比如Q-learning)埋下了伏笔——因为如果你知道所有Q(s,a),你就可以直接选argmax_a Q(s,a)作为新策略,而不用管原来的π。
3.5 常见问题排查:算V和Q时,新手必踩的 3 个计算坑
即使理解了概念,手工计算时仍容易因细节翻车。以下是三个血泪经验总结的坑:
坑 1:混淆“到达奖励”和“状态价值”,把+10直接当V(G)
现象:算到V(G)时,写V(G) = +10,导致后续所有计算全错。
原因:没吃透V(s)的定义是“从s开始的未来回报”,而到达G的+10是进入G这个动作的奖励,属于R(s,a,G),不是V(G)。V(G)是“从G开始的未来回报”,而G是终止状态,未来为 0。
解决:在草稿纸上,用两种颜色笔:蓝色写所有R(...)(奖励),红色写所有V(...)(价值)。强制区分。
坑 2:忽略γ的幂次,在长轨迹中算错折扣
现象:轨迹s0→s1→s2→s3=G,奖励r1,r2,r3,错误计算G = r1 + r2 + r3,漏了γ。
原因:忘记G_t = r_{t+1} + γ*r_{t+2} + γ²*r_{t+3} + ...,γ的指数等于“步数减一”。
解决:在轨迹下方,用小字标出每步的γ幂次:r1对应γ⁰,r2对应γ¹,r3对应γ²。哪怕γ=1,也标上,养成习惯。
坑 3:在非确定性策略下,错误地只算一条轨迹
现象:策略是π(right|s)=0.7, π(down|s)=0.3,却只算了“右→右→下”的路径,忽略了“下→...”的路径。
原因:把期望值E[G]当成了“最可能路径的G”。
解决:画树状图!从s开始,分叉画出所有可能动作,每条边标概率;再从每个后继状态继续分叉。每条完整路径的权重 = 各边概率乘积,G值 = 该路径奖励和(带γ)。最后加权平均。树画出来,就不会漏。
4. 从“会算”到“会解”:亲手跑通第一个值迭代算法
理解了V^π(s)和贝尔曼方程,下一步就是:如何不靠人肉,让计算机自动算出最优策略?这就是第 4 章的核心——值迭代(Value Iteration)和策略迭代(Policy Iteration)。它们不是黑箱算法,而是对“如何逼近最优”这一思想的数学实现。本章的目标,是让你亲手敲出并跑通一个最简版的值迭代,看着它从一片混沌的初始价值表,一步步收敛到清晰的最优决策图。
我们继续用 3x3 网格,但这次目标升级:不预设策略,而是找出能让V(s)最大的那个策略π*。这就是“最优控制”问题。
4.1 值迭代(Value Iteration):用“贪婪更新”逼近最优贝尔曼方程
最优状态值V*(s)满足贝尔曼最优方程(Bellman Optimality Equation, BOE):
V*(s) = max_a Σ_s' P(s'|s,a) * [ R(s,a,s') + γ * V*(s') ]对比普通贝尔曼方程,区别在max_a:它不再问“按某个策略π走,值多少”,而是问“所有可能动作中,选哪个能带来最大长期收益?” 这个max操作,就是“优化”的来源。
值迭代的思想极其朴素:既然V*是方程的解,那我就从一个随便的V₀开始,反复用右边的式子去更新它,直到它不再变化。更新规则是:
V_{k+1}(s) = max_a Σ_s' P(s'|s,a) * [ R(s,a,s') + γ * V_k(s') ]这个max_a操作,就是“贪婪”(greedy)——每一步都选当下看起来最好的动作。而神奇的是,这个贪婪迭代,最终会收敛到全局最优V*。
4.2 用 Python 实现第一个值迭代:50 行代码看清本质
下面是一个极简、可运行的值迭代实现(基于numpy)。我们不追求工程化,只求逻辑透明:
import numpy as np # 1. 定义网格和参数 GRID_SIZE = 3 S = (0, 0) # 起点 G = (1, 2) # 终点 GAMMA = 0.9 THETA = 1e-6 # 收敛阈值 # 2. 初始化 V(s),全 0 V = np.zeros((GRID_SIZE, GRID_SIZE)) # 3. 定义动作和转移 ACTIONS = [(-1,0), (1,0), (0,-1), (0,1)] # up, down, left, right ACTION_NAMES = ['up', 'down', 'left', 'right'] def get_next_state(s, a): """根据状态s和动作a,返回下一个状态s'和奖励r""" sr, sc = s ar, ac = a nr, nc = sr + ar, sc + ac # 检查是否越界或碰墙 if 0 <= nr < GRID_SIZE and 0 <= nc < GRID_SIZE: next_s = (nr, nc) if next_s == G: reward = 10.0 # 到达目标 else: reward = -1.0 # 普通移动 else: next_s = s # 碰墙,位置不变 reward = -1.0 return next_s, reward # 4. 值迭代主循环 iter_count = 0 while True: iter_count += 1 delta = 0 # 遍历每个状态s for r in range(GRID_SIZE): for c in range(GRID_SIZE): s = (r, c) if s == G: # 终止状态,V* = 0 continue # 计算所有动作a对应的 Q(s,a) 候选值 q_values = [] for a_idx, a in enumerate(ACTIONS): next_s, reward = get_next_state(s, a) nr, nc = next_s # Q(s,a) = R(s,a,s') + γ * V_k(s') q_val = reward + GAMMA * V[nr, nc] q_values.append(q_val) # 贪婪选择:取最大Q值,即 V_{k+1}(s) = max_a Q(s,a) v_new = max(q_values) # 更新并记录变化量 delta = max(delta, abs(V[r, c] - v_new)) V[r, c] = v_new # 检查是否收敛 if delta < THETA: print(f"值迭代收敛于第 {iter_count} 轮") break print("最终状态价值 V*(s):") print(V)运行这段代码,你会看到V矩阵逐渐从全 0,变成类似这样:
[[ 5.2 6.8 8.2] [ 4.1 5.7 10. ] [ 3.2 4.3 5.1]]解释一下:
V[1,2] = 10.0是G,但注意:这是V矩阵的索引,`G=(1,
本文还有配套的精品资源,点击获取