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

