V. *_*Gai 2 classification machine-learning svm scikit-learn
我在 Iris 数据集上使用来自 sklearn 的支持向量分类器。当我调用 decision_function
它时返回负值。但是分类后测试数据集中的所有样本都具有正确的类别。我认为当样本是内点时,decision_function 应该返回正值,如果样本是异常值,则应该返回负值。我错在哪里?
from sklearn import datasets
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
iris = datasets.load_iris()
X = iris.data[:,:]
y = iris.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.3,
random_state=0)
clf = SVC(probability=True)
print(clf.fit(X_train,y_train).decision_function(X_test))
print(clf.predict(X_test))
print(y_test)
Run Code Online (Sandbox Code Playgroud)
这是输出:
[[-0.76231668 -1.03439531 -1.40331645]
[-1.18273287 -0.64851109 1.50296097]
[ 1.10803774 1.05572833 0.12956269]
[-0.47070432 -1.08920859 -1.4647051 ]
[ 1.18767563 1.12670665 0.21993744]
[-0.48277866 -0.98796232 -1.83186272]
[ 1.25020033 1.13721691 0.15514536]
[-1.07351583 -0.84997114 0.82303659]
[-1.04709616 -0.85739411 0.64601611]
[-1.23148923 -0.69072989 1.67459938]
[-0.77524787 -1.00939817 -1.08441968]
[-1.12212245 -0.82394879 1.11615504]
[-1.14646662 -0.91238712 0.80454974]
[-1.13632316 -0.8812114 0.80171542]
[-1.14881866 -0.95169643 0.61906248]
[ 1.15821271 1.10902205 0.22195304]
[-1.19311709 -0.93149873 0.78649126]
[-1.21653084 -0.90953622 0.78904491]
[ 1.16829526 1.12102515 0.20604678]
[ 1.18446364 1.1080255 0.15199149]
[-0.93911991 -1.08150089 -0.8026332 ]
[-1.15462733 -0.95603159 0.5713605 ]
[ 0.93278883 0.99763184 0.34033663]
[ 1.10999556 1.04596018 0.14791409]
[-1.07285663 -1.01864255 -0.10701465]
[ 1.21200422 1.01284263 0.0416991 ]
[ 0.9462457 1.01076579 0.36620915]
[-1.2108146 -0.79124775 1.43264808]
[-1.02747495 -0.25741977 1.13056021]
...
[ 1.16066886 1.11212424 0.22506538]]
[2 1 0 2 0 2 0 1 1 1 2 1 1 1 1 0 1 1 0 0 2 1 0 0 2 0 0 1 1 0 2 1 0 2 2 1 0
2 1 1 2 0 2 0 0]
[2 1 0 2 0 2 0 1 1 1 2 1 1 1 1 0 1 1 0 0 2 1 0 0 2 0 0 1 1 0 2 1 0 2 2 1 0
1 1 1 2 0 2 0 0]
Run Code Online (Sandbox Code Playgroud)
您需要分别考虑决策函数和预测。决定是从超平面到样本的距离。这意味着通过查看符号,您可以判断您的样本是位于超平面的右侧还是左侧。所以负值非常好并表示负类(“超平面的另一侧”)。
对于 iris 数据集,您会遇到多类问题。由于 SVM 是二元分类器,因此不存在固有的多类分类。两种方法是“一对一”(OvR)和“一对一”方法,它们从二元“单元”构建多类分类器。
既然您已经了解了 OvR,那么掌握 OvA 就没有那么难了。您基本上构建了类对(A,B)的每个组合的分类器。在您的情况下:0 对 1、0 对 2、1 对 2。
注意:(A, B) 和 (B, A) 的值可以从单个二元分类器中获得。您只更改被认为是正类的内容,因此您必须反转符号。
这样做会给你一个矩阵:
+-------+------+-------+-------+
| A / B | #0 | #1 | #2 |
+-------+------+-------+-------+
| | | | |
| #0 | -- | -1.18 | -0.64 |
| | | | |
| #1 | 1.18 | -- | 1.50 |
| | | | |
| #2 | 0.64 | -1.50 | -- |
+-------+------+-------+-------+
Run Code Online (Sandbox Code Playgroud)
请阅读以下内容:A 类(行)与 B 类(列)竞争时的决策函数值。
为了提取结果,进行投票。在基本形式中,您可以将其想象为每个分类器可以投的单票:是或否。这可能导致平局,因此我们使用整个决策函数值。
+-------+------+-------+-------+-------+
| A / B | #0 | #1 | #2 | SUM |
+-------+------+-------+-------+-------+
| | | | | |
| #0 | - | -1.18 | -0.64 | -1.82 |
| | | | | |
| #1 | 1.18 | - | 1.50 | 2.68 |
| | | | | |
| #2 | 0.64 | -1.50 | - | 0.86 |
+-------+------+-------+-------+-------+
Run Code Online (Sandbox Code Playgroud)
结果列再次为您提供一个 vector [-1.82, 2.68, 0.86]
。现在申请arg max
,它符合您的预测。
我保留这一部分以避免进一步混淆。scikit-lear SVC分类器 (libsvm) 有一个decision_function_shape
参数,它让我误以为它是 OvR(我大部分时间都在使用 liblinear)。
对于真正的 OvR 响应,您可以从每个分类器的决策函数中获得一个值,例如
[-1.18273287 -0.64851109 1.50296097]
Run Code Online (Sandbox Code Playgroud)
现在要从中获得预测,您可以只应用arg max
,这将返回值为 的最后一个索引1.50296097
。从这里开始不再需要决策函数的值(对于这个单一的预测)。这就是为什么你注意到你的预测没问题。
但是,您还指定了probability=True
,它使用 distance_function 的值并将其传递给sigmoid 函数。示例原理如上,但现在您还有 0 和 1 之间的置信值(我更喜欢这个术语而不是概率,因为它只描述到超平面的距离)。
编辑: 糟糕,sascha 是对的。LibSVM 使用一对一(尽管决策函数的形状不同)。
归档时间: |
|
查看次数: |
3104 次 |
最近记录: |