1. 为什么要直接优化策略?
Value-based 方法(如 DQN)虽然强大,但有局限:
- 无法处理连续动作:如果动作是“方向盘转动角度(0度到360度)”,Q-learning 需要求,这在连续空间是很难的。
- 无法学习随机策略:Value-based 最终给出的通常是确定性策略(选 Q 最大的)。但在石头剪刀布游戏中,最好的策略是随机的。
Policy Gradient (PG) 方法直接对策略进行参数化(比如用神经网络),然后通过调整来最大化期望回报。
2. 策略梯度定理 (Policy Gradient Theorem)
我们想最大化目标函数。
我们需要求梯度来进行梯度上升(Gradient Ascent)。
神奇的 Policy Gradient Theorem 告诉我们:
$$
利用 Log-Derivative Trick (),可以写成期望形式:
$$
直观解释:
- :告诉我们如何调整参数能让动作的概率变大。
- :这个动作好不好?
- 乘起来:如果动作好(Q大),就多增加它的概率;如果不好(Q小),就少增加甚至减少(如果 Q 是负的)。
3. REINFORCE 算法
REINFORCE 是最基础的 PG 算法。它使用 Monte Carlo 方法来估计,即直接用实际回报代替。
更新公式:
$$
3.1 缺点
由于是单次采样的回报,方差极大。这导致 REINFORCE 训练非常不稳定。
改进:引入 Baseline,减去一个基线(通常是),变成,这不改变期望但能显著降低方差。
4. PyTorch 代码实战:REINFORCE
我们用 PyTorch 实现一个简单的 REINFORCE 来玩 CartPole。
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| import torch import torch.nn as nn import torch.optim as optim from torch.distributions import Categorical
class PolicyNetwork(nn.Module): def __init__(self, state_dim, action_dim): super(PolicyNetwork, self).__init__() self.fc = nn.Sequential( nn.Linear(state_dim, 128), nn.ReLU(), nn.Linear(128, action_dim), nn.Softmax(dim=-1) ) def forward(self, x): return self.fc(x)
class REINFORCE: def __init__(self, state_dim, action_dim): self.policy = PolicyNetwork(state_dim, action_dim) self.optimizer = optim.Adam(self.policy.parameters(), lr=1e-3) self.gamma = 0.99 self.log_probs = [] self.rewards = [] def select_action(self, state): state = torch.from_numpy(state).float().unsqueeze(0) probs = self.policy(state) m = Categorical(probs) action = m.sample() self.log_probs.append(m.log_prob(action)) return action.item() def update(self): R = 0 policy_loss = [] returns = [] for r in self.rewards[::-1]: R = r + self.gamma * R returns.insert(0, R) returns = torch.tensor(returns) returns = (returns - returns.mean()) / (returns.std() + 1e-9) for log_prob, R in zip(self.log_probs, returns): policy_loss.append(-log_prob * R) self.optimizer.zero_grad() policy_loss = torch.cat(policy_loss).sum() policy_loss.backward() self.optimizer.step() self.log_probs = [] self.rewards = []
|
5. 总结
本章我们解锁了 Policy-based 方法。
- Policy Gradient Theorem 是核心基石。
- REINFORCE 是最简单的实现,虽然方差大,但它展示了 PG 的基本逻辑。
REINFORCE 的方差问题如何彻底解决?
答案是结合 Value-based 和 Policy-based 的优点,这就引出了下一章的终极形态:Actor-Critic 方法。
上一章:第8章 - 值函数近似 | 下一章:第10章 - Actor-Critic 方法 >>