为啥 cross_val_predict 不适合测量泛化误差?
Posted
技术标签:
【中文标题】为啥 cross_val_predict 不适合测量泛化误差?【英文标题】:Why is cross_val_predict not appropriate for measuring the generalisation error?为什么 cross_val_predict 不适合测量泛化误差? 【发布时间】:2019-07-27 07:51:38 【问题描述】:当我使用交叉验证训练 SVC 时,
y_pred = cross_val_predict(svc, X, y, cv=5, method='predict')
cross_val_predict
为X中的每个元素返回一个类预测,所以y_pred.shape = (1000,)
当m=1000
。
这是有道理的,因为cv=5
以及因此 SVC 在 X 的不同部分上进行了 5 次训练和验证。在五次验证中的每一次验证中,对五分之一的实例(m/5 = 200
)进行了预测。随后,将 5 个向量(每个向量包含 200 个预测)合并到y_pred
。
考虑到所有这些,我有理由使用 y_pred
和 y 计算 SVC 的整体准确度。
score = accuracy_score(y, y_pred)
但是(!)cross_val_predict
的文档指出:
cross_val_predict 的结果可能与得到的不同 使用 cross_val_score 作为元素以不同的方式分组。 函数 cross_val_score 对交叉验证取平均值 折叠,而 cross_val_predict 只返回标签(或 概率)来自几个未区分的不同模型。因此, cross_val_predict 不是泛化的适当度量 错误。
有人可以解释一下为什么cross_val_predict
不适合测量泛化错误,例如通过accuracy_score(y, y_pred)
?
编辑:
我首先假设使用cv=5
在 5 个验证中的每一个中都会对 X 的所有实例进行预测。但这是错误的,每次验证仅对 1/5 的 X 实例进行预测。
【问题讨论】:
【参考方案1】:cross_val_score vs cross_val_predict
cross_val_predict
和cross_val_score
之间的区别here 描述的很清楚,里面还有另一个链接,所以你可以关注兔子。
本质上:
cross_val_score
返回分数每折
cross_val_predict
对每个数据点进行不折叠预测。
现在,您无法知道 cross_val_predict
中的哪些预测来自哪个折叠,因此您无法像 cross_val_score
那样计算每个折叠的平均值。您可以平均 cross_val_score
和 accuracy_score
的 cross_val_predict
,但 average of averages is not equal to average,因此结果会有所不同。
如果一个折叠的准确率非常低,它对整体平均值的影响会比平均cross_val_predict
的情况更大。
此外,您可以对这七个数据点进行不同的分组并获得不同的结果。这就是为什么会有关于分组的信息有所作为。
cross_val_score 和 cross_val_predict 的区别示例
让我们假设cross_val_predict
对 7 个数据点使用 3 次折叠,折叠外预测是 [0,1,1,0,1,0,1]
,而真正的目标是 [0,1,1,0,1,1,0]
。准确度分数将计算为 5/7(只有最后两个预测错误)。
现在将这些相同的预测分成以下 3 份:
[0, 1, 1]
- 预测和 [0, 1, 1]
目标 -> 第一次折叠的准确度为 1
[0, 1]
- 预测和[0, 1]
目标 -> 再次完美准确
[0, 1]
- 预测和[1, 0]
目标 -> 0 准确度
这就是cross_val_score
所做的并将返回一个精度元组,即[1, 1, 0]
。现在,您可以平均这个元组,总准确率是2/3
。
看到了吗?使用相同的数据,您将获得两个不同的准确度度量(一个是5/7
,另一个是2/3
)。
在这两种情况下,分组都会改变您获得的总准确度。 cross_val_score
的分类器错误更严重,因为每个错误对组的准确性的影响大于它对所有预测的平均准确性的影响(您可以自己检查)。
虽然两者都可以用于评估模型在验证集上的性能,但我没有看到任何禁忌症,只是行为不同(折叠错误没有那么严重)。
为什么两者都不是泛化的衡量标准
如果您根据交叉验证方案拟合您的算法,则您正在执行数据泄漏(针对训练和验证数据进行微调)。为了获得泛化错误的感觉,您必须将部分数据排除在交叉验证和训练之外。
您可能想要执行双重交叉验证,或者只保留测试设置,以了解您的模型的实际泛化程度。
【讨论】:
当然,除了验证集之外,您还需要一个测试集来评估模型的泛化程度。让我重新表述我的问题。如果我有一个 C=1 的 SVC A 和一个 C=100 的 SVC B,我想知道:我可以使用预测y_pred
(通过 cros_val_predict
计算)来计算性能统计信息,例如我的 SVC 的准确性A 和 B 来评估 C=1 还是 C=100 是我的数据更好的超参数?
这取决于我的回答中描述的程序是否适合您。你会从cross_val_score
平均和cross_val_predict
平均得到不同的结果,因为某些错误的权重不同。总而言之,是的,您可以这样做,并且您将能够评估哪些超参数集可能更好(我在这里没有看到任何禁忌症,如果我错了,请有人纠正我)。
“cross_val_predict
averaged”到底是什么意思?平均cross_val_predict
的输出意味着平均一个包含类预测的向量,这对我来说毫无意义。根据这个预测向量计算的准确度得分对我来说也没有意义,因为它是一个单一的值。
平均accuracy_score
的cross_val_predict
和目标,这就是我的意思。每个预测都是在未训练分类器的折叠上进行的,因此您会得到所谓的折叠预测,其形状等于目标 (y
)(这就是在你的编辑:)。是的,你会得到一个值,这就是 accuracy_score
所做的,也是你最初所追求的:With all of this in mind it would be reasonable for me to calculate the overall accuracy of the SVC using y_pred and y.
,不是吗?
非常感谢。这个例子真的很有帮助!我做了同样的计算,但各个 cv 组的大小总是完全相同。在这种情况下,平均值等于平均值(至少里卡多在您发给我的链接中是这么说的)。以上是关于为啥 cross_val_predict 不适合测量泛化误差?的主要内容,如果未能解决你的问题,请参考以下文章
为啥当 cv=5 时 cross_val_predict 只返回单个预测数组
sklearn TimeSeriesSplit cross_val_predict 仅适用于分区