machine-learning - 负决策函数值

标签 machine-learning scikit-learn classification svm

我在 Iris 数据集上使用 sklearn 的支持向量分类器。当我调用决策函数时,它返回负值。但分类后测试数据集中的所有样本都有正确的类别。我认为当样本是内点时,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)

这是输出:

[[-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]

最佳答案

您需要分别考虑决策函数和预测。决定因素是从超平面到样本的距离。这意味着通过查看标志,您可以判断样本是位于超平面的右侧还是左侧。因此负值完全可以表示负类(“超平面的另一边”)。

对于 iris 数据集,您会遇到多类问题。由于SVM是二元分类器,不存在固有的多类分类。两种方法是“一对一”(OvR)和“一对一”方法,它们从二进制“单元”构造多类分类器。

一对一

既然您已经了解了 OvR,那么 OvA 也就不难掌握了。您基本上构建了类对的每个组合的分类器(A, B)。在你的情况下:0 vs 1、0 vs 2、1 vs 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 |  --   |
+-------+------+-------+-------+

阅读如下: 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  |
+-------+------+-------+-------+-------+

结果列再次为您提供一个向量[-1.82, 2.68, 0.86]。现在应用arg max,它与您的预测相符。

一对多

我保留这一部分是为了避免进一步困惑。 scikit-lear SVC分类器 (libsvm) 有一个 decision_function_shape 参数,它欺骗我,让我误以为它是 OvR(我大部分时间都使用 liblinear)。

对于真正的 OvR 响应,您可以从每个分类器的决策函数中获得一个值,例如

 [-1.18273287 -0.64851109  1.50296097]

现在,要从中获得预测,您只需应用 arg max,它将返回值为 1.50296097 的最后一个索引。从这里开始,不再需要决策函数的值(对于这个单一的预测)。这就是为什么您注意到您的预测是正确的。

但是您还指定了 probability=True,它使用 distance_function 的值并将其传递给 sigmoid function 。原理示例如上所述,但现在您还拥有介于 0 和 1 之间的置信值(相对于概率,我更喜欢这个术语,因为它只描述到超平面的距离)。

编辑: 哎呀,萨沙是对的。 LibSVM 使用一对一(不管决策函数的形状如何)。

关于machine-learning - 负决策函数值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46820154/

相关文章:

arrays - 数组的转换产生一个空占位符

python - 将 SciPy 优化应用于拟合的 sci-kit 模型

python - 如何在 sklearn 中使用逻辑回归来获取连续但有界的因变量?

python - 如何获得Scikit-learn RandomForest的训练精度?

python - Scikit-学习 GridSearchCV : Avoid function to copy data for each process in parallel

performance - MATLAB 中人工神经网络的回归与性能图之间的差异

python - 使用 XGBoost 和 hyperopt 进行交叉验证和参数调整

python - Python scikit learn 中分类和回归分数的差异

python - sklearn 管道 - 在管道中应用多项式特征变换后应用样本权重

使用 RandomizedSearchCV 对 XGBClassifier 进行 Python 超参数优化