首届世界科学智能大赛:生命科学赛道——生物学年龄评价与年龄相关疾病风险预测
阿里云 天池大赛
比赛链接:
首届世界科学智能大赛:生命科学赛道——生物学年龄评价与年龄相关疾病风险预测_算法大赛_天池大赛-阿里云天池的排行榜 (aliyun.com)
目录
一、比赛信息
1.1比赛背景
DNA甲基化是一种常见的表观遗传学现象,它属于基因组核酸序列的功能性修饰,可以在不改变 DNA 序列的情况下影响基因的表达,其基本特点是在DNA分子中添加一个甲基基团,会对基因表达和细胞功能产生重要影响。甲基化通常发生在CpG位点,即一个C碱基与紧邻的G碱基相连的位置。该过程由DNA甲基转移酶催化,将甲基选择性地添加到特定碱基上。
随着个体年龄的增长,DNA甲基化的模式和水平也会发生变化。这种变化可以反映细胞和组织的衰老过程,在整体上与个体的年龄相关联,并在一定程度上解释了为何随着年龄的增长,个体更容易患上与年龄相关的疾病,是预测衰老、疾病与死亡的个体化生物时钟。
1.2比赛数据
公开数据包含10296个样本,其中7833个样本为健康样本。每一个样本提供485512个位点的甲基化数据、年龄与患病情况。抽取80%作为训练样本,20%作为测试样本。
以训练集为例,一共包括8233样本,其中健康样本6266个,其余为患病样本,共涉及Alzheimer's disease,schizophrenia,Parkinson's disease,rheumatoid arthritis,stroke,Huntington's disease,Graves' disease,type 2 diabetes,Sjogren's syndrome等类型。
解压后近100GB的数据,处理大数据比赛的难点之一。
1.3比赛任务
年龄回归与疾病预测。年龄上使用MAE(在患病样本上鼓励预测更大的年龄),疾病预测(阿尔兹海默症),使用F1-score作为标准
最后的总榜以两者加权值作为最后排名依据
二、个人比赛回顾
2.1 基础Baseline运行
由于是第一次打刷榜比赛,我最开始是通过Datawhale提供Baseline进行入手
AI夏令营第三期 - 生物学年龄评价与年龄相关疾病风险预测教程 - 飞书云文档 (feishu.cn)
(Baseline代码精读可以戳这个的链接,写的非常完善,而且有视频讲解)
这张图也是Datawhale的夏令营提供的,个人很喜欢,直接把整个流程框架写出来了,我也会在最后附上补充整理的思维导图。
在跑通baseline之后,我最开始增加了一些迭代次数和入模特征数,短期内都有个不错的提升,这一点在Datawhale飞书链接中也有体现。
Datawhale飞书链接参考的数值结果
2.2特征筛选
之后由于数据维度过大48w维,计算资源仅最多支持4w维度的GBDT模型的计算,小组尝试了分批次,每次4w维的catboost,xgboost,lightgbm的模型训练,各获取模型提示的重要性最高的1000个特征,最后融合成了筛选过的12000个特征。
2.3模型融合
使用筛选的特征,分别训练catboost,xgboost,lightgbm三个模型获得预测结果,每个模型都比原有的结果确实明显提升,达到2.55。
此后我也做了模型的融合,不同与datawhale的简单的将三者取平均值,我还是将三个输出和真实年龄再重新训练了一个线性回归模型(因为我发现lightgbm在线下测试集上明显不如另外两者,具体原因也未知。同时又因为只有三个变量,训练复杂模型过于苛责,所以直接暴力线性回归了),获得一定的提升效果,score到2.3左右,已经是GBDT的极限了
2.4模型更换
此时组内的大佬更换了模型,使用了autogluon,在同样的数据上获得更好的结果,达到2.19
2.5问题发现
此时我们也发现一个问题:mae-control和mae-case无论在哪个模型上都有极大的差异,很朴素的想法就是,我们通过数据先去预测一下是否患病,再分别训练两个模型。同时也对数据进行重新的理解,发现确实患病者的年龄分布平均更高。特别是阿尔兹海默,这也很make sense,毕竟是神经退行性疾病,老年人才可能患病。
2.6伪标签与额外的模型
此时知道了复赛的另一个标准是预测阿尔兹海默,一开始直接对是否是阿尔兹海默症进行预测,线下预测的效果其实尚可,但是对预测出的阿尔兹海默病人,用训练集全是阿尔兹海默的样本训练的模型,mae-case反而变大了,这一点在修改了假阳性的惩罚比重,获取了更保守的阿尔兹海默患者(一度只预测了6个病人,我相信这6个应该都是患病的,提交线上的mae-control确实没有改变),仅仅修改这几位一定是阿尔兹海默的病人的年龄,但mae-case仍然没有变好。后来反思应该是训练模型中阿尔兹海默的病人数据、分布等没有进行更深刻的理解,在后续读取经验分享的时候才意识到这一点。
2.7统计学分析
此时我们才做一些样本统计值的分析(说实话有些本末倒置,一开始就框框无脑跑流程,反而没有关注数据本身),最基本的从患病/对照组,以及男女等,都还是有明显的差异。而且也发现了一个很重要的问题:在年龄数据中有很多0值,这个0值是意味着刚出生还是该数据缺失,虽然没有做过试验,但更倾向于是前者,后来想想其实可以把0值剔除了,再直接跑后续的模型,再反过来预测这些标签是0的样本,如果回归结果不是负值or很小的值比如20以内,那确实说明是年龄缺失的脏数据。
2.8生物学分析
毕竟小组成员都是生信和生物学背景,此时我们也去关注了生物学意义,也对甲基化的数据(beta值和M值进行了一个最基本的理解,比赛使用的是M值具有更好的统计意义,更适合下游分析),也去搜了相关的数据科学比赛、论文与数据库。
甲基化芯片中的M值和B值 - Zhongxu blog (zxzyl.com)(甲基化芯片中的M值和B值,计算公式)
AMP®-Parkinson's Disease Progression Prediction | Kaggle Kaggle上帕金森预测比赛
DNA甲基化时钟和衰老的关系是什么? - 知乎 (zhihu.com) DNA甲基化时钟和衰老的关系是什么?
Making sense of the ageing methylome | Nature Reviews Genetics 相关综述论文
后续进入复赛组员都有各自的工作太忙了没打下去,略显可惜。但也能感同身受到切榜的时候,初赛的模型效果非常非常差的阵痛,甚至f1-score只有0。初复赛的数据明显不一致也是组委会所说的一个难点,所以后续对答辩视频的总结也会着重读一读几位大佬是如何处理的。
三、决赛视频总结
3.1 shakeupupup
(1)非正态分布,使用box-cox变换使得成为正态
缺失分析,初复赛前后缺失分布不一致剔除
(2)特征交叉 显示特征交叉 隐交叉,FM FFM deepcross等
不同变量之间的相乘(内积等等),适配高纬度。Top特征的交叉
特征交叉的本质与构造方法(图解) - 知乎 (zhihu.com)
特征衍生+python案例 - 知乎 (zhihu.com)
评委:交叉的结果可能丢失生物学的意义。需要在生物学意义上增加显示隐式的交叉
这点我其实感同身受,这个学期学了一些类似于WGCNA的原理,深刻意识到协同变化的重要性,这是生物信息所必须要考虑的,全局的统计值如均值、方差在模型中都并不重要可能并没有明显的意义,需要对甲基化位点更深刻的理解,去创建特征。
(3)对抗验证,面对样本分布改变的情形(对应交叉验证)
个人觉得有GAN的感觉在里面
构造一个分类模型,来预测样本是训练集或测试集的概率,AUC在0.7以上),那么可以说明我们的训练集和测试集存在较大的差异。
1.选取模型更可能是测试集的训练集样本用于训练的验证集(纠偏,切不浪费已有训练集【不是删除其他的】)
2.人工划分,有充分的理解下划分,选取与检验集属性最相近的作为验证集
3.有权重的交叉验证,对更相近的权重变大(按分类器的概率来定权重)
由于所有的优化模型的决定,都将基于验证集,而交叉验证无法准确评估模型在测试集上的效果,这将导致很多优化模型的决定是错误的。要有一个合理的验证集!
这一点流程的是刷榜比赛,因为刷榜是以成绩为首要条件的,但同时最近组里面讨论到:做科学研究,碰到不同医院的数据分布不一致,该如何解决,当然最理想的是获取一个绝对的标准进行归一化,或者是理解到不同批次的客观影响(类似于知道图像复原中的退化机理),但这在多中心数据中很难去实现。
个人目前朴素的认为是可以将上述思维反方向的去做,用数据去分别是否是不同医院/批次的数据,将分别医院/批次的重要性的特征进行读取与理解。
同时我也学习了RNA-seq和单细胞相关的消除批次影响的一些资料,但时间有限,我还没去读详细的原理,仍然不知道是否适用在其他场景。(ps:机器学习相关模型我老早就开始无脑用了,但最近去读了西瓜书等详细的算法原理,才发现有些东西可能不能想当然的认为,而知道了原理也才可以更好将数据前处理,不然永远就是garbage in, garbage out)
下面提到的combat去除批次效应是基于经验贝叶斯框架来矫正的,时间有限,之后读完了我再补充吧
RNAseq数据分析|1.消除批次效应 - 知乎 (zhihu.com)
Combat 去除批次效应(batch effect) - 知乎 (zhihu.com)
(4)特征选择的进化,不仅是看模型输出的结果
Null-importance 好的特征在原有的重要性是很高的,对于打乱标签的重要性应该是低的,可以通过差值进行分析那些事重要的,用null importance来对实际的importance做一个修正,得到真实的特征重要性。
imp_df["importance_gain"] = clf.feature_importance(importance_type='gain')
imp_df["importance_split"] = clf.feature_importance(importance_type='split')
树模型的特征选择-Null Importance - 知乎 (zhihu.com)
两个重要性gain 更加注重于特征对于模型预测性能的贡献度,而 split 更加注重于特征的使用频率,这一点也是在后续读西瓜书的时候再进一步补充吧。
(5)解决样本不均衡问题:SMOTE过采样 插值合成样本
参考:解决样本不均衡问题:SMOTE过采样详解 - 知乎 (zhihu.com)
1.对于每一个少数类样本,计算其与所有其他少数类样本之间的距离,并找到其K个最近邻居。
2.从这K个最近邻居中随机选择一个样本,并计算该样本与当前样本的差异。
3.根据差异比例,生成一个新的合成样本,该样本位于两个样本之间的连线上。
4.重复上述步骤,生成指定数量的合成样本。
(6)多任务学习模型DeepFM MMoR。
多任务学习MTL模型:MMoE、PLE - 知乎 (zhihu.com)
多任务学习也是我很久之前听说的,但一直没去学习的内容,也挖个坑后续来补把
(7)Embedding的操作,得到nn的隐式空间,获取位置关系的信息
3.2 猫猫摸鱼大队
(1)特征取值范围的意义,甲基化beta值M值
(2)样本正则化,均值方差受outliner的影响,使用分位数正则化,25%与75%分位数
(3)1d-cnn 捕捉cp岛的局部特征,但是考虑到主办方提供的数据混杂,可能是乱序,先全连接层重排特征,
组内做超大规模RNA序列预训练模型的大佬当时看到数据就说,如果序列本就是强连续序列性质的话,就可以用transformer等大模型读上下文关系了。
(4)TabNet模型,既考虑树模型,又考虑神经网络。TabNet继承了树方法的优点 (可解释性和稀疏特征选择),又继承了DNN的优点 (表征学习和端对端训练)。此外,TabNet的设计考虑了两个需求:高的模型表现和可解释性。其中一个比较重点的是tabnet使用mask,对部分内容进行激活
(5)用knn作为一个基本的case和control的标签的提供,分类讨论,这点其实很多组包括我自己也想过尝试过
(6)损失函数使用Huber loss对异常值不那么敏感
(7)通过beta分布对数据进行融合(类似插值),实现数据增强
3.3 左纳乌能源研究所
(1)EWAS数据库(虽然数据库仍然认为位点是独立的,但已经初见生物学上的理解)
(2)Statsmodel的p值检验,暴力计算
(3)读取甲基化位点的知识,比如在哪个染色体,互相影响的关系(生物学的影响,包括性别的信息,XY染色体)。
评委:这部分或许能通过神经网络 隐空间上进行读取到
(4)直接把54岁以上的置为有AD,朴素的方法,获取较高的F1值,或许可以简单的将原有概率和年龄做一个简单的二元变量训练模型?
这位大佬是华大的工程师,算力资源是真的足
3.4 小概率
(1)MLP,最基本的1536输出隐藏层,BN和RELU提升稳定性,dropout提升过拟合。模型非常轻量,推理速度快,也算是一个巨大优势
(2)清洗脏数据,训练集中重复or特征一致但标签错误的剔除,同时将模型训练集预测错误的数据删除
3.5 hahahah
(1)数据洞察,分布的分析,年龄分布统计分析,双峰分布
(2)特征选择,类似于数字信号处理重叠相加法的shift and overlap方案分批学习,分析不同批次重要性的差异(若考虑上下文关系,有效减少了不同批次之间的断层)
这点其实也是我之前分批次处理中没有去考虑的,或许能有一定的提升
(3)Bias Learning via Pseudo Label 伪标签的概念
Pseudo Label 以sample type为目标,二分类交叉熵,作为新标签(上面第二组也做过这样的工作),为正常样本的概率,作为新的条件输入,告诉模型具有bias。
这点我在比赛的时候其实也想过,先预测是否患病,再进一步预测疾病和年龄,但当时效果不佳,甚至预测疾病的正确率也不高。这里很好的规避了这个问题:既然正确率不高,那就都融合加权训练,或者仅仅是告诉模型对疾病样本需要添加一个先验的bias
3.6 牛刀小试
(1)传统的lasso和逐步逻辑回归特征筛选很耗时与资源,舍弃
(2)Sex_mapping 以-1 0 1 女 未知 男(很细节的小技巧,虽然说一些模型支持分类输入,但或许这样的mapping会比简单的类别更容易被学习)
(3)各组甲基化均值的差异,选出组间差异最大的组并剔除。为什么剔除,剔除什么非常重要!
第一列是阿尔兹海默,第六列是对照,甲基化形式是完全相反的(颜色一深一浅),而其他疾病的表达模式具有相似(比如第三列亨廷顿与阿尔兹海默非常类似【或许是因为神经退行性疾病,那么这些甲基化位点是否能对神经疾病作为指导影响?】),对模型会有干扰,所以把其他疾病的样本直接剔除。
(3)与年龄的线性回归bonferroni的检验寻找位点(与模型训练找出的位点重要性有何互相可参考借鉴的地方?)
(4)Ad模型几乎沿用与年龄相同的框架,但把年龄值也作为一个变量放入ad的模型进行训练,多任务学习是否可以用循环的迭代验证?将疾病的结果再反向放入年龄预测中,这样子实现迭代优化的多任务学习。
(5)MLP模型也是基本的BatchNorm和RELU,其实非常朴素,但仍然有很好的效果
四、更新的思维导图
五、总结
数据分析的工具和专业知识,缺一不可。
之前一直信奉去套用更高级的模型,从传统模型到集成模型再到神经网络,同样的数据得到的效果确实有一些提升,但这都是短暂的麻痹神经的奖励罢了。算力的提升也是同样的道理。
“garbage in, garbage out”,一方面从模型算法本身的角度,目前有很多我当做经验或者已有的结论去使用,诸如模型更适配高斯分布的数据,后续仍然去要理解详细的算法核心,才能知其然而知其所以然,使用的时候才不是当做黑箱去处理
当然,另一方面,生物学医学的知识也是及其的重要,虽然这次打榜比赛,我有意识的去搜索了一些甲基化相关的论文,但对相关知识的理解仍然不够。没有这些基础,更不可能构建出合适的特征,也更不可在先进的模型框架上,设计自己的创新。
或许这也是我从进大学选择生医工,再接着想做生物信息or计算生物学的我,最终的梦想与目标吧:能懂算法,能懂生物学意义,能懂医学问题。从医学中寻找问题,将其生物学意义极佳的契合到算法上;从而让算法指引生物学的发展,从而解决医学问题。当然其实更高的梦想,是能从生物学中仿生概念来设计算法,但开山之作是天才的工作,或许我与之无缘。当然无论是上述哪个模块。如果我的未来,能做出那么一点点的贡献,我也应该就十分满足了吧。
与诸君共勉。