【项目小结】大规模数据(含缺失值)在机器学习中的处理及训练小结(基于python)

最近跟另一个室友在忙某网贷融资平台发布的客户分类、信用评级、还款预测的实时排行竞赛。平台提供附带标签训练数据集与不带标签的验证集,参赛选手提交验证集的预测结果,平台返回模型评价指标值。

其实就我们目前的烂水平来说做机器学习也没有我们太多事情,也就是安装好别人写好的函数库,导入数据,调好参数,剩下就是CPU跟GPU的事情了。然而很多问题都是尝试之后才会出现的,这半个月的瞎折腾也算是积累了一些经验,做个小结方便自己将来再做到相似项目时回顾参考,以供分享学习

准备工具

python 3.x

sklearn

我们的机器学习基于python3,以sklearn包的分类回归算法为主,也尝试了其他诸如imbalance、xgboost、lightgbm等独立算法包的数据处理以及训练学习的算法。限于笔者的水平,下面主要就数据预处理以及训练验证中出现的问题以及我们的解决方案做一个简要的报告。

数据预处理中

训练数据集的过程总体来说主要存在三个重大问题:

(1)数据规模较大

平台提供的数据是一个100000样本数×6813特征的带标签的训练数据,然后基于20000个验证集样本给出预测结果。训练数据集大小接近4G,这对于我们队中每个人都只有一台8G内存的笔记本是有很大承载压力的——每次读入数据是一个相当耗时的流程,而且很多算法在处理数据过程中会产生大量的缓存(如Kmeans需要存储相当于样本总数维度的相似矩阵),在数据预处理及训练过程中极容易出现Memory Out或者计算机直接卡机的问题。

对于数据规模较大的问题我们大致有如下的一些思路(有一些之后因为种种原因被弃用了,但是我认为是有参考意义的):

  1. 最直接的想法是采样和PCA等数据降维的做法,事实上我认为采样对样本的结构影响可能较大,并且PCA无法对存在缺失值的数据进行计算,关于缺失值的填充之后会提到,但是无论怎么填缺失值,对实际数据的分布拟合得好也是个极靠运气且很难验证的事情;
  2. 对训练数据预分类,如采用Kmeans,MiniBatchKmeans等分类算法先对样本数据进行初步无监督学习分类(比如根据某个指标分成5类左右,我们初期是根据缺失值NaN的分布进行的初步分类,这个在之后会提到),然后对每一类分别学习一个模型。然后对验证数据进行预测时首先套用预分类模型预测出其应归为哪一类,然后再使用每个预分类下的子模型进行预测标签,这样可以有效减小对计算机内存的压力;
  3. 对训练特征预分类,这个主要是因为缺失值NaN的分布在不同特征上的分布存在明显区别(当然不同数据集的特征不同,我认为完全可以因地制宜,学习算法中很多参数调整本身就是有经验成分的,没有必要生搬硬套已有的论文或结论),因此可以考虑将特征进行预先分组,对每一组的特征分别根据标签学习出模型然后投票加权或外套一个新的学习算法进行标签预测;
  4. 一个小细节:关于pandas.read_csv()函数,它其中有一个参数chunksize(整型),当使用默认值(即不修改chunksize)时函数返回DataFrame数据类型,若修改chunksize(比如chunksize=5)则函数将返回另一种类似list的数据类型TextReader,这是一个iterable的数据类型,其中保存着一个个样本数为5的DataFrame数据类型。我的理解是其相当于省去了拼接DataFrame的时间,因此可以大大加快读入数据的时间(chunksize越小越快,但是获取的数据都是按顺序被拆分成一块一块的,我认为比较适合需要进行交叉验证Cross Validation时的操作);
  5. 使用内存友好型的算法(如lightGBM等,这个在之后的训练验证中会详细说明);

(2)存在缺失值NaN

经过统计验证集中缺失值NaN大约占总数据元素比重的10%,缺失值NaN的存在是会导致大部分的机器学习算法无法正常运行。我找到的一般的填值方法大概有一下种:

  1. 填写特征列的平均值;
  2. 填写特征列的众数;
  3. 填写特征列的中位数;
  4. 填写零;
  5. scipy.interpolate.lagrange模块的拉格朗日插值法(这个方法比较适合时间序列形式的数据,无序的数据利用拉格朗日插值是没有科学依据的);
  6. pyMC包,蒙特卡洛马尔可夫采样工具。这个包的User Guide链接 http://pymc-devs.github.io/pymc/ 我没有特别看懂,但是好像这个包既能处理空值填写也能处理样本标签不均衡的问题。但是我的理解是认为pyMC还是比较适用于时间序列式的数据集,而我们处理的这种纯静态的数据好像不太适合用这个方法;

我认为如果一次性就给整个训练集将缺失值NaN全部填满是极容易影响训练集分布的,后来我有了一种想法,是否能通过交换不同样本的位置(即交换行)与交换不同特征的位置(即交换列)来使得大部分的空值能够集中成块状,这样能够方便我们约去一些空值来实现更好的预分类。一个比较直观的想法就是将行列分别按照其数据缺失值比率升序排列,这样数据的缺失率从左上到右下近似递增,这样可以尽可能得让缺失值汇集成块从而消除掉,将矩阵剩下的区域进行切片分区分别进行训练,对训练结果加权投票或者套一个新的分类算法实现标签预测。

下面是对训练数据集的缺失值NaN分布的可视化黑白图(白色表示缺失值,每张图是10000样本×6813特征的数据,这里截取了最上面3张图和最后一张图以供参考)。

 

 

可以看到特征列粗分可以归为6~7类,将一些缺失较多的特征列与样本行删除后再进行填写缺失值NaN,可以少“猜”很多缺失值,从而尽可能的使得填值保持原数据集的分布状态。然后进行切片学习,不失为一种思路方法。

(3)标签分布不均衡

根据对训练数据集的观察与分析,我们发现训练数据集中零一标签的比例大约为1:12(即按期还款标签大约是逾期还款标签的12倍)。标签分布不均衡一般会使得学习器在学习中偏向大标签,从而使得小标签的预测精确度相当不堪。举个简单的例子,学习器将全部数据预测为按期还款也可以拥有90%以上的精确度。但是通常对于网贷平台来说,精确预测逾期还款标签对它更有意义,因此如何处理标签分布不均衡问题是十分具有现实意义的。

通常的处理方法有大标签的欠采样与小标签的过采样。

一般来说欠采样在实际操作中使用较少,因为一方面欠采样导致训练数据数量大量减少,学习器的置信度会降低,另一方面欠采样使得对大标签的数据分布可能会有极大的影响,从而极大的影响全数据的分布。为了减小欠采样的负面影响,可以通过先对大标签进行聚类,再对每个分类分层抽样,这样可以尽可能的还原原数据的分布。

过采样的方法有很多,imbalance包中提供了常用的一些过采样方法(SMOTE,bSMOTE等)。根据这次项目中情况看来,SMOTE这种通过近邻再取线性组合的方法不仅最终的效果很差(我觉得两样本的线性组合仍然对样本结构造成了较大的影响),而且SMOTE的效率很低(大数据集下的SMOTE耗内存且速度很慢)。我们采取的过采样方法就采用了简单的BootStrap自助可重复采样方法,我认为这样相当于在损失函数中提高了小标签预测错误的权重代价,本质上没有对样本数据增加新的信息。

当然在数据规模已经巨大的情况下,仍然单纯采取过采样可能不是个灵活的方法,可以考虑过采样与欠采样相结合的方法,可以保持数据规模大小,免得被Memory Out的问题困扰。

模型训练验证

这部分是11月10日更新的。昨天奋斗了一晚上终于赶在零点前把期中项目交上去了。后来一阵子仍然没有得到较好的结果,可笑的是昨天花了半小时试了的Logistic Regression竟然可以跑到与目前我们组最好成绩相仿的结果,然而这几天花大把时间训练的SVM在训练集上可以达到0.80以上的AUC,但是提交上去竟然只有0.6都不到的AUC,就算是过拟合这在训练集的效果过拟合的也太“差”了。

有点累今天,大致总结一下各个模型的结果以及训练验证的历程。

最一开始使用Logistic Regression对不经任何特殊处理的训练集训练(即只填空值,不作分割),可以达到0.60左右的AUC。第一次使用的数据集分割策略是基于空值分布,对样本行进行Kmeans分割,最后试验结果是7分类最优,在这7分类上使用Logistic Regression, Decision Tree, Adaboost(套LR, DT), SVM(曾经12个小时没有能够得到训练结果,遂放弃), XGBoost,最好的结果是XGBoost得到的,接近0.70左右。

中途我忽然想研究训练数据集的空值分布,于是得到了博客上文的黑白像素图,基于黑白像素图,我们把训练数据集按特征列分成了5份(ABCDE),其中AB的非空值密度较大(在99%以上),因此我们计划分别按照AB, ABC, ABD, ABE切片制作了4个模型然后加权投票,另外我们在学习算法上做了改进,采用了比较流行的LightGBM,事实证明效果有了显著提升,最好已经达到了0.737。由于效果又很难再得到进一步的提升,我们试图重启SVM算法,好消息是SVM在这种分类上可以较快的得到模型(大约每一个切片需要半小时出预测零一的模型,如果需要得到预测概率的模型则需要近3小时)。好不容易得到了4个SVM模型,结果上传的结果竟然只有0.60不到(心灰意冷)。

感觉机器学习实在是还是太过于随缘了,现在是期中项目告一段落,大约到期末仍然会有进一步的改进,持续更新。

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值