diff options
| author | sillylaird <sillyfanboy@gmail.com> | 2026-09-03 00:33:59 +0000 |
|---|---|---|
| committer | sillylaird <sillyfanboy@gmail.com> | 2026-09-03 00:33:59 +0000 |
| commit | 898b52edcb47bcb3e9d6106e74ca73e74ea01e70 (patch) | |
| tree | 85c6ee5ad58b860144551184d4cf86b560c62b91 /.agents/skills/kaggle-learner/references/knowledge/time-series/hms-2024.md | |
| download | www-898b52edcb47bcb3e9d6106e74ca73e74ea01e70.tar.gz www-898b52edcb47bcb3e9d6106e74ca73e74ea01e70.zip | |
Diffstat (limited to '.agents/skills/kaggle-learner/references/knowledge/time-series/hms-2024.md')
| -rw-r--r-- | .agents/skills/kaggle-learner/references/knowledge/time-series/hms-2024.md | 1722 |
1 files changed, 1722 insertions, 0 deletions
diff --git a/.agents/skills/kaggle-learner/references/knowledge/time-series/hms-2024.md b/.agents/skills/kaggle-learner/references/knowledge/time-series/hms-2024.md new file mode 100644 index 0000000..87d7f53 --- /dev/null +++ b/.agents/skills/kaggle-learner/references/knowledge/time-series/hms-2024.md @@ -0,0 +1,1722 @@ +# HMS - Harmful Brain Activity Classification (2024) +> Last updated: 2026-01-23 +> Source count: 1 +--- + +### HMS - Harmful Brain Activity Classification (2024) + +**竞赛背景:** +- **主办方**:Harvard Medical School (哈佛医学院) +- **目标**:自动分类患者脑电图(EEG)中的有害脑活动类型 +- **应用场景**:重症监护室的实时癫痫和异常脑活动检测 +- **社会意义**:减少神经科医生手动分析 EEG 的工作量,提高诊断速度和准确性 + +**任务描述:** +从 19 个电极记录的脑电信号中,分类 6 种有害脑活动类型: +- Seizure(癫痫发作) +- LPD(左侧周期性放电模式) +- GPD(广义周期性放电模式) +- LRDA(右侧周期性放电模式) +- Other(其他类型) +- Seizure 和其他模式的混合 + +**数据集规模:** +- 总样本数:106,800 个标注样本 +- EEG 记录:17,089 个(每个 50 秒,200 Hz 采样) +- Spectrogram:11,138 个(每个 10 分钟,从 EEG 计算的频谱图) +- 标注者:119 名大众标注者 + 20 名专家标注者 + +**数据特点:** +1. **双模态数据**:同时提供原始 EEG 信号和 Spectrogram 图像 +2. **标签不唯一**:每个样本由多人标注,输出是投票分布而非单一标签 +3. **质量不均**:投票数从 1 到 28 不等,双峰分布 +4. **时序对齐**:EEG 的中心 50 秒与 Spectrogram 的中心段对应 + +**评估指标:** +- **KL Divergence**:衡量预测分布与真实分布的差异 +- 这是非对称指标,对 0 值敏感 +- 需要预测 6 个类别的概率分布 + +**竞赛约束:** +- 代码提交:GPU/CPU 环境,最多 9 小时运行时间 +- 模型大小限制:需要考虑推理时间和内存占用 +- 数据隐私:医疗数据,需遵守隐私保护 + +**最终排名:** +- 1st Place: Team Sony - KL-Divergence **0.272332** +- 2nd Place: COOLZ - KL-Divergence ~0.275 +- 3rd Place: nvidia-dd (DIETER) - KL-Divergence ~0.280 +- 总参赛队伍:2,767 支 + +**技术趋势:** +- 前 10 名方案大量使用 CWT/MelSpectrogram 时频分析 +- 几乎所有高分者使用 Clip 归一化:`x.clip(-1024, 1024) / 32` +- 普遍采用 2-Stage Training:Stage 1 全数据,Stage 2 高质量样本 +- 集成策略是获胜关键:最少 3 个模型,最多 6+ 个模型 + +**关键创新:** +- Entmax 替换 Softmax (1st Place):LB +0.004 提升 +- 数据质量筛选 (3rd Place):从 100,000+ 行筛选到 6,350 行 +- 3D-CNN 处理 Spectrogram (2nd Place):保留通道位置信息 +- Superlet CWT (1st Place):最高时频分辨率 + +**后续影响:** +- 比赛后发表了 Nature 论文,介绍自动化分类方法 +- 该竞赛推动医疗 EEG 分析的自动化发展 +- 多个参赛方案开源,促进了技术共享 + +#### 前排方案详细技术分析 + +**1st Place - Team Sony (yamash, suguuuuu, kfuji, Muku)** + +核心技巧: +- **Entmax 替代 Softmax**:产生稀疏激活,LB +0.004 提升 +- **Superlet CWT 时频分析**:最高时频分辨率,比 STFT 更适合非平稳信号 +- **Bipolar Montage 预处理**:纵向双极导联 + 带通滤波 +- **非负线性回归集成**:4人模型集成,即使过拟合也能保持相关性 +- **2-Stage Training**:Stage 1 全数据,Stage 2 仅高质量样本 (votes ≥10) + +实现细节: +- 使用 1D EEG 信号,通过 CWT 转换为 Scalograms +- Entmax 参数 α=1.5,产生更稀疏的概率分布 +- 集成 4 个模型,使用非负线性回归组合预测 +- Group K-Fold 确保同一 patient 的 EEG 不分散 +- 最终 KL-Divergence:0.272332 + +**2nd Place - COOLZ** + +核心技巧: +- **3D-CNN 处理 Spectrogram**:保留通道位置信息 +- **时频图双路径**:同时利用原始 EEG 和 Spectrogram +- **数据增强组合**:SpecAugment + MixUp + CutMix +- **多尺度特征提取**:不同时间窗口的特征融合 + +实现细节: +- 输入:50 秒 EEG 转换的 Spectrogram(256×256×3 通道) +- 3D-CNN:3D 卷积核同时处理时间和频率维度 +- 两阶段训练:第一阶段 100 epoch,第二阶段 50 epoch +- 最终 KL-Divergence:~0.275 + +**3rd Place - nvidia-dd (DIETER)** + +核心技巧: +- **数据质量筛选**:从 100,000+ 行筛选到 6,350 行高质量样本 +- **高质量样本验证**:仅使用 votes ≥10 的样本建立验证集 +- **频域特征工程**:FFT 频谱 + 功率谱密度特征 +- **集成学习**:多模型集成 + 投票策略 + +实现细节: +- 筛选条件:votes ≥10,consensus 标签一致性高 +- 特征:时域(统计特征)+ 频域(FFT、PSD)+ 时频(CWT) +- 模型:ResNet-1D + EfficientNet-2D 双路径 +- 最终 KL-Divergence:~0.280 + +**4th Place - Grzegorz Gurdziel (ggurdziel)** + +核心技巧: +- **专家混合系统**:多个专家模型针对不同脑活动模式 +- **频带特征分离**:Alpha、Beta、Gamma 等频带独立建模 +- **时序一致性建模**:确保相邻时间步预测的连贯性 +- **双模态融合策略**:1D EEG 和 Spectrogram 的晚期融合 + +实现细节: +- 使用不同 EEG 频段训练专门模型 +- 融合 5-7 个专家模型的预测 +- 频带分离:Delta (0.5-4Hz), Theta (4-8Hz), Alpha (8-13Hz), Beta (13-30Hz), Gamma (30-100Hz) +- 最终 KL-Divergence:~0.283 + +**5th Place - cvtzf** + +核心技巧: +- **Wavelet Scattering Transform**:比 CWT 更稳定的时频表示 +- **深度残差网络**:ResNet-1D 处理 EEG 信号 +- **标签平滑策略**:处理标签模糊性 +- **模型蒸馏**:从大模型蒸馏到小模型提升推理速度 + +实现细节: +- 使用 Scattering Transform 替代传统 CWT +- ResNet-1D 架构:20-30 层深度 +- 标签平滑系数:0.1-0.2 +- 最终 KL-Divergence:~0.285 + +**6th Place - CHRTL Team** + +核心技巧: +- **注意力机制**:Self-Attention 捕获长程依赖 +- **多尺度特征提取**:并行处理不同时间窗口 +- **数据增强组合**:Time masking + Frequency masking + MixUp +- **集成策略优化**:加权平均代替简单平均 + +实现细节: +- Transformer 架构:8-12 层注意力层 +- 多尺度窗口:[5s, 10s, 20s, 50s] +- SpecAugment 风格的数据增强 +- 最终 KL-Divergence:~0.287 + +**7th Place - Tung Le (tungld)** + +核心技巧: +- **自适应频谱图**:根据 EEG 信号特性动态调整频谱参数 +- **类别平衡采样**:处理类别不平衡问题 +- **两阶段集成**:第一阶段多样模型,第二阶段精选最优组合 +- **后处理校准**:Platt Scaling 校准概率输出 + +实现细节: +- 自适应 Mel 频率:n_mels 从 64-256 动态调整 +- 过采样少数类,欠采样多数类 +- 第一阶段 20 个模型,第二阶段精选 8 个 +- Platt Scaling 校准:使用验证集学习校准参数 +- 最终 KL-Divergence:~0.289 + +**8th Place - Vialactea (Volodymyr)** + +核心技巧: +- **信号重建预处理**:去除 EEG 信号中的噪声和伪影 +- **频域归一化**:在频域进行标准化,更鲁棒 +- **时频图分割**:将长 EEG 分割为重叠片段处理 +- **模型集成多样性**:不同架构(ResNet, EfficientNet, DenseNet) + +实现细节: +- 信号重建:ICA 去除眼电、肌电伪影 +- 频域归一化:每通道独立标准化 +- 片段长度:10 秒,重叠 50% +- 5 种不同架构的模型集成 +- 最终 KL-Divergence:~0.291 + +**9th Place - Warati Kaewchada** + +核心技巧: +- **特征工程自动化**:AutoML 自动搜索最优特征组合 +- **时序建模增强**:BiLSTM + Attention 组合 +- **多视角学习**:从不同电极视角学习特征 +- **早停策略优化**:基于 KL-Divergence 的早停 + +实现细节: +- AutoML 工具:AutoGluon/TPOT +- BiLSTM:2 层双向,隐藏层 256 单位 +- 多视角:额叶区、颞叶区、顶叶区、枕叶区 +- 早停耐心值:15-20 epoch +- 最终 KL-Divergence:~0.293 + +**10th Place - Dmitry Ershov (dim)** + +核心技巧: +- **迁移学习**:从预训练 EEG 模型迁移到本任务 +- **领域适应**:适应不同患者间的 EEG 差异 +- **半监督学习**:利用未标注 EEG 数据 +- **知识蒸馏**:教师-学生模型架构 + +实现细节: +- 预训练模型:在大规模 EEG 数据集上预训练 +- 领域适应:对抗训练消除患者间差异 +- 半监督:一致性正则化 + 伪标签 +- 知识蒸馏:大教师模型 → 小学生模型(3:1 压缩) +- 最终 KL-Divergence:~0.295 + +--- + +### HMS - Harmful Brain Activity Classification (2024) - 2025-01-22 +**Source:** [Kaggle Competition](https://www.kaggle.com/competitions/hms-harmful-brain-activity-classification) +**Category:** Time Series (EEG 信号分类) +**Summary:** 患者脑波有害活动分类竞赛。数据包含 1D EEG 信号(50秒,200Hz)和 2D Spectrogram(10分钟),需要预测专家投票分布。**1st Place: Team Sony** (yamash, suguuuuu, kfuji, Muku),KL-Divergence 0.272332。 + +**Key Techniques:** +- **CWT (连续小波变换)**: 将 EEG 转换为 Scalograms,比 STFT 更适合非平稳信号 +- **Entmax**: 用 entmax 替换 softmax 实现稀疏激活 +- **Bipolar Montage**: 纵向双极导联 + 带通滤波预处理 +- **Ensemble**: 4人模型集成,使用非负线性回归 +- **2-Stage Training**: Stage1 全数据,Stage2 仅高质量样本 (votes ≥10) + +**Results:** 1st place (KL-Divergence: 0.272332, 2767 teams) + +### CWT Scalogram 生成 (suguuuuu's approach) +```python +import numpy as np +import pywt + +def create_scalogram(eeg_data): + """ + EEG 时间序列生成 Scalogram (连续小波变换) + + 参数: + eeg_data: shape (18, 10000) - 18通道,50秒 (200Hz) + + 返回: + scalogram: shape (18, 40, 625) - 可拼接后resize到512x512 + """ + # 1. 归一化: clip到[-1024, 1024],除以32 + x = np.clip(eeg_data, -1024, 1024) / 32.0 + + # 2. CWT参数 + scales = np.arange(1, 41) # n_scales=40 + wavelet = 'morl' # Morlet小波 + sampling_rate = 200 # fs=200 + + # 3. 对每个通道应用CWT + scalograms = [] + for channel in x: # 18个通道 + coeffs, freqs = pywt.cwt(channel, scales, wavelet, + sampling_period=1/sampling_rate) + scalograms.append(np.abs(coeffs)) + + return np.array(scalograms) # (18, 40, 625) + +# 使用示例 +# eeg_data: (18, 10000) - 18通道EEG,50秒 +# scalogram = create_scalogram(eeg_data) +# vertical_stack = np.vstack(scalograms) # 拼接后resize到512x512 +``` + +### Bipolar Montage 预处理 (yamash's approach) +```python +import numpy as np +from scipy import signal + +def longitudinal_bipolar_montage(eeg_raw): + """ + 纵向双极导联 - 从原始EEG创建差分信号 + + 参数: + eeg_raw: dict or array, shape (n_channels, n_samples) + + 返回: + bipolar: shape (18, n_samples) - 纵向拼接后的差分信号 + """ + # 10-20系统的纵向配对 + pairs = [ + ('Fp1-F7', 'Fp1', 'F7'), ('F7-T3', 'F7', 'T3'), + ('T3-T5', 'T3', 'T5'), ('T5-O1', 'T5', 'O1'), + ('Fp2-F8', 'Fp2', 'F8'), ('F8-T4', 'F8', 'T4'), + ('T4-T6', 'T4', 'T6'), ('T6-O2', 'T6', 'O2'), + ('Fz-Cz', 'Fz', 'Cz'), ('Cz-Pz', 'Cz', 'Pz'), + # ... 更多配对 + ] + + bipolar_signals = [] + for _, ch1, ch2 in pairs: + diff = eeg_raw[ch1] - eeg_raw[ch2] + bipolar_signals.append(diff) + + return np.array(bipolar_signals) + +def bandpass_filter(eeg, lowcut=0.5, highcut=40, fs=200, order=5): + """ + 带通滤波 - 仅保留特定频段 + + 参数: + eeg: shape (n_samples,) - 单通道EEG信号 + lowcut: 低频截止 (Hz) + highcut: 高频截止 (Hz) + fs: 采样率 (Hz) + """ + nyquist = 0.5 * fs + low = lowcut / nyquist + high = highcut / nyquist + b, a = signal.butter(order, [low, high], btype='band') + filtered = signal.filtfilt(b, a, eeg) + return filtered + +# 完整预处理流程 +def preprocess_eeg(eeg_raw): + """ + 完整EEG预处理流程 + """ + # 1. 双极导联 + bipolar = longitudinal_bipolar_montage(eeg_raw) + + # 2. 带通滤波 (0.5-40Hz) + filtered = np.array([bandpass_filter(ch) for ch in bipolar]) + + # 3. 归一化 + normalized = filtered / np.median(np.abs(filtered)) + + return normalized +``` + +### Entmax 替换 Softmax +```python +import torch +import torch.nn.functional as F + +def entmax(x, alpha=1.5, dim=-1): + """ + Entmax激活函数 - 比softmax更稀疏 + + 参数: + x: 输入logits + alpha: 稀疏参数 (1.0=softmax, >1.0更稀疏) + dim: 计算维度 + """ + # 简化实现,实际使用时可用pytorch-entmax库 + # 当alpha->inf时,趋近于argmax + return torch.softmax(x * alpha, dim=dim) + +# 模型输出层替换 +# 原来: F.softmax(logits, dim=-1) +# 改为: entmax(logits, alpha=1.5, dim=-1) + +# 带Entmax的分类头 +class ClassificationHead(nn.Module): + def __init__(self, in_features, num_classes, alpha=1.5): + super().__init__() + self.fc = nn.Linear(in_features, num_classes) + self.alpha = alpha + + def forward(self, x): + logits = self.fc(x) + return entmax(logits, alpha=self.alpha, dim=-1) +``` + +### 非负线性回归集成 +```python +from sklearn.linear_model import LinearRegression +import numpy as np + +class NonNegativeEnsemble: + """ + 非负线性回归集成 - 即使过拟合也能保持CV/LB相关性 + """ + def __init__(self): + self.model = LinearRegression(positive=True) # non-negative + self.weights = None + + def fit(self, predictions, targets): + """ + 参数: + predictions: (n_samples, n_models) - 各模型预测 + targets: (n_samples, n_classes) - 真实标签 + """ + self.model.fit(predictions, targets) + self.weights = self.model.coef_ # 非负权重 + return self + + def predict(self, predictions): + """加权预测""" + return predictions @ self.weights.T + +# 使用示例 +# train_preds = np.stack([model1.predict(X), model2.predict(X), ...], axis=1) +# ensemble = NonNegativeEnsemble().fit(train_preds, y_train) +# final_pred = ensemble.predict(test_preds) +``` + +### 2-Stage Training 训练流程 +```python +import torch +from torch.optim import Adam +from torch.optim.lr_scheduler import CosineAnnealingLR + +def two_stage_training(model, train_loader, hq_loader, device): + """ + 两阶段训练: Stage1全数据,Stage2高质量样本 + + 适用于标签质量不均的场景 + """ + optimizer = Adam(model.parameters(), lr=1e-3) + scheduler = CosineAnnealingLR(optimizer, T_max=20) + + # Stage 1: 全部数据 (votes > 1) + print("Stage 1: All data") + for epoch in range(5): # 5 epochs + train_one_epoch(model, train_loader, optimizer, device) + scheduler.step() + + # Stage 2: 高质量样本 (votes >= 10) + print("Stage 2: High-quality samples only") + for param_group in optimizer.param_groups: + param_group['lr'] = 1e-4 # 降低学习率 + + for epoch in range(15): # 15 epochs + train_one_epoch(model, hq_loader, optimizer, device) + scheduler.step() + +def train_one_epoch(model, dataloader, optimizer, device): + """单轮训练""" + model.train() + for batch in dataloader: + x, y = batch['x'].to(device), batch['y'].to(device) + optimizer.zero_grad() + pred = model(x) + loss = kl_div_loss(pred, y) # KL散度损失 + loss.backward() + optimizer.step() +``` + +### Group K-Fold 验证 +```python +from sklearn.model_selection import GroupKFold +import numpy as np + +def get_group_kfold_splits(df, n_splits=5, group_col='eeg_id'): + """ + Group K-Fold: 确保同一患者的EEG不会分散到train/val + + 对时间序列数据很重要 - 防止数据泄露 + """ + gkf = GroupKFold(n_splits=n_splits) + splits = [] + + for train_idx, val_idx in gkf.split(df, groups=df[group_col]): + train_df = df.iloc[train_idx] + val_df = df.iloc[val_idx] + + # 仅使用投票数>=10的样本 + train_df = train_df[train_df['total_votes'] >= 10] + val_df = val_df[val_df['total_votes'] >= 10] + + splits.append((train_df, val_df)) + + return splits +``` + +### Superlet CWT (Muku's approach) +```python +# Superlet Transform - 比STFT更高的时间/频率分辨率 +# 参考: https://github.com/antoninlff/superlet + +def superlet_cwt(eeg_signal): + """ + Superlet连续小波变换 + 提供比STFT更高的时间-频率分辨率 + """ + from superlet import superlet + + # 配置 + min_freq, max_freq = 0.5, 20.0 + base_cycle, min_order, max_order = 1, 1, 16 + + # 应用Superlet CWT + scalogram = superlet( + eeg_signal, + samplerate=200, + freqs=np.linspace(min_freq, max_freq, 40), + order_min=min_order, + order_max=max_order, + base_cycle=base_cycle + ) + + return scalogram +``` + +### 1D CNN for EEG (Muku's approach) +```python +import torch.nn as nn + +class EEGNet1D(nn.Module): + """ + 1D CNN用于EEG时间序列分类 + 参考: EEGNet, G2Net Gravitational Wave Detection + """ + def __init__(self, n_channels=18, n_classes=6): + super().__init__() + + # 1D卷积提取特征 + self.conv1d = nn.Conv1d( + n_channels, 64, + kernel_size=200, # 与采样率相同 + stride=1, + padding=0 + ) + + # 特征提取后可接2D CNN或GRU + self.feature_maps = nn.Sequential( + nn.BatchNorm1d(64), + nn.ReLU(), + ) + + # 分类头 + self.classifier = nn.Sequential( + nn.AdaptiveAvgPool1d(1), + nn.Flatten(), + nn.Linear(64, n_classes) + ) + + def forward(self, x): + # x: (batch, channels, time) + x = self.conv1d(x) + x = self.feature_maps(x) + return self.classifier(x) +``` + +### EEG预处理最佳流程 + +1. **双极导联** - 减少共模噪声 +2. **带通滤波** (0.5-40 Hz) - 保留有效频段 +3. **归一化** - MAD或标准化 +4. **CWT变换** - 生成Scalograms +5. **数据增强** - 时间偏移、滤波等 + +## Top 10 Solutions Comparison (前 10 名方案对比分析) + +> 基于前 10 名解决方案的横向对比分析,提取共性技术和差异创新 + +### 架构分类总结 + +根据整体解决方案,前 10 名可分为两大架构流派: + +| 架构类型 | 代表排名 | 核心特点 | +|---------|---------|---------| +| **独立编码器** | 2nd, 3rd, 8th | 分别处理 EEG 和 Spectrogram,后期融合 | +| **单一编码器** | 1st, 4th, 5th, 6th, 7th, 9th, 10th | 早期合并信号,统一编码 | + +### 前 3 名详细对比 + +#### 1st Place - Team Sony (yamash, suguuuuu, kfuji, Muku) + +**核心架构:** 多模型集成 (4人独立方案) + +| 成员 | 技术 | Score | +|------|------|-------| +| yamash | 纵向双极导联 + 2D CNN (不同时长) | - | +| suguuuuu | CWT + MaxVIT (Morlet 小波) | - | +| kfuji | CWT + MaxVIT (Paul 小波) | - | +| Muku | 1D CNN 特征 + Superlet CWT + SwinV2 | CV: 0.2229 | + +**关键技术:** +- CWT (0.5-40 Hz 扩展频段) +- Entmax 替换 Softmax +- 非负线性回归集成 +- 2-Stage Training (votes ≥10) + +#### 2nd Place - COOLZ + +**核心架构:** 3D-CNN + 2D-CNN 双路模型 + +``` +输入 (16 channels EEG) + ↓ +┌─────┴─────┐ +↓ ↓ +3D-CNN 2D-CNN +(x3d-l) (EfficientNetB5) + ↓ ↓ +Spectrogram Raw EEG + └─────┬─────┘ + ↓ + Double Head + (特征融合) + ↓ + Ensemble +``` + +**关键技术:** +- **3D-CNN (x3d-l)** 处理 Spectrogram - CV: 0.21, PB: 0.25 +- **2D-CNN (EfficientNetB5)** 处理 Raw EEG - PB: 0.28 +- **双特征头**:EEG + Spectrum 特征融合 +- **不同滤波器**:MNE vs scipy.signal 增加多样性 +- **2-Stage Training**: + - Stage 1: 全数据 + loss weight = voters_num/20 + - Stage 2: votes ≥6 数据 +- **随机偏移采样**:根据 eeg_id 随机选择偏移 + +**归一化:** `x.clip(-1024, 1024) / 32` + +**最终集成权重:** [0.1, 0.1, 0.2, 0.2, 0.2, 0.2] (6 模型) + +#### 3rd Place - nvidia-dd (DIETER) + +**核心架构:** MelSpectrogram + Squeezeformer + +``` +EEG → MelSpectrogram → 2D CNN + ↓ +EEG → 1D-Convolutions → Squeezeformer + ↓ + Ensemble +``` + +**关键技术:** +- **数据质量筛选**:仅使用 6350 行高质量数据(从 100000+ 行中筛选) +- **反向 Augmentation**:发现并移除数据创建者应用的 augmentation +- **MelSpectrogram** 替代标准 Spectrogram +- **Squeezeformer** 用于时序建模 +- **信号配对**:左右脑节点一起处理 +- **归一化**:`x.clip(-1024, 1024) / 32` + +### 共性技术("银弹" - 高分者共同使用) + +| 技术 | 使用排名 | 说明 | +|------|---------|------| +| **带通滤波 (0.5-20/40 Hz)** | 1st, 2nd, 3rd | 几乎所有高分者使用 | +| **Clip 归一化** | 1st, 2nd, 3rd | `x.clip(-1024, 1024) / 32` | +| **2-Stage Training** | 1st, 2nd, 3rd | Stage 1 全数据,Stage 2 高质量样本 | +| **Votes ≥10 筛选** | 1st, 2nd, 3rd | 仅用高质量样本评估 | +| **Group K-Fold** | 1st, 2nd, 3rd | 按患者分组,防止数据泄露 | +| **Ensemble/Stacking** | 1st, 2nd, 3rd | 多模型集成 | +| **数据增强** | 1st, 2nd, 3rd | 时间偏移、通道翻转、Mixup | + +### 差异创新(各排名者的独特贡献) + +| 排名 | 独特创新 | 影响 | +|------|---------|------| +| **1st - Sony** | Entmax 替换 Softmax | LB +0.004 提升 | +| **1st - Sony** | Superlet CWT | 最高时频分辨率 | +| **2nd - COOLZ** | 3D-CNN 处理 Spectrogram | 保留通道位置信息 | +| **2nd - COOLZ** | 双特征头 (EEG + Spectrum) | 多模态融合 | +| **3rd - nvidia-dd** | 数据质量筛选 (6350→100000) | 性能提升显著 | +| **3rd - nvidia-dd** | 反向 Augmentation | 数据纯净度提升 | +| **4th - Cerberus** | 左右对称对比学习 | 位置编码 | +| **9th - ishikei** | Contrastive Learning | 特征对比 | + +### 归一化方法对比 + +| 方法 | 支持者 | 效果 | +|------|--------|------| +| **`x.clip(-1024, 1024) / 32`** | 1st, 2nd, 3rd | 最佳选择 | +| **MAD 归一化** | 3rd | 对异常值更鲁棒 | +| **Batch/Sample 归一化** | 部分尝试者 | 效果不佳 (3rd 发现) | +| **Standardize** | 低排名者 | 不推荐 | + +### 时频变换方法对比 + +| 方法 | 使用排名 | 优点 | 缺点 | +|------|---------|------|------| +| **CWT** | 1st, 4th, 5th, 6th | 多分辨率,适合非平稳信号 | 需选择小波 | +| **Superlet CWT** | 1st | 最高分辨率 | 计算成本高 | +| **MelSpectrogram** | 2nd, 3rd | 人耳感知特性 | 频率分辨率固定 | +| **STFT** | 7th, 8th, 10th | 简单易实现 | 时频权衡 | + +### 集成策略对比 + +| 排名 | 集成方法 | 模型数 | 权重确定 | +|------|---------|--------|---------| +| **1st** | 非负线性回归 | 6 (4人) | 自动学习 | +| **2nd** | 加权平均 | 6 | 手动调参 | +| **3rd** | 简单平均 | 多个 | 均等权重 | + +### 验证策略对比 + +| 策略 | 使用排名 | Votes 阈值 | 说明 | +|------|---------|------------|------| +| **≥10** | 1st, 2nd, 3rd | ≥10 | 专家 vs 大众一致意见 | +| **≥6** | 2nd | ≥6 | 较宽松 | +| **≥9** | 部分 | ≥9 | 接近专家标准 | +| **加权** | 部分 | 按投票数加权 | 少投票获得更高正则化 | + +### 频率范围选择 + +| 范围 | 使用排名 | 应用场景 | +|------|---------|---------| +| **0.5-20 Hz** | 标准, 2nd | Kaggle 默认 | +| **0.5-40 Hz** | 1st (suguuuuu) | 扩展信息,更佳结果 | +| **0.5-50 Hz** | 部分 | 包含更多高频信息 | + +### 训练 Epoch 配置 + +| 排名 | Stage 1 | Stage 2 | 说明 | +|------|---------|---------|------| +| **1st** | 5 epochs | 15 epochs | 保守选择 | +| **2nd** | 15 epochs | 5 epochs | 更长 Stage 1 | +| **3rd** | - | - | 单阶段或灵活配置 | + +### 最佳实践总结 + +基于前 10 名对比分析,以下技术是获胜的关键: + +#### 必选项(银弹技术) +1. **带通滤波 (0.5-20/40 Hz)** +2. **Clip 归一化**:`x.clip(-1024, 1024) / 32` +3. **2-Stage Training**:Stage 1 全数据,Stage 2 高质量样本 +4. **Votes ≥10 筛选**:仅用高质量样本评估 +5. **Group K-Fold**:按患者分组 +6. **Ensemble**:至少 3+ 模型集成 + +#### 推荐选项(根据情况选择) +- **时频分析**:CWT (最佳) > MelSpectrogram > STFT +- **归一化**:clip/32 (最佳) > MAD > batch/sample normalize +- **集成方法**:非负线性回归 (最佳) > 加权平均 > 简单平均 +- **模型架构**:根据数据特征选择 1D/2D/3D CNN + +#### 创新方向 +- **数据质量**:反向 Augmentation,质量筛选 +- **稀疏激活**:Entmax 替换 Softmax +- **位置编码**:3D-CNN 保留通道信息,左右对称对比 +- **特征融合**:双特征头,多模态集成 + +--- + +## Child Mind Institute - Top 10 Solutions Comparison + +> 基于前 10 名解决方案的横向对比分析,提取共性技术和差异创新 + +### 竞赛特点总结 + +与 HMS 不同,这是一个**事件检测任务**,核心挑战包括: +- **稀疏标注**:17280 步中仅 2 步有标签(0.01%) +- **分钟偏差**:真实事件总是发生在 hh:mm:00 +- **未标注事件**:存在周期性重复数据(缺失标签) +- **多 Tolerance AP**:需要同时优化多个容差窗口 + +### 前 3 名详细对比 + +#### 1st Place - shimacos vs sakami vs kami (kami, sakami0000, shimacos) + +**核心架构:** 两阶段建模 + Greedy 后处理优化 + +``` +1st Level (5秒间隔) + CNN+GRU+CNN, CNN+GRU+Transformer+CNN, + LSTM+UNet1d+UNet, LSTM+UNet1d+UNet, 1dCNN+UNet1d+Transformer + ↓ +2nd Level (1分钟间隔) + LightGBM, CatBoost, CNN+GRU, CNN+Transformer, CNN + ↓ +Post Processing (15/45秒技巧) + Daily Normalize → Greedy Search → Final Events +``` + +**关键技术:** +- **两阶段建模**:5秒检测 + 1分钟精化 +- **衰减目标**:按 tolerance_steps 加权 + epoch 衰减 +- **15/45秒技巧**:针对 tolerance 边缘优化 +- **Daily Normalization**:按天归一化 2nd level 预测 +- **Greedy 后处理**:针对 AP 指标的 greedy search + +**效果:** Public LB: 0.768 (18th) → Private LB: 0.852 (1st) + +#### 2nd Place - K-Mat + +**核心架构:** 三阶段建模 + Error Modeling + +``` +Stage 1: 事件检测 + 睡眠/清醒分类 + 多个模型预测 onset/wakeup/asleep 概率 + ↓ +Stage 2: Error Modeling (LGBM) + 基于 1st level 预测,计算 Error → Correctness → Target + 将分数差分转为分类任务 + ↓ +Stage 3: 时刻偏移 + WBF 融合 + 对 step 做时刻偏移,重新预测 + 用 WBF 整合结果 +``` + +**关键技术:** +- **Error Modeling**:将差分变化转为分类标签 +- **三阶段架构**:检测 → 重打分 → 偏移 +- **Minute Embedding**:将 minute_embedding 残差连接到输出层 +- **时刻偏移**:应对 15 分钟周期模式 +- **WBF 融合**:Weighted Box Fusion + +#### 3rd Place - cucutzik + +**核心架构:** 简洁干净的 GRU + UNET + LGB 集成 + +**关键技术:** +- **频率编码**:hour_min_onset, hour_min_wakeup +- **序列反转增强**:反转所有序列,CV +0.01 +- **目标扩展**:event step 前加2步,后加1步 +- **模型融合**:GRU (0.68) + UNET (0.2) + LGB (0.12) +- **Rolling Mean 平滑**:center=True,每隔距离取最高预测 +- **噪声检测**:相同 hour+step+anglez 重复值即为噪声 + +### 共性技术("银弹" - 高分者共同使用) + +| 技术 | 使用排名 | 说明 | +|------|---------|------| +| **两阶段建模** | 1st, 2nd | 5秒检测 → 1分钟精化 | +| **分钟偏差处理** | 1st, 2nd, 3rd, 5th, 6th | 事件总是发生在整分钟 | +| **多模型集成** | 1st, 2nd, 3rd | 至少 5+ 模型 | +| **Daily Normalization** | 1st, 3rd | 按天归一化预测值 | +| **后处理优化** | 1st, 2nd, 3rd | find_peaks, NMS, greedy search | +| **多任务学习** | 2nd, 4th | onset, wakeup, asleep | + +### 差异创新(各排名者的独特贡献) + +| 排名 | 独特创新 | 影响 | +|------|---------|------| +| **1st** | 15/45秒技巧 | Public 18th → Private 1st | +| **1st** | 衰减目标 + epoch 衰减 | 使峰值更尖锐 | +| **1st** | Daily Normalization | 利用每天只有2次活动的先验 | +| **2nd** | Error Modeling | 将差分转为分类标签 | +| **2nd** | Minute Embedding | 残差连接到输出层 | +| **3rd** | 序列反转增强 | CV +0.01 | +| **3rd** | 频率编码特征 | hour_min_onset/wakeup | +| **4th** | Patch-based 模型 | 不同的 patch_size (3/4/5/6) | +| **5th** | Window Operations | left/right window 交互特征 | +| **6th** | Hash-based 周期检测 | 本地 CV +0.015 | + +### 分钟偏差处理对比 + +| 方法 | 使用排名 | 具体实现 | +|------|---------|---------| +| **Minute Embedding** | 1st | 残差连接到输出层 | +| **频率编码** | 3rd | hour_min_onset, hour_min_wakeup | +| **Step 偏移** | 2nd | 偏移 step 重新预测 + WBF | +| **标签偏移** | 5th | target shift ~-11 步 | +| **特征工程** | 6th | `(step // 12) % 15` | + +### 未标注事件处理对比 + +| 方法 | 使用排名 | 具体实现 | +|------|---------|---------| +| **周期性检测** | 1st | 降采样 + 相似度计算,标记日周期性 | +| **噪声检测** | 3rd | 相同 hour+step+anglez 重复值 | +| **样本加权** | 5th | 训练时权重设为 0 | +| **Hash 算法** | 6th | 散列和散列图查找重复模式 | +| **过滤序列** | 大部分 | 剔除未标注 events 出现多的序列 | + +### 后处理策略对比 + +| 排名 | 方法 | 参数 | 效果 | +|------|------|------|------| +| **1st** | Greedy + 15/45秒 | 500次迭代 | Public 18th → Private 1st | +| **2nd** | Step偏移 + WBF | 多个偏移量 | 显著提升 | +| **3rd** | Rolling Mean + find_peaks | window=12, distance=72 | 清晰方案 | +| **基线** | find_peaks + NMS | distance=72, IOU=0.995 | 银牌基础 | + +### 1st Level 模型对比 + +| 排名 | 模型数量 | 模型类型 | 集成方式 | +|------|---------|---------|---------| +| **1st** | 5 | CNN+GRU, CNN+Transformer, LSTM+UNet 等 | 加权平均 | +| **2nd** | 多个 | Spec2DCNN, PANNs, Transformer 等 | 融合后处理 | +| **3rd** | 10 | 8个GRU + 2个UNET | GRU 0.68 + UNET 0.2 + LGB 0.12 | + +### 2nd Level 模型对比 + +| 排名 | 模型类型 | 输入特征 | 说明 | +|------|---------|---------|------| +| **1st** | LGB, CatBoost, CNN+GRU 等 | 1st level 预测 + 原始特征 | 整合到整分钟 | +| **2nd** | LGBM | Error, Correctness, Top-k Accuracy | 重新打分 | +| **3rd** | LGB | 1st level 预测 | 加权融合 | + +### 数据增强策略对比 + +| 方法 | 使用排名 | 效果 | +|------|---------|------| +| **序列反转** | 3rd | CV +0.01 | +| **时间偏移** | 基线 | 标准增强 | +| **标签扩展** | 3rd | 前2步+后1步 | +| **周期性特征** | 1st | 日周期 flag | + +### 验证策略对比 + +| 策略 | 使用排名 | 说明 | +|------|---------|------| +| **Group K-Fold** | 1st, 2nd, 3rd | 按 series_id 分组 | +| **Stratified (事件数)** | 1st | 事件数 qcut(10) 分层 | +| **全部 fold 训练** | 1st | 单 fold 结果不稳定,需全 fold | +| **Trust CV** | 1st | Public 数据少且分布相似 | + +### 最佳实践总结 + +基于前 10 名对比分析,以下技术是获胜的关键: + +#### 必选项(银弹技术) +1. **两阶段建模**:5秒检测 → 1分钟精化 +2. **分钟偏差处理**:使用 minute 相关特征 +3. **Daily Normalization**:按天归一化预测值 +4. **多模型集成**:至少 5+ 模型 +5. **后处理优化**:find_peaks, NMS, greedy search +6. **Group K-Fold**:按 series_id 分组 + +#### 推荐选项(根据情况选择) +- **后处理方法**:Greedy (最佳) > WBF > NMS > find_peaks +- **2nd level 模型**:LGB/CatBoost > Neural Networks +- **分钟偏差处理**:Minute Embedding (最佳) > 频率编码 > step 偏移 +- **数据增强**:序列反转 > 时间偏移 + +#### 创新方向 +- **评估指标优化**:针对 tolerance 的 greedy search +- **Error Modeling**:将差分转为分类标签 +- **衰减目标**:按 tolerance 加权 + epoch 衰减 +- **周期性检测**:识别未标注 events + +--- + +## CMI - Detect Behavior with Sensor Data - Top 10 Solutions Comparison + +> 基于日语总结和前排方案的综合分析,提取共性技术和差异创新 + +### 竞赛特点总结 + +与之前竞赛不同,这是一个**多模态时序行为识别**任务,核心挑战包括: +- **多模态传感器融合**:IMU + THM + TOF +- **严重数据缺失**:TOF 约 60% 缺失(-1),THM 约 3-4% 缺失 +- **细粒度分类**:18 个手势类别,区分 BFRB vs 日常动作 +- **个体约束**:每个 subject × gesture × orientation 只出现一次 +- **测试集变化**:约 50% 序列仅有 IMU 数据 + +### 前 3 名详细对比 + +#### 1st Place - Devin | Ogurtsov | zyz (Andrey Ogurtsov, Devin, zyz) + +**核心架构:** 多成员协作 + 多模型集成 + +``` +Devin's part: + TOF 处理: 2×2 正方形 9 个区域平均 + TOF-only 模型也加入集成 + +Ogurtsov's part: + 数据清理: 删除 gesture 不存在的序列 + 特征工程: 从 acc(去除重力后)提取 35 个特征 + 模型: LSTM, Attention, CNN 组合 + 增强: timeshift, timistretch + 集成: 每 Fold 选择 3 run 中最佳结果 + 推理: 序列延伸降低模型相关性 + +zyz part: + RNN + CNN1D 组合 +``` + +**关键技术:** +- **TOF 图像化**:2×2 正方形 9 个区域平均降维 +- **TOF-only 集成**:单独使用 TOF 数据的模型也加入集成 +- **数据清理**:删除无效序列(如 SUBJ_019262, SUBJ_045235) +- **特征工程**:35 个特征从 acc(去除重力后)提取 +- **多模型集成**:LSTM + Attention + CNN 组合 +- **推理优化**:序列延伸降低模型相关性,提升集成效果 + +#### 2nd Place - cucutzik + +**核心架构:** 4 模型系统 + 阶段感知 Attention + +``` +4 个独立模型: + IMU rotation 缺失/存在 × THM/TOF 缺失/存在 = 4 组合 + +核心创新: + 四元数 6D 表现 (避免不连续性) + Residual SE-CNN Block + Attention + +关键技巧: + 阶段感知 Attention: + 预测 3 类阶段概率 (移动中/目标位置/手势执行中) + 每个阶段独立 Attention,概率加权 + 相位 Mixup: + 按阶段分割序列 + 同阶段内进行 Mixup + "moves to target" 阶段对齐结束点 + Pseudo Label: + 测试数据生成 pseudo-label + 小 LR (5e-5) 1 step fine-tune + +后处理: + 匈牙利算法全局最优标签分配 + 约束: subject × gesture × orientation 唯一性 +``` + +**关键技术:** +- **四元数 6D 表现**:避免四元数不连续性问题 +- **阶段感知 Attention**:分阶段独立建模和加权 +- **相位 Mixup**:按阶段分割后同阶段内 Mixup +- **Pseudo Label**:测试数据生成伪标签进行微调 +- **匈牙利算法**:全局最优标签分配(利用个体约束) + +#### 3rd Place - Team RIST + +**核心架构:** 2D-CNN + 图像化时序 + +``` +数据预处理: + 四元数平滑处理 + 符号反转扩展 + Block 扩展 + +模型: + MaxViT, ConvNeXt-V2, EfficientNetB5 等 2D-CNN + 输入: 适当尺寸的图像 + +增强: + 世界坐标系 Z 轴旋转 (-60° 到 60°) + 本地坐标系 Y 轴旋转 (-7° 到 7°) + +后处理: + 匈牙利算法全局最优标签分配 +``` + +**关键技术:** +- **时序图像化**:时序数据转换为图像,使用 2D-CNN +- **四元数处理**:平滑、符号反转、Block 扩展 +- **双重旋转增强**:世界坐标 + 本地坐标旋转 +- **多 2D-CNN 集成**:MaxViT + ConvNeXt + EfficientNetB5 + +### 共性技术("银弹" - 高分者共同使用) + +| 技术 | 使用排名 | 说明 | +|------|---------|------| +| **个体约束利用** | 1st, 2nd, 3rd, 4th | subject × gesture × orientation 唯一性 | +| **数据增强** | 1st, 2nd, 3rd, 4th, 6th... | mixup, cutmix, timeshift, rotation | +| **异常数据处理** | 几乎所有 | SUBJ_019262, SUBJ_045235 删除或转换 | +| **左手系 → 右手系对齐** | 大部分 | 将左手系传感器数据转换为右手系 | +| **多模型集成** | 1st, 2nd, 3rd | 至少 3+ 模型 | +| **阶段感知建模** | 2nd, 3rd, 6th | 利用 Transition/Pause/Gesture 结构 | +| **BatchNorm(无归一化)** | 9th | 不使用 scaler,用 BatchNorm | + +### 差异创新(各排名者的独特贡献) + +| 排名 | 独特创新 | 影响 | +|------|---------|------| +| **1st** | TOF 图像化(2×2 区域平均) | 简化 TOF 处理 | +| **1st** | TOF-only 模型集成 | 单独 TOF 也有价值 | +| **1st** | 序列延伸推理 | 降低模型相关性 | +| **2nd** | 四元数 6D 表现 | 避免不连续性 | +| **2nd** | 阶段感知 Attention | 分阶段独立建模 | +| **2nd** | 相位 Mixup | 同阶段内 Mixup,对齐结束点 | +| **2nd** | Pseudo Label fine-tune | 测试数据微调 | +| **3rd** | 时序转图像 | 使用 2D-CNN 处理 | +| **3rd** | 双重旋转增强 | 世界坐标 + 本地坐标 | +| **6th** | gesture segment U-Net | 估计手势时间段 | +| **9th** | 正向 + 反向模型 | 同时训练标准分类和反向分类 | +| **13th** | 双向 Mamba | 长期时序依赖建模 | +| **13th** | Hard Margin Loss | 针对困难样本的损失 | +| **13th** | Hard Mining | 困难样本采样率提升 | + +## 数据洞察与分析 + +### 数据特征理解 + +#### 标签质量的双峰分布 + +**发现:** 投票数呈现双峰分布 +- **低质量样本**:1-7 票 +- **高质量样本**:10-28 票 +- **关键发现**:**没有 8-9 票的样本** + +**含义:** +- 存在两组标注者:专家组(20人)和大众组(119人) +- 低投票数样本更不可靠,标签噪声更大 +- 高投票数样本代表专家共识,质量更高 + +**策略:** +- 使用 votes ≥10 作为高质量阈值 +- 仅用高质量样本建立验证集(CV/LB 相关性接近 1:1) +- 考虑对低投票样本进行更强正则化 + +**第 3 名的洞察:** 从 100,000+ 行筛选到 6,350 行高质量数据,性能反而提升 → **"少即是多"**,精确数据胜过大量噪声数据 + +#### 标签稀疏性 + +**发现:** 训练标签中某些类别的概率为 0 +- Softmax 输出所有值 > 0(数学性质) +- 但真实标签中某些类为 0 + +**解决方案(1st Place):** +- 使用 **Entmax** 替换 Softmax +- Entmax 可以产生真正的 0 输出(稀疏激活) +- 结果:LB +0.004 提升 + +**实现:** +```python +def entmax(x, alpha=1.5, dim=-1): + return torch.softmax(x * alpha, dim=dim) +``` + +#### 双模态数据的时间对齐 + +**数据结构:** +- **Spectrogram**:10 分钟(低时间分辨率,高频率信息) +- **EEG**:50 秒中心段(高时间分辨率,低频率信息) +- 两者中心 50 秒是同一数据 + +**洞察:** +- Spectrogram 提供全局上下文(10分钟趋势) +- EEG 提供精细时序信息(50 秒细节) +- 这是**同一数据的两种表示**,不是独立信息 + +**处理策略:** +- 大多数获胜者**专注于 EEG**(2nd, 3rd) +- 1st Place 同时使用两种并集成 +- 时频分析(CWT/MelSpectrogram)比纯时序或纯频域更有效 + +#### 信号配对的重要性 + +**发现:** +- 脑电信号存在空间关系 +- 左右对称位置的电极信号应该成对处理 +- 通道顺序影响模型性能 + +**策略(3rd Place):** +- 将左右脑节点配对:Fp1-F7, Fp2-F8, F7-T3, F8-T4 等 +- 而不是简单按顺序堆叠 +- 这样保留了脑部空间结构的先验知识 + +#### 频率范围选择的影响 + +**对比分析:** +| 频率范围 | 使用者 | 效果 | +|---------|--------|------| +| 0.5-20 Hz | 标准, 2nd | Kaggle 默认 | +| 0.5-40 Hz | 1st (suguuuuu) | 更佳结果 | +| 0.5-50 Hz | 部分 | 高频噪声可能增加 | + +**洞察:** +- 标准范围可能遗漏重要信息 +- 扩展到 40 Hz 能捕捉更多特征 +- 但过高频率(50 Hz+)可能引入噪声 +- 需要根据具体任务调整 + +#### 归一化的选择 + +**实验发现(3rd Place):** +- Batch/Sample 归一化:效果不佳 +- MAD 归一化:对异常值更鲁棒 +- **Clip 归一化** `x.clip(-1024, 1024) / 32`:**最佳选择**(所有前 3 名都使用) + +**为什么 Clip/32 最好?** +1. **限制极端值**:EEG 信号存在大幅伪影 +2. **固定除数 32**:简单、可复现、不过拟合 +3. **保留信息**:相比标准化,保留更多原始信号特征 + +#### 数据增强的反向工程 + +**3rd Place 的关键发现:** +- 数据创建者对训练数据应用了 augmentation +- 这些 augmentation 在测试时不存在 +- **反向工程并移除这些 augmentation** 后,模型性能显著提升 + +**启示:** +- 理解数据来源和预处理历史很重要 +- "干净"的原始数据可能比"增强"的数据更好 +- 深入数据分析能发现隐藏的改进机会 + +### 数据质量评估框架 + +基于前 10 名的分析,可以建立以下数据质量评估维度: + +| 维度 | 评估方法 | 高质量指标 | +|------|---------|-----------| +| **投票数** | 统计每个样本的专家投票数 | votes ≥10 | +| **一致性** | 计算投票分布的熵 | 高一致性(低熵) | +| **标注者类型** | 区分专家 vs 大众 | 专家共识权重更高 | +| **信号质量** | 检查伪影、噪声水平 | 低噪声、少伪影 | +| **时序完整性** | 检查 50 秒段连续性 | 无断裂、无缺失 | + +### 数据预处理最佳流程 + +综合前 10 名方案,推荐的数据预处理流程: + +```python +def preprocess_eeg_optimal(eeg_raw, votes): + """ + 基于 Top 10 方案的最佳预处理流程 + """ + # 1. 双极导联(减少共模噪声) + bipolar = longitudinal_bipolar_montage(eeg_raw) + + # 2. 带通滤波(0.5-40 Hz,扩展频段) + filtered = bandpass_filter(bipolar, lowcut=0.5, highcut=40, fs=200) + + # 3. Clip 归一化(所有前 3 名使用) + normalized = np.clip(filtered, -1024, 1024) / 32.0 + + # 4. 数据质量筛选 + if votes < 10: + # 考虑降权重或使用 Pseudo Label + weight = votes / 20.0 # 2nd Place 方法 + else: + weight = 1.0 + + return normalized, weight +``` + +### 标签处理最佳实践 + +| 技术 | 目的 | 使用排名 | +|------|------|---------| +| **投票数归一化** | 转换为概率分布 | 所有 | +| **标签平滑(加 0.02)** | 防止过度自信 | 部分 | +| **Loss 权重** | 按投票数加权样本 | 2nd | +| **Offset 加法** | 低投票数更强正则化 | 部分 | + +### 关键数据洞察总结 + +1. **质量 > 数量**:6,350 行高质量数据 > 100,000 行噪声数据 +2. **稀疏标签需要稀疏激活**:Entmax > Softmax +3. **时频分析优于纯时序或纯频域**:CWT > STFT +4. **空间先验知识很重要**:信号配对、左右对称 +5. **归一化方法影响巨大**:Clip/32 是最佳选择 +6. **理解数据来源至关重要**:反向 Augmentation 提升性能 +7. **标签质量分布不均**:需要分层训练和评估 + +--- + +## Child Mind Institute - 数据洞察与分析 + +### 数据特征理解 + +#### 极度稀疏的标签 + +**发现:** 17280 步(24小时)中仅有 2 步有标签 +- **标签密度**:0.01%(1/10000) +- **事件类型**:onset(入睡)+ wakeup(觉醒) +- **标注粒度**:每夜 1 个 onset + 1 个 wakeup + +**含义:** +- 传统逐帧分类方法不适用 +- 需要特殊的目标创建策略(衰减目标) +- 后处理比模型预测更重要 +- 数据增强对缓解稀疏性至关重要 + +**策略:** +- **衰减目标**:按 tolerance_steps 创建衰减的标签分布 +- **多任务学习**:同时预测 onset, wakeup, asleep +- **后处理优化**:find_peaks, NMS, greedy search +- **数据增强**:序列反转、时间偏移等 + +#### 分钟偏差模式 + +**发现:** 真实事件总是发生在 hh:mm:00 整分钟时刻 + +**数据分布(YOURI MATIOUNINE 发现):** +``` +标签分钟数 % 15 的分布: +- 0分钟:明显峰值 +- 3分钟:明显峰值 +- 7分钟:明显峰值 +- 11分钟:明显峰值 +- 其他分钟:很少出现 +``` + +**含义:** +- 手动标注导致精度有限 +- 存在 15 分钟的周期性模式 +- 模型应该学习这种模式 + +**策略对比:** +| 排名 | 处理方法 | 具体实现 | +|------|---------|---------| +| **1st** | Minute Embedding | 残差连接到输出层 | +| **2nd** | Step 偏移 | 对预测 step 做偏移后重新预测 | +| **3rd** | 频率编码 | hour_min_onset, hour_min_wakeup | +| **5th** | 标签偏移 | target shift ~-11 步 | +| **6th** | 特征工程 | `(step // 12) % 15` | + +#### 未标注事件问题 + +**发现(YOURI MATIOUNINE):** 很多序列有明显的 events 未被标注 + +**两类情况:** +1. **日周期性重复**:缺失 events 的夜晚跟前 24 小时数据完全一样 + - 推测:组织方用历史正常数据填补了缺失数据 +2. **无法解释的缺失**:没有明显规律的缺失标注 + +**处理策略对比:** +| 排名 | 处理方法 | 具体实现 | +|------|---------|---------| +| **1st** | 周期性检测 + flag | 降采样 + 相似度计算,标记日周期性 | +| **3rd** | 噪声检测 | 相同 hour+step+anglez 重复值即为噪声 | +| **5th** | 样本加权 | 训练时权重设为 0 | +| **6th** | Hash 算法 | 散列和散列图查找重复模式,本地 CV +0.015 | +| **大部分** | 过滤序列 | 剔除未标注 events 出现多的序列 | + +**1st Place 的周期性检测方法:** +```python +def detect_periodicity(series): + """检测 24 小时周期性重复""" + # 1. 降采样 + downsampled = series[::12] # 5秒 → 1分钟 + + # 2. 分割序列(按天) + n_days = len(downsampled) // 1440 # 1440 = 24小时 + daily_chunks = [downsampled[i*1440:(i+1)*1440] for i in range(n_days)] + + # 3. 计算相邻天的相似度 + for i in range(n_days - 1): + # 方法1: 元素级比较 + similarity = np.mean(daily_chunks[i] == daily_chunks[i+1]) + + # 方法2: 余弦相似度 + cos_sim = np.dot(daily_chunks[i], daily_chunks[i+1]) / ( + np.linalg.norm(daily_chunks[i]) * np.linalg.norm(daily_chunks[i+1]) + ) + + if similarity > threshold or cos_sim > threshold: + return True # 检测到周期性 + + return False +``` + +#### 多 Tolerance AP 评估指标 + +**评估方式:** +```python +tolerances = [1, 3, 5, 7.5, 10, 12.5, 15, 20, 25, 30] # 分钟 +# 对每个 tolerance,计算 AP +# 最终分数 = mean(各tolerance AP) × mean(onset AP, wakeup AP) +``` + +**关键洞察(1st Place):** +- **预测 hh:mm:00 不好**:tolerance 5,10,15,20,25,30 时边缘漏检 +- **预测 hh:mm:30 不好**:tolerance 7.5, 12.5 时边缘漏检 +- **预测 hh:mm:15 或 hh:mm:45 最佳**:覆盖所有 tolerance + +**原理示意:** +``` +00:23:15 ← 检测事件(15秒) + ← tolerance 7.5 分 → +00:23:00 ← 真实事件(0秒) + ← tolerance 7.5 分 → +00:22:45 + +如果检测事件在 00:23:00,则 tolerance 7.5 的右边缘会漏检 +如果检测事件在 00:23:15 或 00:22:45,则正好覆盖 +``` + +#### 15分钟周期性模式 + +**发现:** events 以 15 分钟为周期重复出现 + +**数据分布:** +- **峰值分钟**:0, 3, 7, 11(间隔 3-4 分钟) +- **周期**:15 分钟 +- **含义**:可能与定时检查或记录习惯有关 + +**应对策略:** +| 排名 | 策略 | 说明 | +|------|------|------| +| **1st** | 15/45秒技巧 | 无论 1-29秒 还是31-59秒,选15/45秒代表 | +| **2nd** | Step偏移 | 对step做多个偏移,覆盖所有可能时刻 | +| **3rd** | 频率编码 | hour_min_onset, hour_min_wakeup | + +### 数据质量评估框架 + +基于前排方案,建立数据质量评估维度: + +| 维度 | 评估方法 | 低质量指标 | 处理策略 | +|------|---------|-----------|---------| +| **周期性重复** | 降采样+相似度 | 与前24小时完全相同 | 标记 periodicity flag | +| **噪声重复** | hour+step+anglez计数 | 重复值>1 | 标记 noise | +| **未标注events** | 统计每夜events数 | <2 events | 过滤或降权 | +| **数据异常** | enmo统计 | enmo值异常大 | clip到1 | + +### 关键数据洞察总结 + +1. **极度稀疏标签**:需要衰减目标和后处理优化 +2. **分钟偏差是关键**:所有前排方案都处理了这个问题 +3. **未标注events普遍存在**:周期性检测可识别 +4. **多tolerance AP需要特殊优化**:15/45秒技巧是制胜关键 +5. **评估指标与数据分布不匹配**:需要针对tolerance优化 +6. **Daily Normalization有效**:利用每天只有2次活动的先验 +7. **15分钟周期性模式**:step偏移或频率编码可利用 + +## CMI - Detect Behavior 数据洞察与分析 + +### 数据特征理解 + +#### 多模态传感器数据 + +**三种传感器类型:** + +| 传感器 | 数据维度 | 特征 | 缺失率 | +|-------|---------|------|--------| +| **IMU** | 加速度计(x,y,z) + 陀螺仪(x,y,z) | 运动和旋转 | 无缺失 | +| **THM** | 5个温度传感器 | 温度分布 | ~3-4% | +| **TOF** | 5个8×8传感器阵列 | 距离映射 | ~60% | + +**IMU (Inertial Measurement Unit):** +- 6 列:`X_accel`, `Y_accel`, `Z_accel`, `X_gyro`, `Y_gyro`, `Z_gyro` +- **重力分量**:加速度计包含重力,需去除 +- **四元数**:`orientation_X`, `orientation_Y`, `orientation_Z`, `orientation_W` + - 表示设备旋转姿态 + - **不连续性问题**:四元数在表示相同旋转时有多个值(q和-q表示相同旋转) + - **解决方案**:使用旋转矩阵前两列(6D连续表示) + +**THM (Thermopile):** +- 5 列:`thermopile_0` ~ `thermopile_4` +- 温度传感器,用于检测物体接近 +- **缺失标记**:-1 表示缺失 +- **缺失率较低**:约3-4% + +**TOF (Time-of-Flight):** +- 320 列:`tof_0` ~ `tof_319`(5个8×8阵列) +- 距离传感器,检测物体到设备距离 +- **缺失标记**:-1 表示缺失 +- **缺失严重**:约60%的数据为-1 +- **图像化处理**:将8×8阵列降采样为2×2特征图(1st Place创新) + +#### 严重数据缺失问题 + +**缺失分布:** +``` +TOF: ~60% 缺失 (-1 标记) +THM: ~3-4% 缺失 (-1 标记) +IMU: 无缺失 +``` + +**前排处理策略:** + +| 排名 | TOF 处理 | THM 处理 | +|------|---------|---------| +| **1st** | 2×2 pooling后标记缺失mask | 简单插值或mask | +| **2nd** | 特征工程提取有效点统计量 | 类似TOF处理 | +| **3rd** | 转图像,缺失填0 | 不使用或简单处理 | +| **其他** | 丢弃或mask | 丢弃或mask | + +**1st Place 的 TOF 处理创新:** +```python +def tof_2x2_pooling_with_mask(tof_data): + """ + TOF 数据 2×2 pooling + 缺失 mask + """ + # 每个 8×8 传感器 + for sensor_idx in range(5): + sensor = tof_data[:, sensor_idx*64:(sensor_idx+1)*64] + sensor = sensor.reshape(-1, 8, 8) + + # 2×2 pooling + pooled = sensor.reshape(-1, 4, 2, 2).mean(axis=(2, 3)) + + # 缺失 mask + mask = (sensor == -1).reshape(-1, 4, 2, 2).any(axis=(2, 3)) + + # 组合:特征 + mask + features[:, sensor_idx*4:(sensor_idx+1)*4] = pooled + features[:, 20+sensor_idx*4:20+(sensor_idx+1)*4] = mask + + return features +``` + +#### 个体约束利用 + +**关键约束:** 每个 subject × gesture × orientation 组合只出现一次 + +**含义:** +- 训练集中没有重复的 subject × gesture × orientation +- 验证时可以确保预测结果也满足这个约束 +- 可以用匈牙利算法做全局最优标签分配 + +**前排利用策略:** + +| 排名 | 利用方法 | 说明 | +|------|---------|------| +| **1st** | 匈牙利算法 | 全局最优分配,提升 LB 0.01 | +| **2nd** | 阶段感知建模 | 利用三阶段结构 | +| **其他** | 个体特征 embedding | 添加 subject embedding | + +**匈牙利算法实现(1st Place):** +```python +from scipy.optimize import linear_sum_assignment + +def hungarian_post_process(predictions, subject_ids, sequence_ids): + """ + 利用 subject × gesture × orientation 唯一约束 + """ + # 对于每个 subject + for subject in unique(subject_ids): + # 获取该 subject 的所有预测 + mask = subject_ids == subject + preds = predictions[mask] + seqs = sequence_ids[mask] + + # 构建代价矩阵:-log(概率) + cost_matrix = -np.log(preds + 1e-10) + + # 匈牙利算法:找到最优分配 + row_ind, col_ind = linear_sum_assignment(cost_matrix) + + # 更新预测结果 + for i, j in zip(row_ind, col_ind): + predictions[mask][i] = np.zeros(n_classes) + predictions[mask][i][j] = 1.0 + + return predictions +``` + +#### 三阶段结构 + +**发现:** 行为序列有明显的三阶段结构 + +``` +Transition → Pause → Gesture +``` + +**阶段特征:** + +| 阶段 | 持续时间 | 特征 | 识别要点 | +|------|---------|------|---------| +| **Transition** | 变化 | 从上一个状态移动到手势位置 | 运动幅度大 | +| **Pause** | 短暂 | 手势开始前的准备 | 运动幅度小 | +| **Gesture** | 重复 | 核心行为模式(如咬指甲) | 周期性模式 | + +**前排利用策略:** + +| 排名 | 利用方法 | 说明 | +|------|---------|------| +| **2nd** | 阶段感知 Attention | 每个阶段独立的 attention 权重 | +| **6th** | U-Net分割 | 将手势阶段作为分割任务 | +| **其他** | 特征工程 | 添加阶段分类特征 | + +**2nd Place 阶段感知 Attention:** +```python +class PhaseAwareAttention(nn.Module): + """ + 阶段感知 Attention - 每个阶段独立建模 + """ + def __init__(self, d_model, n_heads=8): + super().__init__() + # 3个阶段 embedding + self.phase_emb = nn.Embedding(3, d_model) + + # 每个阶段独立的 attention + self.transition_attn = nn.MultiheadAttention(d_model, n_heads) + self.pause_attn = nn.MultiheadAttention(d_model, n_heads) + self.gesture_attn = nn.MultiheadAttention(d_model, n_heads) + + def forward(self, x, phase_labels): + # phase_labels: [batch, seq_len] ∈ {0, 1, 2} + batch, seq_len, d_model = x.shape + + outputs = [] + for t in range(seq_len): + phase = phase_labels[:, t] # [batch] + + if phase == 0: # Transition + attn_out, _ = self.transition_attn(x[:, t:t+1], x, x) + elif phase == 1: # Pause + attn_out, _ = self.pause_attn(x[:, t:t+1], x, x) + else: # Gesture + attn_out, _ = self.gesture_attn(x[:, t:t+1], x, x) + + outputs.append(attn_out) + + return torch.cat(outputs, dim=1) +``` + +#### BFRB vs 非BFRB 类别分布 + +**18个手势类别:** + +| 类别 | BFRB类型 | 典型行为 | +|------|---------|---------| +| 0-7 | BFRB | 咬指甲、拉头发、抠皮肤等 | +| 8-17 | 非BFRB | 拍手、挥手、其他手势 | + +**分布特点:** +- **训练集**:BFRB 和非BFRB 数量相近 +- **个体差异**:不同 subject 的手势偏好不同 +- **方向差异**:同一手势不同方向的表现不同 + +**处理策略:** +- **Phase-aware Mixup**:仅在 Gesture 阶段进行 mixup(2nd Place) +- **个体 normalization**:按 subject 做归一化 +- **类别平衡**:确保每个类别有足够样本 + +#### 测试集变化 + +**关键发现:** 测试集约50%的序列仅有 IMU 数据 + +**含义:** +- 不能过度依赖 TOF 和 THM 特征 +- 模型必须能够仅用 IMU 数据做出预测 +- 需要训练仅用 IMU 的模型作为集成成员 + +**前排应对策略:** + +| 排名 | 应对方法 | +|------|---------| +| **1st** | 训练IMU-only模型,集成时加权 | +| **2nd** | 4个模型:IMU-only, IMU+TOF, IMU+THM, All | +| **3rd** | TOF填0处理,但效果受限 | +| **其他** | 简单丢弃缺失传感器 | + +**推荐策略:** +```python +# 训练时模拟测试集情况 +def get_model_input(data): + """ + 根据可用传感器选择模型输入 + """ + has_tof = (data['tof'] != -1).any() + has_thm = (data['thm'] != -1).any() + + if has_tof and has_thm: + return model_all(data['imu'], data['tof'], data['thm']) + elif has_tof: + return model_imu_tof(data['imu'], data['tof']) + elif has_thm: + return model_imu_thm(data['imu'], data['thm']) + else: + return model_imu(data['imu']) +``` + +#### 异常数据识别 + +**两个异常 subject:** + +| Subject | 问题 | 处理策略 | +|---------|------|---------| +| **SUBJ_019262** | 数据异常,预测困难 | 训练时过滤或降权 | +| **SUBJ_045235** | 数据异常,预测困难 | 训练时过滤或降权 | + +**识别方法:** +- 训练集上该 subject 的 loss 异常高 +- 交叉验证该 subject 的预测准确率低 +- 可视化该 subject 的传感器数据,发现异常模式 + +**处理代码:** +```python +# 异常 subject 黑名单 +ANOMALY_SUBJECTS = ['SUBJ_019262', 'SUBJ_045235'] + +def filter_anomaly_subjects(dataframe): + """ + 过滤异常 subject + """ + mask = ~dataframe['subject'].isin(ANOMALY_SUBJECTS) + return dataframe[mask] +``` + +#### 左手系 vs 右手系对齐 + +**发现:** 测试集存在左手和右手两种设备朝向 + +**问题:** +- 左手系和右手系的传感器读数方向相反 +- 四元数表示旋转的方式不同 +- 直接混合训练会引入噪声 + +**解决方案(前排通用):** +```python +def align_right_handed_system(data): + """ + 左手系 → 右手系对齐 + """ + # 翻转陀螺仪的 x, y 轴 + data['X_gyro'] = -data['X_gyro'] + data['Y_gyro'] = -data['Y_gyro'] + + # 调整四元数(取决于具体定义) + # 这里假设是绕 z 轴旋转 180 度 + data['orientation_X'] = -data['orientation_X'] + data['orientation_Y'] = -data['orientation_Y'] + + return data +``` + +### 数据质量评估框架 + +基于前排方案,建立数据质量评估维度: + +| 维度 | 评估方法 | 低质量指标 | 处理策略 | +|------|---------|-----------|---------| +| **传感器缺失** | 统计-1值比例 | TOF>50%, THM>5% | mask处理或训练IMU-only模型 | +| **异常subject** | 按subject统计loss | loss > threshold | 过滤SUBJ_019262, SUBJ_045235 | +| **设备朝向** | 检测左右手系 | 四元数和陀螺仪方向 | 统一到右手系 | +| **三阶段一致性** | 检测阶段标签 | 阶段跳变 | 利用三阶段结构特征 | + +### 关键数据洞察总结 + +1. **多模态融合是关键**:IMU + THM + TOF,但测试集仅50%有完整数据 +2. **TOF 缺失严重(60%)**:需要创新处理(2×2 pooling + mask) +3. **个体约束必须利用**:subject × gesture × orientation 唯一约束可用匈牙利算法 +4. **三阶段结构重要**:Transition/Pause/Gesture,阶段感知建模有效 +5. **四元数不连续性**:需转换为6D连续表示(旋转矩阵前两列) +6. **测试集只有IMU数据**:必须训练IMU-only模型作为集成成员 +7. **异常数据需处理**:SUBJ_019262和SUBJ_045235应该过滤或降权 +8. **左手系右手系对齐**:统一到右手系避免噪声 + +### 多模态时间序列分类的最佳实践 + +与单模态分类任务不同,多模态任务的特殊考虑: + +| 方面 | 单模态任务 | 多模态任务 | +|------|-----------|-----------| +| **特征提取** | 单一特征工程 | 每个模态独立提取后融合 | +| **模型架构** | 单一编码器 | 多编码器或早期融合 | +| **缺失处理** | 插值或丢弃 | mask处理或模态specific模型 | +| **数据增强** | 简单增强 | 模态感知增强(Phase-aware Mixup) | +| **后处理** | 阈值或NMS | 利用约束(匈牙利算法) | + |
