sklearn.SVC 在使用带有小型平衡数据集的 GridSearchCV 时返回完全不同的预测(模型)
Posted
技术标签:
【中文标题】sklearn.SVC 在使用带有小型平衡数据集的 GridSearchCV 时返回完全不同的预测(模型)【英文标题】:sklearn.SVC returns radically different predictions (models) when utilizing GridSearchCV with small balanced dataset 【发布时间】:2018-05-14 18:33:05 【问题描述】:在使用 sklearn.GridSearchCV 而不是 sklearn.SVC(probability=True) 时,当训练数据较小且平衡(相对于较小且不平衡)时,将返回完全不同的预测/模型。考虑这个例子:
from sklearn.model_selection import GridSearchCV
from sklearn.svm import SVC
from sklearn import svm, datasets
iris = datasets.load_iris()
# Take the first two features. We could avoid this by using a two-dim dataset
X = iris.data[:, :2]
y = iris.target
index = [0,1,2,3,51,52,53,54]
index_unequal = [0,1,2,3,51,52,53,54,55]
new_predictions = [5, 6, 7, 56, 57, 58]
pred_mat, pred_y = X[new_predictions], y[new_predictions]
c_s = [0.01, 0.1, 1.0, 10.0, 100.0]
gamma = [1e-4, 1e-3, 1e-2, 1e-1, 1, 10]
svc_params = ['kernel': ['rbf'], 'gamma': gamma, 'C': c_s,
'kernel': ['linear'], 'C': c_s]
mat, ye = X[index], y[index]
mat_unequal, y_unequal = X[index_unequal], y[index_unequal]
balanced = GridSearchCV(SVC(probability=True), svc_params, cv=4).fit(mat, ye)
unbalanced = GridSearchCV(SVC(probability=True), svc_params, cv=4).fit(mat_unequal, y_unequal)
print(balanced.predict_proba(pred_mat))
print(unbalanced.predict_proba(pred_mat))
在平衡数据上训练的模型对所有新数据返回0.5
的概率,而使用不平衡数据训练的模型返回通常预期的结果。我知道这个例子中使用的训练数据很小,但只有 1 的差异,我很好奇正在改变什么机制来提供如此完全不同的模型/概率。
更新 #1
在深入研究这一点并考虑下面 Vivek 的回复(感谢非常棒的链接!)之后,了解 predict
和 predict_proba
之间的区别是成功的一半。我可以为 GridSearch 选择一个评分函数来优化概率而不是决策函数(例如,将 scoring='neg_log_loss'
添加到我的 GridSearchCV
调用中)。这将在两个模型之间提供更好的结果。但是,我仍然对上述问题的结果感到好奇。如果您深入研究这两个模型之间的差异,唯一的两个差异是附加数据和交叉验证生成器(即StratifiedKFold
上的 cv 属性)选择划分数据的方式。例如,考虑这些分层的 k 折指数:
balanced_cv_iter = [(np.array([1, 2, 3, 5, 6, 7]), np.array([0, 4])),
(np.array([0, 2, 3, 4, 6, 7]), np.array([1, 5])),
(np.array([0, 1, 3, 4, 5, 7]), np.array([2, 6])),
(np.array([0, 1, 2, 4, 5, 6]), np.array([3, 7]))]
unbalanced_cv_iter = [(np.array([1, 2, 3, 6, 7, 8]), np.array([0, 4, 5])),
(np.array([0, 2, 3, 4, 5, 7, 8]), np.array([1, 6])),
(np.array([0, 1, 3, 4, 5, 6, 8]), np.array([2, 7])),
(np.array([0, 1, 2, 4, 5, 6, 7]), np.array([3, 8]))]
balanced_cv_iter_new = [(np.array([1, 2, 3, 5, 6]), np.array([0, 4, 7])),
(np.array([0, 2, 3, 4, 6, 7, 1]), np.array([5])),
(np.array([0, 1, 3, 4, 5, 7, 2]), np.array([6])),
(np.array([0, 1, 2, 4, 5, 6]), np.array([3, 7]))]
balanced_cv_iter
和 unbalanced_cv_iter
是上述代码生成的两个潜在列表,与两个模型的训练/测试数据相关。但是,如果我们通过使训练/测试具有一些奇数个元素(不平衡的训练/测试集)来改变balanced_cv_iter
,那么我们可以得到balanced_cv_iter_new
。这样做会导致平衡模型和不平衡模型之间的预测相似。 我想这里的教训是针对模型的预期用途进行优化(即选择与模型的用途一致的评分函数)?但是,如果还有其他关于为什么的想法/cmets GridSearch 选择了一个带有超参数的 SVM 估计器,在不平衡的框架下会产生更好的概率模型,我想知道。
【问题讨论】:
【参考方案1】:你看错了。这与 GridSearchCV 无关。但是用 svm。
您看,您正尝试在 SVC 上使用 predict_proba()
,已知它的输出令人困惑,并且这些输出可能与 predict()
函数的实际输出不匹配。
我只做了一点小改动就运行了你的代码:
print(balanced.predict(pred_mat))
print(unbalanced.predict(pred_mat))
输出是:
[0 0 0 1 0 1]
[0 0 0 1 1 1]
如您所见,这两种情况并没有太大区别。在这两个输出中我能想到的唯一差异来源是,在第二种情况下,您有 1 个关于第二类的额外数据,这有助于比第一种情况更好地识别它。您可以通过更改类的样本来验证这一点。
现在关于为什么 predict_proba 给出这样的结果的解释请看:
Scikit-learn 关于it in documentation的澄清
This answer 由 scikit 开发人员之一在 *** 上发表
This excellent explanation 另一个 scikit 开发人员的差异。 (请阅读 cmets)
【讨论】:
Vivek,感谢您花时间研究这个问题。我已经更新了上面的帖子,并使用您的 cmets 和链接来帮助向其他用户解释一种潜在的解决方案。但是,我仍然很好奇为什么在这种情况下不平衡的设计会导致更好的概率模型(即使考虑到我何时选择会导致不平衡设计的交叉验证对象)。以上是关于sklearn.SVC 在使用带有小型平衡数据集的 GridSearchCV 时返回完全不同的预测(模型)的主要内容,如果未能解决你的问题,请参考以下文章