600. HMS - Harmful Brain Activity Classification | hms-harmful-brain-activity-classification
我简直不敢相信能够通过每天一次实验,仅用少量实验就获得了一枚单人金牌。我现在非常开心,也非常感谢 Kaggle 社区的每一位分享者。感谢 Chris Deotte 为大家分享的精彩内容,也感谢 seanbearden 提供的两阶段训练思路。
在初期,我尝试了 Kaggle 频谱图,随后是 Kaggle + EEG 频谱图,再往后是 Kaggle + EEG 频谱图 + 原始 50 秒 EEG。最终,我采用了多模态模型,使用 4 种输入:Kaggle 频谱图、EEG 频谱图、原始 50 秒 EEG 数据和原始 10 秒 EEG 数据。模型包含 4 个独立的 backbone,分别处理各输入。我使用 50 秒(20 秒)原始 EEG 数据提取全局特征,使用 10 秒原始 EEG 数据提取局部特征。
我使用 GroupKFold,以 patient_id 作为分组依据。
eeg_id。我对 Kaggle 频谱图进行裁剪并做对数变换:
spec_img = np.clip(spec_img, np.exp(-4), np.exp(8))
spec_img = np.log(spec_img)
spec_img = np.nan_to_num(spec_img, nan=0.0)
使用均值和标准差进行归一化。
我使用 4 条链路,每条链路包含 4 个特征:
Fp1-F7, F7-T3, T3-T5, T5-O1 Fp1-F3, F3-C3, C3-P3, P3-O1 Fp2-F8, F8-T4, T4-T6, T6-O2 Fp2-F4, F4-C4, C4-P4, P4-O2
eeg_label_offset_seconds 裁剪原始 EEG 片段,并使用 signal.spectrogram 生成频谱图。将 16 张形状为 (128, 142) 的图像拼接成 4×4 的图像,形状为 (512, 568)。nperseg 从 70 改为 39,以生成更大的图像,形状为 (128, 256)。4×4 图像的新形状为 (512, 1024)。A.XYMasking。我使用 Adan 优化器配合单周期学习率调度器,模型 EMA 衰减为 0.995,使用梯度检查点。学习率 LR = 0.00017。Backbone 采用 timm 库中的 dinov2 vit 系列。训练时每个 epoch 随机选取一个 eeg_label_offset_seconds;评估时使用每个 eeg_id 的第一个 eeg_label_offset_seconds。
用 5 个 epoch 训练投票数 < 10 的数据。
用 7 个 epoch 训练投票数 ≥ 10 的数据。
使用 3×TTA,针对 10 秒原始 EEG 输入:向左平移 2 秒、居中、向右平移 2 秒。3×TTA 仅提升了一点公开分数,约 < 0.01。
| 模型 | OOF | OOF Kaggle 频谱 | OOF EEG 频谱 | OOF 全局原始 | OOF 局部原始 | Public | Private |
|---|---|---|---|---|---|---|---|
| 模型 1 | 0.221329 | 0.318149 | 0.267640 | 0.251836 | 0.264803 | 0.232427 | 0.289764 |
| 模型 2 | 0.217614 | 0.325917 | 0.266803 | 0.240895 | 0.264423 | 0.229686 | 0.287550 |
| 模型 3 | 0.217881 | 0.317720 | 0.268293 | 0.247168 | 0.263158 | 0.228330 | 0.285105 |
| 模型 4 | 0.218214 | 0.315174 | 0.264225 | 0.250879 | 0.263150 | 0.229865 | 0.290503 |
| 模型 5 | 0.223236 | 0.318931 | 0.334042 | 0.248258 | 0.261953 | 0.230250 | 0.287976 |
| 集成 | 0.22600 | 0.283302 |
我的方案不足之处是集成缺乏多样性。由于 GPU 显存限制,无法在所有 backbone 上使用 ViT‑Base 或 ViT‑Large。