我编写了一个函数来从混淆矩阵中计算敏感性和特异性,后来才发现caret
包中有一个类似的函数,confusionMatrix()
。当我尝试使用它时,情况变得非常混乱,因为看起来caret
似乎使用了错误的公式?
示例数据:
dat <- data.frame(real = as.factor(c(1,1,1,0,0,1,1,1,1)), pred = as.factor(c(1,1,0,1,0,1,1,1,0)))cm <- table(dat$real, dat$pred)cm 0 1 0 1 1 1 2 5
我的函数:
model_metrics <- function(cm){ acc <- (cm[1] + cm[4]) / sum(cm[1:4]) # 准确率 = 正确标记的对象与所有对象的比率 = (TP+TN)/(TP+FP+FN+TN) sens <- cm[4] / (cm[4] + cm[3]) # 敏感性/召回率 = 正确标记为阳性的对象与所有实际阳性对象的比率 = TP/(TP+FN) spec <- cm[1] / (cm[1] + cm[2]) # 特异性 = 正确标记为阴性的对象与所有实际阴性对象的比率 = TN/(TN+FP) err <- (cm[2] + cm[3]) / sum(cm[1:4]) #(所有错误 / 所有) metrics <- data.frame(Accuracy = acc, Sensitivity = sens, Specificity = spec, Error = err) return(metrics)}
现在比较confusionMatrix()
函数的结果与我的函数的结果:
library(caret)c_cm <- confusionMatrix(dat$real, dat$pred)c_cm ReferencePrediction 0 1 0 1 1 1 2 5c_cm$byClassSensitivity Specificity Pos Pred Value Neg Pred Value Precision Recall 0.3333333 0.8333333 0.5000000 0.7142857 0.5000000 0.3333333model_metrics(cm) Accuracy Sensitivity Specificity Error1 0.6666667 0.8333333 0.3333333 0.3333333
敏感性和特异性似乎在我的函数和confusionMatrix()
之间被交换了。我原本以为我使用了错误的公式,但我在维基百科上再次确认,我是正确的。我还再次确认了我从混淆矩阵中调用了正确的值,我非常确定我是正确的。caret
的文档也表明它使用的是正确的公式,所以我完全不知道发生了什么。
caret
函数是错误的,还是(更可能的是)我犯了一个明显的错误?
回答:
caret函数并没有错误。
首先,考虑一下你是如何构建表格的。table(first, second)
会生成一个表格,其中first
在行,second
在列。
此外,在子集化表格时,应该按列计数单元格。例如,在你的函数中,正确计算敏感性的方法是
sens <- cm[4] / (cm[4] + cm[2])
最后,当一个函数没有给你预期的结果时,总是阅读该函数的帮助页面是个好主意。?confusionMatrix
会给你显示帮助页面。
在阅读这个函数的帮助页面时,你会发现你可以指定哪个因子级别被视为阳性结果(使用positive
参数)。
此外,使用函数时要小心。为了避免混淆,我建议使用命名参数而不是依赖于位置指定参数。
第一个参数是数据(预测类别的因子),第二个参数是参考(观察类别的因子,在你的例子中是dat$real
)。
要得到你想要的结果:
confusionMatrix(data = dat$pred, reference = dat$real, positive = "1")Confusion Matrix and Statistics ReferencePrediction 0 1 0 1 2 1 1 5 Accuracy : 0.6667 95% CI : (0.2993, 0.9251) No Information Rate : 0.7778 P-Value [Acc > NIR] : 0.8822 Kappa : 0.1818 Mcnemar's Test P-Value : 1.0000 Sensitivity : 0.7143 Specificity : 0.5000 Pos Pred Value : 0.8333 Neg Pred Value : 0.3333 Prevalence : 0.7778 Detection Rate : 0.5556 Detection Prevalence : 0.6667 Balanced Accuracy : 0.6071 'Positive' Class : 1