返回列表

3rd Place Solution

683. NFL Big Data Bowl 2026 - Prediction | nfl-big-data-bowl-2026-prediction

开始: 2025-09-25 结束: 2025-12-03 运动员表现 数据算法赛
```html 第三名解决方案 - NFL 轨迹预测

第三名解决方案

预训练 - 微调:用于 NFL 轨迹预测的带有多种辅助损失函数的时空 Transformer
作者: heng (Grandmaster) 及团队 (yanqiangmiffy, 灵曜,sayoulala)
发布日期: 2026-01-15
竞赛排名: 第 3 名

首先,感谢 NFL、Kaggle 和所有组织者提供的数据和计算资源——这是我们唯一可以在场上测试模型的地方。

感谢我的队友们日夜不停地打磨特征、调整超参数和修复 bug;第三名的奖杯属于我们要所有人。

下面,我将分以下几个部分介绍我们的解决方案:

  1. 特征工程
  2. 数据集构建
  3. 数据增强
  4. 额外数据的使用
  5. 预训练与微调
  6. 模型架构
  7. 损失函数
  8. 训练正则化与优化
  9. 测试时增强 (TTA)
  10. 模型集成
  11. 无效的方法

特征工程

原始特征

x, y, s, a, dir, o, ball_land_x, ball_land_y, num_frames_output

速度分解

velocity_x, velocity_y

角度 / 运动方向

angle_to_ball, dir_rad

球员角色 / 掩码

player_side_bool, is_passer, is_receiver

几何距离

distance_to_passer, distance_to_receiver, distance_to_ball_land, passer_to_ball_land, receiver_to_ball_land

几何投影 / 面积

distance_to_passing_line, projection_on_passing_line, triangle_area_ratio (球员 - 四分卫 - 接球手构成的三角形面积比)

时间 / 全局上下文

time_elapsed

数据集构建

我们将每个 play 沿时间轴展开,并将 22 名球员布局为固定槽位(缺失的球员进行零填充)。槽位分配在每个 play 中仅执行一次:

  • 在每个 play_id 的第一帧 (frame_id = 1):
    a. 进攻方:按与传球手 (QB) 的欧几里得距离升序排列 11 名球员 → 槽位 0 … 10
    b. 防守方:按相同的距离升序排列 11 名球员 → 槽位 11 … 21
  • 此排序在整个 play 中是冻结的:所有后续帧、特征和标签都使用步骤 1 中创建的"nfl_id → slot"映射填充到张量中。
  • 数据集返回形状为 (batch_size, time_steps, players, features) 的张量。
  • 在比赛后期,我们发现确切的球员顺序几乎不重要;随机打乱球员并随机屏蔽其中一些作为增强带来了显著提升(参见“数据增强”部分)。

数据增强

  • 水平翻转:沿中场线 (y) 镜像左右;进攻/防守标签保持不变,路线变得对称。
  • 180° 旋转 (H + V):翻转 x 和 y;进攻/防守标签保持不变,路线保持对称。
  • 随机球员丢弃
    a. 统计第一帧中的有效球员数;如果 ≤ 4 则跳过。
    b. 随机选择 1–min(5, valid−4) 名球员,将其 36 帧张量归零 + 设置 mask = False。
    c. 将剩余球员推到前 k 个槽位,其余用零填充。
  • 随机球员重排序:在进攻和防守区域内应用 randperm,打破“槽位 0 = 离 QB 最近”的偏差,迫使模型依赖几何特征而不是槽位 ID。
  • 随机输入裁剪:如果 seq_len > 12,从头部丢弃 2–6 帧,保留至少 7 个尾部帧,然后用零填充回 36。

所有增强在验证期间均被禁用;仅使用原始数据以保持指标可比性。

额外数据的使用

我们将官方允许的 2018 追踪数据集 (2018nfldata) 纳入了训练。

数据过滤

2018nfldata 包含一个 event 列。根据 NFL 规则,我们将以下三个事件视为与本竞赛关键时刻等效:

  • ball_snap – 比赛开始
  • pass_forward – 球离开传球手的手
  • pass_arrived – 球变得可接住(飞行结束)

因此,我们只保留事件链为 ball_snap → pass_forward → pass_arrived 的 play。

输入 / 输出分割

  • 输入帧:从 ball_snap 到包括 pass_forward
  • 输出帧:从 pass_forward + 1 到包括 pass_arrived

ball_land_x / ball_land_y

team == 'football' 的行给出球的坐标。

我们取:

  • ball_land_x = xevent == 'pass_arrived' & team == 'football' 的行
  • ball_land_y = y 在同一行

球员角色

  • 传球手:2018nfldata/players.csv 中 position == 'QB' 的球员
  • 目标接球手:在 event == 'pass_arrived' 时距离 (ball_land_x, ball_land_y) 最近的进攻球员

预训练与微调

我们使用两阶段流程:

  • 预训练:在 2018nfldata + 2026 竞赛数据上,使用一小部分可信特征集:x, y, s, a, dir, o, ball_land_x, ball_land_y, distance_to_passer, num_frames_output, player_side_bool, velocity_x, velocity_y, time_elapsed(预训练模型的离线验证分数范围从 0.62 到 0.68)
  • 微调:构建一个新模型,添加一个小的线性“桥接”层(参见模型架构部分),加载预训练权重,然后在 2018nfldata + 2026 竞赛数据上,使用特征部分描述的完整特征栈进行微调。

模型架构

关键设计点

  1. 双路径:Graph-Transformer 路径捕捉球员间互动 (参考);主路径捕捉个体运动模式。
  2. 位置编码:分离的时间 + 球员嵌入以保持时空顺序。
  3. 掩码:处理每个 play 中有效球员数量的变化。
  4. 多任务:四个输出头提供丰富的监督。
  5. 残差连接:每个投影层都有跳过连接以避免梯度消失。
Model Architecture Diagram

其他说明

  1. Dropout:在每个模块中设置为 0;对于纯回归,任何 dropout 都有害。
  2. 宽度 vs 深度:宽而浅 (hidden_size=384, num_layers=2) 优于窄而深 (hidden_size=128, num_layers=6)。

损失函数

主要损失

TemporalHuberAdapted

  • 时间衰减权重:e^(−0.03·t)
  • 速度平滑度 (1 阶差分)
  • 加速度平滑度 (2 阶差分)

辅助损失

  • 帧间位移损失 (Inter-frame displacement loss)

输入序列内的自监督下一帧预测。

  1. 预测从每个输入帧到后续输入帧的变化
  2. 目标:时间一致性
  3. 监督:输入中已有的真实帧到帧的增量
a. i = 0: 预测整个序列 → 全局运动趋势
b. i = T-1: 从最后一帧预测 → 瞬时变化
c. 中间帧:学习多尺度运动
  • 终点预测损失 (End-point prediction loss)

迫使模型在每个时间步都“知道”最终目标。

  1. 预测从当前输入帧 (i = n) 到最终目标 (o = T) 的位移
  2. 每一步的终点感知
  3. 路径规划先验
  4. 全局收敛保证
  • 全时空对应损失 (Full spatio-temporal correspondence loss)
  1. 预测从任何输入帧 (i = n) 到任何输出帧 (o = m) 的位移 – 所有对
  2. 对每个可能的 (n, m) 对进行密集监督
  3. 一致性约束:来自不同起点的预测必须一致
方面 帧间 (Inter-frame) 终点 (End-point) 全时空 (Full spatio-temporal)
目标 输入 → 后续输入 输入 → 最终目标 输入 → 任何输出
时间链接 因果链 单方向 (到终点) 全连接
主要作用 运动建模 终点引导 时空一致性
计算成本 中等
提升 (LB) 0.02 0.01 0.003

总损失

loss = 1 × primary + 1 × inter-frame + 0.1 × end-point + 0.1 × full-correspondence

训练正则化与优化

  1. AdamW
  2. 分层学习率 (Layer-wise LR):线性层 3e-4, Transformer 5e-5
  3. 余弦退火 (Cosine annealing) 降至 1e-5
  4. 梯度裁剪 (Gradient clipping) max_norm = 1.0
  5. EMA (decay = 0.999) 用于验证和最终模型 – 仅微调阶段

测试时增强 (TTA)

在推理时,我们应用两种增强:

  1. 水平翻转
  2. 随机输入裁剪

单模型预测是加权平均:

pred = 0.50 * pred_orig + 0.25 * pred_tta1 + 0.25 * pred_tta2

添加更多增强并没有带来提升。

模型集成

我们使用 game_id 7 GroupKFold 离线训练了七个模型:(每个模型 50 个 epoch),cv 约为 0.469。我们获得了 LB 分数 0.458。

最后,通过集成四个 7 折交叉验证模型(不同种子),我们实现了轻微的提升。简单平均后的公共 LB 分数:0.456。

无效的方法

  1. 更多的几何距离 / 几何投影 / 面积特征
  2. 按与接球手的距离而不是 QB 的距离重新排序球员
  3. 额外的增强:小角度旋转、每步噪声、时间掩码 + 线性填充
  4. 更大的模型
```
同比赛其他方案