返回列表

42th Solution (Late sub private=0.854)

665. CMI - Detect Behavior with Sensor Data | cmi-detect-behavior-with-sensor-data

开始: 2025-05-30 结束: 2025-09-02 健康管理与公共卫生 数据算法赛
第 42 名解决方案(晚期提交 私榜=0.854)

第 42 名解决方案(晚期提交 私榜=0.854)

左右手不变方法

作者: Bilzard (tatamikenn)
发布时间: 2025-09-06
竞赛: CMI - Detect Behavior with Sensor Data

TL; DR (太长不看)

  • 将左手传感器数据转换为伪右手数据,我认为这导致私榜波动不大。
  • 三塔模型,由 IMU/ToF/IMU+ToF 分支组成。
  • 多模态训练略微稳定:手势、方向、目标类型、行为。
  • 关键因素:为每个目标拆分时间注意力模块是关键(我假设不同的时间帧对每个目标很重要)。

架构

模型架构
  • 早期模型在时间注意力模块之前有 squeezeformer 块,但后来这些块被丢弃了,因为仅使用几层时间注意力模块表现相当。
  • 开发了用 CrossAttention、BERT、LSTM 替换时间注意力模块的架构。其中,BERT 是最好的,但 LSTM 模型似乎在集成中表现出更好的正交性。

结果

单一架构 (5 折交叉验证)

模型 ID 模型 模型数量 数据增强 集成方法 翻转校正 交叉验证 (仅 IMU, 完整) 公榜 私榜
1 d01_sf_mca_sp_triple_tower_v4_1_l3_b3_cdf_stm256 5 heavy12 prob - 0.825 (0.787, 0.863) - -
2 d01_sf_mca_sp_triple_tower_v4_1_l3_b3_cdf_stm256 5 heavy13 prob - 0.839 (0.811, 0.867) 0.842 0.832
3 d05_sf_bert_isolated_ncl_full_l0_b6_cdf_stm128 5 heavy14 prob - 0.843 (0.809, 0.878) 0.845 0.840
3 d05_sf_bert_isolated_ncl_full_l0_b6_cdf_stm128 5 heavy14 prob 0.843 (0.809, 0.878) 0.845 0.846
4 d09_bilstm_isolated_ncl_full_b1 5 heavy15 prob - 0.845 (0.814, 0.875) 0.841 0.832
5 d09_3b_bert_null_emb_isolated_ncl_full_b12 5 heavy15 prob - 0.849 (0.812, 0.885) 0.838 0.833
  • l{n}_b{m} 表示 n 层 squeezeformer 和 m 层时间注意力模块。

集成

集成 ID 模型 模型数量 集成方法 翻转校正 交叉验证 (仅 IMU, 完整) 公榜 私榜 备注
top3 ensemble {3,4,5} 15 prob - 0.858 (0.826, 0.890) 0.853 0.841 最终提交
top4 ensemble {2,3,4,5} 20 prob - 0.861 (0.83, 0.892) 0.853 0.843 最终提交
top4 ensemble {2,3,4,5} 20 rank - 0.859 (0.828, 0.89) 0.852 0.844 晚期提交
top4 ensemble {2,3,4,5} 20 prob 0.861 (0.83, 0.892) 0.853 0.854 晚期提交

将左手传感器数据转换为伪右手传感器数据

  • 将左手数据转换为“模仿”右手数据。
  • 我没有在 LB 上测试,但在交叉验证中始终比原始数据表现更好。
不变变换 ToF

概念和手写笔记已分享于此:
https://www.kaggle.com/competitions/cmi-detect-behavior-with-sensor-data/discussion/603566

与 Jack 的方法几乎相同,因此此处省略细节。
https://www.kaggle.com/competitions/cmi-detect-behavior-with-sensor-data/writeups/6th-place-solution

训练集中翻转主体的数据校正

同上。

私榜测试集中翻转主体的数据校正 [晚期提交]

  • 通过应用翻转主体的逆变换自动生成翻转数据,概率 p=0.066。
  • 使用类似于手势分类模型的架构训练分类器 100 个 epoch。

结果

  • 精确率 (Precision): 0.996
  • 召回率 (Recall): 0.980

如果概率 > 0.5 则进行数据校正 -> 私榜提高了 +0.01 (0.844 -> 0.854),这是一个显著的影响。

翻转检测截图

其他训练细节

  • 余弦调度 (cosine schedule),每个 epoch 重启 -> 相比单周期余弦调度略微稳定。
    • 注意,这种调度被视为一种“无调度”训练,如果有检查点可用,我们可以在任何 epoch 重启训练。
训练调度截图
  • 数据增强
    • 用具有相同方向/手势的不同序列采样替换非手势帧 -> 交叉验证略有改善。
    • 仅在手势帧上重采样。
    • 绕 Z 轴旋转 (-90, 90)。
    • 其他增强稳定了训练,但对交叉验证改进较小。
    "heavy15": Compose(
        # Resample All Series
        RandomCropOnlyGesture(max_crop_ratio=0.5, min_gesture_length=10, p=1.0),
        Choice(
            RandomResampleOnlyGestureV2(resample_rate_range=(1.0, 2.0), p=0.4),
            RandomResampleOnlyGestureV2(resample_rate_range=(0.5, 1.0), p=0.2),
            ResampleOnlyGesture(sample_rate=(1.0, 1.2), p=0.2),
            p=0.8,
        ),
        # IMU Transformations
        Compose(
            RandomRotateZ(angle_range=90, p=1.0),
            RandomEulerRotation(
                angle_range=20,
                transform_features=("acc",),
                p=1.0,
            ),
            Choice(
                RandomEye(["sensor_basis_world"]),
                RandomZeroOut(["acc"]),
                p=0.15,
            ),
        ),
        # ToF/Thermo Transformations
        Compose(
            RandomAffine(
                keys=("tof",),
                translate_range=(-1, 1),
                rotation_range=(-15, 15),
                scale_range=(0.9, 1.1),
                p=0.3,
            ),
            RandomAdditiveNoise(key="thermo", shift=1.0, scale=0.3, p=0.3),
            RandomAdditiveNoise(key="tof", shift=5.0, scale=10.0, p=0.3),
            SensorChannelDropout(key="tof", drop_prob=0.5, p=0.5),
            SensorChannelDropout(key="thermo", drop_prob=0.5, p=0.5),
            Choice(
                RandomZeroOut(["thermo"]),
                RandomZeroOut(["tof"]),
                p=0.25,
            ),
        ),
        Choice(
            # Completely Drop ToF/Thermo or IMU data
            RandomZeroOut(["tof", "thermo"], p=0.7),
            Compose(RandomEye(["sensor_basis_world"]), RandomZeroOut(["acc"]), p=0.05),
            Identity(p=0.25),
        ),
    ),
同比赛其他方案