返回列表

6th place solution: spectrograms, wavelets, convnets, unets, and transformers

555. Parkinsons Freezing of Gait Prediction | tlvmc-parkinsons-freezing-gait-prediction

开始: 2023-03-09 结束: 2023-06-08 临床决策支持 数据算法赛
第6名解决方案:频谱图、小波、卷积网络、UNet和Transformer
竞赛排名:第6名
作者:Shujun、Ahmet Erdem
分数:0.369/0.462(公开/私有排行榜)

首先,感谢竞赛主办方提供了数据有趣的 meaningful 竞赛。其次,祝贺获奖者!我们团队经历了一些波动,最终以一名之差与获奖区失之交臂。总的来说,我仍然感到高兴,因为我们成功度过了波动期。我也很期待看到前5名团队是如何创造出与我们之间的显著差距的。

我们的最终集成方案结合了频谱图模型、小波模型和1D卷积模型,得分0.369/0.462。下面我将讨论这些模型以及其他重要的技术细节。概览图如下:

解决方案概览图

验证设置

由于数据噪声较大,验证设置非常重要。我最终采用了嵌套CV(交叉验证)设置。具体流程如下:

  • 将数据按数据类型分层、按受试者分组,分为4折
  • 留出验证折(我称之为外折)
  • 将3个训练折重新划分为4折并进行交叉验证(我称之为内折)
  • 取最后一个epoch或验证分数最高的epoch
  • 使用4个内折模型平均预测外折

通过这种设置,我们可以更准确地模拟拥有250个测试序列并平均各折模型预测的情况。之后,我改为在完整的内折数据上训练4次(无验证),并使用最后epoch的模型在外折集上评估。

输入特征

我们所有模型都使用3个波形波和pct_time特征。此外,Ahmet的模型还使用了一些元数据特征。

频谱图模型

当我第一次看到数据时,觉得它看起来像某种波形,比如音频数据,因此认为使用频谱图建模可能效果不错。三维波形波通过STFT(短时傅里叶变换)转换为2D频谱图。重要的是,转换为频谱图会显著降低时间维度的数据量,由于我使用64/50的hop length,每个帧代表0.5秒窗口,基本上我是在对0.5秒窗口进行预测。训练期间,标签使用torchvision的resize功能调整大小以匹配频谱图的时间维度,推理时再将模型输出调整回完整维度。序列被切割为128秒(256个频谱图帧)的块来生成频谱图。

使用频谱图的另一个重要问题是,如果使用常规的2D卷积模型(如resnet18),无法保留频谱图的完整维度(例如256x256经过resnet18后变为8x8)。为了解决这个问题,我考虑使用UNet在卷积网络后上采样小特征图。之后,频谱图沿频率维度池化,得到1D序列,然后输入Transformer网络输出预测。

最佳单频谱图模型提交得分为0.432/0.372。频谱图模型擅长预测StartHesitation和Turn,但在Walking上表现较差。

小波模型

小波与频谱图类似,但也有不同之处:小波在不同频率下具有不同的频率/时间分辨率。将波形转换为小波也不会降低尺度图(scaleogram)的维度(我认为这是小波变换后图像的术语)。由于时间维度没有下采样,不再需要UNet,我直接使用resnet18/34,它们将尺度图下采样至与频谱图模型经过UNet后相同的时间分辨率。同样,我也在对0.5秒窗口进行分类。类似地,序列被切割为128秒(256帧)的块来生成小波。

最佳单小波模型提交得分为0.386/0.345。小波模型擅长预测Walking,但在StartHesitation和Turn上表现较差,因此与频谱图模型形成很好的互补。

Transformer建模

直接插入Transformer实际上效果不佳,因为它容易过拟合,因此我使用一个浮点偏置掩码来偏置Transformer的自注意力机制,使每个预测都依赖于相邻时间点,这有助于模型更好地预测长事件。

浮点偏置掩码如下所示:

注意力掩码图示
def get_distance_mask(L, power):
    m = torch.zeros((L, L))
    for i in range(L):
        for j in range(L):
            if i != j:
                m[i, j] = (1 - abs(i - j) / L) ** 2
            if i == j:
                m[i, i] = 1.0
    return m

数据增强

我对频谱图/小波模型使用了以下数据增强(主要来自audiomentations):

  • 时间拉伸(time stretch)
  • 高斯噪声(gaussian noise)
  • 音高偏移(pitch shift)
  • 波形缩放增强(随机将波形乘以0.75~1.5以获得尺度不变性)
  • 时间特征偏移增强(time feature shift aug)
self.augment = Compose([
    AddGaussianNoise(min_amplitude=0.001, max_amplitude=0.015, p=0.5),
    TimeStretch(min_rate=0.8, max_rate=1.25, p=0.5, leave_length_unchanged=False, n_fft=n_fft, hop_length=hop_length),
    PitchShift(min_semitones=-4, max_semitones=4, p=0.5, n_fft=n_fft, hop_length=hop_length),
])
# 波形缩放增强
if np.random.uniform() > 0.5:
    data['wave'] *= np.random.uniform(0.75, 1.5)
# 时间特征偏移增强
if self.train and np.random.uniform() > 0.5:
    data['time'] = data['time'] + np.random.uniform(-0.1, 0.1)

频率编码和范围

不使用傅里叶变换的高频部分非常重要,因此我直接舍弃它们,只保留前64个bin(对应0-15 Hz)。对于频谱图模型,我还使用torch.linspace(0,15,n_bins)对频率bin进行编码,并在时间和通道维度上扩展,然后拼接,因此2D卷积网络的输入有4个通道(3个方向的频谱图+频率编码)。将波形重采样至较低频率也很有用,我认为这能降低噪声水平。频谱图模型使用32、64和128 Hz,小波模型使用64 Hz。defog波形被重采样以匹配tdcsfog波形的采样率。

if self.df.loc[idx, 'data_type'] == 'defog':
    data['wave'] = FA.resample(data['wave'], 100, self.sample_rate)
else:
    data['wave'] = FA.resample(data['wave'], 128, self.sample_rate)

1D卷积模型

1D卷积模型是Ahmet的解决方案。详情如下:

  • 首先在时间轴上对齐defog和tdcs数据(分别降采样32和25倍,但保留其标准差作为特征)
  • pct_time、total_len、Test被用作独立特征,它们的预测与1D CNN的预测相加
  • 由于输入仅约7秒长,还将累积和特征输入1D CNN
  • 降低异常主导受试者的权重
  • 使用快照集成(snapshot ensembling)
  • 通过对预测取最大值来使用notype数据

1D卷积模型相比其他两种较弱,得分为0.373/0.293,但仍然是集成的好补充。有趣的是,1D卷积模型和频谱图模型在公开和私有排行榜之间的差距相似,均为0.09,而小波模型的差距仅为0.04。我们认为这是由于公开/私有排行榜之间类别平衡的变化:公开排行榜有更多start hesitation,私有排行榜有更多walking。

集成权重调整

对于我们的集成,权重首先手动调整作为起点,然后使用GP_minimize来最大化CV分数。我们最终使用了两种权重调整方案:
1. 4折的map + 排除Subject 2d57c2的完整数据map
2. 排除包含Subject 2d57c2的3折的map + 排除Subject 2d57c2的完整数据map
我们这样做是因为我们认为Subject 2d57c2是一个异常值。

results = gp_minimize(get_score, boundaries, x0=w, verbose=1, n_jobs=48, acq_optimizer='lbfgs', random_state=0)

我们的模型权重如下(我们在其中一些模型中将2d57c2的损失权重降至0.2):

  • [0.1821, 0.2792, 0.1052] Ahmet模型
  • [0.2153, 0.0, 0.0] test257(32 Hz频谱图)
  • [0.6026, 0.1734, 0.0] test262(64 Hz频谱图)
  • [0.0, 0.0287, 0.2579] test264小波
  • [0.0, 0.2168, 0.0] test265(32 Hz频谱图)降低2d57c2权重
  • [0.0, 0.1734, 0.2997] test266小波降低2d57c2权重
  • [0.0, 0.1284, 0.1124] test263 128 Hz频谱图
  • [0.0, 0.0, 0.2248] test271小波双倍频率尺度

如有疑问请随时询问,如果有些细节忘记提及也请不要惊讶。代码目前有些混乱,但我很快会清理并发布。

同比赛其他方案