在 Matlab 中用 SVM 编写成本函数的正确方法 - 无法理解“成本”矩阵

Posted

技术标签:

【中文标题】在 Matlab 中用 SVM 编写成本函数的正确方法 - 无法理解“成本”矩阵【英文标题】:Proper way to write the cost function in SVM in Matlab - unable to understand 'Cost' matrix 【发布时间】:2018-11-18 21:43:23 【问题描述】:

我想将 SVM 应用于不平衡的数据集,answer1、answer2 建议可以通过调整 fitcsvm 函数的参数来实现。虽然 SVM 可能不是不平衡数据的好选择,但我希望看到结果用于教育目的。

如何调整 SVM 中的参数以对真实类(标记为 1)的错误分类错误施加更大的惩罚,因为我的数据自然不平衡,与 @987654326 相比,1 的数量更少@ (错误的)。只有 2% 被标记为1

数据集有 1473 个样本 (98%) 标记为 0,27 个样本 (2%) 标记为 1

训练数据有 1000 个样本标记为 0 和 12 个样本为1

测试数据有 473 个样本 (97%) 为 0 和 15 个样本 (3%) 为 1。我使用成本矩阵c1 施加了两次惩罚,如下所示:
c=[0 2.2;1 0];
model = fitcsvm(train_x,train_y,'KernelFunction', 'rbf', 'Cost',c);
[predLabel,score] = predict(model,test_x);

结果是

Precision for label 0: 9.692623e-01
Precision for label 1: NaN
Recall for label 0: 1
Recall for label 1: 0

Accuracy = 96.9%
Average err = 0.03

混淆矩阵是

    473     0
    15     0

predict 向量中的答案都是1 标签。显然,成本矩阵无法正常工作。如果我要惩罚 0(多数类)或 1(少数类)的错误分类,我不太明白查看成本矩阵。为什么第一行和第一列元素=0,另一个是2。 请帮忙。

【问题讨论】:

【参考方案1】:

这可以使用一些测试数据来显示,例如:

rng(42)
X = randn(1000, 2);
y = rand(1000, 1) >= 0.98;
X(y==1, :) = X(y==1, :) + [2, 2];

由于类不平衡,具有高斯核函数的简单 SVM 将无法正常工作:

model = fitcsvm(X, y, 'KernelFunction', 'rbf')
confusionmat(y, model.predict(X))

ans =

   979     2
    14     5

正如您已经认识到的,'Cost' 参数可用于通过对少数类的错误分类施加更高的惩罚来补偿不平衡。在二维情况下,成本矩阵的构建如下:

[ Cost(0, 0),    Cost(0, 1)
  Cost(1, 0),    Cost(1, 1) ]

现在,Cost(0, 0) 是将属于类 0 的样本分类为类 0 的成本。这是一个正确的分类,因此通常将成本设置为 0。接下来,Cost(0, 1) 是将属于类 0 的点分类为类 1 的成本,即错误分类。

在您的示例中,0 类比1 类更可能出现,因此我们应该对将0 类(大多数)中的样本分类为1 类(少数),以及将1(少数)类的样本分类为0(多数)类的高处罚。所以Cost(0, 1) 应该很低,Cost(1, 0) 应该很高。

通过设置 c = [0, 2.2; 1, 0],您做了相反的事情 - 您建议 fitcsvm 函数将少数样本归类为多数而不是相反:

c = [0, 2.2; 1, 0];
model = fitcsvm(X, y, 'KernelFunction', 'rbf', 'Cost', c);
confusionmat(y, model.predict(X))

ans =

   981     0
    19     0

如果你在成本矩阵c中使用相同的权重,但是切换Cost(0, 1)Cost(1, 0),那么就会出现想要的效果:

c = [0, 1; 2.2, 0];
model = fitcsvm(X, y, 'KernelFunction', 'rbf', 'Cost', c);
confusionmat(y, model.predict(X))

ans =

   973     8
     7    12

这确实改善了我们的结果:总的来说,我们的错误分类数量相似:错误分类总数为 15 个,而不是 16 个,但我们的 19 个少数类样本中有 12 个在新模型中是正确的,而之前只有 5 个。

【讨论】:

感谢您的回答以及如此易于遵循的说明。您能否澄清以下几点? (1) 在我的数据集中,实际上只有 2% 是真正的正类。通过包含成本和不包含成本,我在混淆矩阵和准确性方面得到了相同的结果。我检查了不同的成本值,例如 2.2、3、4、5,但没有效果。因此,这种方法是否可能不适合我的数据集? (2) 成本值是否有最大值和最小值范围?如何决定是放 2 还是 3 等?和 (3) 一般来说,一旦模型训练完毕,我该如何使用训练后的模型?我应该在看不见的数据上使用经过训练的模型模型,但它在 Matlab 中的功能是什么? 我看到从 2.2 到 49 的成本值分类没有变化,cconfusion 矩阵保持不变,即[473, 0; 15, 0]。当我将成本从 2.2 增加到 50 时,我才看到变化并得到了少数类 1 的所有正确预测,但随后类 0 的预测变得很差。因此,我怎么知道错误分类成本值增加了多少?【参考方案2】:

根据您的结果,这两个类似乎属于同一个分布。尝试对您的训练数据进行过采样(使用可用的正样本生成更多正样本)并在此基础上构建模型,然后在测试中测试您的模型。

【讨论】:

以上是关于在 Matlab 中用 SVM 编写成本函数的正确方法 - 无法理解“成本”矩阵的主要内容,如果未能解决你的问题,请参考以下文章

svmtrain - 指定错误分类的成本

matlab利用hinge loss实现多分类SVM

求基于matlab的EMD代码,急!

Matlab编写的PCA+SVM人脸识别

如何在MATLAB中添加SVM函数工具箱

Matlab 中的 SVM:函数 fitcsvm 中参数“框约束”的含义