A2C & A3C
Advantage Actor-Critic: 并行计算让强化学习飞起来。
Actor-Critic 架构
纯策略梯度(如 REINFORCE)方差大,纯值函数方法(如 DQN)难以处理连续动作。Actor-Critic 结合了两者的优点。
Actor (策略网络)
负责选择动作。通过梯度上升优化 $\pi_\theta(a|s)$,使其选择高价值动作的概率变大。
Critic (价值网络)
负责评估动作的好坏。通过最小化 TD Error 来优化 $V(s)$ 或 $Q(s,a)$。
为什么要用“优势” (Advantage)?
如果我们只看回报 $R$,很难判断一个动作好不好,因为 $R$ 很大可能是因为状态本身就好,而不是动作好。 我们需要一个基线(Baseline)来比较。通常用状态价值 $V(s)$ 作为基线。
这就是 **优势函数**。如果 $A > 0$,说明该动作比平均水平好;反之则差。引入优势函数能显著降低方差。
并行训练:A3C 与 A2C
传统的强化学习是单进程的,效率低且样本相关性强。 **A3C (Asynchronous Advantage Actor-Critic)** 引入了多进程异步更新。
A3C (异步)
每个 Worker 独立与环境交互,计算梯度,然后异步地推送到全局网络。就像多个程序员向同一个 Git 仓库提交代码,不需要等别人。
A2C (同步)
OpenAI 后来发现,同步更新(等待所有 Worker 跑完一步,汇总梯度再更新)通常更有效且利用 GPU 效率更高。这就是 A2C (Advantage Actor-Critic)。
import ray import time # 定义一个并行 Worker @ray.remote def worker_task(worker_id): print(f"Worker {worker_id} starting...") time.sleep(1) # 模拟环境交互 return f"Worker {worker_id} done" # 启动 Ray ray.init() # 并行启动 4 个任务 futures = [worker_task.remote(i) for i in range(4)] # 等待所有任务完成 (同步) results = ray.get(futures) print(results)
广义优势估计 (GAE)
如何估计优势 $A_t$?
• MC 估计 ($A_t = G_t - V_t$):无偏,但方差大。
• TD 估计 ($A_t = r + \gamma V_{t+1} - V_t$):方差小,但有偏差。
GAE (Generalized Advantage Estimation) 通过引入 $\lambda$ 参数,在两者之间取得平衡。
其中 $\delta_t = r_t + \gamma V(s_{t+1}) - V(s_t)$ 是 TD Error。 $\lambda=1$ 时退化为 MC,$\lambda=0$ 时退化为 TD。通常取 $\lambda=0.95$。
def compute_gae(rewards, values, dones, gamma=0.99, lam=0.95): T = len(rewards) advantages = torch.zeros(T) last_adv = 0.0 for t in reversed(range(T)): if dones[t]: next_val = 0.0 last_adv = 0.0 # 终止状态优势重置 else: next_val = values[t + 1] # TD Error delta = rewards[t] + gamma * next_val - values[t] # GAE 递推: A_t = delta_t + gamma * lambda * A_{t+1} advantages[t] = delta + gamma * lam * last_adv last_adv = advantages[t] return advantages
常见问题与思考
2. 优势函数:用相对值代替绝对回报,评估更准确。
3. 并行训练 (A3C/A2C):极大地提高了数据收集速度和样本多样性。