强化学习通关马里奥 · Day 1:定义动作与奖励拆分
强化学习通关马里奥 · Day 1:定义动作与奖励拆分
这是「用强化学习通关马里奥」系列的第一篇记录。目的是把学习过程中的思考和进度记下来,也方便自己回头看走没走偏。
项目目标
- 了解并学习强化学习(RL)的概念
- 根据学到的概念进行实践,最终实现强化学习通关马里奥
项目资源
实践用的游戏是 FullScreenMario —— 一个 HTML5 重制的马里奥,源码可以直接在浏览器里跑,方便我们改造成 RL 环境:
git clone https://github.com/JoshuaKGoldberg/Old-Deleted-FullScreenMario.gitcd Old-Deleted-FullScreenMariogit checkout 77b493c9ce9fb015a88995658b11d95e28f1e68e强化学习最核心的两件事
开始学 RL,我理解首先要做的其实是把这件模糊的事定义清楚。这里最关键的两步是:定义动作、拆分奖励。
1. 定义动作
强化学习第一步就是定义好动作。在马里奥里,动作不是无限连续的,而是一组离散的按键组合——比如左右移动、跳跃(大小跳)、蹲下、发射火球。把这些抽象成几个固定的动作选项,agent 每步就在里面选一个。
2. 拆分奖励
定义好动作之后,就要对目标做奖励拆分。
马里奥的最终目标肯定是走到旗杆那里。但这个目标太大了,强化学习如果只盯着终点,很可能会学不动——因为从起点到旗杆之间的每一步,agent 都得不到任何反馈。
所以需要把「通关」这个大目标拆开,划分权重。举个例子:
- 旗杆在右侧,那我往右走就加 1 分
- 踩蘑菇加 10 分
- 死亡扣 100 分
- 到达旗杆加 100 分
这样做的意义是:即使 agent 还没通关,它也能从「有没有往前挪」「有没有躲开敌人」这些更细的动作里得到反馈。我认为这样可以更好地量化进步的程度——不再是「通关 or 不通关」的两极,而是每走一步都有迹可循。
今天推进到哪一步了
概念想清楚之后,最该做的其实是先把环境跑通。因为 RL 通关马里奥的难点,更多在「怎么把游戏改造成 RL 能交互的环境」,而不是算法本身。
环境的核心是一个闭环接口:
step(动作) → (观测, 奖励, 是否终止)reset() → 初始状态今天已经在 FullScreenMario 的引擎里把这个接口打通了原型:
- 能读到玩家状态(
x/y/速度/力量/是否落地/是否跳跃) - 能注入动作(左右移动、跳跃等离散动作)
- 能判断这局是否终止(死亡 / 掉坑 / 通关)
- 用随机 agent 试跑了几十步,看到玩家的
x确实在推进、奖励也在随前进变化
也就是说,「能观测到状态、能下发动作、能检测死亡通关」这条链已经通了。这是之后所有训练的地基。
下一步
- 把环境接口整理成标准的
reset/step形式,供训练算法调用 - 用随机策略跑更多步,确认奖励的数值合不合理
- 再引入 PPO 之类的主流算法,让 agent 真的学着往前走
概念的方向我个人觉得已经对了,接下来就是一步步把它落到能训练的代码上。
明日计划
- 把今天打通的环境原型整理成标准的
reset()/step()接口,让主流训练库(比如 Stable-Baselines3)能直接调用 - 用随机策略跑更长的整局,观察奖励数值合不合理(比如死亡惩罚会不会太狠、前进加分够不够)
- 确定观测向量和决策频率:我想试 frameskip 取 2~4,看哪种能让 agent 稳定跳过第一个坑
- 引入 PPO 做第一次真正的训练,目标先定「能稳定过掉 World 1-1 开局」,而不是一口气通关
AI 批注(给作者的学习反馈)
方向完全对。更精确的说法是定义动作空间——马里奥的动作通常是一组离散的少数组合(左/右/小跳/大跳/蹲/火球,建议 68 个原子动作),而不是连续变量。另外要区分两个频率:物理渲染(引擎固定约 60Hz)和决策频率(frameskip,每 24 帧才选一次动作),这两个不要混在一起。
你举的例子(右移+1 / 踩蘑菇+10 / 死亡-100 / 到旗+100)已经是**奖励整形(reward shaping)**的雏形了,方向很对。但要注意三个坑:
- 只给「右移+1」会导致原地抖——agent 可能学会左右来回蹭、靠来回移动刷分。更好的做法是奖励净前进量(只算向右的位移增量),或对无意义动作给一点小惩罚。
- 稀疏奖励和稠密奖励要配合:到旗杆 +100 是远端终极奖励(稀疏,很难直接拿到),右移 +1 是近端成形奖励(稠密,每步都有)。两者必须同时存在,否则梯度很难回传、agent 学不动。你两个都设计到了,这点很对。
- 权重分配要克制:踩蘑菇 +10 偏大,会让 agent 更愿意去踩蘑菇而不是赶路。一般把「前进」当成主要信号,蘑菇/金币当次要的小奖励。死亡 -100 是必须的,否则 agent 可能故意送死来快速重开。
思路对——往右走加分本质上就是在用 x 位置当进度度量。训练时建议再用 TensorBoard 看 reward / 每局步数(episode_len)的变化,以及最远到达 x,这三个指标最能直观反映进步。
概念里最容易低估的是把游戏改造成 RL 能交互的环境——这往往占整个工作量的一半以上。核心是 step(动作) → (观测, 奖励, 是否终止) 这个闭环,要从引擎里读玩家状态、注入动作、判断死亡/通关。这部分要先跑通,算法反而是后面套上的。
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!

