Proximal Policy Optimization Algorithms
Paper • 1707.06347 • Published • 11
YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
基于 Transformer 的 2048 游戏人工智能训练器,使用 PPO(Proximal Policy Optimization)强化学习算法,让 AI 学会玩 2048 游戏。
本项目实现了一个完整的 2048 游戏 AI 训练系统,包括:
采用小型 Transformer 架构,专为 CPU 训练优化:
传统 2048 计分方式,每次合成砖块获得合成后砖块的数值作为分数。
综合评估当前局面的质量,鼓励 AI 保持良好局面:
局面分数 = 空格数 × 10 + 最大连续相邻数 × 15 + log₂(最大砖块) × 5 + 单调性奖励
使用 Proximal Policy Optimization 算法进行训练:
基于 PyQt5 的图形界面:
训练模式:
演示模式:
cd game2048
pip install -r requirements.txt
torch>=2.0.0 # 深度学习框架
numpy<2 # 数值计算
PyQt5>=5.15.0 # GUI 框架
matplotlib>=3.7.0 # 绘图库
python main.py
启动图形界面后:
训练模式:
checkpoints/model.pt演示模式:
# 训练 1000 局
python main.py --train --games 1000
# 使用 4 个并行环境
python main.py --train --games 1000 --envs 4
# 设置随机种子
python main.py --train --games 1000 --seed 42
# 加载模型并演示 5 局
python main.py --demo --model checkpoints/model.pt --games 5
# 不加载模型(随机权重)
python main.py --demo --games 3
python train_simple.py
修改脚本末尾可调整训练参数:
train_simple(num_games=500, save_path="checkpoints/model.pt")
game2048/
├── TASK.md # 任务需求文档
├── PLAN.md # 项目计划文档
├── README.md # 本文件
├── main.py # 程序入口
├── game.py # 2048 游戏核心逻辑
│ ├── Game2048 # 游戏类
│ ├── move() # 移动操作
│ ├── get_state() # 获取状态
│ └── calculate_situational_score() # 计算局面分数
│
├── model.py # Transformer 模型
│ ├── Game2048Transformer # Transformer 模型
│ ├── Game2048CNN # CNN 备选模型
│ └── get_action() # 动作选择
│
├── trainer.py # PPO 训练器
│ ├── PPOTrainer # PPO 训练类
│ ├── RolloutBuffer # 经验缓冲区
│ ├── Transition # 状态转移数据结构
│ └── TrainingStats # 训练统计
│
├── parallel.py # 并行训练环境
│ ├── ParallelGameEnv # 并行游戏环境
│ ├── TrainingWorker # 训练工作器
│ └── TrainingLoop # 训练循环
│
├── gui.py # GUI 界面
│ ├── MainWindow # 主窗口
│ ├── GameBoardWidget # 游戏面板
│ ├── ScoreWidget # 分数显示
│ ├── PlotCanvas # 曲线绑图
│ └── SimpleTrainingThread # 训练线程
│
├── train_simple.py # 简化训练脚本
├── utils.py # 工具函数
├── requirements.txt # 依赖列表
└── checkpoints/ # 模型保存目录
└── model.pt # 训练好的模型
# 棋盘状态 (4, 4)
# 每个格子值转换为 log₂(value),空格为 0
state = [[0, 1, 2, 0], # 对应 [空, 2, 4, 空]
[1, 2, 3, 1], # 对应 [2, 4, 8, 2]
...]
# 分数特征 (2,)
# [归一化累积分数, 归一化局面分数]
scores = [0.05, 0.85]
Input: (batch, 4, 4) board + (batch, 2) scores
↓
Position Embedding: (batch, 16, 64)
+ Spatial Embedding: (batch, 16, 64)
+ Score Embedding: (batch, 1, 64)
↓
Transformer Encoder (2 layers)
- Multi-Head Attention (4 heads)
- Feed-Forward Network (dim=128)
↓
Global Mean Pooling: (batch, 64)
↓
├── Policy Head → (batch, 4) # 动作概率
└── Value Head → (batch, 1) # 状态价值
reward = 局面分数变化 × 0.7 + 累积分数增量 × 0.003
# 游戏结束惩罚
if game_over:
reward -= 10.0
| 参数 | 值 |
|---|---|
| Learning Rate | 3e-4 |
| Batch Size | 64 |
| PPO Clip Ratio | 0.2 |
| GAE Lambda | 0.95 |
| Discount Factor (γ) | 0.99 |
| Entropy Coefficient | 0.01 |
| 指标 | 数值 |
|---|---|
| 平均分数 | ~2500 |
| 最高分数 | 6812 |
| 最大砖块 | 512 |
| 训练时间 | ~9 分钟 |
随机权重: 平均 ~800, 最高 ~2000
训练 500 局: 平均 ~2500, 最高 ~6800
game.py 中的 calculate_situational_score()model.py 中的网络结构trainer.py 中的超参数# 在 game.py 中测试游戏逻辑
if __name__ == "__main__":
game = Game2048()
print(game)
game.move(Game2048.LEFT)
print(game)
MIT License
本项目由 GLM-5 开发实现