用Python和Pandas手把手实现你的第一个Q-learning寻宝游戏(附完整代码)

张开发
2026/4/19 23:19:42 15 分钟阅读

分享文章

用Python和Pandas手把手实现你的第一个Q-learning寻宝游戏(附完整代码)
用Python和Pandas手把手实现你的第一个Q-learning寻宝游戏附完整代码在人工智能的众多分支中强化学习因其独特的试错学习机制而备受关注。想象一下你正在教一个孩子玩迷宫游戏——你不会直接告诉他每一步该怎么走而是让他在尝试中找到通往终点的最佳路径并在每次成功时给予奖励。这正是Q-learning的核心思想通过与环境互动来学习最优策略。本文将带你用Python和Pandas从零构建一个完整的Q-learning寻宝游戏。不同于理论讲解我们会聚焦于可运行的代码实现让你在动手实践中理解如何用Pandas DataFrame构建Q-tableε-greedy策略的Python实现细节时序差分(TD)更新的具体计算过程可视化环境反馈的技巧1. 环境搭建与基础配置1.1 初始化游戏环境我们的寻宝游戏设定在一个线性轨道上探险者o需要找到宝藏T。环境状态可以用字符串表示例如-o---T表示探险者在第二个位置宝藏在最右侧。首先导入必要的库并设置超参数import numpy as np import pandas as pd import time # 设置随机种子保证结果可复现 np.random.seed(2) # 游戏参数配置 N_STATES 6 # 状态数量轨道长度 ACTIONS [left, right] # 可用动作 EPSILON 0.9 # ε-greedy策略参数 ALPHA 0.1 # 学习率 GAMMA 0.9 # 奖励衰减系数 MAX_EPISODES 13 # 最大训练轮次 FRESH_TIME 0.3 # 可视化刷新间隔1.2 构建Q-tableQ-table是Q-learning的核心数据结构记录每个状态-动作对的预期收益。我们用Pandas DataFrame实现def build_q_table(n_states, actions): 初始化Q-table return pd.DataFrame( np.zeros((n_states, len(actions))), columnsactions ) # 示例输出 left right 0 0.0 0.0 1 0.0 0.0 2 0.0 0.0 3 0.0 0.0 4 0.0 0.0 5 0.0 0.0 注意初始时所有Q值设为0表示智能体对环境的初始无知状态2. 核心算法实现2.1 ε-greedy动作选择平衡探索(exploration)与利用(exploitation)是强化学习的关键挑战。我们采用ε-greedy策略def choose_action(state, q_table): 基于ε-greedy策略选择动作 state_actions q_table.iloc[state, :] # 10%概率随机选择探索或当所有Q值为0时 if np.random.uniform() EPSILON or state_actions.all() 0: return np.random.choice(ACTIONS) # 90%概率选择当前最优动作利用 return state_actions.idxmax()2.2 环境反馈机制定义状态转移和奖励规则def get_env_feedback(S, A): 环境对动作的反馈 if A right: if S N_STATES - 2: # 到达宝藏位置 return terminal, 1 return S 1, 0 else: # 向左移动 return max(S - 1, 0), 0 # 确保不会越界2.3 可视化更新为直观观察训练过程添加可视化功能def update_env(S, episode, step_counter): 更新命令行可视化 env [-]*(N_STATES-1) [T] if S terminal: print(f\rEpisode {episode1}: steps{step_counter}, end) time.sleep(2) else: env[S] o print(\r .join(env), end) time.sleep(FRESH_TIME)3. Q-learning主循环3.1 TD更新实现时序差分(Temporal Difference)是Q-learning的核心更新方法def rl(): q_table build_q_table(N_STATES, ACTIONS) for episode in range(MAX_EPISODES): step_counter 0 S 0 # 初始状态 is_terminated False update_env(S, episode, step_counter) while not is_terminated: A choose_action(S, q_table) S_, R get_env_feedback(S, A) # 计算预测值和目标值 q_predict q_table.loc[S, A] q_target R if S_ terminal else R GAMMA * q_table.iloc[S_].max() # Q-table更新 q_table.loc[S, A] ALPHA * (q_target - q_predict) S S_ step_counter 1 is_terminated S_ terminal update_env(S, episode, step_counter) return q_table3.2 训练过程解析让我们拆解一个训练episode的完整流程初始化状态S0最左侧位置根据当前Q值和ε-greedy策略选择动作执行动作获得新状态S和奖励R计算TD误差(R γ*maxQ(S) - Q(S,A))更新Q-tableQ(S,A) α * TD误差重复直到到达terminal状态4. 结果分析与优化4.1 训练结果观察运行完整训练后典型的Q-table输出如下left right 0 0.000000 0.005314 1 0.000000 0.027405 2 0.000000 0.112025 3 0.000000 0.378929 4 0.000000 0.747209 5 0.000000 0.000000从Q-table可以看出右侧动作的Q值随着接近宝藏位置逐渐增大左侧动作始终为0因为向左移动无法获得奖励状态5宝藏位置的Q值为0因为到达后episode结束4.2 参数调优建议通过实验发现以下规律参数增大效果减小效果α学习更快但可能不稳定学习稳定但速度慢γ更重视远期奖励更关注即时奖励ε更多探索更多利用已知策略推荐初始参数组合ALPHA 0.1 # 适中学习率 GAMMA 0.9 # 适度考虑远期奖励 EPSILON 0.9 # 高探索率4.3 常见问题排查问题1智能体始终随机行动检查ε值是否过高确认奖励设置是否正确问题2Q值不收敛尝试减小学习率α增加训练episode数量问题3可视化显示异常确保终端支持\r回车符调整FRESH_TIME避免刷新过快5. 项目扩展方向5.1 增加环境复杂度将线性环境扩展为网格世界# 二维状态表示 states [(x,y) for x in range(5) for y in range(5)] actions [up, down, left, right]5.2 添加障碍物修改环境反馈函数def get_env_feedback(S, A): if S obstacle_pos and A right: return S, -1 # 碰到障碍物惩罚 ...5.3 改用神经网络近似Q函数对于大型状态空间可以用深度学习替代Q-tableimport torch import torch.nn as nn class QNetwork(nn.Module): def __init__(self, state_dim, action_dim): super().__init__() self.fc nn.Sequential( nn.Linear(state_dim, 64), nn.ReLU(), nn.Linear(64, action_dim) ) def forward(self, x): return self.fc(x)在实际项目中我发现调整ε的衰减策略能显著提升性能——初期高探索率帮助广泛尝试后期逐渐降低以利用学到的策略。一个简单的线性衰减实现epsilon max(0.01, 0.9 - 0.8 * episode / MAX_EPISODES)

更多文章