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

强化学习实战:用Python手搓Sarsa和Q-Learning,在悬崖漫步里看谁更“怂”

强化学习实战:Python实现Sarsa与Q-Learning在悬崖漫步中的策略差异

从游戏视角理解强化学习核心算法

想象你正站在一个4×12的网格世界起点,目标是到达右下角的终点。但中间有一片"悬崖"——任何踏入都会让你回到起点并承受巨大惩罚。每走一步都会消耗体力(负奖励),而安全到达终点则获得奖励。这就是经典的"悬崖漫步"环境,也是理解强化学习基础算法的绝佳试验场。

本文将带你用Python实现两种最基础的时序差分(TD)算法——Sarsa和Q-Learning,通过直观的代码实验揭示它们在策略安全性上的本质差异。不同于单纯的理论讲解,我们将:

  1. 使用Gym库搭建可视化环境
  2. 从零编写算法代码
  3. 调整关键参数观察策略变化
  4. 可视化智能体的"走位"决策过程
import gym import numpy as np import matplotlib.pyplot as plt # 创建悬崖漫步环境 env = gym.make('CliffWalking-v0') print(f"状态空间大小: {env.observation_space.n}") print(f"动作空间: {env.action_space.n}") # 0:上, 1:右, 2:下, 3:左

1. 环境解析与Q表初始化

悬崖漫步环境是一个典型的离散状态-动作空间问题,非常适合表格型方法。环境特点:

  • 状态:48个离散位置(4行×12列)
  • 动作:4个方向移动(上、右、下、左)
  • 奖励
    • 每步:-1
    • 掉崖:-100并重置
    • 到达终点:0

我们先初始化Q表,这是两种算法共享的数据结构:

class CliffWalkingAgent: def __init__(self, env, alpha=0.1, gamma=0.9, epsilon=0.1): self.env = env self.alpha = alpha # 学习率 self.gamma = gamma # 折扣因子 self.epsilon = epsilon # 探索率 self.q_table = np.zeros((env.observation_space.n, env.action_space.n))

2. Sarsa算法实现:保守派的路径选择

Sarsa是一种on-policy算法,其名称源自更新公式中使用的状态-动作序列:(S, A, R, S', A')。核心特点是当前策略决定下一个动作,导致更保守的行为模式。

2.1 算法原理

Sarsa的更新公式:

Q(S,A) ← Q(S,A) + α[R + γQ(S',A') - Q(S,A)]

其中:

  • α:学习率
  • γ:折扣因子
  • A':根据当前策略在S'状态下选择的动作
class SarsaAgent(CliffWalkingAgent): def update(self, s, a, r, s_, a_): # Sarsa更新公式 td_target = r + self.gamma * self.q_table[s_, a_] td_error = td_target - self.q_table[s, a] self.q_table[s, a] += self.alpha * td_error def train(self, episodes=500): rewards = [] for _ in range(episodes): s = env.reset() a = self._choose_action(s) episode_reward = 0 done = False while not done: s_, r, done, _ = env.step(a) a_ = self._choose_action(s_) self.update(s, a, r, s_, a_) episode_reward += r s, a = s_, a_ rewards.append(episode_reward) return rewards

2.2 策略可视化与结果分析

训练完成后,我们可以可视化学习到的策略:

def plot_policy(q_table): arrows = ['↑', '→', '↓', '←'] policy = np.argmax(q_table, axis=1).reshape(4,12) for row in range(4): line = [] for col in range(12): if row == 3 and (0 < col < 11): line.append('×') # 悬崖 else: line.append(arrows[policy[row,col]]) print(' '.join(line))

典型输出:

→ → → → → → → → → → → ↓ → → → → → → → → → → → ↓ → → → → → → → → → → → ↓ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ →

可以看到Sarsa倾向于选择远离悬崖的安全路径,尽管这条路更长。这是因为:

  1. 在靠近悬崖的状态下,随机探索可能导致掉崖
  2. 算法会将这些高风险状态的Q值降低
  3. 最终策略会避开这些高风险区域

3. Q-Learning实现:冒险家的最优路径

Q-Learning是off-policy算法,其更新公式为:

Q(S,A) ← Q(S,A) + α[R + γmax_a' Q(S',a') - Q(S,A)]

关键区别在于使用最优未来价值而非实际采取的动作。

3.1 代码实现

class QLearningAgent(CliffWalkingAgent): def update(self, s, a, r, s_, done): # Q-Learning更新公式 if done: td_target = r else: td_target = r + self.gamma * np.max(self.q_table[s_]) td_error = td_target - self.q_table[s, a] self.q_table[s, a] += self.alpha * td_error def train(self, episodes=500): rewards = [] for _ in range(episodes): s = env.reset() episode_reward = 0 done = False while not done: a = self._choose_action(s) s_, r, done, _ = env.step(a) self.update(s, a, r, s_, done) episode_reward += r s = s_ rewards.append(episode_reward) return rewards

3.2 策略对比

Q-Learning的典型策略:

→ → → → → → → → → → → ↓ → → → → → → → → → → → ↓ → → → → → → → → → → → ↓ ↑ → → → → → → → → → → →

Q-Learning倾向于贴着悬崖的最短路径,因为:

  1. 它学习的是最优策略的价值估计
  2. 不考虑探索时的随机动作影响
  3. 理论上当探索率ε→0时能收敛到最优路径

4. 参数实验:探索率ε的影响

探索率ε是控制算法行为的关键参数。我们通过实验观察不同ε值对策略的影响:

epsilons = [0.01, 0.1, 0.3] results = {} for eps in epsilons: agent = SarsaAgent(env, epsilon=eps) results[f'Sarsa(ε={eps})'] = agent.train() agent = QLearningAgent(env, epsilon=eps) results[f'Q-Learning(ε={eps})'] = agent.train() # 绘制学习曲线 plt.figure(figsize=(10,6)) for label, rewards in results.items(): plt.plot(np.convolve(rewards, np.ones(50)/50, mode='valid'), label=label) plt.legend() plt.xlabel('Episode') plt.ylabel('Average Reward') plt.title('Performance under Different Exploration Rates') plt.show()

实验发现:

  • Sarsa:高ε值导致更保守的策略
  • Q-Learning:高ε值增加掉崖风险但保持最优路径倾向

5. 算法本质差异解析

两种算法在悬崖漫步中表现差异的根本原因:

特性SarsaQ-Learning
策略类型On-policyOff-policy
更新目标当前策略的动作最优可能动作
安全性
路径长度长但安全短但有风险
适用场景高风险环境确定性环境

用驾驶比喻:

  • Sarsa:新手司机,考虑实际可能采取的操作(包括失误)
  • Q-Learning:理想化驾驶,假设总能做出完美决策

6. 进阶技巧与优化

6.1 动态探索率

class DecayEpsilonAgent(CliffWalkingAgent): def __init__(self, env, epsilon_start=1.0, epsilon_end=0.01, epsilon_decay=0.995): super().__init__(env) self.epsilon = epsilon_start self.epsilon_end = epsilon_end self.epsilon_decay = epsilon_decay def _choose_action(self, s): self.epsilon = max(self.epsilon_end, self.epsilon*self.epsilon_decay) return super()._choose_action(s)

6.2 可视化价值函数

def plot_value_function(q_table): v = np.max(q_table, axis=1).reshape(4,12) plt.imshow(v, cmap='hot') plt.colorbar() plt.title('State Value Function') plt.axis('off') for i in range(4): for j in range(12): plt.text(j, i, f"{v[i,j]:.1f}", ha='center', va='center', color='blue')

7. 工程实践建议

在实际项目中应用这些算法时:

  1. 环境敏感性分析:先理解环境特性再选择算法
  2. 超参数调优:系统性地探索参数空间
  3. 可视化调试:价值函数和策略可视化至关重要
  4. 基准测试:与随机策略或规则策略比较
  5. 稳定性处理:考虑使用滑动平均评估性能
# 性能评估函数 def evaluate(agent, runs=100): total_rewards = [] for _ in range(runs): s = env.reset() done = False rewards = 0 while not done: a = np.argmax(agent.q_table[s]) # 使用贪婪策略 s, r, done, _ = env.step(a) rewards += r total_rewards.append(rewards) return np.mean(total_rewards), np.std(total_rewards)

通过这个完整的实现和实验过程,我们直观地验证了:

  • Sarsa的保守特性使其适合安全关键应用
  • Q-Learning在充分探索后能找到最优路径
  • 探索率对策略安全性的显著影响
  • 可视化在强化学习开发中的重要性
http://www.jsqmd.com/news/874859/

相关文章:

  • 用 Matrix Synapse 和 Element 搭建私有聊天服务器
  • 【2026年阿里巴巴集团暑期实习- 5月23日-算法岗-第三题- 寻找满足条件的最优子序列】(题目+思路+JavaC++Python解析+在线测试)
  • AI社交对话设计:如何避免商业场景中的期望违背与尴尬感
  • AI赋能公立高校:四大核心场景降本增效实践与挑战
  • ArcGIS新手别怕!用Union和字段计算器,5步搞定土地利用变化图斑分析
  • 对比直接使用原厂API体验Taotoken在路由容灾与稳定性上的差异
  • SqueezeBERT:用分组卷积思想加速Transformer,实现移动端4.3倍推理提速
  • 统计学习理论:从VC维到泛化误差,构建稳健CV系统的数学基石
  • 别再傻等下载了!手把手教你用wget离线部署sentence-transformers模型(以all-MiniLM-L6-v2为例)
  • 别再傻傻分不清了!TP53、7157、ENSG00000141510... 一文搞懂基因ID转换(附R代码与g:Profiler保姆级教程)
  • 告别ggrcs直方图!用singlercs函数为你的线性回归RCS曲线“瘦身美颜”
  • 人机协作视觉系统自适应:基准测试与概念漂移应对实战
  • 为什么92%的AI Agent项目卡在POC阶段?揭秘头部银行、药企、电网的6个月规模化上线方法论
  • 别再乱试了!这些看似“整蛊”的Windows批处理命令,分分钟让你的电脑报废
  • 从/dev/snd文件看起:手把手教你理解Linux ALSA声卡驱动的设备命名规则
  • 2026年评价高的谐波减速机/ATG减速机高口碑品牌推荐 - 品牌宣传支持者
  • 低代码Agent平台是怎样实现自动化流程编排的?深度拆解2026企业级智能体底层架构
  • 从‘盲人摸象’到‘心中有尺’:聊聊DOA估计里那个绕不开的CRLB到底怎么用
  • AI健康流行病学:量化数字环境暴露与个人防护策略
  • 经济合同纠纷律师费用解析及合规律所参考指南:取保候审缓刑律师咨询/四川墨科律师事务所/律师费用收取标准/房产纠纷律师咨询/选择指南 - 优质品牌商家
  • Win11桌面图标突然锁死?别慌,用这招绕过组策略编辑器直接搞定
  • 事件相机数据预处理:基于线检测的脉冲神经网络能效优化策略
  • iPaaS集成平台:五大产品关键能力速查
  • 强化学习GridWorld实战:值迭代vs策略迭代,哪个算法收敛更快?(Python代码对比)
  • 别再乱拷贝.so文件了!详解银河麒麟下Qt程序、Qt Creator与输入法插件的“版本锁”问题
  • 麒麟V10 SP2服务器mate-indicators内存泄漏?别慌,手把手教你打补丁和降级auditd
  • 电力负荷预测入门:用Python+LSTM搞定短期负荷预测(含风电/光伏/变压器数据集实战)
  • 揭秘60TB中文语料库MNBVC:如何用海量数据训练更懂你的AI大模型?[特殊字符]
  • 天赐范式第52天:Kimi自打跟了我搞CFD没少吃苦,没过一天舒心日子~论Kimi的战斗意志~我必须承认:我分析不下去了,真×1,我放弃逻辑推演×6,最后让代码自己招供,抓出幕后真凶幽灵BUG变量N。
  • 2026年5月重庆洁净工程实力企业深度解析:为何恒德制冷设备值得关注? - 2026年企业推荐榜