当深度学习遇上魔鬼之轮:RL 在欧洲轮盘上的应用(第1部分)
Source: Dev.to
第 1 部分:理论、数学与架构
免责声明
如果你不知何故用这些技巧盈利了,我期待分一杯羹。说真的,给我买杯啤酒或给仓库提交一次代码就行。赌场长期必胜,这点不可改变。但至少我们在此过程中学到了点酷东西。
为什么要为欧洲轮盘构建 RL 代理?
欧洲轮盘的庄家优势约为 2.7 %。从长远来看,赌场必胜,毫无例外。挑战不在于击败庄家,而在于当面对纯随机、灾难性噪声以及 47 维动作空间(大多数决策都会导致亏损)时,推动强化学习(RL)的边界。如果一个代理能够在如此敌对的环境中学到东西,那么它在存在可利用模式的场景下会有多强大,想想就令人激动。
动作空间
欧洲轮盘有 37 个口袋(0‑36)。如果把外部投注算进去,动作空间会扩展到 47 个离散动作:
| 动作 | 描述 | 赔率 |
|---|---|---|
| 0‑36 | 对单个数字的直接投注 | 35:1 |
| 37‑38 | 颜色投注(红/黑) | 1:1 |
| 39‑40 | 奇偶投注(奇/偶) | 1:1 |
| 41‑42 | 高/低(1‑18 对 19‑36) | 1:1 |
| 43‑45 | 十三组(第一/第二/第三十二) | 2:1 |
| 46 | PASS – “不下注”(往往是最聪明的选择) | 0 |
代理不仅要决定 在哪里 投注,还要隐式决定 承担多少风险。
状态表示
- 历史缓冲区 – 最近 20 次旋转的结果(整数 0‑36)。为学习器提供序列信息,尽管从统计上看它毫无意义。
- 收益比率 – 当前 bankroll(资金)除以初始 bankroll。该信息为决策提供上下文(例如,领先时保守,落后时激进)。
加入 bankroll 上下文被证明是必需的;如果没有它,代理会在盈余 50 % 或亏损 80 % 时做出完全相同的决策。
奖励结构
| 结果 | 奖励 |
|---|---|
| 直接投注获胜 | +35 |
| 红/黑、奇/偶、高/低获胜 | +1 |
| 任意投注失败 | –1 |
| PASS 动作 | 0 |
一个回合通常表现为 -1, -1, -1, +1, -1, -1, … —— 正奖励稀疏,负奖励密集。
网络架构(基于 BatchNorm 的 DQN)
Embedding Layer (0‑36 → 64‑dim)
→ Flatten (20 × 64 = 1280)
→ BatchNorm Dense (1280 → 128)
→ BatchNorm Dense (128 → 128)
Gain Network (gain ratio: 1 → 32)
→ Concatenate (128 + 32 = 160)
→ Dense (160 → 64)
→ Dense (64 → 47) → 所有动作的 Q 值
为什么选 BatchNorm 而不是 LSTM?
轮盘旋转相互独立,没有时间依赖性可建模。LSTM 会试图去拟合噪声,导致 Q 值估计不稳定。BatchNorm 在每个小批量内部对激活进行归一化,平滑梯度空间并加速收敛。实际使用中,BatchNorm 版本收敛更快且策略更稳。
Double DQN 更新
标准 DQN 往往会高估 Q 值,因为同一个网络既负责选动作又负责评估动作。Double DQN 通过使用在线网络进行动作选择、目标网络进行评估来缓解这种偏差:
# Double DQN target computation
target = r + γ * Q_target(s_next, argmax_a Q_online(s_next, a))
Q(s, a) ← Q(s, a) + α * (target - Q(s, a))
在轮盘中,这种高估尤为致命,因为大多数动作都会亏钱;若不纠正,代理可能会坚持“下注有利可图”的错误信念,从而延迟发现 PASS 往往是最优的事实。
LSTM 预测器(异常检测器)
另建了一个 仅用于预测下一次旋转 的 LSTM 模型,不参与下注决策:
Embedding (0‑36 → 32‑dim)
→ LSTM (64 hidden)
→ LSTM (64 hidden)
→ Dropout (p=0.2)
→ Linear → Softmax (37 classes)
训练细节
- 损失函数:交叉熵
- 优化器:Adam
- 批大小:64
在真正随机的数据上,准确率徘徊在 2.7 %(1/37),符合预期。当引入微小偏差(例如某些区块出现概率高出 0.5 %)时,LSTM 在几百次旋转后即可检测到。它本身不产生利润,但可作为有效的异常检测器,并可加入多模型集成中。
硬件与性能
- GPU:RTX 3060
- 训练速度:约 15 ms / 批(64 条序列)
- PyTorch:
model.to('cuda')启用 GPU 加速;仅 CPU 训练将极其缓慢。
元学习思路(预览)
与其让单一代理直接学习动作,不如让一个 元代理 学会 何时 信任不同的子模型(例如 BatchNorm DQN、LSTM 预测器、偏差检测器)。这种层级化方法将在系列后续章节中进一步探讨。