在 Matlab 中编写 SVM 成本函数的正确方法 - 无法理解 'Cost' 矩阵
Proper way to write the cost function in SVM in Matlab - unable to understand 'Cost' matrix
我想将 SVM 应用于不平衡的数据集,answer1, answer2 建议可以通过调整 fitcsvm
函数的参数来实现。虽然 SVM 可能不是不平衡数据的好选择,但我希望看到结果用于教育目的。
我如何调整 SVM 中的参数以对真实 class(标记为 1
)的错误 class 化错误施加更大的惩罚,因为我的数据自然是不平衡的, 1
的数量少于 0
(错误)。只有 2% 被标记为 1
。
数据集有1473个样本(98%)标记为0
和27个样本(2%)标记为1
.
训练数据有 1000 个样本标记为 0
和
12 个样本 1
.
- 测试数据有473个样本(97%)为
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);
The result is
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(多数 class)或 1(少数 class)的错误 class 化,我无法完全理解查看成本矩阵。为什么第一行第一列元素=0,另一个是2。
请帮忙。
这可以使用一些测试数据来显示,例如:
rng(42)
X = randn(1000, 2);
y = rand(1000, 1) >= 0.98;
X(y==1, :) = X(y==1, :) + [2, 2];
由于 class 不平衡,具有高斯核函数的简单 SVM 将无法正常工作:
model = fitcsvm(X, y, 'KernelFunction', 'rbf')
confusionmat(y, model.predict(X))
ans =
979 2
14 5
正如您已经认识到的那样,'Cost'
参数可用于通过对少数 class 的错误class 设置更高的惩罚来补偿不平衡。在二维情况下,成本矩阵构建如下:
[ Cost(0, 0), Cost(0, 1)
Cost(1, 0), Cost(1, 1) ]
现在,Cost(0, 0)
是将属于 class 0
的样本 class 化为 class 0
的成本。这是一个正确的class化,所以通常成本设置为0。接下来,Cost(0, 1)
是class化属于class的点的成本0
为 class 1
,即错误的 class化。
在你的例子中,class 0
比 class 1
更有可能发生,所以我们应该对 classifying 施加较低的惩罚来自 class 0
(多数)的样本作为 class 1
(少数),以及对 class 化 [=51] 样本的高惩罚=] 1
(少数)和class 0
(多数)。所以Cost(0, 1)
应该是low而Cost(1, 0)
应该是high。
通过设置 c = [0, 2.2; 1, 0]
,你做了相反的事情 - 你建议 fitcsvm
函数宁愿 class 将少数样本确定为多数而不是相反:
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
这确实改善了我们的结果:总的来说,我们有相似数量的错误class错误:15 个而不是 16 个错误class错误,但在我们的 19 个少数样本中有 12 个class 使用新模型是正确的,而之前只有 5 个。
根据您的结果,类 似乎属于同一个分布。尝试对训练数据进行过采样(使用可用的正样本生成更多正样本)并以此为基础构建模型,然后在测试中测试模型。
我想将 SVM 应用于不平衡的数据集,answer1, answer2 建议可以通过调整 fitcsvm
函数的参数来实现。虽然 SVM 可能不是不平衡数据的好选择,但我希望看到结果用于教育目的。
我如何调整 SVM 中的参数以对真实 class(标记为 1
)的错误 class 化错误施加更大的惩罚,因为我的数据自然是不平衡的, 1
的数量少于 0
(错误)。只有 2% 被标记为 1
。
数据集有1473个样本(98%)标记为
0
和27个样本(2%)标记为1
.训练数据有 1000 个样本标记为
0
和 12 个样本1
.- 测试数据有473个样本(97%)为
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);
The result is
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(多数 class)或 1(少数 class)的错误 class 化,我无法完全理解查看成本矩阵。为什么第一行第一列元素=0,另一个是2。
请帮忙。
这可以使用一些测试数据来显示,例如:
rng(42)
X = randn(1000, 2);
y = rand(1000, 1) >= 0.98;
X(y==1, :) = X(y==1, :) + [2, 2];
由于 class 不平衡,具有高斯核函数的简单 SVM 将无法正常工作:
model = fitcsvm(X, y, 'KernelFunction', 'rbf')
confusionmat(y, model.predict(X))
ans =
979 2
14 5
正如您已经认识到的那样,'Cost'
参数可用于通过对少数 class 的错误class 设置更高的惩罚来补偿不平衡。在二维情况下,成本矩阵构建如下:
[ Cost(0, 0), Cost(0, 1)
Cost(1, 0), Cost(1, 1) ]
现在,Cost(0, 0)
是将属于 class 0
的样本 class 化为 class 0
的成本。这是一个正确的class化,所以通常成本设置为0。接下来,Cost(0, 1)
是class化属于class的点的成本0
为 class 1
,即错误的 class化。
在你的例子中,class 0
比 class 1
更有可能发生,所以我们应该对 classifying 施加较低的惩罚来自 class 0
(多数)的样本作为 class 1
(少数),以及对 class 化 [=51] 样本的高惩罚=] 1
(少数)和class 0
(多数)。所以Cost(0, 1)
应该是low而Cost(1, 0)
应该是high。
通过设置 c = [0, 2.2; 1, 0]
,你做了相反的事情 - 你建议 fitcsvm
函数宁愿 class 将少数样本确定为多数而不是相反:
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
这确实改善了我们的结果:总的来说,我们有相似数量的错误class错误:15 个而不是 16 个错误class错误,但在我们的 19 个少数样本中有 12 个class 使用新模型是正确的,而之前只有 5 个。
根据您的结果,类 似乎属于同一个分布。尝试对训练数据进行过采样(使用可用的正样本生成更多正样本)并以此为基础构建模型,然后在测试中测试模型。