如何用值迭代解决强化学习网格世界?求第1、2轮分步迭代演示
嘿,作为刚入门强化学习的新手,完全懂你想要一步步拆解值迭代的心情!我拿经典的4x4网格世界来给你演示第1次和第2次迭代,再给你讲清楚怎么用值迭代解决这类问题~
先明确网格世界的基础设定
我用最常见的4x4网格来举例,参数如下:
- 网格坐标:从
(0,0)(左上角)到(3,3)(右下角) - 终点状态:
(0,0)和(3,3),到达后获得奖励0,且任务终止 - 动作集合:上、下、左、右,每个动作有0.8的概率成功执行,0.1的概率往垂直方向偏移(比如选「上」,0.8概率向上移动,0.1概率向左偏移,0.1概率向右偏移;如果在网格边缘,撞墙则停在原位置)
- 即时奖励:除终点外,每移动一步获得奖励-1(鼓励尽快到达终点)
- 折扣因子
γ:0.9(衡量未来回报的权重)
第1次值迭代(V₀ → V₁)
值迭代的核心是贝尔曼最优方程:Vₖ₊₁(s) = maxₐ [ 期望回报(Q(s,a)) ],其中Q(s,a) = 即时奖励 + γ * Σ(转移概率 * 下一个状态的当前值)
初始值函数V₀
所有状态的初始值都设为0,终点状态的值始终保持0(因为终止后没有后续回报)。
计算V₁(逐个状态更新)
我挑几个关键状态演示计算过程:
状态(0,1)(左上角终点右侧):
- 动作「左」:0.8概率到终点
(0,0)(奖励0,后续值0),0.1概率向上撞墙(奖励-1,后续值0),0.1概率向下到(1,1)(奖励-1,后续值0)
期望回报:0.8*(0 + 0.9*0) + 0.1*(-1 + 0.9*0) + 0.1*(-1 + 0.9*0) = -0.2 - 动作「上」:0.8概率撞墙(奖励-1),0.1概率到终点,0.1概率到
(0,2),期望回报:0.8*(-1) + 0.1*0 + 0.1*(-1) = -0.9 - 动作「下」「右」的期望回报分别是-0.9和-1.0
- 取最大值,所以
V₁(0,1) = max(-0.2, -0.9, -0.9, -1.0) = -0.2
- 动作「左」:0.8概率到终点
状态(1,1)(网格中心):
所有动作的期望回报都是-1.0(不管往哪个方向走,都到非终点状态,奖励-1,后续值0),所以V₁(1,1) = -1.0
第1次迭代结果
- 终点状态:
V₁(0,0)=V₁(3,3)=0 - 靠近终点的边缘状态(
(0,1),(1,0),(2,3),(3,2)):V₁=-0.2 - 其他非终点状态:
V₁=-1.0
第2次值迭代(V₁ → V₂)
这次用V₁的值来计算新的V₂,同样挑关键状态演示:
状态(0,1):
- 动作「左」:0.8概率到终点(回报0),0.1概率向上撞墙(奖励-1 + 0.9V₁(0,1)= -1 + 0.9(-0.2)= -1.18),0.1概率向下到
(1,1)(奖励-1 + 0.9V₁(1,1)= -1 + 0.9(-1.0)= -1.9)
期望回报:0.8*0 + 0.1*(-1.18) + 0.1*(-1.9) = -0.308 - 其他动作的期望回报分别是-1.134、-1.71、-1.828
- 取最大值,
V₂(0,1)=-0.308
- 动作「左」:0.8概率到终点(回报0),0.1概率向上撞墙(奖励-1 + 0.9V₁(0,1)= -1 + 0.9(-0.2)= -1.18),0.1概率向下到
状态(1,1):
- 动作「左」:0.8概率到
(1,0)(奖励-1 + 0.9V₁(1,0)= -1 +0.9(-0.2)= -1.18),0.1概率到终点,0.1概率到(2,0)(奖励-1 +0.9*(-1.0)= -1.9)
期望回报:0.8*(-1.18) +0.1*0 +0.1*(-1.9) = -1.134 - 动作「上」的期望回报同样是-1.134,「右」「下」的期望回报是-1.9
- 取最大值,
V₂(1,1)=-1.134
- 动作「左」:0.8概率到
第2次迭代结果
- 终点状态仍为0
- 靠近终点的边缘状态:
V₂≈-0.31 - 中心区域状态:
V₂≈-1.13 - 其他非终点状态的值也会相应更新,整体更接近最终的最优值
用值迭代解决网格世界的完整步骤
值迭代的流程可以拆成3个核心阶段:
- 初始化值函数:给所有状态的初始值设为0(终点状态的值固定为0)
- 迭代更新值函数:重复以下操作,直到值函数收敛(相邻两次迭代的最大差值小于设定的阈值,比如
1e-4)- 遍历每个非终点状态
s - 对每个动作
a,计算该动作的期望回报Q(s,a)(按照贝尔曼方程,结合转移概率、即时奖励和当前值函数) - 把所有动作中最大的
Q(s,a)赋值给该状态的新值V_new(s)
- 遍历每个非终点状态
- 提取最优策略:值函数收敛后,对每个状态
s,选择能让Q(s,a)最大的动作a,就是该状态下的最优动作,组合起来就是最优策略
简单Python示例(核心逻辑)
下面是实现上述网格世界值迭代的简化代码,你可以直接运行看结果:
import numpy as np # 网格世界参数 grid_size = 4 gamma = 0.9 threshold = 1e-4 actions = [(-1,0), (1,0), (0,-1), (0,1)] # 上、下、左、右对应的坐标偏移 action_symbols = ['↑', '↓', '←', '→'] # 初始化值函数 V = np.zeros((grid_size, grid_size)) # 值迭代主循环 while True: V_new = np.copy(V) max_diff = 0 # 记录值函数的最大变化量,用于判断收敛 for i in range(grid_size): for j in range(grid_size): # 跳过终点状态 if (i == 0 and j == 0) or (i == grid_size-1 and j == grid_size-1): continue q_values = [] # 存储当前状态下所有动作的Q值 for di, dj in actions: total_q = 0 # 计算主动作(概率0.8)的贡献 ni, nj = i + di, j + dj if 0 <= ni < grid_size and 0 <= nj < grid_size: # 到达终点则奖励0,否则奖励-1 reward = 0 if (ni == 0 and nj == 0) or (ni == grid_size-1 and nj == grid_size-1) else -1 total_q += 0.8 * (reward + gamma * V[ni][nj]) else: # 撞墙,停在原状态 total_q += 0.8 * (-1 + gamma * V[i][j]) # 计算垂直方向偏移动作(各0.1概率)的贡献 if di != 0: # 上下动作,垂直偏移是左右 # 左偏移 ni1, nj1 = i, j - 1 if 0 <= ni1 < grid_size and 0 <= nj1 < grid_size: reward = 0 if (ni1 == 0 and nj1 == 0) or (ni1 == grid_size-1 and nj1 == grid_size-1) else -1 total_q += 0.1 * (reward + gamma * V[ni1][nj1]) else: total_q += 0.1 * (-1 + gamma * V[i][j]) # 右偏移 ni2, nj2 = i, j + 1 if 0 <= ni2 < grid_size and 0 <= nj2 < grid_size: reward = 0 if (ni2 == 0 and nj2 == 0) or (ni2 == grid_size-1 and nj2 == grid_size-1) else -1 total_q += 0.1 * (reward + gamma * V[ni2][nj2]) else: total_q += 0.1 * (-1 + gamma * V[i][j]) else: # 左右动作,垂直偏移是上下 # 上偏移 ni1, nj1 = i - 1, j if 0 <= ni1 < grid_size and 0 <= nj1 < grid_size: reward = 0 if (ni1 == 0 and nj1 == 0) or (ni1 == grid_size-1 and nj1 == grid_size-1) else -1 total_q += 0.1 * (reward + gamma * V[ni1][nj1]) else: total_q += 0.1 * (-1 + gamma * V[i][j]) # 下偏移 ni2, nj2 = i + 1, j if 0 <= ni2 < grid_size and 0 <= nj2 < grid_size: reward = 0 if (ni2 == 0 and nj2 == 0) or (ni2 == grid_size-1 and nj2 == grid_size-1) else -1 total_q += 0.1 * (reward + gamma * V[ni2][nj2]) else: total_q += 0.1 * (-1 + gamma * V[i][j]) q_values.append(total_q) # 更新当前状态的值函数 V_new[i][j] = max(q_values) # 更新最大差值 max_diff = max(max_diff, abs(V_new[i][j] - V[i][j])) V = V_new # 判断是否收敛 if max_diff < threshold: break # 打印收敛后的最优值函数 print("收敛后的最优值函数:") print(np.round(V, 2)) # 提取并打印最优策略 policy = np.full((grid_size, grid_size), '终端') for i in range(grid_size): for j in range(grid_size): if (i == 0 and j == 0) or (i == grid_size-1 and j == grid_size-1): continue q_values = [] for di, dj in actions: total_q = 0 # 重复计算Q值的逻辑(和迭代部分一致) ni, nj = i + di, j + dj if 0 <= ni < grid_size and 0 <= nj < grid_size: reward = 0 if (ni == 0 and nj == 0) or (ni == grid_size-1 and nj == grid_size-1) else -1 total_q += 0.8 * (reward + gamma * V[ni][nj]) else: total_q += 0.8 * (-1 + gamma * V[i][j]) if di != 0: ni1, nj1 = i, j - 1 if 0 <= ni1 < grid_size and 0 <= nj1 < grid_size: reward = 0 if (ni1 == 0 and nj1 == 0) or (ni1 == grid_size-1 and nj1 == grid_size-1) else -1 total_q += 0.1 * (reward + gamma * V[ni1][nj1]) else: total_q += 0.1 * (-1 + gamma * V[i][j]) ni2, nj2 = i, j + 1 if 0 <= ni2 < grid_size and 0 <= nj2 < grid_size: reward = 0 if (ni2 == 0 and nj2 == 0) or (ni2 == grid_size-1 and nj2 == grid_size-1) else -1 total_q += 0.1 * (reward + gamma * V[ni2][nj2]) else: total_q += 0.1 * (-1 + gamma * V[i][j]) else: ni1, nj1 = i - 1, j if 0 <= ni1 < grid_size and 0 <= nj1 < grid_size: reward = 0 if (ni1 == 0 and nj1 == 0) or (ni1 == grid_size-1 and nj1 == grid_size-1) else -1 total_q += 0.1 * (reward + gamma * V[ni1][nj1]) else: total_q += 0.1 * (-1 + gamma * V[i][j]) ni2, nj2 = i + 1, j if 0 <= ni2 < grid_size and 0 <= nj2 < grid_size: reward = 0 if (ni2 == 0 and nj2 == 0) or (ni2 == grid_size-1 and nj2 == grid_size-1) else -1 total_q += 0.1 * (reward + gamma * V[ni2][nj2]) else: total_q += 0.1 * (-1 + gamma * V[i][j]) q_values.append(total_q) # 选择Q值最大的动作 best_action_idx = np.argmax(q_values) policy[i][j] = action_symbols[best_action_idx] print("\n最优策略:") print(policy)
内容的提问来源于stack exchange,提问作者Ahasan Ratul
相关产品推荐
相关产品推荐

