返回列表

#1 Solution - Denoising Autoencoder

497. Tabular Playground Series - Jun 2022 | tabular-playground-series-jun-2022

开始: 2022-06-01 结束: 2022-06-30 数据算法赛
#1 解决方案 - 降噪自编码器

#1 解决方案 - 降噪自编码器

作者: Sebastian van Gerwen | 排名: 第1名

正如大多数人在这次比赛中所注意到的,巨大的挑战在于估计 F4 的条件分布,即给定行中有两个或更多值缺失的情况。为了解决这个问题,我使用了一个降噪自编码器,它可以在给定值缺失位置掩码的情况下估计缺失值的分布。我对 F1 和 F3 进行了均值填充,并完全忽略了 F2。

我的 notebook 的 Pytorch 实现可以在这里找到(它的得分很低,因为我搞砸了提交的数据帧 😅)。

下面是我绘制的该架构图。

DAE Schematic

随机掩码 (Random Mask)

我最初用零填充数据,并创建一个包含原始数据空值位置的源空值矩阵。然后我创建一个二项式随机掩码(其中每行至少有一个值),将其乘以原始数据以随机将值设置为零。模型接收被掩码处理后的数据和输入掩码——输入掩码是源空值和随机掩码向量的组合。

特征级嵌入 (Feature-wise embeddings)

模型将特征和掩码都进行嵌入并将它们相加。这样它就可以学习空值被设置为零的位置的表示,从而知道在哪里集中精力进行填充。这种方法的性能比简单地对被掩码的数据应用 dropout 要好得多。对于这些嵌入,我将输入和掩码向量中的每个特征线性投影到一个嵌入维度(最终提交时为 16),将它们相加,然后将它们展平。

我也尝试过掩码和线性嵌入之间的点积注意力机制(根据这篇论文),但这比简单地将它们相加的效果要差。

MLP 架构

特征/掩码嵌入随后被送入 MLP。我使用了带有跳跃连接的层归一化,包含 7 个使用 mish 激活函数的全连接层。随着层大小的增加,性能也有所提升,但我只尝试了最大 2048 的大小,因为计算时间成了问题,而且我不得不大幅减少批处理大小。

输出计算 (Output Computation)

我将 MLP 输出通过最后一个全连接层,以使维度与输入形状匹配。然后,最终输出取决于该值是否被掩码处理。如果该值被掩码处理,我们使用最后一个全连接层的输出,否则我们只使用模型输入。这使得非掩码输入的梯度在 MSE 损失下等于零,因此网络仅根据其对掩码填充的贡献更新参数。像掩码嵌入一样,这有助于网络关注应该被填充的值。

掩码 MSE 损失

这一步与输出计算非常相似,只是另一种根据条件将损失函数设置为零的方法。在这里,我使用了一个根据掩码将值设置为零的 MSE 损失。这个掩码是真实数据的空值——因此我们永远不会计算原始训练数据中存在的值的损失,但我们仍然可以从这些行中学习,而不会因为在训练期间使用朴素的填充方法而产生偏差。这里使用了类似的方法(相当于在数据空值处将损失设置为零)。这一步本可以作为修改后的输出计算的一部分,但我只想在训练期间包含这一步——否则实现将不得不在预测步骤期间传递一个零向量(这感觉有点笨拙)。

条件集成

我在 Pytorch 和 TensorFlow 中分别运行了 3 次 DAE——TensorFlow 运行的效果明显更好,但所有运行的平均效果最好。该模型在 Private LB 上的得分为 0.83351。为了稍微改善这一点,我仅当 F4 的行空值计数为 1 时,才集成单属性预测运行。这种条件集成使 Private LB 得分达到了 0.83343。

同比赛其他方案