Files
poker_task1/task5_readme.md
2025-09-26 17:08:27 +08:00

178 lines
4.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Task5: 短牌型EHS交叉验证系统
## 概述
Task5实现了一个完整的短牌型德州扑克EHS交叉验证系统用于验证短牌型本地生成与xtask导出的EHS的一致性。
## 核心功能
### 验证目标
从task5_main.py解析xtask导出的数据 → 短牌型生成器重新计算EHS/HIST → EMD距离比较一致性
### 三阶段验证
1. **River阶段**: EHS单值精确匹配验证
2. **Turn阶段**: 30-bin直方图分布验证
3. **Flop阶段**: 465-bin直方图分布验证
## 文件结构
```
├── task5_main.py
├── task5_readme.md
├── cross_validation/
│ ├── __init__.py
│ ├── cross_validation.py #交叉验证
│ └── parse_data.py # 导出数据解
├── shortdeck/
│ └── gen_hist.py # 生成直方图
└── ehs_data/ # xtask导出数据
├── river_ehs.npy
├── turn_hist.npy
└── flop_hist.npy
```
## 关键特性
### 数据类型
用解析器将xtask导出的数据存储未以下结构
```python
# River EHS记录
RiverEHSRecord: board_id, player_id, ehs, board_cards, player_cards
# Turn直方图记录
TurnHistRecord: board_id, player_id, bins[30], board_cards, player_cards
# Flop直方图记录
FlopHistRecord: board_id, player_id, bins[465], board_cards, player_cards
```
### 验证流程
1. **数据解析**: 从.npy文件解析原始数据生成上述结构
2. **牌面解码**: 在解析的数据中取样使用样本的board_cards/player_cards组合成具体牌面
3. **重新计算**: 使用短牌型生成器根据turn/flop/riverplayer_cards+board_cards重算EHS/HIST
4. **一致性比较**: EMD距离/数值差异分析
5. **结果统计**: 通过率、平均误差、分布特征
## 使用方法
### 基本运行
```bash
python task5_main.py
```
### 参数配置
```bash
python task5_main.py --river-samples 10 --turn-samples 5 --flop-samples 3
```
### 参数说明
- `--river-samples`: River阶段验证样本数默认20
- `--turn-samples`: Turn阶段验证样本数默认10
- `--flop-samples`: Flop阶段验证样本数默认5
## 输出示例
```
========== OpenPQLDecoder (短牌型36张牌) ===============
初始化短牌型EHS直方图生成器牌组大小: 36
牌型范围: SIX-ACE
验证River EHS样本 (最大样本数: 5)
样本 1: [Qd Ad] + [6s Th Qc Kd Ac]
原始EHS: 0.692118
重算EHS: 0.692118
差异: 0.000000
验证Turn直方图样本 (最大样本数: 3)
样本 1: [8h 8s] + [6s Qd Kd Kh]
原始直方图: bins=30, sum=13.640, 非零bins=30
生成直方图: bins=30, sum=13.677, 非零bins=30
归一化后EMD距离: 0.021985
验证Flop直方图样本 (最大样本数: 2)
样本 1: [Qd Kd] + [7h Qh Qs]
原始直方图: bins=465, sum=422.320, 非零bins=465
生成直方图: bins=465, sum=427.315, 非零bins=465
归一化后EMD距离: 1.509076
```
## 验证标准
### River阶段
- **成功标准**: 匹配率 > 80% 且平均差异 < 0.05
- **评估方法**: 直接数值比较容差1e-6
### Turn/Flop阶段
- **成功标准**: 低EMD率 > 60% 且平均EMD < 0.5
- **EMD阈值**: < 0.2视为低距离
- **评估方法**: Wasserstein距离量化分布差异
## 数据处理
### 解码
```python
# Board ID → 公共牌组合
board_cards = decoder.decode_board_id(board_id, num_cards)
# Player ID → 手牌组合
player_cards = decoder.decode_player_id(player_id)
```
### 导出数据结构
```python
# river_ehs.npy
{
'board': int64, # 公共牌ID5张牌的编码
'player': int64, # 玩家手牌ID2张牌的编码
'ehs': float64 # EHS值0.0-1.0之间的浮点数)
}
# turn_hist.npy
{
'board': int64, # 公共牌ID4张牌的编码
'player': int64, # 玩家手牌ID2张牌的编码
'bins': ndarray # 30维直方图数组
}
# flop_hist.npy
{
'board': int64, # 公共牌ID3张牌的编码
'player': int64, # 玩家手牌ID2张牌的编码
'bins': ndarray # 465维直方图数组
}
```
### 编码方式
- **Card64编码用于3-5张公共牌**
64位每个suit占16位
每位表示对应rank的牌是否存在
用于board_id公共牌编码
- **Hand<2>编码用于2张牌**
16位低8位和高8位分别编码两张牌
每张牌用8位编码高4位=suit低4位=rank
用于player_id手牌编码
## 短牌型
- **牌组**: 6, 7, 8, 9, T, J, Q, K, A (四花色共36张)
- **组合数**: Flop阶段C(31,2)=465, Turn阶段30种可能
- **EHS计算**: 枚举所有对手组合,计算胜率期望
## 版本信息
- **Version**: 1.0
- **Python**: 3.13+
- **依赖**: numpy, scipy, dataclasses
## 遗留
1. **抽样优化**
2. **牌面同构优化**
3. **解析数据存储**
4. **反向验证对比**