在 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
。
0
和 15 个样本 (3%) 为 1
。我使用成本矩阵c
对1
施加了两次惩罚,如下所示:
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 编写成本函数的正确方法 - 无法理解“成本”矩阵的主要内容,如果未能解决你的问题,请参考以下文章