当前位置: 首页 > news >正文

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

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

在人工智能的众多分支中,强化学习因其独特的"试错学习"机制而备受关注。想象一下,你正在教一个孩子玩迷宫游戏——你不会直接告诉他每一步该怎么走,而是让他在尝试中找到通往终点的最佳路径,并在每次成功时给予奖励。这正是Q-learning的核心思想:通过与环境互动来学习最优策略。

本文将带你用Python和Pandas从零构建一个完整的Q-learning寻宝游戏。不同于理论讲解,我们会聚焦于可运行的代码实现,让你在动手实践中理解:

  1. 如何用Pandas DataFrame构建Q-table
  2. ε-greedy策略的Python实现细节
  3. 时序差分(TD)更新的具体计算过程
  4. 可视化环境反馈的技巧

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-table

Q-table是Q-learning的核心数据结构,记录每个状态-动作对的预期收益。我们用Pandas DataFrame实现:

def build_q_table(n_states, actions): """初始化Q-table""" return pd.DataFrame( np.zeros((n_states, len(actions))), columns=actions ) # 示例输出 """ 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 {episode+1}: 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_table

3.2 训练过程解析

让我们拆解一个训练episode的完整流程:

  1. 初始化状态S=0(最左侧位置)
  2. 根据当前Q值和ε-greedy策略选择动作
  3. 执行动作,获得新状态S'和奖励R
  4. 计算TD误差:(R + γ*maxQ(S') - Q(S,A))
  5. 更新Q-table:Q(S,A) += α * TD误差
  6. 重复直到到达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:智能体始终随机行动

  • 检查ε值是否过高
  • 确认奖励设置是否正确

问题2:Q值不收敛

  • 尝试减小学习率α
  • 增加训练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-table:

import 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)
http://www.jsqmd.com/news/668341/

相关文章:

  • python重命名文件 发生的一些问题记录
  • Java代码静态分析深度解析:java-callgraph2架构设计与企业级应用实践
  • 别再死磕公式了!用MATLAB手把手复现DIC中的FA-GN与IC-GN算法(附完整代码)
  • 文本文件名相似度筛选
  • 【量化实战】解码期权PCR:从情绪指标到稳健策略的构建与优化
  • 2025届学术党必备的十大降AI率神器推荐
  • 用Python实战模糊粗糙集:从理论到代码,5步搞定高维数据降维
  • 从‘救命稻草’到‘瑞士军刀’:嵌入式老鸟教你用U-Boot命令诊断与修复启动故障
  • 逆向实战:手把手带你用Node.js复现某音a_bogus算法核心步骤(含完整代码)
  • Cadence SPB16.6 自带400+原理图库(.olb)快速盘点与高效复用指南
  • 别再只写CRUD了!用SpringBoot+MyBatis实现CRM,这些设计亮点值得抄作业
  • 2026年昆明优秀少儿美育启蒙机构有哪些 - 云南美术头条
  • 解密WPF黑盒:5分钟掌握dnSpy BAML反编译核心技术
  • 从手机屏幕到嵌入式开发:一文搞懂ILI9341驱动的TFT-LCD底层原理
  • Ant Design表单布局实战:labelCol与wrapperCol的栅格化应用解析
  • github操作入门
  • [CentOS 7] 从零部署TeamSpeak语音服务器:一站式配置与排错指南
  • 从语言模型到机械臂控制器:AGI物理世界接入的3层协议栈重构(附ROS2-GPT网关开源实践)
  • R语言实战:手把手教你用CIBERSORT分析肿瘤免疫浸润(附LM22文件下载与避坑指南)
  • 4090多卡使用sglang推理框架开发版布署qwen3.5-35B - yi
  • 四十二、Fluent欧拉模型流化床模拟:从基础设置到颗粒动力学解析
  • 【AGI战争伦理黄金三角模型】:从算法偏见、责任归属到人机指挥链,20年军工AI治理实战验证的4层动态防护体系
  • 第 1 行:定义扫描变量
  • Linux内核调试进阶:手把手教你编写第一个kprobe内核模块(以do_fork为例)
  • 极客卸载进阶秘籍:解锁隐藏功能与专业使用技巧
  • 别再死记硬背Faster RCNN了!用PyTorch手把手复现RPN网络(附代码与可视化)
  • CSS圆角效果在低版本浏览器失效_使用PIE.htc行为与渐进增强
  • Pixel Epic智识终端部署教程:GPU算力优化适配AgentCPM-Report推理
  • 【限时首发】AGI迁移学习能力分级认证标准(L1–L5):工信部AI实验室联合发布的首份可验证评估协议
  • OpenClaw能力扩展机制完全解读:插件、Skill、API,怎么玩都行