SVM-OVO 与 SVM-OVA 的一个非常基本的例子
SVM-OVO vs SVM-OVA in a very basic example
为了了解 SVM-OVR(One-Vs-Rest)的工作原理,我测试了以下代码:
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]
在class 100
中被正确预测(很明显,因为[1,2]
也被用于训练)。
但是,让我们看一下决策函数。 SVM-OVA 应该生成三个 classifier,即三行。第一个将 class1
与 class2 U class3
分开,第二个将 class2
与 class1 U class3
分开,第三个将 class3
与 class1 U class2
分开。我最初的目标正是了解决策函数值的含义。我知道正值意味着样本在平面的右侧,反之亦然;并且值越大,样本与超平面(在本例中为一条线)之间的距离越大,样本属于 class.
的置信度就越大
然而,由于两个决策函数值是正的,所以显然有些地方是错误的,而假设只有正确的 class 应该报告一个正的决策函数(因为预测值也是训练样本)。出于这个原因,我尝试绘制分隔线。
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
.
我也试过添加 class:
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 策略一样)。
classifier.decision_function([[1,2]])
[[ 2.14182753 3.23543808 0.83375105 -0.22753309]]
classifier.coef_
array([[ 0. , -0.9 ],
[-1. , 0.1 ],
[-0.52562421, -0.49934299],
[-1. , 1. ],
[-0.8 , -0.4 ],
[-0.4 , -0.8 ]])
我的最后一个问题:决策函数值代表什么?为什么即使在应用 OVA 策略时,也会生成 n(n-1)/2
个超平面,而不是 n
个?
重点是,默认情况下,SVM 会实施 OvO 策略(请参阅 here 以供参考)。
SVC and NuSVC implement the “one-versus-one” approach for multi-class classification.
同时,默认情况下(即使在您的情况下您已经明确表示)decision_function_shape
设置为 'ovr'
。
"To provide a consistent interface with other classifiers, the decision_function_shape option allows to monotonically transform the results of the “one-versus-one” classifiers to a “one-vs-rest” decision function of shape (n_samples, n_classes).
实施 OvO 策略的原因是 SVM 算法无法根据训练集的大小进行扩展(并且使用 OvO 策略时,每个分类器仅在与 类它必须区分)。
原则上,您可以通过 OneVsRestClassifier
的实例强制 SVM 分类器实现 OvA 策略,例如:
ovr_svc = OneVsRestClassifier(SVC(kernel='linear'))
为了了解 SVM-OVR(One-Vs-Rest)的工作原理,我测试了以下代码:
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]
在class 100
中被正确预测(很明显,因为[1,2]
也被用于训练)。
但是,让我们看一下决策函数。 SVM-OVA 应该生成三个 classifier,即三行。第一个将 class1
与 class2 U class3
分开,第二个将 class2
与 class1 U class3
分开,第三个将 class3
与 class1 U class2
分开。我最初的目标正是了解决策函数值的含义。我知道正值意味着样本在平面的右侧,反之亦然;并且值越大,样本与超平面(在本例中为一条线)之间的距离越大,样本属于 class.
然而,由于两个决策函数值是正的,所以显然有些地方是错误的,而假设只有正确的 class 应该报告一个正的决策函数(因为预测值也是训练样本)。出于这个原因,我尝试绘制分隔线。
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
.
我也试过添加 class:
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 策略一样)。
classifier.decision_function([[1,2]])
[[ 2.14182753 3.23543808 0.83375105 -0.22753309]]
classifier.coef_
array([[ 0. , -0.9 ],
[-1. , 0.1 ],
[-0.52562421, -0.49934299],
[-1. , 1. ],
[-0.8 , -0.4 ],
[-0.4 , -0.8 ]])
我的最后一个问题:决策函数值代表什么?为什么即使在应用 OVA 策略时,也会生成 n(n-1)/2
个超平面,而不是 n
个?
重点是,默认情况下,SVM 会实施 OvO 策略(请参阅 here 以供参考)。
SVC and NuSVC implement the “one-versus-one” approach for multi-class classification.
同时,默认情况下(即使在您的情况下您已经明确表示)decision_function_shape
设置为 'ovr'
。
"To provide a consistent interface with other classifiers, the decision_function_shape option allows to monotonically transform the results of the “one-versus-one” classifiers to a “one-vs-rest” decision function of shape (n_samples, n_classes).
实施 OvO 策略的原因是 SVM 算法无法根据训练集的大小进行扩展(并且使用 OvO 策略时,每个分类器仅在与 类它必须区分)。
原则上,您可以通过 OneVsRestClassifier
的实例强制 SVM 分类器实现 OvA 策略,例如:
ovr_svc = OneVsRestClassifier(SVC(kernel='linear'))