File size: 2,312 Bytes
f0ec44f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
---
license: apache-2.0
library_name: coreml
pipeline_tag: reinforcement-learning
tags:
- coreml
- apple-neural-engine
- super-mario-bros
- imitation-learning
- dagger
- game-playing
---

# MarioStudent (Core ML)

A 9.0M-parameter pixel policy that plays Super Mario Bros. (NES) on the Apple Neural Engine.

It is a MobileNetV3-Large that looks at the screen around Mario (now and 4 frames earlier) and picks one of 11
eight-frame moves: run, walk, hold, jump, hop, up, left, leftjump, wait, swim, down. It was trained by imitation on
a save-state beam-search solver that clears all 32 levels, plus DAgger rounds, with auxiliary tile and enemy grid
targets. It was not distilled from JEV.

- `MarioStudent.mlpackage`: fp16, 17 MB, all 185 ops on the Neural Engine, about 0.5 ms per decision (M5 Pro). Its
  move choice matches PyTorch on CPU, GPU and ANE.
- `mario-student.pt`: the PyTorch checkpoint.
- `config.json`: inputs, outputs and move order.

## Results

32 levels × 3 start offsets:

| | Flags | Levels cleared at least once | Cleared every time |
|---|---|---|---|
| Model alone | 53/96 | 23 | 12 |
| Model + lookahead | 78/96 | 30 | 21 |

Lookahead: before each move, candidate moves are simulated on an emulator save state, each followed by the model's
next 6 moves, and the first that survives and gains ground is played. With lookahead the result is the model plus
emulator simulation, not the network alone. The maze castles 4-4 and 8-4 are not cleared.

## Input / output

- Input `crop`: [1, 6, 120, 96] fp16 in [0, 1]. RGB now, then RGB 4 frames earlier, covering 32 px behind Mario to
  160 px ahead, every 2nd pixel of the 256×240 NES frame.
- Output `logits`: 11 move logits (order in `config.json`), then 11 survival logits.
- Moves are 8-frame button macros. The last input is held while the game has control, e.g. during a pipe entry.
- Mario's on-screen x, which places the crop, is read from emulator RAM.

## Demo

[FluidUse `Sources/JevMarioDemo`](https://github.com/FluidInference/FluidUse/tree/main/Sources/JevMarioDemo) is a
SwiftUI app that runs this model on the Neural Engine, with or without lookahead, next to
[JEV-9B on Core ML](https://huggingface.co/FluidInference/jev-9b-coreml).

You need your own copy of the game. No ROM, frames or gameplay video are included here.