sklearn - 模型过拟合

6

我正在寻求关于如何解决当前机器学习问题的建议。

问题的概述及我的做法如下:

  • 我有900多个EEG数据试验,每个试验持续1秒。每个试验的地面真相都已知,并将其分类为状态0和状态1(40-60%的分割)
  • 每个试验都经过预处理,其中我过滤并提取特定频段的功率,这些构成一组特征(特征矩阵:913x32)
  • 然后我使用sklearn来训练模型。使用交叉验证,测试大小为0.2。分类器设置为具有rbf内核的SVC,C = 1,gamma = 1(我尝试了许多不同的值)

您可以在此处找到代码的缩短版本:http://pastebin.com/Xu13ciL4

我的问题:

当我使用分类器对测试集进行标签预测时,每个预测结果都是0。 训练准确率为1,而测试集准确率约为0.56。 我的学习曲线图如下所示:

enter image description here

现在,这似乎是一个典型的过拟合案例。然而,在这种情况下,过拟合不太可能是由于特征数量与样本数量不成比例(32个特征,900个样本)。我尝试了许多方法来缓解这个问题:
  • 我尝试使用降维(PCA),以防我有太多的特征,但准确性得分和学习曲线图看起来与上面的一样。除非我将组件数设置为低于10,此时训练准确度开始下降,但考虑到你正在开始失去信息,这不是有点预期吗?
  • 我尝试过对数据进行标准化和归一化。标准化(SD = 1)对训练或准确性得分没有任何改变。归一化(0-1)会使我的训练准确度降至0.6。
  • 我尝试了各种C和gamma设置用于SVC,但它们都不改变得分
  • 尝试使用其他评估器,如GaussianNB,甚至集成方法如adaboost。没有变化
  • 尝试使用linearSVC显式设置正则化方法,但情况并没有改善
  • 我尝试了使用Theano运行相同的特征的神经网络,我的训练准确度约为0.6,测试准确度约为0.5
我很乐意继续思考这个问题,但目前我需要在正确的方向上得到一点指引。我的问题可能出在哪里?我该如何解决它?
我的特征集有可能无法区分这两个类别,但在得出这个结论之前,我想尝试一些其他选项。此外,如果我的特征无法区分,那么测试集得分低就可以解释了,但在这种情况下如何获得完美的训练集分数呢?这是可能的吗?

可能值得了解一下当前Kaggle竞赛涉及EEG数据的竞争对手们正在做些什么 - 特别是脚本和论坛。 https://www.kaggle.com/alexandrebarachant/grasp-and-lift-eeg-detection/beat-the-benchmark-0-67 和 https://www.kaggle.com/c/grasp-and-lift-eeg-detection - Ryan
测试中0.56的平坦学习曲线非常奇怪。所有样本都独立吗(来自不同的主题)?您如何构建训练/测试分割? - ldirer
所有样本都需要独立吗?我有大约900个试验,涉及大约20个受试者,所以不需要独立... - Simon
样本不需要独立。但这会影响你如何将数据集分成训练/测试集。这也取决于你的预测任务。如果你在训练集中有主题1-16的所有样本,而在测试集中有主题17-20,那么你的模型可能会找到与主题17-20无关的特征。这只是一个想法,并不是说如果没有意义就应该“分割”给定的主题。 - ldirer
啊,是的,那是一个非常好的观点。最初我按照您提到的方式进行了切分,但这是不正确的。我现在开始使用sklearn.train_test_split和sklearn.ShuffleSplit,我相信这两个都会随机洗牌特征向量,除非我错了? - Simon
使用留一法交叉验证来观察差异。 - seralouk
1个回答

7
我会首先尝试在参数空间上进行网格搜索,同时在训练集上使用k折交叉验证(当然要将测试集保留在一边)。然后选择从k折交叉验证中泛化最佳的参数集。建议使用GridSearchCVStratifiedKFold(当将分类器作为估计器传递时,它已经是默认策略)。
假设带有rbf的SVM可以完美地拟合任何训练集,因为VC维是无限的。因此,如果调整参数不能帮助减少过度拟合,则可能需要尝试类似的参数调整策略,例如线性SVM或其他适合您领域的分类器。
正则化如您所提到的,如果可用,绝对是一个好主意。
预测相同标签让我想到标签不平衡可能是一个问题,对于这种情况,您可以使用不同的类权重。因此,在SVM的情况下,每个类别都有自己的C惩罚权重。 sklearn中的一些估计器接受fit params,允许您设置样本权重以设置单个训练样本的惩罚量。
现在,如果您认为特征可能是一个问题,我会使用通过查看f_classif提供的F值进行的特征选择,并且可以与SelectKBest等内容一起使用。另一个选择是使用带有交叉验证的递归特征消除。如果使用sklearn Pipeline API,则可以将特征选择包装到网格搜索中。

你应该使用随机网格搜索。它更快,并且已经被证明优于传统的网格搜索。尝试在范围 [0, 1] 中进行搜索,然后,如果随机搜索返回接近该区间边缘的超参数值,则增加该超参数的搜索范围。请参阅 http://www.jmlr.org/papers/volume13/bergstra12a/bergstra12a.pdf。 - IVlad
明天我会尝试更多的参数调整。我在想,也许存在比那个更明显的问题,但我们将看到结果。你能解释一下f_classif到底是做什么的吗?它只是一个单向方差分析,其中我的每个特征都是整体检验中的一个水平吗?因为我刚刚在我的特征集上运行了它,没有一个p值小于0.05,它们大多数都在0.1-0.8的范围内... - Simon
我使用optunity选择最理想的超参数,而不是GridSearchCV,但是在调整参数后,我的训练准确率降到了约0.6左右,这很好,因为我不再过拟合。我想我只是没有非常好的特征。 - Simon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接