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

4.9 KiB
Raw Permalink Blame History

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导出的数据存储未以下结构

# 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. 结果统计: 通过率、平均误差、分布特征

使用方法

基本运行

python task5_main.py

参数配置

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距离量化分布差异

数据处理

解码

# Board ID → 公共牌组合
board_cards = decoder.decode_board_id(board_id, num_cards)

# Player ID → 手牌组合  
player_cards = decoder.decode_player_id(player_id)

导出数据结构

# 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. 反向验证对比