这些问题涉及如何计算和减少机器学习中的过拟合。我认为许多初学者都会有同样的疑问,因此我尽量通过我的例子和问题来清晰表达,希望这里的回答能帮助到其他人。
我有一个非常小的文本样本,我试图预测与它们相关的值。我使用了sklearn来计算tf-idf,并将这些值插入到回归模型中进行预测。这给了我26个样本和6323个特征 – 数量不多,我知道:
>> count_vectorizer = CountVectorizer(min_n=1, max_n=1)>> term_freq = count_vectorizer.fit_transform(texts)>> transformer = TfidfTransformer()>> X = transformer.fit_transform(term_freq) >> print X.shape(26, 6323)
将这26个样本的6323个特征(X)和相关得分(y)插入到LinearRegression
模型中,得到的预测结果很好。这些结果是通过留一法交叉验证获得的,来自cross_validation.LeaveOneOut(X.shape[0], indices=True)
:
使用ngrams (n=1): human machine points-off %error 8.67 8.27 0.40 1.98 8.00 7.33 0.67 3.34 ... ... ... ... 5.00 6.61 1.61 8.06 9.00 7.50 1.50 7.50mean: 7.59 7.64 1.29 6.47std : 1.94 0.56 1.38 6.91
非常好!使用ngrams (n=300) 而不是单字(n=1),得到了类似的结果,这显然是不正确的。没有任何文本中出现300个单词,所以预测应该失败,但它没有:
使用ngrams (n=300): human machine points-off %error 8.67 7.55 1.12 5.60 8.00 7.57 0.43 2.13 ... ... ... ...mean: 7.59 7.59 1.52 7.59std : 1.94 0.08 1.32 6.61
问题1: 这可能意味着预测模型对数据过拟合了。我之所以知道这一点,是因为我选择了一个极端值的ngrams (n=300),我知道这不可能产生好的结果。但如果我没有这种知识,你通常如何判断模型是否过拟合?换句话说,如果使用了一个合理的度量(n=1),你如何知道好的预测结果是由于过拟合还是模型本身工作得好?
问题2: 在这种情况下,防止过拟合的最佳方法是什么,以确保预测结果是好的还是不好的?
问题3: 如果使用LeaveOneOut
交叉验证,模型如何可能在得到好的结果的同时过拟合?过拟合意味着预测准确性会受到影响 – 那么为什么在留出的文本上的预测没有受到影响?我能想到的唯一原因是:在一个主要是0的tf-idf稀疏矩阵中,由于许多项都是0,文本之间有很强的重叠 – 回归模型因此认为文本之间高度相关。
请回答任何一个问题,即使你不知道所有问题。谢谢!
回答:
你通常如何判断模型是否过拟合?
一个有用的经验法则是,当你的模型在其自身训练集上的表现远好于在保留的验证集上或在交叉验证设置中的表现时,你可能在过拟合。不过,这并不是全部。
我链接的博客文章描述了一种测试过拟合的程序:绘制训练集和验证集错误作为训练集大小的函数。如果它们在图的右端显示出稳定的差距,你可能在过拟合。
在这种情况下,防止过拟合的最佳方法是什么,以确保预测结果是好的还是不好的?
使用一个保留的测试集。只有在完全完成模型选择(超参数调整)后,才在这个集合上进行评估;不要在上面训练,也不要在(交叉)验证中使用它。你在测试集上得到的分数是模型的最终评估。这应该能显示出你是否意外地过拟合了验证集(们)。
[机器学习会议有时被设置为一种竞赛,研究人员在向组织者提交最终模型之前不会得到测试集。在此期间,他们可以随意使用训练集,例如通过使用交叉验证来测试模型。Kaggle也做类似的事情。]
如果使用
LeaveOneOut
交叉验证,模型如何可能在得到好的结果的同时过拟合?
因为你可以在这个交叉验证设置中尽可能地调整模型,直到它在CV中表现得几乎完美。
作为一个极端的例子,假设你实现了一个本质上是随机数生成器的估计器。你可以不断尝试随机种子,直到你找到一个“模型”,在交叉验证中产生非常低的错误,但这并不意味着你找到了正确的模型。这意味着你对交叉验证过拟合了。
另见这个有趣的战争故事。