1. 跨越:从“有模型”到“无模型”

在之前的章节中,我们假设自己是“上帝”,完全知道环境的秘密:状态转移概率 $P$ 和奖励函数 $R$。但在现实中(如炒股、下棋),这些参数通常是不可知的。

蒙特卡洛 (Monte Carlo, MC) 方法 的出现,标志着我们进入了 Model-free (无模型) 学习的领域。它的核心思想极度朴素:“实践出真知” —— 如果我不知道概率,那我就多试几次,然后算平均值。


2. 蒙特卡洛估算 (MC Prediction)

2.1 核心思想:大数定律

我们想求 $v_
ps(s) = [G_t | S_t = s]$。
根据大数定律,如果我们能生成很多条从状态 $s$ 出发的轨迹(Episodes),并记录每一条的回报 $G$,那么它们的平均值就会收敛于期望。

$$ v_
ps(s) r rac{1}{N} sum_{i=1}^N G_i
$$

2.2 两种采样方式

  • First-visit MC: 在一个 Episode 中,如果多次经过 $s$,只计算第一次访问后的回报。
  • Every-visit MC: 只要经过 $s$,就计算一次回报。
  • 结论: 两种方法都会收敛,但 First-visit 在数学处理上更简单。

3. 蒙特卡洛控制 (MC Control)

我们不仅想评估策略,还想改进策略。在 Model-free 场景下,我们面临一个尴尬:

如果只有 $v(s)$,即便我知道当前状态值多少钱,我也不知道该做哪个动作,因为我没有 $P$ 矩阵来算下一步去哪。

解决方案: 直接估计 动作价值 $q_
ps(s, a)$

有了每个动作的 Q 值,我就能通过 $max$ 直接改进策略。

3.1 MC Basic 算法

这是最原始的无模型算法逻辑:

  1. 评估: 通过大量采样,算出当前策略 $
    ps$ 的 $Q(s, a)$ 表。
  2. 改进: $
    ps_{new}(s) = max_a Q(s, a)$。
  3. 重复直到收敛。

3.2 探索性初始化 (Exploring Starts)

致命缺陷: 如果我们的 Agent 比较“固执”,它可能永远不去尝试某些动作,导致那些动作的 Q 值永远得不到更新。
Exploring Starts: 强制要求采样时,每一对 $(s, a)$ 都要有一定概率作为起始点。但这在现实中很难(比如自动驾驶,你不能强制让它从“撞墙”动作开始)。


4. 探索与利用 (Exploration vs Exploitation)

为了在不依赖 Exploring Starts 的情况下保持探索,我们引入了著名的 $$-greedy 策略

  • Exploitation (利用): 以 $1-$ 的概率选择当前最优动作(榨取已知信息)。
  • Exploration (探索): 以 $$ 的概率随机选一个动作(寻找潜在可能)。

$$
ps(a|s) = egin{cases} 1 -  + rac{}{||} & ext{if } a = a^* \ rac{}{||} & ext{if } a
e a^*
u}
$$

视频中赵老师强调:$$-greedy 是一种折中,它虽然可能导致我们在已知最优的情况下偶尔“乱走”,但它保证了我们不会错过更好的世界。


5. Python 代码实战:MC 价值估算

在这个例子中,我们不再需要 $P$ 矩阵,而是需要一个可以 env.step() 的环境。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import numpy as np
from collections import defaultdict

def mc_prediction(env, policy, num_episodes, gamma=1.0):
"""
使用 First-visit MC 估计策略的价值函数 V
"""
# 存储每个状态的回报总和与访问次数
returns_sum = defaultdict(float)
returns_count = defaultdict(float)
V = defaultdict(float)

for i in range(num_episodes):
# 1. 生成一个 Episode (s0, a0, r1, s1, a1, r2, ...)
episode = []
state = env.reset()
while True:
action = policy[state]
next_state, reward, done = env.step(action)
episode.append((state, reward))
if done: break
state = next_state

# 2. 计算每个状态的回报 G (反向遍历效率更高)
G = 0
visited_states = set()
for s, r in reversed(episode):
G = r + gamma * G
# First-visit 检查
if s not in visited_states:
returns_sum[s] += G
returns_count[s] += 1
V[s] = returns_sum[s] / returns_count[s]
visited_states.add(s)

return V

6. MC 方法的优缺点 (Bilibili 重点)

  • 优点:
    • 不需要模型: 只要能交互就能学。
    • 局部更新: 如果我只关心某个特定状态的价值,我只需要采样相关的轨迹,不需要像 DP 那样遍历全图。
  • 缺点:
    • 低效: 必须等到 Episode 结束才能更新。
    • 方差大: $G_t$ 受到整条轨迹随机性的累积影响。

预告:
既然 MC 要等到结束才更新,能不能“走一步更新一步”?这就是下一章我们要聊的强化学习最伟大的发明:时序差分 (Temporal Difference, TD)


上一章:第4章 - 值迭代与策略迭代 | 下一章:第6章 - 随机近似 >>