第一次跑强化学习,最容易被劝退的不是算法公式,而是“装库”。我见过太多人把一整天耗在依赖冲突、版本对不上、各种 import 报错上,最后甚至连 PPO 长什么样都没见到。Baselines3 这个库本身并不难装,真正难的是你不太清楚它背后还站着一堆“老朋友”:PyTorch、Gymnasium、Numpy、TensorBoard。这是一篇“从零开始、只讲环境配置实战”的记录,目标是让你照着做,半小时内把 Stable-Baselines3 跑起来,并且后面自己加项目时不会再被环境问题绊倒。
这篇笔记适合两类人:一是刚接触强化学习、想用现成算法跑通一个 Demo 的同学;二是之前用其他框架写过策略梯度、现在想迁移到 SB3 的人。我会把安装顺序、版本避坑、首次验证、常见报错全拆开讲,重点讲“为什么这么做”,而不是只丢给你几条命令。跟着做,你的第一个 CartPole 决策模型就能在十分钟内跑起来。
1. SB3 到底解决了什么问题
Stable-Baselines3(下面简称 SB3)是基于 PyTorch 的一套强化学习算法库。它把常用的强化学习算法做成了统一接口,PPO、A2C、DQN、SAC、TD3、DDPG 这些都直接能用,不用你自己从头实现。对于做实验、跑对比、验证想法的人来说,这简直是省时间的利器。
1.1 算法库的定位:别从轮子开始造车
你可能会想:强化学习算法也不难,自己写一个 PPO 不就行了?确实,网上有大量从零实现 PPO 的教程,代码也就一百多行。但问题在于,那些“教学版” PPO 大多只适合 CartPole,换个环境、换种连续动作、加个 RNN 策略,立刻开始抽风。SB3 的做法是:算法实现对标原始论文和官方基准,并且做了大量工程化处理,比如向量环境、自动学习率、回调系统、模型保存与加载。
用生活类比来说,自己写算法相当于自己种小麦再磨面粉做面包;SB3 相当于买一袋专业面粉,你只需要决定放多少水、烤多少分钟。省下来的时间应该花在“调奖励、改环境、分析训练曲线”这些真正影响结果的事情上。
1.2 环境配置的本质:版本匹配游戏
很多新人不理解,为什么 SB3 已经发布这么多年了,安装还是经常出错。因为 SB3 不是独立运行的软件,它是一个“中间层”——上面接你的策略和训练代码,下面接 PyTorch,旁边依赖 Gymnasium 定义环境接口,还会有 Numpy、TensorBoard、Cloudpickle 等一堆底料。每一个都有自己的版本迭代,SB3 跟它们的兼容关系是“有范围的”,不是“更新越好”。
这才是环境配置问题的核心:不是命令难,而是版本匹配思路不清晰。所以我会先从最上游的 Python 和 PyTorch 说起,再一层层往上装,最后一刻才碰 SB3。这个顺序,恰恰是让你少踩坑的关键。
2. 配置前的准备:先把坑隔离在虚拟环境里
2.1 Python 版本与虚拟环境方案选择
先说结论:Python 3.10 是我测试下来最省心、最少踩坑的版本。PyTorch 和 SB3 对 Python 的适配速度并不完全同步,SB3 官方对较新 Python 的适配往往滞后几个版本。你用 Python 3.12 或 3.13 去装某个老版本 SB3,很可能遇到“没有对应 wheel”或者“编译依赖挂掉”的尴尬。
可能有人会说“我 Python 3.11 跑过没问题”,这我相信,但那是特定版本组合下的结果。对于第一次配置环境的新手,我坚持推荐用一个独立的虚拟环境,并且固定 Python 3.10。虚拟环境是安全隔离的第一道防线,不会把你系统里原来用的 Python 环境搞得乱七八糟,也不会让 base 环境里的包互相污染。
两个常用方案:
- conda(推荐,适合要碰数值计算的人)
- venv(轻量,适合只用 pip 的人)
conda create -n rl python=3.10 -y conda activate rlvenv 对应的做法是:
python3.10 -m venv rl_env source rl_env/bin/activate # Windows 用 rl_env\Scripts\activate选择哪个不重要,关键是养成“一个项目一个环境”的习惯。我自己的做法是:强化学习项目单独建一个rl环境,Web 项目、数据处理项目各用各的。每次新开项目时宁可花五分钟重新建环境,也不想某次升级把之前所有结果的复现环境搞坏。
2.2 PyTorch 底座:先装、装对、装快
SB3 的算力底座是 PyTorch,所以安装顺序一定是:先 PyTorch,后 SB3。如果你反向操作,pip 在解析依赖时可能顺手帮你装一个最新版 PyTorch,然后你发现它跟 SB3 不兼容,或者在你机器上根本跑不起来。先手动装 PyTorch 最大的好处是,你清楚知道这个版本是自己选的,不是 pip 自动猜的。
有 NVIDIA 显卡并准备用 GPU 加速的,先确认驱动可用,再安装带 CUDA 的版本。最简单的方式是直接去 PyTorch 官网用它的安装命令生成器,选好你的系统、CUDA 版本,复制命令执行。这里不贴死版本号,因为 PyTorch 迭代太快,硬编码一个版本再过几个月就失效了。
如果没有独立显卡,或者你跟我一样经常临时在 CPU 机器上调试,那装 CPU 版即可:
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu这里有一个常见误区:CPU 版本不代表“弱版”,它只是没有 CUDA 相关模块。对于 CartPole 这类小环境,CPU 和 GPU 差别根本体现不出来。而且 CPU 版本的安装包更小、依赖更少,不容易出幺蛾子。如果你不确定要不要 GPU,后面再换也来得及,PyTorch 本身就是可重装的。
装完先验证一下:
python -c "import torch; print(torch.__version__); print(torch.cuda.is_available())"能打印出版本号,CUDA 那行显示False也没关系,说明 PyTorch 已经能干活了。如果这里都报错,不要急着往下走,先把这一步解决。PyTorch 没装好,后面所有报错都是疑难杂症,排查起来非常痛苦。
3. 正式安装 Stable-Baselines3 与第一次验证
3.1 安装命令与依赖管理
PyTorch 就位后,SB3 本身是很好装的。官方推荐直接 pip:
pip install stable-baselines3[extra]这里特别说明一下[extra]的作用。基础安装只包含算法和核心依赖,加[extra]会一并装好 TensorBoard、Matplotlib、Seaborn 等辅助工具。TensorBoard 用来记录训练曲线和评估指标,几乎是强化学习训练离不开的东西,建议直接带上。
如果你想安装到/usr/local或者特定路径,可以用pip install --target=...,但新手不建议这么做,会让包的查找路径变得复杂。默认安装到当前环境即可。
安装完成后,用下面命令验证版本:
python -c "import stable_baselines3 as sb3; print(sb3.__version__)"到这里,如果打印出版本号,说明核心库已经装通了。但“能 import”和“能训练”是两码事,真正的问题往往藏在实际跑环境的那一刻。
3.2 跑一个 CartPole 验证整个链路
CartPole 是强化学习里的 “Hello World”:一根杆子立在小车上,通过左右移动小车让杆子保持平衡。这个环境简单、状态维度低、训练快,最适合用来验证环境配置是否完整。
新建一个脚本test_sb3.py,把下面代码放进去:
import gymnasium as gym from stable_baselines3 import PPO env = gym.make("CartPole-v1") model = PPO("MlpPolicy", env, verbose=1) model.learn(total_timesteps=20_000) obs, info = env.reset() for _ in range(1000): action, _ = model.predict(obs, deterministic=True) obs, reward, terminated, truncated, info = env.step(action) if terminated or truncated: obs, info = env.reset()然后执行:
python test_sb3.py正常情况下你会看到 PPO 的训练日志滚动输出,包括time/、rollout/、train/等很多指标,训练结束后模型会在 CartPole 上保持一段时间不倒。
这段代码里值得注意的有两点。第一,环境用的是gymnasium.make,不是gym.make。Gymnasium 是旧版 Gym 的继任者,SB3 2.0 以后默认支持的是 Gymnasium,如果你还用旧版 Gym,很快就会遇到“环境 API 不匹配”的尴尬。第二,terminated和truncated是两回事:前者表示杆子倒了,后者表示步数耗尽或其他中止条件。初学者习惯性只用一个done判断,在 Gymnasium 里这样写样本效率会打折扣。
跑完这一遍,你的 SB3 环境就算真正打通了。接下来我会把配置过程中最容易踩的五个坑逐一拆开说,这些都是我在不同机器上实打实碰过的。
4. 环境配置的五个常见“翻车门”与排查方法
4.1 gym 还是 gymnasium:版本分裂问题
这是新手遇到最多的报错之一:AttributeError: module 'gym' has no attribute 'make',或者ImportError: cannot import name 'Env' from 'gym'。为什么?因为 SB3 2.0 以上版本已经全面转向 Gymnasium,但你的环境里还残留着旧版 Gym,两个包名相似、API 不同,同一个环境名字背后对应的是不同的实现规则。
解决思路就一条:统一使用 Gymnasium,不混用两个库。在你的项目环境里执行:
pip install gymnasium然后在代码里强制使用import gymnasium as gym,千万别图省事直接import gym。如果你之前装过 gym,也建议在同环境里卸载掉,或者干脆新建一个干净环境重来。
提示:如果代码里因为历史项目必须用旧版 Gym,那你也别想着升级 SB3,老老实实用 SB3 1.x 版本,否则 API 会越混越乱。新旧版本不能靠“碰运气”兼容。
4.2 PyTorch / SB3 / Numpy 的版本强匹配
第二个高发问题是版本组合不匹配。SB3 官方对 PyTorch、Numpy 都有版本范围限制。比如某些 SB3 版本在 Numpy 2.x 下会报_ARRAY_API not found这类底层错误,因为 Numpy 2.x 对大数组 ABI 做了调整,老版本编译的扩展就跟不上了。
我自己遇到过的经典组合是:PyTorch 1.13 + 最新版 SB3 + Numpy 2.x,跑起来就报错。解决办法不是硬刚,而是根据 SB3 版本反推依赖。
最稳妥的排查方法,是先看你的 SB3 版本:
pip show stable-baselines3然后去它的官方发布说明里看支持的 PyTorch、Gymnasium、Numpy 版本范围。如果版本范围里写着 Numpy<2.0,那你就在环境里固定:
pip install "numpy<2.0"同样地,PyTorch 和 SB3 的匹配关系也类似。一般来说,SB3 2.x 配 PyTorch 2.x 是稳妥的;SB3 1.x 配 PyTorch 1.13 或老版本更稳。这种“版本强匹配”问题没有统一命令,因为每个小版本都有细微差别,但只要记住一个原则:不盲目追求最新版,只追求兼容版,就能避开大部分麻烦。
4.3 Windows 上的 DLL 与 C++ 运行库问题
Windows 用户容易遇到一个很邪门的报错:OSError: [WinError 126] 找不到指定的模块,或者加载某个.dll文件失败。这种情况大多不是 SB3 的问题,而是 PyTorch 或 Numpy 的二进制包依赖了微软的 C++ 运行库,你的机器上没有对应的运行库。
解决方法很直接:安装微软提供的 “Visual C++ Redistributable” 最新版本,装完重启终端即可。如果你装了很多工具都遇到类似的 DLL 问题,那基本就是缺少这个运行库。
另外,Windows 和 Linux 在路径处理上也有差异。训练时如果用了绝对路径,注意 Windows 的反斜杠需要转义,或者统一用正斜杠。模型保存路径、TensorBoard 日志路径、向量环境缓存路径,这几个地方我都踩过路径解析的坑。
4.4 无 GPU / 苹果 M 系列芯片下的 CPU 模式
很多人的电脑没有独立显卡,或者用的是苹果 M 系列芯片。PyTorch 在 M 系列芯片上能自动用上 MPS 加速,但 SB3 对 MPS 的支持并不完美,某些算子会报NotImplementedError。在这种情况下,我建议直接指定 CPU 设备,省心且稳定。
在 SB3 里,模型初始化时支持通过device参数指定设备:
model = PPO("MlpPolicy", env, device="cpu", verbose=1)这样即便你机器上有 GPU,也只是显式用 CPU 跑。对于 CartPole、LunarLander 这类小环境,CPU 跑得已经够快,完全没必要因为“看别人用 GPU”而焦虑。等到你真正需要训练大规模连续控制任务、且能明显感受到 CPU 扛不住时,再考虑 GPU 也不迟。
4.5 一套速查表:现象、原因、解法
| 常见现象 | 大概率原因 | 解决思路 |
|---|---|---|
module 'gym' has no attribute 'make' | gym 与 gymnasium 混用 | 统一用 gymnasium,不import gym |
_ARRAY_API not found | Numpy 2.x 与低版本 SB3 不兼容 | 固定numpy<2.0或升级 SB3 |
加载.dll/.so失败 | 缺少 C++ 运行库 | 安装 Visual C++ Redistributable |
MPS 算子报NotImplementedError | M 系列芯片 GPU 兼容问题 | 模型初始化指定device="cpu" |
训练时env没有reset返回元组 | Gymnasium 新 API 变化 | 使用obs, info = env.reset() |
check_env提示 observation 类型不对 | 自定义环境状态空间定义错误 | 改用Box/Discrete/Dict正确声明 |
这张表是我自己排查时的惯性思路,也基本覆盖了 SB3 初次配置的大多数报错。遇到问题时先对照这个表,能省下大量 Google 时间。
5. 从“能跑”到“能训练”:第一次完整 RL 示例
很多教程跑完 CartPole 就结束了,但实际项目不是跑一个 Demo 这么简单。你需要知道怎么保存最优模型、怎么评估策略、怎么在训练过程中记录日志。这一节我会给出一套可以直接套用的模板。
5.1 一个带回调的完整训练脚本
先看这段代码,它在原有 Demo 基础上加了两个回调:CheckpointCallback定期保存模型快照,EvalCallback定期用独立环境评估当前策略,并保存表现最好的模型。
import gymnasium as gym from stable_baselines3 import PPO from stable_baselines3.common.callbacks import ( CheckpointCallback, EvalCallback, ) from stable_baselines3.common.env_util import make_vec_env train_env = make_vec_env("CartPole-v1", n_envs=4, seed=0) eval_env = make_vec_env("CartPole-v1", n_envs=1, seed=0) model = PPO( "MlpPolicy", train_env, verbose=1, tensorboard_log="./tb_logs/", ) checkpoint_callback = CheckpointCallback( save_freq=5000, save_path="./checkpoints/", name_prefix="ppo_cartpole", ) eval_callback = EvalCallback( eval_env, best_model_save_path="./best_model/", log_path="./eval_logs/", eval_freq=2000, n_eval_episodes=5, deterministic=True, ) model.learn( total_timesteps=100_000, callback=[checkpoint_callback, eval_callback], ) model.save("./ppo_cartpole_final")这里有几个细节值得展开说。
make_vec_env("CartPole-v1", n_envs=4)的意思是同时跑 4 个 CartPole 环境,并行采集训练数据。SB3 的核心优势之一是向量环境支持,它可以把多个环境包装成一组,让样本采集效率大幅提升。对 CartPole 来说 4 个并行环境有点大材小用,但对 LunarLander、HalfCheetah 这类复杂环境,并行数量直接影响训练速度。
EvalCallback里设置deterministic=True也很重要。评估策略时我们通常希望用“确定性策略”,也就是每次面对同一个状态都选同一个最优动作,这样可以稳定评估策略的真实水平。如果你用随机策略去评估,同一个模型每次得分可能差很大,就分不清模型到底进步没有。
tensorboard_log是另一个容易被忽略的点。训练过程中示教级的verbose=1会在终端打印表格,但数据量一大你根本看不过来。有了 TensorBoard,你只需要在训练结束后运行:
tensorboard --logdir ./tb_logs/然后打开浏览器地址,就能看到奖励曲线、损失曲线、学习率变化等关键指标。强烈建议一上来就习惯这种方式,而不是靠肉眼盯终端输出。
5.2 自定义环境:上手前先学会验证
训练到一定程度你就想跑自己的环境,比如某个机器人仿真环境、某个业务流程模拟环境,这时最重要的一件事不是直接开训,而是先用官方提供的check_env验证环境定义是否合法。
from stable_baselines3.common.env_checker import check_env import gymnasium as gym env = gym.make("CartPole-v1") check_env(env)如果环境没问题,它会安静地返回;如果状态空间或动作空间定义有误,它会报出具体问题和修复建议。我在自定义环境上最常遇到的坑是:观察空间用Box定义了,但实际reset()返回的数据类型不对,比如返回了 Python list 而不是 Numpy 数组;或者动作空间声明的范围跟step()里实际执行的逻辑不一致。这些错误在训练早期不会立刻暴露,往往要等几千步之后才突然崩,那时候再排查成本就高了。所以每次写完自定义环境,都先跑一遍check_env,这是必须养成的职业习惯。
5.3 算法选型的第一次取舍
如果你用的是 SB3,第一次练手与其纠结算法,不如先记住一个简单原则:表格型环境优先 DQN,连续控制直接上 PPO,连续控制且样本效率要求极高就用 SAC。
为什么不是“哪个算法最先进就选哪个”?因为先进算法往往对超参数更敏感。DQN 在 CartPole 上跑得很欢,但它本质上是强化学习里的“老前辈”,模型容量有限;PPO 是当前实践中最通用的策略优化算法,对超参数相对鲁棒,适合跑通全流程;SAC 这类基于最大熵的方法,在连续动作任务上效果确实好,但需要调很多参数,不适合作为第一次练手。
我在实际项目中常用的一个策略是:先用 PPO 跑通流程,拿到一条稳定可复现的训练曲线,再根据任务类型切换到 DQN 或 SAC。这样可以避免算法问题、环境问题、依赖问题混在一起,到时候想排查都不知道从哪里下手。
写在最后
我始终觉得,强化学习环境配置最需要建立的意识不是“背命令”,而是“知道什么该先装、什么该后装,以及报错时往哪个方向查”。在我自己的项目里,我会把 Python 版本三级头固定死,先装 PyTorch,再装 SB3,任何一次升级都是小步慢走,绝不一把梭。后来帮别人排查环境问题时,发现十次里有八次都是版本组合混乱导致的。
如果你看完这篇还是担心自己环境会有其他问题,那就先按文章里的步骤完整跑一遍 CartPole。能跑通,说明你的机器、Python 环境、PyTorch、SB3 这条链路是通的,后面再上任何自定义环境,心智负担都会小很多。第一次配置就成功,比什么都重要。