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



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

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

  • 该数据集有 1473 个样本 (98%( 标记为0和 27 个样本 (2%( 标记为1

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

  • 测试数据有473个样本(97%(作为0和15个样本(3%(作为1。我使用成本矩阵对1施加了两次罚款,c如下:
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。 请帮忙。

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

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 个。

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

最新更新