我有关于在matlab中计算分类器的精度和召回率的问题。我使用fisherIris数据(由150个数据点,50个setosa,50个versicolor,50个virginica组成)。我使用kNN算法进行了分类。这是我的困惑矩阵:
50 0 0
0 48 2
0 4 46
正确的分类率是96%(144/150),但如何用matlab计算精度和召回率,有什么功能吗?我知道该精度的公式= tp /(tp + fp),并且召回= tp /(tp + fn),但我在识别组件时丢失了。例如,我可以说矩阵的真阳性是144吗?假阳性和假阴性怎么样?请帮忙!!!我真的很感激!谢谢!
要添加到pederpansen的答案,这里有一些匿名的Matlab函数,用于计算每个类的精度,召回和F1分数,以及所有类的平均F1分数:
precision = @(confusionMat) diag(confusionMat)./sum(confusionMat,2);
recall = @(confusionMat) diag(confusionMat)./sum(confusionMat,1)';
f1Scores = @(confusionMat) 2*(precision(confusionMat).*recall(confusionMat))./(precision(confusionMat)+recall(confusionMat))
meanF1 = @(confusionMat) mean(f1Scores(confusionMat))
正如丹在他的评论中指出的那样,精确度和召回率通常仅针对二元分类问题进行定义。
但是你可以为每个班级单独计算精确度和召回率。让我们稍微注释你的混淆矩阵:
| true |
| | seto | vers | virg |
-----------------------------------
| seto | 50 0 0
predicted | vers | 0 48 2
| virg | 0 4 46
这里我假设通常的约定成立,即列用于真值,行用于学习算法预测的值。 (如果你的矩阵是相反的,那么只需要对混淆矩阵进行转置。)
每个类(=行/列索引)tp(i)
的真阳性(i
)由该行/列中的对角元素给出。然后真正的负数(tn
)由剩余对角元素的总和给出。请注意,我们只是将每个类i
的负数定义为“not class i
”。
如果我们将假阳性(fp
)和假阴性(fn
)分别定义为给定行或列中非对角线条目的总和,我们可以计算每个类的精度和召回率:
precision(seto) = tp(seto) / (tp(seto) + fp(seto)) = 50 / (50 + (0 + 0)) = 1.0
precision(vers) = 48 / (48 + (0 + 2)) = 0.96
precision(virg) = 46 / (46 + (0 + 4)) = 0.92
recall(seto) = tp(seto) / (tp(seto) + fn(seto)) = 50 / (50 + (0 + 0)) = 1.0
recall(vers) = 48 / (48 + (0 + 4)) = 0.9231
recall(virg) = 46 / (46 + (0 + 2)) = 0.9583
这里我使用类名而不是行索引来说明。
请查看this question的答案,了解有关多级分类问题时性能测量的更多信息 - 特别是如果您希望每个类最终只有一个数字而不是一个数字。当然,最简单的方法是平均每个类的值。
我意识到你实际上正在寻找一个Matlab函数来做到这一点。我认为没有任何内置函数,在Matlab文件交换中我只发现了一个function for binary classification problems。但是,任务非常简单,您可以轻松定义自己的功能,如下所示:
function y = precision(M)
y = diag(M) ./ sum(M,2);
end
function y = recall(M)
y = diag(M) ./ sum(M,1)';
end
这将返回一个列向量,分别包含每个类的精度和重新调用值。现在你可以简单地打电话
>> mean(precision(M))
ans =
0.9600
>> mean(recall(M))
ans =
0.9605
获取模型的平均精度和召回值。
另一种方法
confMat=[50,0,0;0,48,2;0,4,46];
for i =1:size(confMat,1)
precision(i)=confMat(i,i)/sum(confMat(i,:));
end
precision(isnan(precision))=[];
Precision=sum(precision)/size(confMat,1);
for i =1:size(confMat,1)
recall(i)=confMat(i,i)/sum(confMat(:,i));
end
Recall=sum(recall)/size(confMat,1);
F_score=2*Recall*Precision/(Precision+Recall);
使用以下matlab代码
actual = ...
predicted= ...
cm = confusionmat(actual,predicted);
cm = cm';
precision = diag(cm)./sum(cm,2);
overall_precision = mean(precision)
recall= diag(cm)./sum(cm,1)';
overall_recall = mean(recall)