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

我想将SVM应用于一个不平衡的数据集,回答1, 回答2 建议可以通过调整fitcsvm函数的参数来实现。尽管SVM可能不是处理不平衡数据的好选择,但我出于教育目的想看看结果。

由于我的数据自然不平衡,标记为1(真实类别)的样本数量远少于0(假类别),只有2%的样本被标记为1。我如何调整SVM的参数以对真实类别的误分类错误施加更大的惩罚?

  • 数据集有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);

结果是

标签0的精确度: 9.692623e-01标签1的精确度: NaN标签0的召回率: 1标签1的召回率: 0准确率 = 96.9%平均误差 = 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个。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注