作者:黄天元,复旦大学博士在读,热爱数据科学与开源工具(R/Python),致力于利用数据科学迅速积累行业经验优势和科学知识发现,涉猎内容包括但不限于信息计量、机器学习、数据可视化、应用统计建模、知识图谱等。知乎专栏:R语言数据挖掘 邮箱:huang.tian-yuan@qq.com.欢迎合作交流。
前文提要:
本次试验要做的是,采用一些通用的方法来做自动特征筛选。尽管后面有想法自己做轮子,但是在自己做之前,我们还是先了解一下我们能够直接用的轮子。
基本自动化步骤:1、提供数据集并设置相关处理参数;2、建模;3、根据不同的模型提取变量重要性;4、为每个模型计算泛化误差;5、根据泛化误差对变量重要性排名进行标准化;6、把所有结果放在一张表格中展示出来。详细例子见官网文档:https://cran.r-project.org/web/packages/fscaret/vignettes/fscaret.pdf
这是一个基于caret包构建的自动特征工程工具,通过建模和提取变量重要性(varImp函数),综合各个模型的变量重要性结果来对变量的重要程度进行评价。实话说,这个方法有点迷。其中一个地方是每次训练的模型要实现自动化,但是超参数的变化引入随机性,究竟是如何初始化超参数的?这一点不是非常确定。
另一点在于是否能够把不同模型得到的变量排名进行比较和融合?我还是用通俗语言来讲:如果一个人才去了阿里的一个部门能够拿到P5,但是去另一个部门评级可能就是P7,我们能用P6来评价他的水平吗?不同的部门对个人才能的发挥有不同,因此对他的评价也不尽相同,但是个人本身的特性却没有变化。因此对于一个模型来说,相同的特征在不同的模型中重要性不一样,这是很正常的事情。但是这个特征能不能就简单地标准化,然后作为评价这个特征是否能够解决问题的标准?我认为就是不行,模型不符合实际情况,再好的特征也没法进行正确和准确的预测。从这一点看来,这个模型有点“一锅端”的意思。当然有的符合的特征,无论在任何模型中都会有举足轻重的位置,正如厉害的人到哪个岗位都能胜任,这样的事情肯定是有的。因此它具有一定的价值,以后在一些特定的场景中,也许能够派得上用场。

mlr包做特征工程的手段有两种:
1、过滤法:采用一种外部算法(基于特征与响应变量的关系)计算变量的重要性并进行排序,随后根据一定的规则(取最重要的n个特征或最重要特征数量的占比)筛选特征。筛选后可以直接进行建模。
2、包装法:随机挑选特征进行建模(像随机森林),通过交叉验证得到不同特征组合构建模型的表现,最终可以得到一个最佳的特征组合。这个方法需要的计算成本是巨大的。
如果大家没看懂上面讲的,我重新描述一次:
1、过滤法:公司招人,看看每个人跟岗位的匹配程度,然后把最为匹配的n个人挑出来,正式签约成为员工。
2、包装法:公司招人,让这些人随机组合成团队,然后来做同样一件事情,看看团队的表现如何。定期会有人员的流动轮转,最后看看哪些人构成的团队最为优秀,就把这个团队的人都留下来签约为正式员工。这个方法成本特别高(特殊方法比如末位淘汰、优胜劣汰的方法也是有的,这在筛选特征过程中也有对应的算法)。
mlr这个包做得特别精细,就过滤法而言,能够封装不同的算法来对特征的契合度进行计算,其支持的算法见Integrated Filter Methods。此外,遴选特征的方法也有很多种,包括最符合数量(abs)、最符合比例(perc)和阈值法(threshold)。这些方法不仅可以单独使用,也能够直接与整个mlr机器学习框架结合起来,从而构建新的学习器(learner)。此外,关于最佳特征数量还可以做调优(相当于告诉大家团队有几个人最为合适)。使用包装法,则需要确定:1、如何评价模型表现;2、用什么模型;3、如何构建特征集。构建特征集的方法包括:1、极限搜索;2、随机搜索;3、遗传算法;4、先后向确定搜索。
能够与mlr框架结合在一起是一个特色,能够自如封装很多当前优秀的特征筛选包的功能是很大的优势,能够节省大家学习各种不同包的时间。如果场景符合,非常值得尝试。需要注意的是,要使用这个技能请在github上下载这个包(`remotes::install_github("mlr-org/mlr")`),否则可能版本不够新不能使用部分功能。mlr包马上要迭代为mlr3包(mlr-org/mlr3),未来可能会有更加炫酷的特性,持续关注中。

这个看起来有点小众的包可能会发挥很大的作用。它的初衷是针对生物信息学中高维转录数据的变量筛选,但是作者表示,引用其论文的工作几乎没有来自生物医学领域的(原话:“The article describing FCBF has more than 1800 citations, but almost none from the biomedical community”。原文:FCBF : Fast Correlation Based Filter for Feature Selection)。这个包目前只有4个函数(其中一个是可调用的数据,见https://bioconductor.org/packages/release/bioc/manuals/FCBF/man/FCBF.pdf),解决的问题单一而专精。这里重点谈谈算法哲学:选择那些与响应变量高相关而彼此之间不那么相关的变量。通过筛选之后,与响应变量Y最相关的特征X的相关性为cor,那么,筛选子集中将没有任意一个变量与X的相关性能够超过cor(这里其实已经有梯度下降的意思了)。
值得一提的是,这个包的全称为Fast Correlation Based Filter for Feature Selection,也就是说它是非常快的。但是它的快并不是基于底层与硬件结合得有多好,而是它的算法极其简单粗暴。它对相关性的计算并没有使用经典的Pearson或Spearman,而是基于Symmetrical Uncertainty(对称不确定性)。所以应用范围不是特别广,它只能解决分类问题,而且必须对特征进行二值分箱(分箱后只有high和low两类)。需要调节的参数主要有两个,一个确定了分箱规则(无论分箱多少个,会把第一个箱作为high,其余都是low);另一个是相关性阈值设定,默认值为0.25(特征与响应变量的相关性必须高于0.25才会入选)。
牺牲了一些细节信息,但是在高维数据的特征选择中,确实是一把好筛子,有很好的借鉴意义。更重要的是,它是一个特别快的算法,方便部署。看起来只能解决分类问题,其实不尽然,我们完全可以吧响应变量也进行区间化,把所有数值都进行区间化,然后来做初筛。筛选之后,我们仍然可以用原始的数值进行建模。这正如某些企业筛选求着这,就问四六级有没有过,至于真实分数的多少要不要看,可以后面慢慢考虑。在特征特别多的时候,非常适用。
可以认为上面讲的FCBF属于过滤法的一种,那么下面介绍的Boruta则属于包装法。这是一个基于随机森林的变量筛选方法,每次迭代中要把所有特征做一个备份,然后在备份中进行混洗。在这个数据集的基础上来做随机森林模型,然后比较经过混洗和原来特征的重要性,如果原特征的重要性比混洗之后还差,那么这个特征被认为“不重要”。如果混洗之后,重要性总是比原来的特征要低,那么这个特征是“重要”的。这个方法是非常巧妙的,这个包也已经非常成熟(当前版本6.0.0,简要入门见https://cran.r-project.org/web/packages/Boruta/vignettes/inahurry.pdf),实现起来也非常地快。
我在想,如果不用随机森林,但是借用这个混洗的概念,是不是可以呢?后面在设计自己的套路时可以借鉴一下。
其实还看了很多其他的包,不过有的已经过时了,有的则目标定义不明确,或者统计基础太晦涩而程序设计不友好,易用性差。最后上一个近期Plos One发表的一篇关于特征工程的论文:
Accurate and fast feature selection workflow for high-dimensional omics data
作者中有Applied Predictive Modelling的作者Max Kuhn,让我眼前一亮。不过这个文章最后做的包没有上CRAN或Bioconductor,只有Github版本(enriquea/feseR)。值得称道的是里面的一个流程图,可以参考一下:

这也许不是完美的自动化特征筛选流程,但是这个框架为后续我们做全自动特征筛选提供了很好的模板。首先进行单变量的筛选,筛选完毕之后对变量之间的相关性进行分析再次剔除一些变量。然后在训练数据的过程中继续做变量筛选,基于机器学习模型的特质最后迭代出一个精致的特征集,最后得到模型并进行评估。翻译成通俗语言是:公司招人,基本素质不好的先拒绝掉。然后在第二轮考核中,看到有的人特点差不多,那么就适当留三四个,其他特点一样的就拒绝了。然后把这些人放在不同的团队中,让他们完成相同的工作,看看他们能够发生什么样的化学反应。实习期经过了一段时间,对他们在不同团队中的表现进行综合评估,最后决定人员的去留。留下来的就签约,开始稳定的工作内容,并在工作中不断调整自身和团队的关系(调参),来最大化公司的盈利能力。
经过这一轮探索,我们对自动化特征工程基本的套路有所理解了。事实上我从rmcfs包中也得到一个启发(https://cran.r-project.org/web/packages/rmcfs/vignettes/v85i12.pdf),尽管不一定能够派上用场。每个特征就是一列,特征之间能够求距离,最后得到相似度矩阵,然后可视化为网络(可视化只是手段,其实心中有网络即可)。那么网络中节点表示特征,边表示特征之间的相互关系。我们可以把响应变量引入,作为特殊节点。那么我们要做的就是找到与特殊节点相关的特征,并摒弃与特殊节点无关的特征。同时,让直接与特殊节点连接的节点相互时间的联系最低。这样,我们就把特征工程转化成了最优网络搜索的问题,这种方法也许能够在未来的算法设计中起到作用。
别人的轮子都看完了,后面要造自己的轮子了。如果有更多的建议,请各位大佬不吝赐教。
原文作者:;如有侵权,请联系管理员删除。