665. CMI - Detect Behavior with Sensor Data | cmi-detect-behavior-with-sensor-data
我们要向竞赛主办方表示最诚挚的感谢!在整个竞赛期间我们非常享受这个过程。
本解题报告分为两部分:由 @chimaki821 负责的观察、预处理和后处理,以及由 @tokkiwa 负责的建模和深度学习。
像大多数参与者一样,我们实施了以下技术:
acc_y、rot_x 和 rot_y 值,交换 THM 通道 3↔5,交换 ToF 通道 3↔5,并反转 8×8 正方形区域。orientation(方向)和 behavior(行为)作为辅助损失项。在实施这些基线方法后,我的队友 @tokkiwa 通过对管道和各种集成方法的多种增强,显著改进了模型。这非常有价值,因为我几乎没有机器学习背景。
下面,我描述了几项有助于上述方法的关键技术,以及我实施的其他方法:
我还总结了:
这部分是与 @epopaca 合作开发的。
我们创建了一个 Notebook,当提供特定的被试者 (subject) 和手势 (gesture) 时,它会将所有相关数据合并到一张图像中。81 名被试者 × 18 种手势 = 1,458 张图像保存在我的智能手机上,一有时间我就不断观察它们。
例如 (SUBJ_000206, 手势:耳上 - 拉头发)
利用这种可视化,我们对左手修正和安装调整进行了分析。通过检查 acc_x, acc_y, acc_z 值,我们确定 SUBJ_019262 和 SUBJ_045235 可能存在安装不当。考虑到 Herios 传感器附件的潜在问题,主要有四种可能的场景(包括正常情况):
(关于传感器 xyz 轴方向的参考,请参阅此 讨论帖)。
| 正常 (原始) | 绕 Y 轴旋转 180° |
|---|---|
![]() |
![]() |
| 绕 Z 轴旋转 180° | 绕 Y 轴 180° + 绕 Z 轴 180° |
![]() |
![]() |
考虑到测试数据也可能包含类似的安装错误,我们实施了一个二分类系统来检测安装异常并在推理时应用修正。然而,由于公共测试中相关案例数量有限,效果难以察觉。因此,在这次提交中,我们优先考虑减少误报,将阈值设置为 0.9,导致效果有限。在迟交提交 (Late Submission) 中将阈值降低到 0.5 时,我们的分数提高到了 0.862 😢
基于传感器方向固定的假设,我们解决了“即使安装正确,绕 Y 轴也会发生轻微旋转”的情况。因此,我们实施了:
通过将推理角度设置为 [0, +5, -5, +15, -15],我们在多次实验中观察到公共 LB 平均提高了约 +0.002。私有 LB 也显示出类似的性能提升。
对于此实现,我们 carefully 应用了“旋转操作应从左侧作用于加速度数据,从右侧作用于旋转数据”的原则。
这部分是与 @mckmckmck 合作开发的。
虽然之前的优化侧重于“防止遗漏困难的被试者”,但当我们按手势类型检查 OOF 分数时,我们发现某些手势特别难以预测。以下是仅 IMU 模型的示例:
-----------------------------------------------------
F1 score for class[0] = 0.666 tp=417, fp=197, fn=221
F1 score for class[1] = 0.643 tp=405, fp=214, fn=235
F1 score for class[2] = 0.824 tp=548, fp=142, fn=92
F1 score for class[3] = 0.442 tp=286, fp=369, fn=352
F1 score for class[4] = 0.609 tp=384, fp=238, fn=256
F1 score for class[5] = 0.538 tp=340, fp=284, fn=300
F1 score for class[6] = 0.693 tp=444, fp=198, fn=196
F1 score for class[7] = 0.517 tp=328, fp=305, fn=309
F1 score for class[8] = 0.985 tp=2998, fp=54, fn=40
-----------------------------------------------------
Macro F1 = 0.6573605192818119
BFRB Macro F1 = 0.6164599766386722
Score = (Binary F1 + Macro F1) / 2 = 0.824077831125434
※ Class 8 代表非 BFRB 手势。Class 0-7 对应:
0: 耳上 - 拉头发
1: 前额 - 拉发际线
2: 前额 - 抓挠
3: 眉毛 - 拉头发
4: 睫毛 - 拉头发
5: 颈部 - 捏皮肤
6: 颈部 - 抓挠
7: 脸颊 - 捏皮肤
此外,我们可视化了 BFRB 类别的混淆矩阵(其中元素 (i, j) 代表真实标签为 i 且预测标签为 j 的序列数量):
从这些观察中,我们确定:
然后我们在 One-hot 编码后引入了软标签,为类似的手势类别分配小的权重,这在整体上产生了 modest 但明显的改进。
改进领域
我考虑过的其他方法
如果有人有关于这些领域的成功实施或见解,我将非常感谢您的反馈!!
我们的主模型由三部分组成:(1) 逐通道特征提取器,(2) BiGRU 和 (3) MLP 头。
后两部分没那么有趣,所以我们专注于特征提取器。我们首先注意到 这个 Notebook 中的通道独立 CNN 模型比其他模型表现更好。以下是代码片段:
self.branches = nn.ModuleList(
[
nn.Sequential(
MultiScaleConv1d(1, 12, kernel_sizes=[3, 5, 7]),
ResidualSEBlock(36, 48, 3, dropout=0.3),
ResidualSEBlock(48, 48, 3, dropout=0.3),
)
for _ in range(num_channels)
]
)
该模型为每个通道独立准备 CNN 管道。由于传感器数据对于每个通道具有完全不同的模态,因此使用独立内核来提取丰富的特征是合理的。我们进一步使用分组卷积重写了分支,最初是为了加速。出乎意料的是,将通道独立卷积与通道间 SE 块相结合,比完全通道独立处理表现要好得多。
此外,我们的队友 @chimaki821 为 ToF 特征采用了 3D-CNN,以捕捉传感器的时空关系。
self.tof_branch = nn.Sequential(
nn.Conv3d(tof_sensors, 24 * tof_sensors, (5,2,2), padding='same', groups=tof_sensors, bias=False),
nn.BatchNorm3d(24 * tof_sensors), nn.ReLU(), nn.MaxPool3d((1,2,2)),
nn.Conv3d(24 * tof_sensors, tof_out_channels * tof_sensors, (7,2,2), padding='same', groups=tof_sensors, bias=False),
nn.BatchNorm3d(tof_out_channels * tof_sensors), nn.ReLU(),
nn.AdaptiveMaxPool3d((None, 1, 1)),
)
特征随后被送入 BiGRU 和 Attention Pooling,添加高斯噪声,最后输入到小型 MLP 头。请参阅我们的代码以获取更多细节。
对于提交,我们训练了该模型的一些变体(例如添加了 FFT 特征)以及在公共 Notebook 中看到的其他简单 CNN 模型。
我们对 behavior、orientation 和 gesture 使用 separate losses 并将它们相加(最初由 @chimaki821 实施)。
具体来说,orientation 和 gesture 应用交叉熵(对于 gesture,label smoothing = 0.2 是我们的最佳实践),behavior 应用 nn.BCEWithLogitsLoss。
我们最终使用了 Cosine Annealing LR、Adam 和以下数据增强:
实施了 Focal loss、指数移动平均 (EMA)、radam 和归一化,但对我们的模型无效。
Wandb sweep 的结果表明,列的归一化对我们的模型影响很差。多任务训练的增益也有限,但我们认为它可能对集成有好效果,因为该方法使模型能够以不同方式学习。