mjAi/README.md

351 lines
16 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 成都麻将Ai
## 项目目录结构
#### **1. 项目根目录**
- `README.md`:描述项目的目标、规则实现、训练流程和使用方法。
- `requirements.txt`:列出项目依赖的库,例如 `torch`、`gym`、`numpy` 等。
- `setup.py`:如果希望将项目打包为模块供他人使用,可以在此配置。
#### **2. 配置目录 (`configs/`)**
- `training_config.yaml`:包含训练超参数,如学习率、批量大小、强化学习算法的参数。
- `game_rules.yaml`:定义麻将规则,如番种加分规则、牌的花色、缺一门规则等。
#### **3. 数据目录 (`data/`)**
- `raw/`:存储原始麻将对局数据(如网络抓取或模拟对局)。
- `processed/`:存储格式化后的训练数据,例如 Numpy 数组或 Tensor 格式。
- `self_play/`:存储自我对弈产生的对局记录,用于强化学习。
#### **4. 模型目录 (`models/`)**
- `checkpoints/`:保存模型的中间状态,用于断点恢复训练或版本管理。
- `trained_model.py`:最终导出的模型文件,可直接加载和部署。
#### **5. 核心代码目录 (`src/`)**
##### **游戏引擎 (`engine/`)**
- `mahjong_engine.py`:实现成都麻将规则,包括摸牌、打牌、碰、杠、胡牌等逻辑。
- `game_state.py`:描述麻将局面状态的建模,包括手牌、牌河、明牌等。
- `utils.py`:通用工具函数,例如洗牌、牌序转换等。
##### **AI 模块 (`ai/`)**
- `model.py`:定义 AI 的深度学习模型(例如基于卷积或 Transformer 的网络)。
- `training.py`:训练脚本,包含监督学习或强化学习的逻辑。
- `evaluation.py`:评估模型表现的代码,支持对局胜率、番数统计等。
- `self_play.py`:实现自我对弈逻辑,用当前模型生成新训练数据。
##### **强化学习环境 (`environment/`)**
- `gym_env.py`:封装麻将引擎为 OpenAI Gym 环境,用于强化学习训练。
- `reward.py`:定义奖励函数,例如胡牌加分、放炮减分等。
##### **数据处理 (`data_processing/`)**
- `preprocess.py`:从原始数据中提取特征并转化为模型输入格式。
- `augmentation.py`:数据增强方法,例如随机调整牌序、模拟不同对局风格。
- `data_loader.py`:实现批量加载数据的逻辑。
##### **单元测试 (`tests/`)**
- 测试麻将引擎、AI 模型和强化学习环境的模块,确保代码可靠性。
#### **6. 脚本目录 (`scripts/`)**
- `train.py`:启动训练流程,包括加载数据、定义模型和运行训练。
- `evaluate.py`:加载模型并运行评估对局。
- `self_play.py`:启动 AI 自我对弈,生成强化学习数据。
- `preprocess_data.py`:将原始数据预处理为训练格式。
#### **7. 日志目录 (`logs/`)**
- 记录训练过程中的指标、对局日志和评估结果。
## 成都麻将规则:
- 成都麻将使用的是108张牌包括条、筒、万三种花色每种花色从1到9各四张没有东南西北风牌和中发白字牌。
### 基本规则
- **缺一门**:玩家必须选择缺少一种花色(条、筒、万中的任意一种),即只能用两种花色来胡牌。如果手中只有单一花色,则为清一色。
- **定缺**:游戏开始时,每位玩家需要扣下一张牌作为自己缺的那门,并且不能更改。如果本身就是两门牌,则可以报“天缺”而不扣牌。
- **起牌与打牌**:庄家通过掷骰子决定起牌位置,然后按顺序抓牌。庄家先出牌,之后每家依次摸牌打牌。
- **碰、杠**:允许碰牌和杠牌,但不允许吃牌。杠牌分为明杠和暗杠,明杠是其他玩家打出的牌刚好与你手里有三张的牌相同;暗杠则是你自己摸到四张相同的牌。
- **胡牌**胡牌的基本条件是拥有一个对子加上四个顺子或刻子三个相同牌。自摸为三家给分点炮则由放炮者给分。n*AAA+m*ABC+DD mn可以等于0。
- **血战到底**:一家胡牌后,其他未胡牌的玩家继续游戏,直到只剩下最后一位玩家或者黄庄(所有牌都被摸完)为止。
### 特殊规则
- **下雨**:指杠牌,分为明杠和暗杠,明杠只收一家的钱,而暗杠可以收三家的钱。
- **查叫**:当出现黄庄时,需要检查每个玩家是否已经听牌(即差一张牌就能胡牌的状态),如果没有听牌,则可能需要赔偿其他玩家。
### 胡牌番数
- 根据不同的胡牌方式,有不同的计分方法。例如,清一色、带根(有额外的杠)、对子胡等都有相应的加分规则。
#### 详细番数计算
**平胡(基本胡)**四坎牌加一对将四坎牌可以是刻子或顺子计为1番。
**带根** 在玩家胡牌的手牌当中,有四张牌是一摸一样的,这样的牌就叫做带根。牌型如:一二三,三三三,万。四五六,五六七,九九条。
**对子胡**玩家的手牌除了一对将牌以外剩下的牌都是三张一样的一共四对这样的牌型胡牌就叫做对子胡。计1番。牌型如一一一三三三四四四万六六六七七筒。
**清一色**
不带杠的清一色称为“素清”计为2番。
带杠的清一色或清一色对子胡简称“清对”计为3番称为“极品”。
带两杠的清一色或清一色对子胡带杠计为4番称为“极中极”或“精品”。<!--存疑-->
**将对** 玩家手上的牌是带二、五、八的对对胡这样的牌型叫将对。计3番。牌型如二二二五五五八八八万五五五八八筒。
**七对**玩家胡牌的手牌全部都是两张一对的没有碰过牌和杠过牌。这样的牌型叫做七对或暗七对。计2番。牌型如一一三三四四六六万五五七七九九筒。
**清七对**玩家手上的牌是清一色的七对这样的牌型叫清七对。计4番。牌型如一一三三四四六六七七八八九九万。
**龙七对**玩家手中的牌为暗七对牌型没有碰过牌杠过牌时并且有四张牌是一模一样的这样的牌型叫做龙七对。计为4番。牌型如一一二二二二四四万 五五七七八八筒。
**清龙七对**玩家手上的牌是清一色的龙七对这样的牌型叫清龙七对。计5番。牌型如一一二二四四四四五五七七九九万。
**带幺九**
- **带幺九**指玩家手上的牌全部是由1和9组成的顺子、刻子或对子。例如123, 789, 111, 999, 11等。计为2番。
- **清带幺九**指玩家手上的牌不仅全部由1和9组成而且是同一花色条、筒、万即清一色的带幺九。计为4番。
**杠上开花**另外再单独计算带根的番数玩家的手牌已经下叫并且玩家在杠牌时杠起一张牌正好是玩家自己所要的叫牌这时玩家可以选择胡牌这种情况叫做杠上花。计为1番。每杠加1番。
**杠上炮**玩家在杠牌时先杠一张牌再打掉一张牌而打出的这张牌正好是其它玩家胡牌所需要的叫牌时这种情况叫做杠上炮。每杠加1番。
**报叫**庄家在配牌完成后打出第一张牌就下叫或者闲家在配牌完成后就下叫并宣告下叫庄家闲家都要之后不等变更手牌。计2番。
**天胡**庄家起牌后直接胡牌计为5番。
**地胡**闲家在第一轮打牌时就胡牌计为5番。
#### 不确定是否有的类型
1. **全求人**所有牌都是通过碰、杠、吃别人打出的牌来完成的计为3番。
1. **抢杠胡**当其他玩家明杠时你正好可以胡那张牌计为1番。
2. **大对子**手牌由四个对子加一个刻子组成计为2番。
3. **小七对**有六对加上一个对子计为2番。
4. **金钩吊**手上只剩下一张牌等别人打出然后胡牌计为1番。
5. **海底捞月**最后一张牌被玩家摸到并胡牌计为1番。
6. **海底炮**最后一张牌被打出导致玩家胡牌计为1番。
这些番数可以叠加例如如果一个玩家同时满足了清一色和七对那么他的总番数就是2番清一色+ 2番七对= 4番。
### 计分规则
- **基本分值**每番的具体分值可以根据不同的玩法和地区有所不同但一般情况下每番的分值可以设定为一个固定的数值比如5分、10分等。
- **翻倍规则**:某些地方可能会有额外的翻倍规则,例如,如果胡牌者是在“海底捞月”或“杠上开花”等特殊情况下胡牌,可能会有额外的加分。
**自摸 **:是指玩家通过自己摸牌完成胡牌。自摸时,其他玩家都需要给赢家支付相应的分数。
## 成都麻将游戏流程
1.确定庄家:通常在第一局开始时通过掷骰子来决定庄家。以后每局由上一局胡牌的玩家坐庄,如果流局则庄家不变。
2.庄家摸牌从掷骰子确定的位置开始庄家先摸14张牌其他玩家每人摸13张牌。
3.庄家出牌:庄家先打出一张牌,开始这一局的游戏。
4.顺时针出牌:接下来按照顺时针方向,每位玩家依次摸牌和出牌。
5.摸牌与出牌:每个玩家轮流摸一张牌,然后选择出一张牌。玩家可以进行碰、杠等操作。
6.打缺一门:玩家必须选择先打完定缺的花色牌,才能出其他牌。(缺一种花色(筒、条、万中的一种),即手牌中只能保留两种花色)
7.自摸:玩家摸到的牌使自己胡牌。
8.点炮:其他玩家打出的牌使自己胡牌。
9.计分:胡牌后根据胡牌的番数和其他规则进行计分。)
10.结算
## 成都麻将规则建模
麻将游戏引擎建模代码于项目根src/engine/目录下。
## 算法
#### **1. 强化学习**
适用于学习最佳策略帮助AI根据牌局动态决策如摸牌、出牌、胡牌等
**Q-Learning/Deep Q-Learning (DQN)**:
使用价值函数近似,适用于简单麻将变体。
在复杂麻将中可能遇到状态空间爆炸的问题。
**Policy Gradient(如 REINFORCE、PPO、A3C)**:
- 直接学习策略,适合连续决策问题。
- Proximal Policy Optimization (PPO) 是目前表现较好的强化学习算法。
**AlphaZero/Monte Carlo Tree Search (MCTS)**:
- 结合深度神经网络和搜索算法,模拟多局游戏,适用于探索全局最优策略。
**适用场景**
自主对局学习(自我博弈)。
学习如何综合权衡得失(如是否碰牌、杠牌或放弃操作)。
#### **2. 模拟和搜索算法**
适用于推理对手手牌或牌堆剩余牌,提升策略的稳定性。
**算法**
- Monte Carlo Tree Search (MCTS):
- 模拟多个可能的后续动作,估算每个动作的收益。
- 常用于长序列决策,如考虑碰、杠、胡等多步操作的效果。
- Minimax with Alpha-Beta Pruning:
- 在两人麻将(或简化版本)中,模拟对手的可能操作。
**适用场景**
需要进行搜索优化的场景(如判断是否选择碰、杠)。
分析未来几步操作对得分的影响。
#### **3. 监督学习**
适用于模仿人类玩家的决策或历史数据学习。
**算法**
- 分类算法
(如 Logistic Regression、Random Forest、XGBoost、Neural Networks
- 学习单步决策(如出哪张牌)。
- 适用于学习简单的局部决策。
- 序列模型
(如 RNN、LSTM、Transformer
- 学习决策的序列模式(如出牌顺序和策略连贯性)。
- Transformer 可以捕捉复杂的上下文关系。
**适用场景**
有大量玩家对局数据作为训练集。
模拟人类打牌风格。
#### **4. 混合方法**
结合强化学习和监督学习的优点,以应对麻将的高复杂性和多样化。
**示例方法**
- Imitation Learning + Reinforcement Learning
:
- 先使用监督学习模仿玩家风格,再用强化学习微调策略。
- AlphaZero-like Framework
:
- 结合深度强化学习和搜索(如 MCTS强化对局策略。
**适用场景**
需要在短时间内获得可用的AI策略。
想进一步优化模型的决策能力。
#### **对抗学习**
让AI与自身对局自我博弈或与其他AI对局提升对抗能力。
#### **工具和框架**
1. 强化学习框架:
- **Stable-Baselines3**: 简单易用支持PPO、DQN等算法。
- **Ray RLlib**: 分布式强化学习框架,适合复杂任务。
2. 深度学习框架:
- TensorFlow 或 PyTorch构建神经网络和深度学习模型。
3. 麻将环境:
- 自定义麻将环境或使用已有开源环境(如 OpenAI Gym 或 MahjongRL
### PPOProximal Policy Optimization算法
TensorBoard 通常会记录和可视化多种训练指标。你提到的这些图表代表了 PPO 训练过程中的不同方面。下面是对每个图表的解释:
### 1. `train/loss`
- **含义**:总损失函数值。
- **用途**:这是所有损失项的综合,包括策略梯度损失、价值函数损失等。通过观察这个指标,可以了解整个训练过程中的总体损失趋势。
### 2. `train/policy_gradient_loss`
- **含义**:策略梯度损失。
- **用途**这表示策略网络更新时的损失。PPO 通过剪裁来限制策略更新的幅度,以确保稳定的学习过程。观察这个指标可以帮助你了解策略更新的情况。
### 3. `train/value_loss`
- **含义**:价值函数损失。
- **用途**:这表示价值网络(用于估计状态值或状态-动作对的价值)的损失。价值函数的准确性对于评估策略的好坏非常重要。通过观察这个指标,可以了解价值网络的学习情况。
### 4. `train/learning_rate`
- **含义**:当前的学习率。
- **用途**:学习率是优化器的一个重要超参数,控制着每次更新时权重调整的幅度。观察学习率的变化可以帮助你了解学习率调度策略的效果。
### 5. `train/explained_variance`
- **含义**:解释方差。
- **用途**:这是一个衡量价值函数预测与实际回报之间差异的指标。解释方差越接近 1说明价值函数的预测越准确。通过观察这个指标可以评估价值函数的性能。
### 6. `train/entropy_loss`
- **含义**:熵损失。
- **用途**:熵损失鼓励策略具有一定的随机性,以防止过早收敛到局部最优解。通过观察这个指标,可以了解策略的探索程度。
### 7. `train/clip_range`
- **含义**:剪裁范围。
- **用途**PPO 使用剪裁来限制策略更新的幅度,以确保稳定性。剪裁范围是一个重要的超参数,决定了剪裁的严格程度。观察这个指标可以帮助你了解剪裁策略的效果。
### 8. `train/clip_fraction`
- **含义**:被剪裁的比例。
- **用途**:这个指标表示有多少比例的更新被剪裁。如果剪裁比例很高,可能意味着你的策略更新过于激进,需要调整剪裁范围或其他超参数。
### 9. `train/approx_kl`
- **含义**:近似 KL 散度。
- **用途**KL 散度衡量新旧策略之间的差异。PPO 通过控制 KL 散度来确保策略更新的稳定性。通过观察这个指标,可以了解策略更新的幅度和稳定性。
### 总结
这些图表提供了关于 PPO 训练过程的全面视图,帮助你监控和调试模型。以下是每个图表的主要用途:
- **`train/loss`**:总体损失,反映训练的整体进展。
- **`train/policy_gradient_loss`**:策略梯度损失,反映策略网络的更新情况。
- **`train/value_loss`**:价值函数损失,反映价值网络的学习情况。
- **`train/learning_rate`**:学习率,反映优化器的设置。
- **`train/explained_variance`**:解释方差,反映价值函数的准确性。
- **`train/entropy_loss`**:熵损失,反映策略的探索程度。
- **`train/clip_range`**:剪裁范围,反映策略更新的限制。
- **`train/clip_fraction`**:被剪裁的比例,反映策略更新的稳定性。
- **`train/approx_kl`**:近似 KL 散度,反映策略更新的幅度和稳定性。