
这次不是在云端 GPU 上跑通强化学习而是把 MicroDuck 的 RL 训练流程搬到了英伟达 ThorNVIDIA Thor / Jetson AGX Thor上。MicroDuck 是 Hugging Face 上非常有名的入门级开源强化学习项目核心目标是让一只仿真 Duckiebot 小车在 Duckietown 城市环境中通过 PPO 算法学会自主导航。它的训练成本被压得非常低属于“几分钟跑一轮、网页上看曲线、模型传到 Hub”的轻量级 RL 例子也因此成为很多人入门具身智能和深度强化学习的第一站。这篇文章会围绕“在英伟达 Thor 上实现 MicroDuck 强化学习”这一主线展开。先看这个项目解决什么问题再梳理核心能力、硬件门槛和使用边界然后给出一套可落地的部署流程环境准备、容器启动、训练脚本、效果验证、模型上传最后补充资源占用观察、常见问题和批量调参建议。虽然示例以 MicroDuck 为主但整套思路对其它 SB3 / Gymnasium 类强化学习项目同样适用。1. MicroDuck 核心能力速览能力项说明项目定位Hugging Face 上用于入门深度强化学习RL的微型自动驾驶训练示例技术栈Stable-Baselines3、PPO 算法、Duckietown 仿真环境、Hugging Face Hub核心功能在仿真城市环境中训练 Duckiebot 自主导航训练完成后可保存并上传模型运行平台CPU 可训练GPU 可加速英伟达 Thor / Jetson 平台属于典型端侧部署环境显存需求轻量级训练场景具体显存占用需按模型版本、分辨率、批大小实测启动方式命令行启动训练脚本可选 TensorBoard 观察训练曲线是否支持 API项目本身以训练为主不提供标准 HTTP API训练产物可用于后续推理接口封装是否支持批量任务支持通过脚本循环执行超参数扫描、批量训练和模型版本管理学习成本低适合首次接触 PPO 和具身智能的开发者需要强调一点MicroDuck 的“轻”是它最大的优势。训练环境是低分辨率图像仿真策略网络也是图像输入的小规模 CNN不需要像大语言模型那样依赖大规模 GPU 集群。从项目资源需求来看它完全适合在边缘计算设备上做端侧训练和验证这也是它能在英伟达 Thor 上跑通的价值点不需要数据中心 GPU一块嵌入式 AI 计算平台就能完成整个 RL 实验闭环。2. 适用场景与使用边界MicroDuck 适合四类人。第一类是刚开始学强化学习的开发者想摆脱 CartPole 这类玩具环境但能力还没到训练真实机械臂的程度Duckietown 仿真刚好在两者之间。第二类是具身智能方向的科研工程人员需要一个可复现、可二次开发的基础导航策略Proto 训练之后再迁移到真实小车。第三类是关注端侧落地的工程师想在英伟达 Thor 这类设备上验证“训练能不能跑、跑得稳不稳、推理性能够不够”。第四类是课程学习者Hugging Face 的 Deep RL 课程里就有基于 MicroDuck 的实践作业本地跑通意味着课程练习能完成闭环。它不能解决什么问题也要说清楚。MicroDuck 解决的是“仿真环境下小型移动体的导航决策”不是高保真工业级自动驾驶方案也不是机械臂操作任务。Duckietown 仿真环境对真实物理世界的模拟有限训练出来的策略直接部署到现实机器人之前必须做域随机化、sim-to-real 迁移测试不能默认“仿真里能跑真车就一定也能跑”。合规性同样需要注意。MicroDuck 本身是开放源码、开放模型权重用于学习和技术验证没有问题但要注意三点一是如果要在商用产品中使用需要核对 Hugging Face 仓库的 License 和 Duckietown 相关依赖的授权条款二是如果后续加入真实环境数据、真实车辆信息或人脸行人图像必须做好数据脱敏和隐私保护三是涉及真实机器人部署时要确保在安全隔离环境测试避免造成人员或财产损失。3. 环境准备与前置条件在英伟达 Thor 上部署 MicroDuck本质上是在 ARM L4T 的嵌入式平台上搭建一套 Python 强化学习环境。由于 Thor 是 NVIDIA 自家的机器人计算平台最常见的运行方式是通过官方 L4T 容器进入开发环境这样能避免自己手动编译 PyTorch、CUDA 依赖的兼容性问题。从通用准备角度建议先确认以下检查项操作系统与驱动Thor 设备已刷好 JetPack / L4T 系统系统自带 NVIDIA GPU 驱动可正常工作。容器或 Python 环境推荐使用 NVIDIA L4T PyTorch 官方容器容器内已经预装 PyTorch、CUDA 相关依赖。Python 版本建议 Python 3.8 或更高版本MicroDuck 依赖的 Stable-Baselines3、Gymnasium 都能在这个范围内运行。磁盘空间至少预留 10GB 左右空间包含 PyTorch 容器、项目代码、依赖包和训练日志如果还要保存多个模型权重再多留 5GB 以上。网络连接需要访问 GitHub、Hugging Face Hub 或镜像站点来拉取代码和模型。端口可用如果使用 TensorBoard 或 Jupyter需要确认 6006、8888 这类端口没有被占用。进入容器后第一件事是验证 PyTorch 是否能识别 GPU 设备。下面的命令在任何 L4T 容器里都能使用python -c import torch; print(torch.__version__, torch.cuda.is_available())如果输出True说明 GPU 设备可达如果输出False不要急着装 MicroDuck先检查容器是否启用 GPU 访问、驱动版本和 PyTorch 编译版本否则后续训练会退化成 CPU 模式性能差异会非常大。还需要确认 Hugging Face Hub 的访问方式。国内访问 Hugging Face 有时不稳定更稳妥的办法是通过环境变量指定镜像站点。下面这段配置适用于从 Hub 下载模型、数据集和上传训练结果export HF_ENDPOINThttps://hf-mirror.com把这一行写入容器的~/.bashrc或~/.profile后续huggingface_hub的下载、上传请求都会走镜像地址能在很大程度上避免模型下载超时、连接失败的问题。如果你的网络访问 Hub 本身没问题也可以不设置镜像。4. 在英伟达 Thor 上部署启动 MicroDuck既然是在 Thor 上部署最稳妥的路径不是直接在系统层用 pip 装一堆包而是先进入官方 L4T PyTorch 容器再在容器里创建独立训练环境。这样可以避免污染系统 Python也方便随时删除重建。先启动 L4T PyTorch 容器将 MicroDuck 项目目录挂载到容器内docker run --runtime nvidia -it --rm \ -e HF_ENDPOINThttps://hf-mirror.com \ -v $(pwd)/microduck:/workspace/microduck \ nvcr.io/nvidia/l4t-pytorch:latest \ /bin/bash说明一下$(pwd)/microduck是宿主机项目目录容器内会映射到/workspace/microduck实际路径需要按你的设备环境调整。镜像 tag 建议以官方仓库最新版本为准这里用latest只是演示用法。进入容器后拉取 MicroDuck 项目代码并安装训练依赖。MicroDuck 依赖 Stable-Baselines3、Gymnasium、huggingface-sb3 等库命令如下cd /workspace/microduck git clone https://github.com/huggingface/micro-duck.git . pip install --upgrade pip pip install stable-baselines3[extra] gymnasium huggingface-sb3 duckietown-sim # 如果环境提供 setup.py 或 requirements.txt优先使用项目自带的安装方式 # pip install -e . 或 pip install -r requirements.txt这里的安装命令是通用模板实际包名和版本请以 MicroDuck 仓库的 README 为准。跑完pip install之后可以用一个最短训练命令验证环境是否完整python -c from stable_baselines3 import PPO; print(SB3 OK) python -c import gymnasium; print(Gymnasium OK)到这里MicroDuck 的运行环境就搭好了。重点不是命令本身而是思路先在官方容器里确认 PyTorch CUDA 正常再在隔离环境里装 RL 依赖最后用最小命令验证环境完整性。这样后续训练脚本出现问题时能快速判断是环境问题还是业务逻辑问题。5. MicroDuck 功能测试与效果验证环境准备好之后不要直接跑几百轮训练。先做一轮小规模训练验证环境、算法、数据流和日志输出是否正常。这个思路和普通软件开发里的“冒烟测试”一致也能避免因为一个小错误浪费几个小时的训练时间。5.1 基础训练测试先写一个最小训练脚本使用 PPO CNN 策略在 Duckietown 环境里训练几万步。脚本逻辑参考下面的结构from stable_baselines3 import PPO from stable_baselines3.common.monitor import Monitor from stable_baselines3.common.vec_env import DummyVecEnv # 根据 MicroDuck 项目实际环境构造 Duckietown 环境 def make_env(): from duckietown_env import DuckietownEnv env DuckietownEnv( map_nameudem1, max_steps1000, camera_width160, camera_height120, domain_randFalse, ) return Monitor(env) env DummyVecEnv([make_env]) model PPO( CnnPolicy, env, verbose1, learning_rate3e-4, n_steps1024, batch_size128, n_epochs10, ) model.learn(total_timesteps50_000) model.save(microduck_ppo_smoke_test) print(训练完成模型已保存)这段脚本里做了两个重要决定一是把 camera_width 和 camera_height 降到 160x120这样显存占用和计算量都会小很多二是只训练 5 万步主要用于验证流程。判断训练是否正常的标准有三个训练进程没有报错、终端能看到 rollout/eval 指标、模型文件能正常保存。如果这一步报错不要盲目增加训练量先处理环境注册、依赖版本和 CUDA 可见性问题。常见的报错集中在DuckietownEnv导入失败、Monitor接口不匹配、CnnPolicy输入尺寸异常。这些都属于环境适配问题和算法本身关系不大。5.2 效果评估测试训练不能只盯着 loss 数字还要实际评估策略在环境中的表现。Stable-Baselines3 提供了evaluate_policy工具可以指定评估轮数统计平均回报和成功率指标from stable_baselines3.common.evaluation import evaluate_policy model PPO.load(microduck_ppo_smoke_test) env make_env() mean_reward, std_reward evaluate_policy( model, env, n_eval_episodes10, deterministicTrue, ) print(f评估平均收益: {mean_reward:.2f} ± {std_reward:.2f})如果平均收益明显高于随机策略说明模型已经学到一定导航能力如果收益没有明显提升也不能断言训练失败可能是因为总步数太少、环境奖励设计稀疏或者超参数不理想。建议同时打开 TensorBoard观察 reward、policy loss 和 entropy 三条曲线tensorboard --logdir./logs --port6006然后在浏览器访问http://localhost:6006就能看到训练过程中每条曲线的变化趋势。曲线平滑上升、熵值稳定下降是比较健康的训练信号如果 loss 剧烈震荡或者 reward 长时间不涨就该考虑降低学习率、增加 n_steps 或调整奖励函数。5.3 模型上传 Hugging Face HubMicroDuck 的价值有一半在 Hugging Face 生态里训练完的模型可以推送到 Hub方便随时下载和对比版本。上传前先配置 HF 登录 tokenhuggingface-cli login然后使用huggingface_sb3工具上传模型权重from huggingface_sb3 import push_to_hub push_to_hub( repo_id你的用户名/microduck-ppo-smoke-test, filenamemicroduck_ppo_smoke_test.zip, commit_messagePPO training on NVIDIA Thor, )上传成功后在 Hugging Face 网站的模型仓库里就能看到对应的权重文件。以后再在别的设备上部署可以直接load_from_hub加载不需要重新训练。5.4 恢复训练与长训练测试冒烟测试和短评估都通过之后可以进入正式训练阶段。推荐继续使用之前的模型作为起点而不是重新从随机权重开始model PPO.load(microduck_ppo_smoke_test) model.set_env(env) model.learn(total_timesteps500_000, reset_num_timestepsFalse) model.save(microduck_ppo_final)长训练阶段要重点观察训练是否稳定、环境是否偶尔卡住、显存占用是否缓慢上升。如果中途断电或手动中断也不要慌SB3 每次保存 checkpoints 后都能从最近的权重恢复只需要把PPO.load的路径改成最新的 checkpoint 文件即可。6. 训练结果的接口封装与批量任务很多人关心一个问题MicroDuck 训练完能不能提供 API严格来说MicroDuck 是训练项目没有自带 REST API但训练完成的策略可以通过 Stable-Baselines3 快速封装成一个推理函数再借助 FastAPI 暴露成 HTTP 服务供上位机或其它模块调用。下面是一个最小推理服务的示例思路接住图像输入返回动作from fastapi import FastAPI import numpy as np from stable_baselines3 import PPO app FastAPI() model PPO.load(microduck_ppo_final) app.post(/predict) async def predict(data: dict): # data[image] 为 Duckietown 仿真环境输出的图像数组 obs np.array(data[image], dtypenp.float32) action, _ model.predict(obs, deterministicTrue) return {action: action.tolist()}启动服务uvicorn api_server:app --host 0.0.0.0 --port 8000这样就把 RL 训练产物变成了一个可调用的推理接口。需要注意这只适合在可信内网环境中开启如果挂到公网必须增加鉴权、限流和输入校验否则任何人都能调用你的模型服务消耗设备资源。批量任务同样是强化学习实验里的高频需求。MicroDuck 训练一轮很快非常适合做超参数网格扫描。可以用 Python 脚本批量训练多个种子下的不同配置import itertools import subprocess param_grid { learning_rate: [1e-4, 3e-4, 1e-3], n_steps: [1024, 2048], seed: [0, 1, 2], } keys list(param_grid.keys()) for values in itertools.product(*param_grid.values()): config dict(zip(keys, values)) tag flr{config[learning_rate]}_nsteps{config[n_steps]}_seed{config[seed]} print(f启动训练: {tag}) subprocess.run([ python, train.py, --learning_rate, str(config[learning_rate]), --n_steps, str(config[n_steps]), --seed, str(config[seed]), --tag, tag, ])批量扫描的关键不只是把训练脚本跑多份而是要在训练脚本里把日志、模型权重、TensorBoard 输出全部按照队名/参数/种子/时间戳的目录结构存放保证每个实验的结果可回溯、可对比。否则批量任务跑完数据堆成一团根本没法分析。另一个工程重点是失败重试。真实批量任务里单次训练很可能因为网络波动、显存峰值、日志写入冲突而中断建议在脚本外层加入“失败保存日志 断点续跑”的逻辑。最简单的方式是每个子实验启动前先检查该实验的模型文件是否已经存在存在就直接跳过不存在才重新训练这样批量任务可以随时重启而不浪费算力。7. 资源占用与性能观察在英伟达 Thor 上训练 MicroDuck资源占用是大家最关心的问题但这里不能给出一个“固定显存值”因为占用取决于三个因素仿真图像分辨率、模型批量大小、是否开启 TensorBoard 渲染和域随机化。更稳妥的方法是自己在训练过程中实测观察。推荐在训练运行时另开一个终端持续监控 GPU 状态# NVIDIA 平台通用 watch -n 2 nvidia-smi # Jetson 平台可用 sudo tegrastatsnvidia-smi能显示显存占用、GPU 利用率和功耗tegrastats更适合记录嵌入式平台的 CPU/GPU 温度、频率、显存和内存占用。训练开始前记录一次空闲占用训练中每 5 分钟记录一次结束再记录一次这样就能得到一条完整的资源使用曲线。MicroDuck 的训练负载大头在仿真环境渲染和策略网络前向反向传播。如果你想降低资源占用优先调整三处第一降低 camera 输入分辨率从 640x480 降到 160x120显存和计算量立刻下降第二降低n_steps和batch_size这会减少单次 gradient update 的最大显存需求第三关闭不必要的渲染选项比如draw_bboxFalse、domain_randFalse可以节省大量 CPU 和 GPU 开销。CPU 推理和 GPU 训练的差异也需要理性看待。MicroDuck 初期环境验证阶段CPU 训练是可以跑的但迭代速度会比较慢。如果在 Thor GPU 上训练主要加速点在于神经网络的卷积计算和梯度更新。实际项目中的建议是小规模调试用 CPU 或低分辨率 GPU 模式正式训练用 GPU TensorBoard 监控不要在 CPU 模式下跑长训练流程否则容易把时间浪费在等待上。如果训练过程中出现显存不足优先做减法降低分辨率、缩小 batch size、减少环境并行数量而不是立刻换一台更高显存的设备。对于 MicroDuck 这种轻量级项目绝大多数资源问题只需要调整参数就能解决不涉及硬件升级。8. 常见问题与排查方法问题现象可能原因排查方式解决方案启动训练脚本报 ModuleNotFoundErrorPython 环境缺少依赖检查当前 Python 环境与安装命令重装 stable-baselines3、gymnasium、huggingface-sb3 等依赖Hugging Face 仓库无法下载模型网络连接 Hub 不稳定检查能否访问 Hub查看下载日志设置HF_ENDPOINThttps://hf-mirror.com后重试PyTorch 报 CUDA 不可用容器未启用 GPU 访问或驱动版本不匹配运行python -c import torch; print(torch.cuda.is_available())使用--runtime nvidia启动容器重新映射 GPU 设备训练过程中显存不足分辨率、批次大小或并行环境数过高观察 nvidia-smi 显存变化调低 camera_width/height、batch_size、n_stepsTensorBoard 页面打不开端口被占用或服务未启动检查浏览器访问地址与进程换端口启动或使用--host 0.0.0.0暴露服务DuckietownEnv 导入失败仿真环境包版本与代码不兼容查看 import 报错栈按项目 README 要求安装指定版本 duckietown-sim训练 reward 一直不涨超参不合适或训练步数太少观察 TensorBoard 曲线降低学习率、增加 n_steps、延长训练轮次模型上传 Hub 返回 401未登录或 token 无效运行huggingface-cli whoami重新执行huggingface-cli login批量任务跑到一半中断网络波动或日志写入冲突查看子进程日志与退出码加入断点续跑逻辑模型文件存在则跳过当前实验强化学习训练结果每次不同种子未固定检查初始化 seed在模型和环境初始化时设置相同 seed这里最容易被忽略的是“模型每次训练结果不一致”。强化学习本身带有随机性环境初始化、网络权重初始化、动作采样都会引入不确定性所以对比实验时一定要固定 seed否则无法判断某一个超参改动是真的有效还是仅仅因为运气好。建议把所有 seed 参数写进实验配置和模型文件放在一起。9. 最佳实践与使用建议从 MicroDuck 初版跑通到在 Thor 上做完整的强化学习实验有几个工程习惯值得养成。第一第一次训练永远先跑小规模冒烟测试。哪怕总步数只有 2 万步只要能在几分钟内跑完并保存模型后面的长训练才有意义。把「先冒烟、再长训」固化下来能省下大量反复排错的时间。第二把「环境依赖」和「项目代码」分开管理。项目代码放在挂载目录里可以随时从宿主机编辑依赖包、缓存、日志放在容器内或独立数据目录避免因为重建容器导致重要实验结果丢失。第三模型文件、训练日志、TensorBoard 事件、上传脚本要分目录管理。推荐这样的目录结构microduck/ ├── checkpoints/ # 训练中间权重 │ └── microduck_ppo_smoke_test.zip ├── logs/ # TensorBoard 和运行日志 ├── scripts/ # 训练、评估、上传脚本 ├── configs/ # 超参数配置文件 └── outputs/ # 最终模型和推理结果第四批量实验必须加日志、固定 seed、支持断点续跑。日志没有记录就等于没跑seed 不固定就等于对比无效不能续跑的批量任务在长训练场景下会非常痛苦。第五注意 Hugging Face 账号和模型仓库的访问权限。如果只是个人学习用私有仓库保存实验版本即可避免公开仓库里堆积大量中间权重。涉及公司业务或真实数据的训练结果更要严格控制上传范围必要时只导出本地模型不和 Hub 同步。第六强化学习训练本身是计算密集型任务。在 Thor 上跑这种端侧实验建议把不必要的图形界面、桌面服务、后台进程都关掉减少非训练任务的资源争抢这样训练指标的参考价值更高。10. 总结与下一步MicroDuck 在英伟达 Thor 上跑通强化学习最有价值的点不是“刷了个 Demo”而是验证了端侧设备具备完整 RL 训练闭环的能力环境构建、PPO 训练、结果评估、模型上传、推理服务封装全部在一台嵌入式 AI 平台上完成。对于想在具身智能、机器人导航方向深入的人这条链路就是最小可行的实践路径。建议第一步先验证最基础的训练流程把官方示例跑起来第二步调整 camera 分辨率、训练步数和学习率理解每个超参对训练曲线的影响第三步把模型上传到 Hugging Face Hub在另一台设备上加载推理走通“训练到部署”的完整链路第四步再基于 Duckietown 地图做真实导航任务优化。最容易踩的坑还是环境适配Thor 上的 Python、PyTorch、仿真环境版本必须匹配用官方 L4T 容器会省掉很多麻烦Hugging Face 下载不稳定就配置国内镜像端点不用蛮力重试。把这几个点处理好MicroDuck 的强化学习实验基本一次就能跑通。后面如果要继续扩展可以考虑把 Duckietown 里的策略迁移到真实小车上这时要重点关注域随机化、sim-to-real 迁移测试和安全边界控制不要直接把仿真权重放到真实设备上使用。