- 教程
- 人工智能
- 机器学习
- 深度学习
【免费下载链接】AI-For-Beginners
12 Weeks, 24 Lessons, AI for All!
深度强化学习(Deep Reinforcement Learning)是 AI for Beginners 课程中"其他 AI 主题"部分的进阶实战章节。本文以 22-DeepRL 课程文档 为核心骨架,结合仓库内 TensorFlow 版 与 PyTorch 版 两个可运行 Notebook 以及 Mountain Car 实验,系统讲解如何用 OpenAI Gym 模拟环境、用神经网络表达策略,并完整落地策略梯度(Policy Gradients)与演员-评论家(Actor-Critic)两种经典 RL 算法。学完本文,你将能够:独立读懂并运行 CartPole 平衡训练代码,理解累计奖励与折扣因子 γ 的作用,掌握演员-评论家双网络结构及其损失函数设计,并把同一套算法迁移到 MountainCar 等新环境中。
一、从"边做边学"理解强化学习的基本范式
在 课程文档 中,强化学习被定位为与监督学习、无监督学习并列的三大机器学习范式之一。监督学习依赖"已知结果"的数据集,而 RL 的核心是learning by doing(通过行动学习):就像第一次见到一款电脑游戏时,我们尚不知道规则就开始试玩,仅仅通过"玩"并不断调整行为,很快就能提升水平。
要执行 RL,必须准备两样东西:
- 环境(Environment)或模拟器(Simulator):定义游戏规则,我们可以在其中反复进行试验并观察结果;
- 奖励函数(Reward Function):指示试验的"成功程度"。例如学习打游戏时,奖励就是最终得分。
RL 与其他机器学习的关键差异在于:在游戏结束之前,我们通常不知道会赢还是会输。因此无法单独判断"某一步走得好不好",只有在整局结束时才收到奖励信号。这带来了 RL 最核心的权衡——在每个试验回合中,既要遵循已经学到的"最优策略"去利用(exploitation),又要探索未知的新状态(exploration)。
二、OpenAI Gym:统一的模拟环境接口
课程推荐的开箱即用工具是OpenAI Gym——一个能够模拟从 Atari 游戏到"杆平衡物理"等多种场景的仿真环境,也是训练强化学习算法最流行的模拟环境之一。
从仓库根目录的 requirements.txt 可以看到,本课程环境锁定了gym==0.26.2、pygame==2.6.0,并配套tensorflow==2.17.0、torchinfo、numpy等依赖,说明 Gym 是整套课程(尤其本课)的标准实验基座。安装后,任意环境都可以用完全相同的接口来操作。
三、CartPole 平衡问题与第一个交互程序
你可能见过 Segway 或陀螺仪这类现代平衡设备:它们根据加速度计/陀螺仪信号调整轮子来自动保持平衡。本课要解决的是类似的"一维杆平衡"问题——就像杂技演员在手上立杆,但只在一个维度上发生。
简化版被称为CartPole 问题:水平滑轨上有一个可左右移动的小车,目标是让竖直立在车上的杆在小车移动过程中保持不倒。环境的交互模型如下(图片来自 课程图片目录):
创建并使用这个环境只需几行 Python 代码(与 课程 README 一致):
import gym env = gym.make("CartPole-v1") env.reset() done = False total_reward = 0 while not done: env.render() action = env.action_space.sample() observaton, reward, done, info = env.step(action) total_reward += reward print(f"Total reward: {total_reward}")其中两个方法构成所有 Gym 环境的通用操作协议:
env.reset():开启一次新的试验;env.step(action):执行一个仿真步。它接收来自动作空间(action space)的一个动作,返回来自观测空间(observation space)的观测(observation),以及奖励 reward 和终止标志 done。
上面的示例每一步都随机采样动作(env.action_space.sample()),因此试验寿命非常短:
在 TensorFlow Notebook 中,程序实际打印出了环境结构:
Action space: Discrete(2) Observation space: Box([-4.8 ... -3.4e38 ...], [4.8 ... 3.4e38 ...], (4,), float32)结合 Notebook 的说明可以确认 CartPole-v1 的接口细节:
- 动作空间
Discrete(2):只有 2 个离散动作(向左推 / 向右推); - 观测空间
Box(4,):4 个连续数值,依次是——小车位置(Position of cart)、小车速度(Velocity of cart)、杆的角度(Angle of pole)、杆的旋转速率(Rotation rate of pole); - 奖励:每存活一个仿真步就获得 1 分,因此最大化总奖励等价于让 CartPole 尽可能久地保持平衡。
RL 算法的目标就是训练一个模型——所谓的策略(policy)π——给定状态返回应执行的动作。策略也可以看作是概率性的:对任意状态s和动作a,它返回在状态s下应采取动作a的概率 π(a|s)。
四、策略梯度算法:用分类网络逼近策略
策略最直观的建模方式是用一个神经网络:输入状态,输出相应动作(或所有动作的概率分布)。从形式上看这与普通分类问题相似,但关键区别是——我们事先并不知道每一步应该采取哪个动作,这正是 RL 特有的"信用分配"难题。
课程给出的解决思路是"估计这些概率"。在 TensorFlow Notebook 中,网络定义非常精简:
import numpy as np import tensorflow as tf from tensorflow import keras num_inputs = 4 num_actions = 2 model = keras.Sequential([ keras.layers.Dense(128, activation="relu", input_shape=(num_inputs,)), keras.layers.Dense(num_actions, activation="softmax") ]) model.compile(loss='categorical_crossentropy', optimizer=keras.optimizers.Adam(learning_rate=0.01))输入维度 4 对应观测空间的 4 个物理量,输出层用 softmax 给出 2 个动作的概率,隐藏层 128 个神经元。PyTorch 版本(见 CartPole-RL-PyTorch.ipynb)结构完全等价:
model = torch.nn.Sequential( torch.nn.Linear(num_inputs, 128, bias=False), torch.nn.ReLU(), torch.nn.Linear(128, num_actions, bias=False), torch.nn.Softmax(dim=1) )训练过程的核心是一个"跑试验并收集轨迹(trace)"的函数,记录每一步的状态、动作、模型推荐的概率和奖励(源码见 Notebook):
def run_episode(max_steps_per_episode = 10000, render=False): states, actions, probs, rewards = [],[],[],[] state = env.reset() for _ in range(max_steps_per_episode): if render: env.render() action_probs = model(np.expand_dims(state,0))[0] action = np.random.choice(num_actions, p=np.squeeze(action_probs)) nstate, reward, done, info = env.step(action) if done: break states.append(state) actions.append(action) probs.append(action_probs) rewards.append(reward) state = nstate return np.vstack(states), np.vstack(actions), np.vstack(probs), np.vstack(rewards)注意动作是按模型输出的概率分布随机采样(np.random.choice)的——这正是"探索与利用平衡"的代码体现。
4.1 折扣奖励(Discounted Rewards):策略梯度的关键技巧
策略梯度算法最微妙的部分是折扣奖励。思路是:计算试验每一步的累计奖励向量,同时用系数 γ=0.99 对较早的奖励打折扣,以削弱早期奖励的权重;再对结果做归一化,因为后面要把它当作训练权重使用。课程 Notebook 给出了完整实现:
eps = 0.0001 def discounted_rewards(rewards, gamma=0.99, normalize=True): ret = [] s = 0 for r in rewards[::-1]: s = r + gamma * s ret.insert(0, s) if normalize: ret = (ret-np.mean(ret))/(np.std(ret)+eps) return ret4.2 训练循环:用折扣奖励强化高回报步
课程 训练循环代码 每轮做五件事:
- 运行试验并收集轨迹;
- 计算实际采取动作的 one-hot 编码与预测概率之差(
gradients),差值越小说明越确定当初动作正确; - 用折扣奖励乘以梯度——使高奖励步对最终结果的影响大于低奖励步;
- 用
alpha参数(相当于 RL 算法的学习率)把预测概率与梯度融合成"期望目标动作"; - 用状态和期望目标动作训练网络,循环往复。
对应代码:
alpha = 1e-4 history = [] for epoch in range(300): states, actions, probs, rewards = run_episode() one_hot_actions = np.eye(2)[actions.T][0] gradients = one_hot_actions - probs dr = discounted_rewards(rewards) gradients *= dr target = alpha*np.vstack([gradients]) + probs model.train_on_batch(states, target) history.append(np.sum(rewards))Notebook 中记录的训练过程显示,随机策略下回合总奖励仅 27~34,而 300 轮训练后单回合奖励可以增长到 400 以上(达到 CartPole 环境的单回合上限附近),说明策略已学会长期保持平衡。
五、演员-评论家算法:策略与价值估计双头网络
策略梯度的改进版是Actor-Critic(演员-评论家)。核心思想是让神经网络同时输出两样东西:
- 演员(Actor):输出策略,决定采取哪个动作;
- 评论家(Critic):输出对当前状态未来总奖励的估计值。
从架构上看,这有点像 GAN 课程 中的双网络互相对抗,但我们的目标是让两个网络协同训练:演员提出该做的动作,评论家对其结果进行批评式评估。
TensorFlow 版本把两个输出头挂在一个共享隐藏层上(源码):
num_hidden = 128 inputs = keras.layers.Input(shape=(num_inputs,)) common = keras.layers.Dense(num_hidden, activation="relu")(inputs) action = keras.layers.Dense(num_actions, activation="softmax")(common) critic = keras.layers.Dense(1)(common) model = keras.Model(inputs=inputs, outputs=[action, critic])由于我们既知道真实的累计奖励、又知道评论家返回的估计值,可以很自然地构造一个最小化两者差异的损失函数——这就是critic loss;而actor loss沿用策略梯度的同一套思路计算。Notebook 中的手动训练循环完整展示了这一机制:
optimizer = keras.optimizers.Adam(learning_rate=0.01) huber_loss = keras.losses.Huber() while True: # 一直训练直到解决 state = env.reset() with tf.GradientTape() as tape: _, _, action_probs, rewards, critic_values = run_episode() episode_reward = np.sum(rewards) running_reward = 0.05 * episode_reward + (1 - 0.05) * running_reward dr = discounted_rewards(rewards) # 评论家的训练标签 actor_losses = [] critic_losses = [] for log_prob, value, rew in zip(action_probs, critic_values, dr): # actor 损失:鼓励演员选择带来更高奖励的动作 diff = rew - value actor_losses.append(-log_prob * diff) # critic 损失:缩小预测值与实际折扣奖励的差距 critic_losses.append(huber_loss(tf.expand_dims(value, 0), tf.expand_dims(rew, 0))) loss_value = sum(actor_losses) + sum(critic_losses) grads = tape.gradient(loss_value, model.trainable_variables) optimizer.apply_gradients(zip(grads, model.trainable_variables)) if running_reward > 195: # 判定任务已解决 print("Solved at episode {}!".format(episode_count)) breakdiff = rew - value正是"优势(advantage)":评论家高估的动作会被压制,低估的动作会被强化。Notebook 输出显示,仅约 114 个回合后 running reward 便突破 195,判定"Solved"。
PyTorch 版本则将 Actor 与 Critic 写成两个独立模块(源码):Actor 用三层线性网络(128→256→2)输出 Categorical 分布,Critic 用同样宽度(128→256→1)输出标量价值;训练时用returns - values计算 advantage,分别对-(log_probs * advantage)与advantage.pow(2)求均值作为 actor/critic 损失。这套写法更贴近工业界 A2C 的标准实现。
训练完成后,CartPole 的表现如课程动画所示——杆可以长时间稳定不倒:
六、动手实验:把同一套算法迁移到 Mountain Car
课程在 实验说明 中布置了一项任务:训练另一个 Gym 环境Mountain Car。该环境里,小车被困在山谷中,目标是借助惯性与动力冲出山谷抵达旗子;可执行的动作是"向左加速 / 向右加速 / 不动"三种,可观测的状态是车沿 x 轴的位置与速度。
实验从 MountainCar.ipynb 开始,Notebook 已帮你创建环境并演示随机试验:
import gym env = gym.make('MountainCar-v0') state = env.reset() while True: env.render() action = env.action_space.sample() state, reward, done, info = env.step(action) if done: break环境示意图如下(图片路径):
接下来留给你自己完成:把本课的策略梯度与演员-评论家算法改写到该问题上。课程明确提示了本次实验的关键收获——把 RL 算法迁移到新环境通常非常直接,因为 OpenAI Gym 对所有环境提供同一接口,算法本身也基本不依赖环境的具体性质;你甚至可以重构 Python 代码,把任意环境作为参数传给同一个 RL 算法函数。
七、RL 的更多应用方向与进一步学习
课程还列举了强化学习当前快速发展的几个代表性应用:
- 教计算机玩 Atari 游戏:难点在于状态不再是向量,而是一张屏幕截图,需要用 CNN 把图像转成特征向量或从中提取奖励信息;Atari 游戏已内置在 Gym 中;
- 教计算机下棋类游戏(如国际象棋、围棋):Alpha Zero 这类程序从零开始训练,两个智能体对弈并在每一步自我改进;
- 工业界控制系统:用 RL 从仿真中构建控制系统,例如微软的 Bonsai 服务专为此设计。
从仓库整体看,本课属于 6-Other 目录 下与遗传算法、多智能体系统并列的专题,前面的计算机视觉(CNN)知识正是处理 Atari 屏幕输入的铺垫。
八、小结与挑战
至此我们完成了两件事:一是理解如何仅凭一个定义"游戏期望状态"的奖励函数、加上对搜索空间的智能探索,就能训练出表现良好的智能体;二是亲手跑通了策略梯度与演员-评论家两种算法,并在较短时间内(TensorFlow 版约 300 回合、Actor-Critic 约 114 回合)取得了优秀成绩。两个 Notebook 在结尾的共同结论值得记住:RL 算法只依赖状态、动作、奖励这些抽象概念,因此可以应用于截然不同的环境;而且它不需要带标签的数据集,可以无限次重放仿真来优化模型。
课程的挑战任务建议:从"更多 RL 应用"一节中选择一个方向(如 Atari、Alpha Zero 思路的自我对弈,或 Mountain Car 迁移实验)动手实现。这将是理解探索-利用权衡、折扣因子选择与优势估计等 RL 核心机制的最好方式。
参考资源(仓库内路径)
- 课程正文:lessons/6-Other/22-DeepRL/README.md
- TensorFlow 实操 Notebook:lessons/6-Other/22-DeepRL/CartPole-RL-TF.ipynb
- PyTorch 实操 Notebook:lessons/6-Other/22-DeepRL/CartPole-RL-PyTorch.ipynb
- Mountain Car 实验:lessons/6-Other/22-DeepRL/lab/README.md 与 MountainCar.ipynb
- 依赖清单(gym 0.26.2 / tensorflow 2.17.0 / pygame 2.6.0):requirements.txt
- 教程
- 人工智能
- 机器学习
- 深度学习
【免费下载链接】AI-For-Beginners
12 Weeks, 24 Lessons, AI for All!
相关推荐
AI for Beginners 深度强化学习实战指南:用 OpenAI Gym 训练 CartPole 平衡策略
AI for Beginners 深度强化学习实战指南:用 OpenAI Gym 训练 CartPole 平衡策略 本文以 AI for Beginners 课
教程人工智能机器学习深度学习AI for Beginners 深度强化学习实战:用 OpenAI Gym 从零训练 CartPole 平衡策略
AI for Beginners 深度强化学习实战:用 OpenAI Gym 从零训练 CartPole 平衡策略 导读 本文是 AI for Beginner
教程人工智能机器学习深度学习深度强化学习实战:在 OpenAI Gym 中训练 CartPole 与 Actor-Critic 算法(AI for Beginners)
深度强化学习实战:在 OpenAI Gym 中训练 CartPole 与 Actor Critic 算法(AI for Beginners) 本文基于 AI f
教程人工智能机器学习深度学习
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考