我正在使用不平衡数据训练正常和平衡的 线性 SVM,并使用 F1 分数进行测试。
(通过平衡线性支持向量机,我的意思是每个观测值的权重与其频率成反比,因此它从少数类“过采样”而从多数类“欠采样”。)
毫不奇怪,使用多类数据集并将其作为一对一二元问题单独解决,平衡线性 SVM 在每个类上都击败了不平衡线性 SVM:
normal vs balanced
target 01 - scores: 0.272 vs 0.608
target 02 - scores: 0.391 vs 0.587
target 03 - scores: 0.433 vs 0.546
target 04 - scores: 0.659 vs 0.655
target 05 - scores: 0.000 vs 0.257
target 06 - scores: 0.431 vs 0.475
target 07 - scores: 0.000 vs 0.249
target 08 - scores: 0.000 vs 0.053
target 09 - scores: 0.576 vs 0.155
target 10 - scores: 0.000 vs 0.550
OneVsRest - scores: 0.565 vs 0.540
但是在使用 OneVsRest 分类器(最后一行)时,使用 F1 分数的平均值,不平衡线性 SVM 击败了线性 SVM。这发生在我的很多数据集中。
这是我使用的代码:
# -*- coding: utf-8 -*-
from sklearn.svm import LinearSVC
from sklearn.multiclass import OneVsRestClassifier
from sklearn.cross_validation import StratifiedShuffleSplit
from sklearn.metrics import f1_score
import numpy as np
d = np.loadtxt('yeast.csv', delimiter=',')
X = d[:, 0:-1]
y = d[:, -1]
print ' none vs balanced'
for target in np.unique(y):
scores = [0] * 2
k = 6
for tr, ts in StratifiedShuffleSplit(y, k, 0.2):
for i, w in enumerate([None, 'balanced']):
_y = (y == target).astype(int)
yp = LinearSVC(class_weight=w).fit(X[tr], _y[tr]).predict(X[ts])
scores[i] += f1_score(_y[ts], yp) / k
print 'target %02d - scores: %.3f vs %.3f' % (target, scores[0], scores[1])
scores = [0] * 2
for tr, ts in StratifiedShuffleSplit(y, k, 0.2):
for i, w in enumerate([None, 'balanced']):
m = OneVsRestClassifier(LinearSVC(class_weight=w))
yp = m.fit(X[tr], y[tr]).predict(X[ts])
scores[i] += f1_score(y[ts], yp, pos_label=None, average='weighted') / k
print 'OneVsRest - scores: %.3f vs %.3f' % (scores[0], scores[1])
作为数据集,我在这里使用了Yeast (UCI),在这里可以找到一个 sklearn-ready 版本。
结果:
none vs balanced
target 01 - scores: 0.241 vs 0.612
target 02 - scores: 0.402 vs 0.604
target 03 - scores: 0.444 vs 0.552
target 04 - scores: 0.666 vs 0.650
target 05 - scores: 0.000 vs 0.286
target 06 - scores: 0.370 vs 0.500
target 07 - scores: 0.000 vs 0.280
target 08 - scores: 0.000 vs 0.082
target 09 - scores: 0.563 vs 0.147
target 10 - scores: 0.000 vs 0.511
OneVsRest - scores: 0.567 vs 0.543
这不是很奇怪吗?我知道 OneVsRest 有很多联系,因此将使用分数,由到分离超平面的距离决定。尽管如此,为什么平衡的线性 SVM 在不断赢得每一场战斗的时候却输掉了这场战争?
编辑:我认为一个模型赢得了几乎每一场“战斗”,而不是“战争”这一事实与 One Vs Rest 使用置信度得分这一事实有关,而不是实际分类,这是有道理的,因为它避免了平局,当 score[k1] > score[k2] 我们可以假设它更喜欢 k1 > k2。参见维基百科。