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

Q-Learning智能体在FrozenLake-v1环境中到达目标步数过多的问题求助

Q-Learning智能体在FrozenLake-v1环境中到达目标步数过多的问题求助

我现在正在用OpenAI Gym的FrozenLake-v1环境实现Q-learning,但我的智能体总是绕很多不必要的路才到达目标。我反复检查了代码,还是找不到问题所在。

我试过给步数过多的情况降奖励——比如找到目标时每多一步就扣0.01奖励,原以为能让智能体明白要少走弯路,但效果并不理想。我还想过不管有没有找到目标,每走一步就减奖励,但又担心奖励变成负数会不会有问题。

以下是我用的代码:

import random
import numpy as np
import gymnasium as gym

def argmax(arr):
    arr_max = np.max(arr)
    return np.random.choice(np.where(arr == arr_max)[0])

def save_q_table(Q):
    np.savetxt("q_table.csv", Q, delimiter=",")

def load_q_table():
    return np.loadtxt("q_table.csv", delimiter=",")

def run(training):
    if not training:
        env = gym.make("FrozenLake-v1", render_mode='human')
    else:
        env = gym.make("FrozenLake-v1")

    Q = np.zeros((env.observation_space.n, env.action_space.n))  # empty q_table
    if not training:
        Q = load_q_table()

    alpha = 0.8
    gamma = 0.95
    episode = 0
    episodes = 10000
    epsilon = 0.95
    epsilon_decay = (2 * epsilon) / episodes
    epsilon_min = 0.05

    env.metadata['render_fps'] = 10

    state, info = env.reset()
    while episode < episodes:
        if random.random() < epsilon and training:
            action = env.action_space.sample()
        else:
            action = argmax(Q[state])

        new_state, reward, terminated, truncated, info = env.step(action)

        if training:
            Q[state, action] = Q[state, action] + alpha * (
                float(reward) + gamma * np.max(Q[new_state]) - Q[state, action])

        state = new_state

        if terminated or truncated:
            if epsilon > epsilon_min:
                epsilon -= epsilon_decay
            episode += 1
            # save on last episode
            if training and episode == episodes:
                print("Saving Q table")
                save_q_table(Q)
            print("Episode: ", episode, "Epsilon: ", round(epsilon, 2), "Reward: ", reward)
            state, info = env.reset()  # Reset the environment

    env.close()

run(training=False)

可能的问题分析与解决方案

1. 奖励函数的设计问题

FrozenLake默认的奖励机制是只有到达终点才给1,其他情况都是0,这种稀疏奖励确实容易让智能体找不到最优路径——因为多走几步和少走几步的即时奖励没区别。你之前尝试的终点扣罚思路方向是对的,但可能力度不够或者时机不对。其实可以调整为每走一步就给一个微小的负奖励,比如-0.01,这样智能体就会主动寻找步数更少的路径,毕竟每多走一步都会损失一点收益,哪怕奖励变成负数也没关系,因为到达终点的1奖励足够抵消之前的小额扣罚,反而能强化“少走弯路”的行为。

修改代码里的奖励计算部分:

# 在step之后修改reward
if training:
    # 每走一步扣0.01,终点的1奖励保留
    modified_reward = reward - 0.01
    Q[state, action] = Q[state, action] + alpha * (
        modified_reward + gamma * np.max(Q[new_state]) - Q[state, action])

2. 探索率(epsilon)的衰减设置

你的epsilon初始是0.95,衰减公式是(2 * epsilon) / episodes,这明显有问题——按这个计算,10000 episodes后epsilon会变成负数,完全不符合预期。正确的衰减步长应该是让epsilon从初始值线性衰减到最小值,调整为:

epsilon_decay = (epsilon - epsilon_min) / episodes

这样10000 episodes后,epsilon刚好降到0.05,既保证前期有足够探索,后期又能让智能体更多利用已有经验。

3. 学习率(alpha)的调整

你的alpha设为0.8,这个值偏大,意味着每次更新Q值时,新的经验占比太高,可能导致Q值不稳定,智能体难以收敛到最优策略。可以尝试把alpha降到0.1-0.3之间,或者用动态衰减的学习率,比如随着episode增加逐渐降低alpha,让前期快速学习,后期慢慢收敛。

4. 训练次数的问题

10000 episodes对于FrozenLake来说可能不够,尤其是在调整奖励和参数后,可以尝试增加到50000甚至100000 episodes,让智能体有足够的时间学习最优路径。

5. Q值初始化的问题

你初始Q值全为0,这在稀疏奖励环境中可能让智能体初期探索效率低。可以尝试把Q值初始化为一个很小的正数(比如0.1),或者随机初始化在0到0.1之间,这样能鼓励智能体初期尝试不同的动作。


备注:内容来源于stack exchange,提问作者Jelles

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.20 08:54:33