使用Numpy实现动态规划求解GridWorld问题的代码错误排查
3x3 GridWorld动态规划值无穷大问题排查
核心错误方向及排查步骤
1. 折扣因子γ设置违规
动态规划的收敛前提是0 ≤ γ < 1,如果把γ设为1或者大于1,只要存在非终止状态的循环移动(比如机器人在网格里来回走),值函数就会不断累加奖励,最终爆到无穷大。先检查代码里有没有定义γ,或者是不是设成了1。
2. 终止状态未锁定
(3,2)和(3,3)的状态值应该固定为-1和+1,完全不参与后续迭代更新。如果代码里还在对这两个状态做值计算,会导致错误的转移累加,甚至触发循环。
- 确认迭代循环里是否跳过了这两个终止状态
- 检查状态转移逻辑:进入终止状态后,是否直接返回对应奖励,不再计算后续状态值
3. 状态转移/奖励逻辑出错
- 动作偏移逻辑混乱:比如执行上移动作时,左右偏移的概率是否正确,有没有处理边界撞墙的情况(撞墙后应该停在原位置,此时奖励通常设为0,要是没处理边界,可能出现错误的状态转移路径)
- 奖励规则错误:如果把每步移动的奖励设为正数值,再加上γ=1,会持续累加导致值爆炸;常规GridWorld里非终止步的奖励都是0
4. 值迭代更新逻辑错误
如果用了异步更新(计算一个状态就立刻覆盖原值,再用新值算其他状态),很容易导致值函数发散。正确的做法是先把所有状态的新值都算完,再一次性替换旧值。
典型错误代码示例及修复
比如这段模拟常见问题的错误代码:
import numpy as np grid_size = 3 V = np.zeros((grid_size+1, grid_size+1)) # 1-based索引 terminal_states = [(3,2), (3,3)] gamma = 1.0 # 致命错误:γ必须小于1 def get_next_state(state, action): x, y = state if action == 'up': next_x, next_y = x-1, y elif action == 'down': next_x, next_y = x+1, y elif action == 'left': next_x, next_y = x, y-1 elif action == 'right': next_x, next_y = x, y+1 # 边界处理缺失:撞墙后直接返回原位置,但未明确奖励规则 if next_x <1 or next_x>3 or next_y<1 or next_y>3: return (x,y) return (next_x, next_y) while True: delta = 0 for x in range(1,4): for y in range(1,4): # 未跳过终止状态,会错误更新 v = V[x,y] new_v = 0 for action in ['up','down','left','right']: # 偏移动作逻辑错误:上下移动的偏移应为左右,左右移动的偏移应为上下 actions = [action, 'left', 'right'] probs = [0.8, 0.1, 0.1] for a, p in zip(actions, probs): next_state = get_next_state((x,y), a) if next_state in terminal_states: reward = 1 if next_state == (3,3) else -1 else: reward = 0 new_v += p * (reward + gamma * V[next_state]) V[x,y] = new_v delta = max(delta, abs(v - new_v)) if delta < 1e-4: break print(V)
修复要点
- 把γ改成小于1的数值,比如
gamma = 0.9 - 迭代时跳过终止状态:在循环里加
if (x,y) in terminal_states: continue - 修正动作偏移逻辑:上下移动的偏移是左右,左右移动的偏移是上下
- 确保边界处理的奖励规则明确(撞墙奖励为0)
- 改用同步更新:先创建一个新的V矩阵存储新值,迭代完所有状态后再替换原V
内容的提问来源于stack exchange,提问作者Agus
相关产品推荐
相关产品推荐

