返回列表

10th Place Solution for the Stanford Ribonanza RNA Folding Competition

587. Stanford Ribonanza RNA Folding | stanford-ribonanza-rna-folding

开始: 2023-09-07 结束: 2023-12-07 基因组学与生物信息 数据算法赛
Stanford Ribonanza RNA Folding竞赛第10名解决方案
作者:greySnow (Kaggle Grandmaster)
排名:第10名
发布时间:2023年12月24日

最初我并不打算公布我的解决方案,因为我使用了一种有趣的损失函数方法(在其他解决方案中没有看到,虽然可能遗漏了),而且由于我没有在价格范围内完成,我想把它留到未来其他兼容的比赛。然而,由于主办方显然有发表论文的计划,我最终决定将其公布。

背景部分

业务背景:Stanford Ribonanza RNA Folding竞赛
数据背景:竞赛数据集

方法概述

我使用了1D卷积+Transformer模型。该模型不包含位置编码,因为卷积层能够"自动"处理位置关系,从而更直接地泛化到更长的序列。我的模型基于@hoyso48在ISLR竞赛中的先前工作;参见他的2nd place解决方案。顺便祝贺他获得第二名。你知道吗,Hoyeol(Hoiso) probably 是我从他的工作中学到最多的人。这个解决方案已经是我获得的第二个金牌,感谢我从他的工作中学到的知识。所以,这是特别的感谢。
Hoiso的原始模型在时间上是因果的;我通过采用适当的填充和掩码将其改为对两侧对称。
我训练了两种模型:model_1仅基于序列训练,model_2包含CapR和每个核苷酸的bpp sum&max。

对我有帮助的要点(我没有进行适当的消融研究,所以大多数时候不会给出确切数字):

  1. 使用Sigmoid裁剪预测:使用Sigmoid函数裁剪预测值(常规裁剪也有帮助,但Sigmoid帮助更大)。这也使收敛更加平滑。
  2. 核苷酸One-hot编码:使用核苷酸的One-hot编码而非嵌入(这主要针对仅序列模型。当包含更多特征时,One-hot是给定的选择)
  3. CapR
  4. BPP sum&max
    我还发现将bpps值注入注意力机制很有帮助,特别是当bpps上使用了2D卷积层时。然而...我对bpps非常非常怀疑。我担心它们在私有测试集上会表现得很差,因为私有测试集包含新序列,我认为即使它在公共集上表现良好,也许BPPs模型是基于相似序列开发的,但对于私有集,它会失败。所以我选择只包含每个核苷酸的sum&max,认为这些"平均"值不太容易过拟合。另外,老实说,我在最后没有足够的时间来研究和集成更复杂模型的集成,因为我在太少的时间内尝试了太多想法,哈哈。
  5. 加权损失函数:
    让我们从结果开始。
    loss(reactivity, reactivity_error, pred) = MAE(reactivity, pred) * potentials
    其中:
    potentials = (1 - 2 * dist.cdf(reactivity - |reactivity - pred|)
    且:
    dist = 正态分布(mu=reactivity, sigma=reactivity_error)
    现在,解释为什么。
    我对损失函数思考了很多。由于我们得到了误差,我寻找将测量不确定度纳入损失函数的适当方法。当我找不到有用的东西时,我有点惊讶——当然,也许我没有深入挖掘,但至少似乎需要大量的挖掘。我找到了几个关于将不确定度纳入预测的方法(即预测预测的不确定度),但我想要相反的效果。
    现在,显而易见的做法是直接根据误差来加权损失——举个例子,Hoiso(第二名)使用了log1p误差,我看到了像1/(1+err)这样的建议。然而,我需要的不止这些:它对高误差和低误差的惩罚都太大了。为了理解为什么,让我们先谈谈误差的含义——一般来说,这意味着我们无法知道确切值,我们只能给出真实值的近似值,其概率分布由以sigma=error为标准的正态分布给出。当我们说reactivity=0 ± 1时,我们给出精确值在-1到1之间的概率为0.68(即在一个标准差范围内)。
    假设我们有reactivity1 = 0 ± 1,reactivity2 = 0 ± 3,pred1 = pred2 = 100。如果我们用1/(1+err)归一化,并使用MAE,则loss1 = 50,loss2 = 25。所以第一个预测对损失的贡献是第二个的两倍,但如果看概率分布——第一个在[-1,1]内的概率为0.68,第二个在[-3,3]内的概率为0.68(在[-6,6]内的概率为0.95),所以对于一个远离大多数分布的预测,我希望两个预测对损失的贡献差不多。当然,我们将预测裁剪在0,1之间,使分析更复杂,取决于每个人应用的具体损失和裁剪。
    另一方面,假设我们有reactivity1=0 ± 0.01,reactivity2=0 ± 0.1,pred1=pred2=0.05,则loss1=0.0495,loss2=0.0454。这次,它们几乎相同——即使我们知道reactivity1在[-0.01, 0.01]内的概率为0.68,这相对于reactivity2的预测(位于真实值分布的一个标准差内)来说远离预测值,所以我希望它对损失的贡献小得多。
    解决这个问题的一种方法是根据它们的概率分布扰动反应性值。然而,这会导致训练不稳定,因为许多值具有高误差,而且它们会被扰动到[0,1]范围之外,导致更多并发症。
    我想将我们对值概率分布的了解正确地纳入损失函数。这时,我受到壳层定理的一些启发,通过将概率分布视为一种"势能",我得出了上述公式。
    这个损失帮助了我的收敛。我不太记得具体有多少,也许大约0.001?不是巨大的提升。但它确实有帮助。它还使收敛更加平滑。我认为这种方法允许包含高误差值,同时从它们那里挤出尽可能多的信息。而且,我相信这比试图伪标记高误差值更好,因为噪声数据仍然是包含真实信息的数据。我们只需要挤出这些信息……
    但等等,还有更多。如果我怀疑我们得到的误差本身不准确怎么办?
    没问题。只需将给定的误差乘以一个因子,加上一些常数误差,并用随机选择的因子集成多个模型。
    这时,我想起了逻辑回归的标签平滑方法,那么,这基本上就是回归的一种标签平滑形式。一旦我将其框架化为标签平滑,就很容易找到类似的想法,例如这篇论文。虽然看起来他们把事情复杂化了一点。
    注意,这同样适用于其他损失,例如对于MSE,将MSE乘以相同的"势能"等。

提交细节

  1. 集成(显然):
    这是一个很好的集成力量图(针对仅序列模型model_1)

  2. 集成bpp+CapR模型与仅序列模型:
    我非常信任我的仅序列模型,胜过信任+bpp&CapR的模型,所以我提交了一个纯仅序列模型的集成。我计划另一个集成只包含+bpp&CapR模型。但就在最后一天,当我准备好两个集成时,我再次查看了R1138v1预测结果的图片。基本上,我们希望模型复制以下图像:
    这是我仅序列模型集成的图片:
    有点难看清,但它恢复了中心线,特别是在2A3图中。然而,侧线缺失了。另一方面,对于+bpp&CapR模型集成:
    情况正好相反。我有侧线的可见痕迹,但中心线几乎什么都没有(可能是一个非常模糊的点)。
    这些图像带来了一个直接的想法……更多集成……(起初这并不明显,因为BPP&CapR模型/集成比仅序列模型的验证/公共分数高得多)
    我只剩下三次提交机会。我尝试了以下权重:6:2、5:3和4:4,偏向仅序列集成。4:4的分数更好,但我太怀疑bpp和CapR了,所以我选择了5:3权重,这与原始的只有bpp+CapR集成分数相似,但预计会更稳健。
    比赛结束后,我尝试了其他权重。这是完整的分析:
    即使我选择了最佳权重,我仍然会在价格范围之外。所以我并不太为自己错过而感到难过。不过,如果我在最后一天选择了4:4权重,我本可以排在第8位。请记住,我的解决方案不包含BPPs的边缘信息,与大多数(全部?)其他顶级解决方案不同。也许,除了第三名,他得到了一个非常强大的仅序列解决方案,比我的好得多。

我尝试过但未包含在最终解决方案中或未成功的方法(可能也因时间不足):

使用外部数据源作为损失的另一个头,使用外部数据源训练模型,在训练集上预测,并将预测用作特征,不同的bpps预测(eterna, contra等)贡献不大或根本没有贡献。结构(即(.)表示法)也没有特别有用。我计划了3D特征但没有足够的时间……我尝试了其他损失方案,例如最小化log损失(sigmoid)(即框架化为逻辑回归,因为值在[0,1]之间)或直接最小化"势能"(见#5.加权损失函数)——没有成功。我尝试了各种将bpp直接注入注意力的方案,有或没有2D卷积,它确实有帮助(至少验证集+0.001,如果提交可能会更多),但如前所述,我不信任bpps和公共LB。

验证方案

在实验过程中,我在长度为177的序列的中间反应性上训练(在核苷酸#36和#116之间,因为我们被告知私有集可能包含边缘核苷酸的数据)。我在长度为206的序列以及177长度序列的开始/结束(直到#36核苷酸和从#116开始)上进行验证。对于提交,我在所有大小的序列上训练,包括边缘反应性,并在我没有用于训练特定模型的随机部分序列上验证每个模型。

我的解决方案的主要收获

我的损失函数和与仅序列模型的集成可能有机会略微提高顶级模型/集成的分数。然而,我不会给太大机会,因为他们的分数远高于我,他们可能已经捕获了大部分可以捕获的内容。即便如此,我认为当我们有更多数据时(私有测试是100万新序列,有关于生产十倍更多数据的讨论),bpps和CapR方法将越来越无用,而从测量中挤出更多数据(正如我试图用我的损失函数做的)将变得比现在更有用。所以我仍然希望我的工作会有一些帮助。

引用来源

我的模型基于Hoyso的ISLR竞赛解决方案;参见他的讨论。
我使用ratthachat的notebook来计算CapR值。
请查看我的GitHub获取数据准备和训练代码。

同比赛其他方案