实战美年健康 AI 大赛之三 _ 大数据量的简化

#算法实战

1. 说明

  美年健康也是一个认真打的比赛,初赛B榜最高分 0.0279,排名 15.

  最初是想用它实践一下自然语言处理,后面发现,另一个与之前比赛不同的地方,就是数据量很大,之前也做过几十上百万条记录的,但是特征少,这次 57000 多个记录,2700 多个特征.从提取特征到训练完成,我的代码要跑近三个小时,后来审核代码的阶段,在群里看到很多人代码都需要运行很长时间.

  初赛 90% 以上的时间都花在自然语言处理上了,像去噪,特征筛选,调参,模型组合,结果分析几乎都没做,能刷到第 15,应该偷笑了.

  在初赛结束后的几天里,开始尝试特征选择,希望优化整个过程,才发现数据量大的不能像之前那么处理.上述没做的那些,不是没有精力,是没时间.在大数据上做这些太花时间.在”大数据”里面,应该先要做一些简化,否则很多时间都浪费掉了.

  本篇就来说说大数据和小数据的不同点以及应对方法.

2. 提取特征

  这个题里面有些文本特征,和一些文本数值混合特征.首先要做的是清理和提取,尤其是”-1”,”正常”,”未见异常”,”阴性”,其实是同一种情况,还有不同单位换算,如果这些不处理好,用什么模型效果都不好.

  尽管特征已经很多,但还得加,因为像B超结果,它确实能提供数值以外的其它信息.

  文本中携带的信息太多了,总结一下大家的做法:

  1. 先把文本为主的和数据为主的分开.

  2. 对文本为主的:分词,提取关键字,统计出现频率(TF/IDF,聚类等等).

  3. 判断高频词是否在字段是存在,生成一些的的布尔特征.

  4. 人工检查高频文本,选出像"脂肪肝","高血糖"这样的关键字及字段写正则.

  5. 还有直接在 Excel 里用公式做的,手工改的…

  总的来说,还是"数据太多",如果只有几个文本字段,且每个都不长,写判断或者正则就好了.但如果是上百个特征,就只能采取一些自动的方法了.

  在这种情况下,注意边取边筛,使用一些"单变量特征选择"的方法,比如计算特征与目标的相关性,分析残差等方法,以避免爆炸式增长.

3. 特征筛选

(1) 删掉缺失值太多的特征

  怎么衡量缺失值的多少?比如说决策树每个叶节点至少 20 个实例,那么非空实例小于 20 的特征肯定没用.从本文中提取特征,也是同理.

(2) 删掉无意义特征

  如果该特征所有取值都是 1,它就没有判断价值,很少有这样的.但可能会有如果有值则为 1,其它全空的情况,这就要看如何处理缺失值.如果均值填充就变成全 1 了.还有枚举型某种取值实例太少,不足一个叶节点的情况.总之,需要看看分布.

(3) 删掉重复特征

  可以直接用 drop_duplicates 删掉的并不多,但在上千个特征的采集过程中,一般都会有些显性和隐性的重复,比如:"子宫","输卵管"这些关键字与"血压"强相关,原因是"性别"和"血压"强相关.所以这样的关键字提取很多也没什么用.

  此时可以分析特征间的相关性 corr().corr() 只能检测线性相关,所以绝对值如果低并不说明无关,但如果值高,一定相关.那如果两个特征相关性为 1,就可以去掉其中一个了?也不行!计算相关性时一般忽略掉空值,这个也要考虑在内.

(4) 单变量特征筛选

 Sklearn 也提供了一些特征筛选的方法:sklearn.feature_selection.*,比如 SelectKBest 可以支持卡方 Chi2.Sklearn 对数据有一些要求,比如有的要求非空.

  另外用于检测单变量与目标相关性的还有互信息,皮尔森相关系数,最大信息系数等等.

  残差分析也是一种常用方法.简单地说就是:计算当 X 位于不同取值范围时,Y 均值的变化.从而检查 X 是否对 Y 有影响,它能检测到一些非线性相关的情况.

(5) 基于模型的特征选择

  基于模型的特征选择,指用模型训练完成之后,通过模型输出的特征重要性 feature_importances_,选取其前 N 个特征.

这个是训练之后才能得到的数据,都训练完了,时间都花掉了,才选出特征有什么用呢?这是个先有鸡还是先有蛋问题.

  首先,用这种方法选出的重要特征可以更好地解释模型和数据.而且它是多特征组合的结果,不只考虑了局部特征.

  另外,还可以用它筛掉一些干涉性特征,比如做 10 折交叉验证,其中 9 次都认为某特征不重要,其余那一次,很可能是干扰,也算一种统计吧.

  一个小技巧是,在提取特征的过程中,可以边提取边训练(设置参数,少量实例,少量特征以快速训练)至少能粗分出某个新特征重要与否,是否应该保留.

(6) 其它方法

  还有主成分分析 PCA 等方法.方差分析 ANOVA,信息值分析 IV 等等.

  上述都是从特征角度筛选,还有从实例角度筛选(不限于此题),比如分析广告和购买时,那些从来不买东西,从来不点广告的人,可能就需要另外处理,或者在回归前先做个分类,计算一些统计特征(有点跑题了).

4. 选择模型

  在梯度下降决策树 GBDT 类算法为例,不同的工具,用时不同,优势不同.

 xgboost 比 sklearn 自带的 GBDT 快,lightgbm 比 xgboost 快,catboost 最慢,但它在小数据集中效果好.一般情况下,xgboost 得分一般比 lightgbm 要高一点.

  也没有哪个好,哪个不好,针对不同的情况选择不同的模型吧.像这种"大数据"的,lightgbm 相对快一些.

5. 交叉验证

 GBDT 类模型一般都会配合交叉验证,这样可以把所有训练数据都用起来,还能得到一个靠谱的本地得分.之前都用 5 折交叉验证,这次从 5 折改到 10 折,分数有明显提高.

  折数设定和数据量相关,假设只有 1000 个实例,用 10 折交叉,仅有 100 个实例用来测试,可想而知,很多情况都测不到,结果不够稳定.如果有 40000 个实例,10 折测试数据也有 4000 个,子训练集增加了 4000,相对更合理.

  但也有相应的问题,就是数据集越大,训练时间越长,5 折变为 10 折,训练时间也会翻倍.

6. 总结

  对于海量数据,除了建立集群,Hadoop 以外,从特征到模型,能做的事情还很多.在数据多的情况下,无论是数据分析,去噪,筛选都需要自动做.我觉得还是多研究现有工具和自己写一些通用的工具吧.