天池精准医疗大赛——个人赛后总结(二)
一、特征选择说明
坊间常说,数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已。当你的数据分布足够好,特征工程足够好,即使用很简单的模型也能得到很好的结果。由此可见特征工程在机器学习中的重要程度不言而喻。一个关键特征(gold feature)甚至可以让你前进几百名,特征选择(feature selection)也是这次比赛中我花费时间最多的部分。
二、特征选择的方法
(1)过滤式选择(Filter):过滤式方法先对数据集进行特征选择,然后再训练学习期,特征选择过程与后续学习无关,这相当于先用特征选择过程对初始特征进行”过滤“,在用过滤后的特征来选择模型。过滤式特征选择的评价标准从数据集本身的内在性质获得,与特定的学习算法无关,因此具有具有较好的通用性。过滤式特征选择的研究者认为,相关度较大的特征或者特征自己会在分类器上获得较高的准确率,dash 和 liu把过滤式特征选择的评价标准分为四种,即距离度量,信息度量,关联度量以及一致性度量。具体的原理和内容可以在论坛上都有相关的资源,也感谢各位大佬的无私分享,这里就不再一一赘述,在做特征工程的时候大家也可以都尝试一下这些方法,选用效果较好的那一种。上篇文章我提到的所采用的皮尔逊系数属于一种关联度量,是过滤式选择的一种。
优点:算法的通用性强,省去了分类器的训练步骤,算法复杂性低,因而适用于大规模数据集,可以快速去除大量不相关的特征,作为特征的预筛选器非常合适的。
缺点:由于算法的评价标准独立于特定的学习算法,所选的特征子集在分类准确率方面通常低于其他方法。
(2)包裹式选择(Wrapper):与过滤式特征选择不考虑后续学习器不同,包裹式特征选择直接把最终将要使用的学习器的性能作为特征子集的 评价准则。换言之,包裹式特征选择的目的就是为了给定学习器选择最有利于其性能、”量身定做“的特征子集。通常会采用基于Lasso的回归进行特征选择,可以使特征稀疏化,即很多参数的系数会为零,这样可以使我们去除系数为零的特征,做出特征选择。更为常见的是基于决策树的特征选择,如随机森林,GBDT,xgboost等树模型,在sklearn中都可以输出feature importance属性,得到特征重要度,从而做出特征选择。(我更愿意使用基于树模型的选择方法,树模型只对数据分布敏感,无须对数据进行归一化或者标准化)
优点:相对于filter方法,wrapper方法找到的特征子集都是为学习器量身打造,分类性能通常更好。
缺点:wrapper方法选出的特征通用性不强,当改变学习算法时,需要针对该学习算法重新进行特征选择,由于每次对子集的评价都要进行分类器的训练和测试,所以算法计算复杂度很高,尤其对于大规模数据集来说,算法的计算开销通常比Filter的方法要大得多。
(3)嵌入式选择(Embedding):在Filter和Wrapper的特征选择方法中,特征选择的过程和学习器训练的过程有明显的分别,与此不同,嵌入式的特征选择则是将特征选择过程与学习器的训练过程融为一体,两者在同一个优化过程中完成,即在学习器训练过程中自动的进行了特征选择。加入L1范数正则化和L2范数正则化,前者能够得到稀疏解,后者可以得到平滑解,都具有一定程度上的防止过拟合的作用。决策树的分裂,也可以看做是一种特征选择的过程。
三、特征选择
在这次比赛中,特征工程花费了我大部分时间。我相信好的特征能够很大程度的提高我模型的性能,同时找出好的特征也正是这次比赛的意义所在。因此我第一反应就是去搜索先验知识,搜索相关医学论文,寻找和糖尿病相关的独立危险性因素。同时发现糖尿病是一种多病因引起的以慢性高血糖为特征的终身性代谢疾病,会引起大量的并发性疾病。长期血糖增高,大血管、微血管受损并危及心、脑、肾、周围神经、眼睛、足等。因此我也去查找了大量相关并发症的独立危险性因素。翻阅了毫不夸张的有150+篇关于糖尿病及其并发症的相关医学论文(找的我头晕眼花,在此也要感谢为我国医学事业潜心研究的学者们),初步得到了很多有价值的特征。如血脂、甘油三酯和高密度脂蛋白胆固醇的比值、高密度脂蛋白胆固醇和低密度脂蛋白胆固醇的比值、中性粒细胞% 和淋巴细胞% 的比值等等大概二十几个。最后和原始特征合在一起做一个特征选择。(这里也有别的选手自己批量生成特征,即利用原始特征加减乘除取对数取平方、或者利用gbdt的子节点作为新特征等等骚操作,我觉得会降低模型的可解释性所以放弃了这种方法。但是这种方法确实取得了不错的效果。)
(1)利用皮尔逊相关系数法得到了各个特征的相关程度。
(2)将这些特征丢进xgboost进行训练,查看feature importance属性,得到各个特征的重要度。
(3)利用已知知识,根据奥卡姆剃刀原理,筛选掉重复特征。比如说:血脂,总胆固醇,甘油三酯三者和血糖值的线性相关性都很高,但是三者彼此之间的关联性也很强,血脂是总胆固醇和甘油三酯之和,在feature importance结果中它们的得分相互影响,所以在这里我选择保留了原始的总胆固醇和甘油三酯两个特征,去除血脂这个后续添加的特征。因为我觉得作为医院的检查指标其可挖掘性更合理更强,去除重复特征可以一定程度的避免冗余特征降低模型的泛化能力,使得模型过拟合。
(4)为了确保在特征选择过程中不丢失重要特征,我最大限度上的保留原始特征,因为我觉得医院的各项检查指标可以比较全面充分的反应我们的身体状况,具有很强的代表性。
(5)综合了一二三四步,最后还采用了一种贪心算法。将筛选出来的各个特征依次加入特征子集中然后训练模型,若学习器性能变好则把该特征加入特征子集中,反之则去除。保留最简单的模型,保证模型的泛化能力,将纷繁复杂的因素抽丝剥茧,只留下关键因素,使真相更容易看得清。
四、特征工程的结果
(1)将乙肝五项五个特征转化为是否检查乙肝一个特征。
(2)将性别进行了one-hot编码
(3)去除了检查日期这一项。(温度会对血糖值造成影响,训练集检查日期跨度从2017年9月至2017年11月,该特征没有缺失项,测试集检查日期为2017年10月。利用简单的可视化分析了各个月平均血糖值的变化,存在细微的波动但无法找出其中的规律。向主办方咨询了数据的出处,想爬取该地的气温将检查日期改为日期特征,但是主办方没有告知城市,因此最后还是选择了放弃改特征。但是依旧觉得其中有值得挖掘的信息,个人水平有限只能交给前排大佬了。)
(4)加入了四个新的特征。(由于比赛还在进行,为了公平起见,暂不公开具体内容)
最后仅仅加入了四个特征,也由于自己第一次参加比赛,经验不足,特征选择还是处理的很粗糙,感觉错过了很多强特,在这个方面今后还是要多加学习、多加改进。可能大致过程写出来也就短短一两千字,但是这其中的细节自己却是摸索了很久,做了很多尝试,查阅了很多资料,也成长了很多。
五、自己解决的几个问题
整理了几个过程中困扰了自己很久的问题。(还有很多都忘记了,之后想起来会依次整理出来)
(1)基于树模型选择特征的特点:对于存在关联的多个特征,其中任意一个都可以作为指示器(优秀的特征),并且一旦某个特征被选择之后,其他特征的重要度就会急剧下降,因为不纯度已经被选中的那个特征降下来了,其他的特征就很难再降低那么多不纯度了,这样一来,只有先被选中的那个特征重要度很高,其他的关联特征重要度往往较低。在理解数据时,这就会造成误解,导致错误的认为先被选中的特征是很重要的,而其余的特征是不重要的,但实际上这些特征对响应变量的作用确实非常接近的(这跟Lasso是很像的)。
(2)L1范数和L2范数:L1范数可以自动化选择特征且能够挑选出一些优质的特征,得到稀疏化的模型,且有很强的可解释性。在需要减少特征维度时很有用,但系数为零的特征并不能说明其不重要。L2范数可以得到相对稳定的模型,对于关联特征,它们能得到相近的分数,不像L1范数那样,系数会因为细微的数据变化而波动,所以L2范数和L1范数提供的价值是不同的,L2范数对于特征理解来说更加有用。而且L1正则化和L2正则化都可以降低模型的过拟合,提高模型的泛化能力。
(3)为什么丢弃某一特征模型性能没有大幅度降低?因为特征子集中某些特征之间存在一定的关联性,在删除某个特征之后,其关联特征一样可以发挥作用,保持模型的稳定性。
(4)如何特征选择?特征选择在很多机器学习和数据挖掘场景中都是非常有用的。在使用的时候要弄清楚自己的目标是什么,然后找到哪种方法适用于自己的任务。当选择最优特征以提升模型性能的时候,可以采用交叉验证的方法来验证某种方法是否比其他方法要好。当用特征选择的方法来理解数据的时候要留心,特征选择模型的稳定性非常重要,稳定性差的模型很容易就会导致错误的结论。对数据进行二次采样然后在子集上运行特征选择算法能够有所帮助,如果在各个子集上的结果是一致的,那就可以说在这个数据集上得出来的结论是可信的,可以用这种特征选择模型的结果来理解数据。