586. Child Mind Institute - Detect Sleep States | child-mind-institute-detect-sleep-states
我要感谢组织者举办这场精彩的竞赛,让我们有机会深入探索使用加速度计时间序列数据检测睡眠事件这一非常有趣的领域。我希望参赛者的解决方案能为儿童心理研究所提供有意义且有价值的见解,以加速并提升他们的研究工作。
这是我首次认真参与的竞赛,在公共数据集上获得了第13名(金牌),在私有数据集上获得了第16名(银牌)(遗憾的是,私有数据的随机排序使我的金牌计划未能实现)。
数据处理/特征工程:
模型:
后处理:
我注意到,当使用过滤后的数据进行训练时,模型在检测虚拟段之外的事件方面表现更好。过滤过程包括识别无标签的间隙,将其从时间序列中移除,但在间隙前的最后一个唤醒后保留300分钟,以及在间隙后第一个可用的 onset 前保留300分钟。保留300分钟是为了保持事件周围的上下文信息。然后,将过滤后的时间序列分割为700分钟的块,重叠350分钟,并打乱分组为5折用于训练和验证。重叠段的预测结果进行了平均。
特征工程最初是对enmo和anglez/90取log1p变换,然后制作窗口长度为12和60的频谱图,以及窗口长度为30、60、120的滚动特征(如绝对差值中位数、标准差和中位数)。此外,还包括了分钟数的正弦值作为附加特征。
事件检测任务的标签是通过在事件周围20分钟范围内使用sigma=0.75的高斯分布生成的。分割任务的标签是通过取 onset 和 wakeup 之间的时间段生成的。
使用LSTM(初始维度为32的全连接层)获得了最佳的CV分数(增加维度会导致结果变差),在LSTM之后添加了CNN头部。随后发现,将具有7个残差层(kernel size 3, dilation 3^(layer-1))的TCNN集成可使LB分数提升约0.004。
为了增加模型集成的多样性,考虑到GRU的门控较少且信息流与LSTM不同,我将其以相同的架构替换LSTM后加入集成,使LB提升了约0.002。
使用CyclicLR训练模型,周期长度等于批次数,最大学习率为0.005,最小学术率为0.0001,取得了最佳结果。我认为这可能与时间序列数据的周期性特性有关。
在可视化预测结果后,我意识到事件检测模型有时会忽略长期依赖。例如,当一段时间后会出现一个很长的真实睡眠状态段时,它们仍可能为间隙前的步骤分配高概率。
为了引入更多上下文信息,我决定训练一个分割模型来划分睡眠/清醒状态,并通过后处理部分将解释的自定义方程应用其概率图。
在尝试了1D U-Net、CNN、RNN等模型后,发现LSTM加CNN头部(与事件检测模型相同架构)获得了最佳的IoU分数。同样使用了CyclicLR,参数与事件检测模型相同。
我发现检测峰时设置7分钟间距可以获得最佳分数。
但由于地面实况的偏移特性,发现在400分钟间隔的宏峰值周围额外查找1分钟间隔的微峰值是有益的,这提高了我不会跳过更接近地面实况峰值的概率。这使LB提升了约0.003。
然后,如预测可视化所示,模型可能在某些间隙前后或睡眠期间波动段(睡眠期间的短暂清醒)前后预测峰值。如果接近地面实况的峰值分数较高,这些小峰值不应影响整体分数。然而,如果接近地面实况的峰值分数与较远峰值的相似,则会显著降低分数。因此,我需要使用分割模型提供的更大上下文来重新评分峰值(例如,对短非睡眠段上方的低概率和真实睡眠段上方的较高概率进行加权)。为此,我设计了以下方程:
为了重新评分onsets,我使用以下方程:
新的onset分数 = 事件检测模型的onset峰值分数 × (1 - MeanSegm(-240分钟) + MeanSegm(+240分钟))/2
其中:1−MeanSegm(−240分钟) 是1减去onset峰值前240分钟段分割图的平均概率。逻辑在于分割模型应给真实onset前的时间序列分配较低的睡眠状态概率。对于onset峰值后的时间序列,逻辑相反,记为MeanSegm(+240分钟)。
为了重新评分wakeups,使用相同的方程但符号相反:
新的wakeup分数 = 事件检测模型的wakeup峰值分数 × (1 - MeanSegm(+240分钟) + MeanSegm(-240分钟))/2
其中:1 - MeanSegm(+240分钟) 是1减去wakeup峰值后240分钟段分割图的平均概率。逻辑在于分割模型应给真实wakeup后的时间序列分配较低的睡眠状态概率。对于wakeup峰值前的时间序列,逻辑相反,记为MeanSegm(-240分钟)。
重新评分使我的LB提升了0.006。
过滤虚拟数据
为了过滤虚拟数据,我将时间戳频率降低至每10分钟一次,然后取每个步长为40的窗口,通过欧氏距离(阈值<0.75)搜索相似窗口。接着,在检测到的虚拟段起始前添加400分钟作为onsets的虚拟数据,在虚拟段结束后同样添加400分钟作为wakeups的虚拟数据。这带来了约0.05的LB提升!
最大重叠
我还注意到,使用较大的重叠会提升分数(它允许模型以稍有不同的上下文查看事件)。因此,对于700分钟的窗口,我选择了650分钟的重叠以适应9小时的限制。