自学教程 学编程从这里开始

Q-learning 与 SARSA

Q-learning 和 SARSA 都是基于值函数的时序差分(TD)强化学习算法,维护一张 Q 表(状态-动作值函数),用来估计(Q(s,a))(Q(s,a)) 。二者最大区别:Q-learning 是离线策略(Off-policy),SARSA 是在线策略(On-policy)。

1. 核心概念回顾

  • (Q(s,a)):在状态 s 执行动作 a,后续能获得的期望累积回报
  • 时序差分 TD:不需要等到回合结束,每一步就更新Q值
  • 在线策略:用来收集样本的策略,和用来更新Q值的策略是同一个
  • 离线策略:用一个策略收集样本,学习另一个更优策略

2. SARSA

名字来源于更新公式里的五元组:(St,At,Rt+1,St+1,At+1)

  • 先在 St选动作 At,得到奖励 Rt+1​、下一个状态 St+1
  • 再用当前策略,在 St+1选出下一个动作 At+1
  • 更新公式:

Q(St,At)←Q(St,At)+α[Rt+1+γQ(St+1,At+1)−Q(St,At)]

特点:

  • On-policy,跟着自己的探索策略学习
  • 更加保守,倾向避开危险、高惩罚的路径
  • 适合环境里有很大风险、需要安全策略的场景

3. Q-learning

更新只使用 (St,At,Rt+1,St+1),不需要预先选 At+1

  • 直接取下一状态里最大的Q值 max⁡aQ(St+1,a)
  • 更新公式:

Q(St,At)←Q(St,At)+α[Rt+1+γmax⁡aQ(St+1,a)−Q(St,At)]

特点:

  • Off-policy,学习最优贪心策略,样本可以来自带有探索的策略
  • 更加大胆,敢于学习最优路径,忽略探索过程里的随机动作
  • 最经典、入门最常用

4. 对比表

项目SARSAQ-learning
策略类型On-policy 在线策略Off-policy 离线策略
目标Q值
Q
(St+1,At+1)
(当前策略选出的动作)
maxa​Q(St+1​,a)(最优动作)
行为风格保守、安全激进、追求最优路线
样本行为策略和目标策略一致行为策略 ≠ 目标策略

5. Python 代码示例

import numpy as np
import matplotlib.pyplot as plt

# 字体配置,解决 DejaVu Sans 中文缺失警告
plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False

np.random.seed(42)
alpha = 0.1
gamma = 0.9
epsilon = 0.1
n_states = 5
n_actions = 2

def choose_action(s, Q):
    if np.random.rand() < epsilon:
        return np.random.randint(n_actions)
    else:
        return np.argmax(Q[s])

# Q-Learning
Q_ql = np.zeros((n_states, n_actions))
for ep in range(300):
    s = 0
    while s != 4:
        a = choose_action(s, Q_ql)
        if a == 1 and s < 4:
            s_next = s + 1
            r = 1 if s_next == 4 else 0
        else:
            s_next = s
            r = 0
        # Q-learning:取max Q
        td_target = r + gamma * np.max(Q_ql[s_next])
        Q_ql[s,a] = Q_ql[s,a] + alpha * (td_target - Q_ql[s,a])
        s = s_next

# SARSA
Q_sarsa = np.zeros((n_states, n_actions))
for ep in range(300):
    s = 0
    a = choose_action(s, Q_sarsa)
    while s != 4:
        if a == 1 and s < 4:
            s_next = s + 1
            r = 1 if s_next == 4 else 0
        else:
            s_next = s
            r = 0
        a_next = choose_action(s_next, Q_sarsa)
        # SARSA:用下一个动作的Q
        td_target = r + gamma * Q_sarsa[s_next, a_next]
        Q_sarsa[s,a] = Q_sarsa[s,a] + alpha * (td_target - Q_sarsa[s,a])
        s, a = s_next, a_next

print("Q-learning Q表:")
print(Q_ql)
print("SARSA Q表:")
print(Q_sarsa)

plt.figure(figsize=(9,4))
plt.subplot(1,2,1)
plt.imshow(Q_ql, cmap="coolwarm")
plt.title("Q-learning Q Table")
plt.xlabel("Action")
plt.ylabel("State")

plt.subplot(1,2,2)
plt.imshow(Q_sarsa, cmap="coolwarm")
plt.title("SARSA Q Table")
plt.xlabel("Action")
plt.ylabel("State")
plt.tight_layout()
plt.show()

运行结果:

6. 适用场景

  • Q-learning:路径规划、游戏、想直接学习全局最优策略
  • SARSA:机器人控制、真实环境,风险高,需要规避危险动作

7. 常见误区

  1. SARSA效果一定比Q-learning差:只是策略风格不同,风险高的场景SARSA更合适
  2. 离线策略一定更好:离线策略样本利用更灵活,但学习稳定性会变差
  3. 两者公式几乎一样,没有本质区别:目标策略是否和行为策略一致是核心差异

思考题

  1. On-policy 和 Off-policy 的区别是什么?
  2. 在有悬崖的格子世界(Cliff Walking),SARSA 和 Q-learning 走出的路线会有什么不同?
标签:

0 条笔记