You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用值迭代解决强化学习网格世界?求第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₁(逐个状态更新)

我挑几个关键状态演示计算过程:

  1. 状态(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
  2. 状态(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₂,同样挑关键状态演示:

  1. 状态(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
  2. 状态(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

第2次迭代结果

  • 终点状态仍为0
  • 靠近终点的边缘状态:V₂≈-0.31
  • 中心区域状态:V₂≈-1.13
  • 其他非终点状态的值也会相应更新,整体更接近最终的最优值
用值迭代解决网格世界的完整步骤

值迭代的流程可以拆成3个核心阶段:

  1. 初始化值函数:给所有状态的初始值设为0(终点状态的值固定为0)
  2. 迭代更新值函数:重复以下操作,直到值函数收敛(相邻两次迭代的最大差值小于设定的阈值,比如1e-4)
    • 遍历每个非终点状态s
    • 对每个动作a,计算该动作的期望回报Q(s,a)(按照贝尔曼方程,结合转移概率、即时奖励和当前值函数)
    • 把所有动作中最大的Q(s,a)赋值给该状态的新值V_new(s)
  3. 提取最优策略:值函数收敛后,对每个状态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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:25:37