Python 在一个非常基本的例子中,SVM-OVO与SVM-OVA

Python 在一个非常基本的例子中,SVM-OVO与SVM-OVA,python,machine-learning,scikit-learn,svm,multiclass-classification,Python,Machine Learning,Scikit Learn,Svm,Multiclass Classification,为了理解SVM-OVR(一对一)的工作原理,我测试了以下代码: import matplotlib.pyplot as plt import numpy as np from sklearn.svm import SVC x = np.array([[1,1.1],[1,2],[2,1]]) y = np.array([0,100,250]) classifier = SVC(kernel='linear', decision_function_shape='ovr') classifier.f

为了理解SVM-OVR(一对一)的工作原理,我测试了以下代码:

import matplotlib.pyplot as plt
import numpy as np
from sklearn.svm import SVC
x = np.array([[1,1.1],[1,2],[2,1]])
y = np.array([0,100,250])
classifier = SVC(kernel='linear', decision_function_shape='ovr')
classifier.fit(x,y)
print(classifier.predict([[1,2]]))
print(classifier.decision_function([[1,2]]))
这些产出是:

[100]
[[ 1.05322128  2.1947332  -0.20488118]]
这意味着样本
[1,2]
在类
100
中得到了正确预测(这一点非常明显,因为
[1,2]
也用于培训)

但是,让我们看看决策函数。SVM-OVA应该生成三个分类器,即三行。第一个将
class1
class2u class3
分开,第二个将
class2
class1u class3
分开,第三个将
class3
class1u class2
分开。我最初的目标就是理解决策函数值的含义。我知道正值意味着样本在平面的右侧,反之亦然;这个值越大,样本在超平面之间的距离就越大(本例中是一条直线),样本属于该类的置信度就越大

然而,由于两个决策函数值为正,而假设只有正确的类应该报告一个正的决策函数(因为预测值也是一个训练样本),因此显然有些错误。出于这个原因,我试图绘制分隔线

fig, ax = plt.subplots()
ax.scatter(x[:, 0], x[:, 1], c=y, cmap=plt.cm.winter, s=25)
# create a mesh to plot in
x_min, x_max = x[:, 0].min() - 1, x[:, 0].max() + 1
y_min, y_max = x[:, 1].min() - 1, x[:, 1].max() + 1
xx2, yy2 = np.meshgrid(np.arange(x_min, x_max, .2),np.arange(y_min, y_max, .2))
Z = classifier.predict(np.c_[xx2.ravel(), yy2.ravel()])
Z = Z.reshape(xx2.shape)
ax.contourf(xx2, yy2, Z, cmap=plt.cm.winter, alpha=0.3)

w = classifier.coef_[0]
a = -w[0] / w[1]
xx = np.linspace(-5, 5)
yy = a * xx - (classifier.intercept_[0]) / w[1]
ax.plot(xx,yy)

w = classifier.coef_[1]
a = -w[0] / w[1]
xx = np.linspace(-5, 5)
yy = a * xx - (classifier.intercept_[1]) / w[1]
ax.plot(xx,yy)

w = classifier.coef_[2]
a = -w[0] / w[1]
xx = np.linspace(-5, 5)
yy = a * xx - (classifier.intercept_[2]) / w[1]
ax.plot(xx,yy)

ax.axis([x_min, x_max,y_min, y_max])
plt.show()
这就是我得到的:

惊奇:事实上,在计算OVO(一对一)策略时,这些分隔线表示超平面:事实上,您可以注意到这些线将
class1
class2
class2
class3
class1
class3
分隔开来

我还尝试添加一个类:

import matplotlib.pyplot as plt
import numpy as np
from sklearn.svm import SVC
x = np.array([[1,1.1],[1,2],[2,1],[3,3]])
y = np.array([0,100,250, 500])
classifier = SVC(kernel='linear', decision_function_shape='ovr')
classifier.fit(x,y)
所发生的是,表示决策函数的向量的长度等于4(与OVA策略相应),但再次生成了6行(就像我实现了OVO策略一样)


我的最后一个问题:决策函数值代表什么?为什么即使在应用OVA策略时,也会生成
n(n-1)/2
超平面,而不是
n
超平面?

关键是,默认情况下,SVM确实实现了OvO策略(请参阅以供参考)

SVC和NuSVC为多类分类实施“一对一”方法

同时,默认情况下(即使在您的案例中,您已经明确表示)
decision\u function\u shape
设置为
'ovr'

“为了提供与其他分类器的一致接口,decision_function_shape选项允许将“一对一”分类器的结果单调转换为形状的“一对一”决策函数(n_样本,n_类)

实现OvO策略的原因是SVM算法不能很好地适应训练集的大小(并且使用OvO策略,每个分类器只在训练集中与其必须区分的类相对应的部分进行训练)。 原则上,您可以通过
OneVsRestClassifier
的实例强制SVM分类器实现OvA策略,例如:

ovr_svc = OneVsRestClassifier(SVC(kernel='linear'))

是的,完全正确。这就是行为。老实说,我从来没有详细讨论过。这可能是一个合适的时机:)目前,我可以报告以下内容。特别是,“如果decision_function_shape='ovo',函数值与样本X到分离超平面的距离成正比。。。如果decision_function_shape='ovr',则decision function是ovo decision function的单调变换。“最终,以下是sklearn实现的相关来源:和。根据发布的链接,使用的单调变换是f:x->x/(3*(|x |+1))好的,谢谢,但是最后一个等式并没有减少形状。这很奇怪。
ovr_svc = OneVsRestClassifier(SVC(kernel='linear'))