5634b04b00
- infer.py: 新增 emb_fp16 CONFIG 选项(默认 False),Embedding 权重可 FP16 省查表带宽 - CLAUDE.md: 补充团队成员表(AI Studio 用户名→真实姓名) - README.md: 新增团队区块,标注三人参赛身份 - .gitignore: 排除 DVC/HF 工具自动生成的元数据文件 Co-Authored-By: Claude <noreply@anthropic.com>
235 lines
11 KiB
Markdown
235 lines
11 KiB
Markdown
# CLAUDE.md
|
||
|
||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||
|
||
## 项目概述
|
||
|
||
百度商业AI技术创新大赛 (CTI) 2026 — **生成式推荐广告排序推理性能优化**。
|
||
|
||
目标:给定 GRAB Transformer 模型,在**不改模型结构、不在测试集训练**的前提下,极致优化推理性能。量化/稀疏/剪枝明确允许。
|
||
|
||
## 环境与常用命令
|
||
|
||
```powershell
|
||
# 激活虚拟环境
|
||
.\.venv\Scripts\Activate.ps1
|
||
|
||
# 本地运行推理(需要 dataset/ 和 ckpt.pt)
|
||
.\.venv\Scripts\python.exe 代码\code\infer.py
|
||
.\.venv\Scripts\python.exe 代码\code\infer.py --ckpt path/to/ckpt.pt
|
||
|
||
# AI Studio SDK(下载数据集、提交)
|
||
.\.venv\Scripts\aistudio.exe download --dataset <id> --local_dir ./dataset --token <token>
|
||
.\.venv\Scripts\aistudio.exe download --model <id> --local_dir . --token <token>
|
||
|
||
# 打包提交
|
||
cd 代码/code && zip -r ../../submit.zip infer.py requirements.txt build_env.sh
|
||
```
|
||
|
||
本地环境仅装 `numpy` + `tqdm` + `aistudio-sdk`(轻量),完整 PyTorch 依赖见 `代码/code/requirements.txt`,训练/推理在服务端跑。
|
||
|
||
## 代码架构
|
||
|
||
```
|
||
infer.py (单文件,~730 行,所有逻辑集中于此)
|
||
├── 数据加载层
|
||
│ ├── _detect_has_clk() — 检测 CSV 是否有 clk 列
|
||
│ ├── load_sample_files() — 加载 CSV → item_dict + user_seq
|
||
│ ├── load_logids_from_file() — 快速提取文件中所有 logid
|
||
│ └── CTRUserDataset(Dataset) — 按用户组织的 CTR 数据集
|
||
│ └── make_collate_fn() — 将用户样本拼接为 batch(含 slot 特征展开)
|
||
├── 模型层
|
||
│ ├── RepEncoder — Slot-wise Embedding → LayerNorm → Linear
|
||
│ │ └── Embedding(5M vocab, 512d) × 28 slots → segment_reduce(sum) → concat
|
||
│ ├── TransformerEncoder (8 层)
|
||
│ │ ├── QKV Projection → Multi-Head Attention (scaled_dot_product)
|
||
│ │ ├── SMoE FFN(8 experts, Top-2 gating, 每层独立)
|
||
│ │ └── Pre-LayerNorm + Residual
|
||
│ ├── CTRModel — RepEncoder + Transformer → Linear → logit
|
||
│ │ └── Causal mask: 同一用户的 tokens 因果遮罩,不同用户隔离
|
||
│ └── load_model(ckpt_path, device) — 模型构建 + 权重加载入口
|
||
├── 推理循环 (main)
|
||
│ ├── 数据加载(优先缓存 shard_*.pt)
|
||
│ ├── 逐 batch 推理 + 计时(只计 model(batch) 耗时)
|
||
│ └── 按 test.csv 顺序写 predict.txt
|
||
└── 打分工具
|
||
└── _cal_score() — AUC + PCOC + latency → score_all
|
||
```
|
||
|
||
**模型参数规模**:Embedding 5M×512 + 8 层 Transformer (d_model=512, n_heads=8, dim_ff=1024) × MoE(8 experts) ≈ ~6.5M~11.3M 参数。
|
||
|
||
## 关键接口(评测系统调用契约)
|
||
|
||
评测系统通过 `from infer import ...` 加载代码,以下是**必须**对齐的接口(来自 `代码/任务提交接口说明.md`):
|
||
|
||
| 接口 | 签名 | 说明 |
|
||
|------|------|------|
|
||
| `load_sample_files` | `(sample_files_list: List[Path]) -> (item_dict, user_seq)` | 数据加载 |
|
||
| `CTRTestSeqDataset` | `(test_logids_ordered, item_dict, user_seq, max_feasign_per_slot, max_ctx_len)` | **必须有 `max_slot_id` 属性** |
|
||
| `make_collate_fn` | `(max_slot_id) -> Callable` | DataLoader 的 collate_fn |
|
||
| `load_model` | `(ckpt_path: Path) -> (model, device)` | 第一个参数是 Path |
|
||
| `move_batch_to_device` | `(batch, device) -> batch` | |
|
||
| `model(batch)` | `-> (logits, moe_loss)` | logits 经 sigmoid 后是点击概率 |
|
||
|
||
**致命不匹配**(baseline `infer.py` 当前存在,提交前必须修复):
|
||
1. 类名 `CTRUserDataset` → 应为 `CTRTestSeqDataset`
|
||
2. 构造参数 `pred_logids` → 应为 `test_logids_ordered`,缺少 `max_ctx_len`
|
||
3. `load_model(device='cuda:0', ckpt_path=None)` → 应为 `load_model(ckpt_path, device='cuda:0')`(Path 作为第一参数)
|
||
|
||
## 提交规范
|
||
|
||
### 压缩包结构
|
||
```
|
||
submit.zip
|
||
├── infer.py # 必需,实现上述全部接口
|
||
├── requirements.txt # 可选,阿里云 PyPI 镜像安装
|
||
└── build_env.sh # 可选,超时 720s,非 0 退出即失败
|
||
```
|
||
|
||
### 硬约束(任一违反 → 总分 0)
|
||
- 推理耗时 < 300s(只计 `model(batch)` 逐 batch 累加)
|
||
- AUC ∈ [0.65, 1.0],PCOC ∈ [0.85, 1.15]
|
||
- 压缩包内**不能**有 `dataset/` 或 `ckpt.pt`
|
||
- 包后缀只能是 `.zip`/`.tar.gz`/`.tar`,解压后文件在根目录
|
||
- 每天最多提交 10 次
|
||
|
||
### 总分公式
|
||
```
|
||
score_latency = max(0, (300 - latency) / 300)
|
||
score_model = ((AUC - 0.65) * 1000 + (0.15 - |PCOC - 1|) / 0.15 * 10) / 360
|
||
score_all = score_latency * 70 + score_model * 30
|
||
```
|
||
|
||
### 评测环境
|
||
|
||
- **硬件**: NVIDIA A800 (80GB, SM80)
|
||
- **软件**: Python 3.10 + PyTorch 2.6.0
|
||
- **评测数据集 ≠ baseline 数据集**(AUC 天然有差异)
|
||
|
||
### 优化合规边界(来自官方 Q&A)
|
||
|
||
| 操作 | 状态 | 说明 |
|
||
|------|------|------|
|
||
| 量化(FP16/INT8) | ✅ 允许 | |
|
||
| Flash Attention | ✅ 允许 | 数学等价实现 |
|
||
| 参数级剪枝/稀疏化(权重置零/mask,形状不变) | ✅ 允许 | 权重矩阵大小、层数、head 数、FFN 维度均不变 |
|
||
| 减少 Transformer 层数 | ❌ 违规 | 改变组网结构 |
|
||
| 减少 hidden 维度 | ❌ 违规 | 改变张量形状 |
|
||
| 删除 attention head | ❌ 违规 | 改变组网结构 |
|
||
| 减少 FFN channel | ❌ 违规 | 改变组网结构 |
|
||
| 序列采样/截断 | ❌ 违规 | |
|
||
| 对测试集训练 | ❌ 违规 | |
|
||
|
||
#### 剪枝细则(来自 Q&A #3)
|
||
|
||
- **结构化剪枝(❌ 不允许)**: 删除整层、整行/整列权重、减少 channel 数等,会改变张量形状或网络拓扑
|
||
- **非结构化剪枝(✅ 允许)**: 仅将单个权重置零或 mask 掉,不改变权重矩阵形状;可删除对输出贡献较小、冗余度高的部分,前提是结构不被破坏
|
||
|
||
> 关键边界:Linear 权重矩阵大小不变、Layer 数量不变、Attention head 数量不变、FFN 维度不变 → 属于合规的参数级剪枝
|
||
|
||
#### 评测细节
|
||
|
||
- **计时范围**: 仅 `model(batch)` 逐 batch 累加,`move_batch_to_device` 不计入
|
||
- **硬件**: NVIDIA A800 (80GB, SM80)
|
||
- **软件**: Python 3.10 + PyTorch 2.6.0
|
||
- **评测数据集 ≠ baseline 数据集**(AUC 天然有差异)
|
||
- **策略指标以 baseline 为上限**,指标下降会扣分,超出范围直接 0 分
|
||
- **人工审核**:最终成绩由人工审核判定合规性
|
||
|
||
## 数据分析
|
||
|
||
### 数据规模
|
||
|
||
| 维度 | 数值 |
|
||
|------|------|
|
||
| 历史数据 | 15 文件 × ~650K 行 = **923 万行**,15GB |
|
||
| 测试集 | **7,774 条预测**,13MB |
|
||
| 缓存 batch | 9 个 shard,17GB,共 **2,039 batch** |
|
||
| Slot 数量 | 1-28(28 个特征槽) |
|
||
|
||
### 数据格式
|
||
|
||
```
|
||
# History(5 列,含 clk):
|
||
logid,userid,adid,clk,timestamp,sign:slot,...
|
||
|
||
# Test(4 列,无 clk):
|
||
logid,userid,adid,timestamp,sign:slot,...
|
||
```
|
||
|
||
### 特征分布特征
|
||
|
||
1. **Slot 28 是瓶颈槽位**:每个样本含 30-50 个 `sign:28` 特征,远超其他 slot。`segment_reduce` 在 slot 28 上占据 RepEncoder 最大开销。
|
||
2. **Slot 19 高度冗余**:同一样本内连续出现大量相同 `sign:19`(如 `96:19` 重复 40+ 次)。在 `segment_reduce(sum)` 中,N 个相同 sign 等价于 `N × emb`,但代码独立查表 N 次再求和,浪费 embedding 带宽。
|
||
3. **特征极度稀疏**:百万级 sign id,每个样本仅 100-200 个 sign。Embedding 查表是主要内存瓶颈。
|
||
|
||
### 数据驱动的可优化方向
|
||
|
||
| 方向 | 合规性 | 预估收益 | 说明 |
|
||
|------|--------|----------|------|
|
||
| Slot 19 同值合并 | ⚠️ | 小 | N 个相同 sign 合并为 `N × emb`,减少 embedding 查表次数。属数据预处理灰区 |
|
||
| Slot 28 segment_reduce 融合 | ✅ | 中 | 将 slot 28 的大量 sign 预先按 offset 分桶,减少 kernel launch |
|
||
| Embedding 查表带宽 | ✅ | 小 | 已用 FP16,embedding 5M×512 约 5GB |
|
||
|
||
## 优化路线图(来自 `推理优化方案.md`)
|
||
|
||
Baseline 数据:推理 229s,AUC 0.759,PCOC 1.110,得分 25.85。
|
||
|
||
1. ✅ **接口对齐** — 确认能在评测系统跑通(得分 > 0)
|
||
2. ✅ **FP16 量化** — `model.half()`,Embedding 保留 FP32,152s
|
||
3. ✅ **Flash Attention** — 替换 `scaled_dot_product` 为 `F.scaled_dot_product_attention`,94.5s
|
||
4. ✅ **inference_mode()** — 替代 `no_grad()`,92.5s(+2s 小幅提升)
|
||
5. ✅ **SMoE 消除 GPU 同步** — 移除 mask.any()(64 次 GPU→CPU 同步/forward),88.1s
|
||
6. ✅ **Expert 权重相似度合并** — 余弦相似度 >0.90 的 expert 合并(权重平均),86.5s
|
||
7. ✅ **稠密向量化 MoE** — einsum 并行算 8 个 expert + gather 选取,消除 nonzero 同步(PR #1)
|
||
8. ✅ **RepEncoder 融合查表** — 28 slot 值拼成一条做单次 segment_reduce,减 per-batch kernel 启动(PR #1)
|
||
9. ✅ **Searchsorted 因果 mask** — 替代 repeat_interleave(张量repeats),消除最后同步点(PR #1)
|
||
10. ✅ **过滤无关用户** — 跳过不含测试样本的用户,省算力(PR #1)
|
||
11. ❌ **torch.compile** — 四种模式全验证,均反效果。CONFIG 默认 compile=false(注释:实测慢5×)
|
||
12. ❌ **MoE Top-1 gating** — PCOC 炸毁
|
||
13. ❌ **2:4 结构化稀疏** — 两次尝试均炸 PCOC
|
||
14. ❌ **INT8 量化** — CUDA 后端不支持
|
||
15. ❌ **varlen attention** — 本地 10.3s 但评测端 148s(慢 65%),已回退
|
||
16. ❌ **FlexAttention** — 比 SDPA 慢,未启用
|
||
|
||
已验证无效/失败:torch.compile(×4)、2:4 稀疏(×2)、MoE k=1(×2)、INT8、varlen attention、FlexAttention
|
||
|
||
## 关键文件
|
||
|
||
| 路径 | 用途 |
|
||
|------|------|
|
||
| `代码/code/infer.py` | 推理主脚本(提交的核心文件) |
|
||
| `代码/code/requirements.txt` | 服务端依赖(torch 2.6.0 + CUDA 12.4) |
|
||
| `代码/code/build_env.sh` | 环境构建脚本(目前为空壳) |
|
||
| `代码/任务提交接口说明.md` | 官方接口规范 |
|
||
| `推理优化方案.md` | 完整优化方案(含合规审查) |
|
||
| `论文/GRAB.pdf` | GRAB 论文 OCR markdown |
|
||
| `论文/HSTU.pdf` | HSTU 论文 OCR markdown |
|
||
| `论文/GRAB_*.pdf` | GRAB 论文(baseline 模型) |
|
||
| `论文/HSTU_*.pdf` | HSTU 论文(架构基础) |
|
||
| `.gitignore` | 排除 ckpt.pt, dataset/, *.zip, .venv/ |
|
||
|
||
## 提交记录
|
||
|
||
| 日期 | 提交次数 | 得分 | AUC | PCOC | 耗时 | 优化手段 | 备注 |
|
||
|------|----------|------|-----|------|------|----------|------|
|
||
| 06/15 | 19 | ? | ? | ? | ? | PR#1: 稠密MoE+融合查表+syncfree mask | 评测中 |
|
||
| 06/15 | 18 | 58.38 | 0.7526 | 1.059 | 88.5s | 旧版回退 | |
|
||
| 06/14 | 17 | **58.86** | 0.7526 | 1.059 | 86.5s | + Expert 相似度合并 | |
|
||
| 06/14 | 16 | 55.19 | 0.7526 | 1.059 | 102.2s | + Expert 合并 th=0.97 | 阈值过高 |
|
||
| 06/12 | 3 | 43.55 | 0.7525 | 1.059 | 152s | + FP16 量化 | |
|
||
|
||
### 团队成员
|
||
|
||
| AI Studio 用户名 | 真实姓名 |
|
||
|------------------|----------|
|
||
| qianban139 | 张君硕 |
|
||
| sidny1988 | 谢松熹 |
|
||
| (队长账号) | 刘航宇 |
|
||
|
||
### 竞品参考
|
||
|
||
| 用户 | 最高分 | 耗时 | AUC | PCOC |
|
||
|------|--------|------|-----|------|
|
||
| qianban139(张君硕) | **67.87** | 47.9s | 0.7525 | 1.059 |
|