分享
机器学习模型的泛化能力不足,有什么改进思路?
二分类问题,采用Adaboost方法,80:20划分训练集和测试集进行交叉验证。通过调整基础分类器的个数,训练集的分类正确率控制在0.6~1.0范围内时,测试集的分类正确率都在0.6左右徘徊,很难提升。通过降低模型复杂度的方式,降低了训练集的分类准确率,但并不能获得更好的泛化能力(测试集表现),请问各位大神有什么提升办法?多谢各位的回答,bow~提问时为了简单明了,已经做的一些尝试没有提到,补充说明一下哈:1.关于模型选择,已经做过,数据集本身线性不可分,用tree族和非线性kernal的svm效果都不错,从效率出发选了tree族的,random forest和adaboost也做了比较,ada更好2.关于模型的参数调优,可以尝试的参数基本都做了grid search,上述是比较好的结果……3.关于测试集正确率,可能我没说明白,并不是在0.6~1.0波动,可以做到1.0, 但是为了获得较好的泛化能力简化模型,使其准确率从1.0下降到0.6的过程中,测试集上的效果并没有提升4.数据集本身有比较严重的imbalanced,所以其实得到比较高的正确率不难但并没有意义(都预测为多数样本的label即可),关键是要得到比较好的AUC。对于imbalance的问题,也通过采样和权重两个方面做了处理,上述是处理之后的结果……5.几位答主提到了特征选择和特征提取,正在尝试中,有好的结果了再上了更新……
回复 ( 10 )
谢邀。
基本思路就是:先把模型搞复杂,复杂到得到令你满意的训练误差(训练误差要低于『令你满意的测试误差』),然后在慢慢调参、简化模型、添加先验和正则、改变数据维度、特征提取等,直到测试误差也满足『低于令你满意的测试误差』。
频率派的模型,提升泛化能力一般就是各种正则。
但问题不一定是模型的泛化能力不足,很可能特征设计不合理。
也有可能你的数据信噪比就是这么样了,无法继续提升。
可以看一些错分的case分析一下原因。
1. Try different hyperparameters. Verify that your simple classifier is appropriate for AdaBoost.
2. Use a different model. Maybe the problem you’re trying to solve would be more easily learned by kernel SVM etc.
3. Look at your learning for each iteration. You might be overfitting without realizing it because you didn’t do early stopping.
对于题主的问题,从工程上看,也许可以从以下几点改进:
1. feature engineering
2. imbalanced dataset
3. ensemble method
第3点目测提升空间不大,题主用的adaboost、rf已经算ensemble了,最多再试下gbdt,或者把这些模型级联、线性加权试试?
第1点,建议试试 @Xinran He 在14年发表的论文 ,算法可以用陈天奇大神开发的xgboost实现;另外不建议做太多特征筛选
第2点,题主已经试过带权采样,其实还有很多方法可以试,可以参考以下链接:
不均匀正负样本分布下的机器学习
改进思路一般有两个:
1、改进模型:
①、换算法;
②、调参数。
2、做好数据预处理:
有一个好的数据集远比有一个好的模型更为重要。这里的“好”主要表现在两方面:
①、做好特征选择;
②、做好数据离散化、异常值处理、缺失填充等。
一些简单的,与数据集无关的方法:
(1)加入正则项
(2)数据中加入噪音
(3)训练多个模型,然后以多个模型投票的结果做为最后结果(bagging);
再有就是根据数据集本身的结构特征,构造一些方法:
(1)特征选择,减少输入参数的数量
(2)特征提取,把多个特征合并为少数几个特征(例如PCA),同样是为了减少输入参数个数
(3)根据已知的数据性质,构造新的样本,比如图像具有微旋转微平移不变性,那么就可以通过旋转和平移构建新样本
(4)根据数据的结构特征选择适合的网络结构,例如图像问题用CNN,时间序列问题用RNN
交叉验证和最后测试差多少, 是不是差的特别大。
差的特别大先看特征是否合理。
细点说:
这个一般是这么分析的。
1. 先不考虑模型是否适用的问题, 对于大多数情况下(图像领域不适用), 模型带来的提升不是很大, 但是也不会有很大的损失, 正确率0.6 肯定不是分类器的问题, 那么先排除分类器的问题。 (还有一种可能分类器是题主自己写的, 。。。。那么就需要考虑分类器的问题, 补充一句, 最好先不要用ada这种模型, 换个单模型的, 比如svm, 先进行摸底比较靠谱, 分析出来的结果也会比较透彻)
2. 在考虑过分类器之后, 如果正确率train和test差得多, 那么要先cv , cv的结果一般来说和test的差距不会很大, 看题主的描述貌似没有cv , 直接用train的结果和test的结果比较, 这是比较没有意义的一件事, 因为一般的模型train的结果都会高很多。 当然也可以不cv , 直接留一些dev , 比如 6:2:2 = train:dev:test。
3. 这里先讨论cv和test 比较一致的情况,这个没什么说的, 回去对着cv调就好了, 而且这里在顺带着说一下, 用正确率衡量结果, 而且是一个不平衡的结果是一个非常傻逼的行为, 非常傻逼, 可选的是auc , 如果是具体业务的话, pr 也是一个不错的选择, 而且cv也可以看得出来数据集sample 等其他步骤有没有问题。
4. 如果是cv 和test 不一致, 那么这个就是特征的问题, 可能的原因是特征里面有时间相关的特征, 影响了最终的结果。 这种情况怎么办呢, 要不然就是盲调, 就是大致根据cv再猜测一下test的情况, 要不然就是研究一下特征具体设计哪里有问题。 还有, 这种情况可以实用一下高斯NB, 说不定有奇效。
至于前面大哥说的, 什么加正则, 加这个加那个的, 我建议还是别试。 比较值得试的是降维、白化, ensemble 啥的最后做。
Feature selection
Parameter tuning
Ensemble method
看了几个答案,提到正则化和validation,这是防止过拟合的俩手段,另外还有人提到调参,这不挨着啊亲。题主问的是泛化误差,是Bound问题,理论。所以,找好的guarantee,推新的算法,去看看deepboosting就知道了。
题主查查:PAC learnable,VC dimension,Rademacher complexity,margin theory。应该就够了。
你的意思是在训练集可以做到准确率是1,在降低训练集准确率的过程中,测试集没有提升?
那么跟泛化能力相关的验证集丢到哪里了。如果嫌训练集多了,分一点给验证集。验证集多,用k fold评价时考虑到泛化性就更多。 验证集验证集,就像是专家打分,打出来高就是高,当然用在其他数据不见得,但你数据就这么点。
测试集都已经是正版发售了,平民玩家给出的反馈。。。我认为多看看验证集上的结果吧。。。
至于验证集和测试集的表现差别大意味着什么。。。
我认为只能说明:‘outlier’存在
但这个问题造成这一结果有几个可能:
1.如果你测试集样本少,可能选到了outlier。。。
2.如果在某个验证集fold中有outlier,造成验证集交叉验证的时候由于kfold间样本权重不权衡,导致了结果朝着某个方向偏斜。而测试集没有outlier。造成结果差异大
等等等…
但我认为,所有的问题都由于样本有‘outlier’造成的。为啥打引号。因为不见得就是有outlier,而是在你的模型中他是outlier。
解决方法很自然:
1.试图在预处理阶段消除这种outlier造成的影响。
2.找个把这个outlier接回家的新模型。相应于adaboost就是换分类器呗(只能挨个试)
3.试图调试k fold过程找到哪个fold是在多种分类器中都显著异常于其他folds的,然后确定哪些样本是可能“有问题”的,剔除掉。
最后,我认为还是你样本不够或者样本有错。