问题描述
我发现 irr
包在计算 weighted kappa
时有两个大错误。
您可以使用以下示例复制错误。
我有 2 对疾病程度评分(从 0 到 100,0 表示健康,100 表示病重)。
在label_test.csv
中(您可以将数据复制并粘贴到您的磁盘中以进行以下测试):
0
1
1
1
0
14
53
3
在pred_test.csv
中:
0
1
1
0
3
4
54
6
在script_r.R
中:
library(irr)
label <- read.csv('label_test.csv',header=FALSE)
pred <- read.csv('pred_test.csv',header=FALSE)
kapp <- kappa2(data.frame(label,pred),"unweighted")
kappa <- getElement(kapp,"value")
print(kappa) # output: 0.245283
w_kapp <- kappa2(data.frame(label,"equal")
weighted_kappa <- getElement(w_kapp,"value")
print(weighted_kappa) # output: 0.443038
当我在 Python
中使用 kappa
计算 weighted_kappa
和 script_python.py
时:
from sklearn.metrics import cohen_kappa_score
label = pd.read_csv(label_file,header=None).to_numpy()
pred = pd.read_csv(pred_file,header=None).to_numpy()
kappa = cohen_kappa_score(label.astype(int),pred.astype(int))
print(kappa) # output: 0.24528301886792447
weighted_kappa = cohen_kappa_score(label.astype(int),pred.astype(int),weights='linear',labels=np.array(list(range(100))) )
print(weighted_kappa) # output: 0.8359908883826879
我们可以发现kappa
和R
计算的Python
是一样的,但是weighted_kappa
的{{1}}远低于{{来自 R
的 weighted_kappa
中的 1}}。哪个是错的?经过 2 天的研究,我发现 sklearn
中的 Python
包中的 weighted_kappa
是错误的。详情如下。
在调试过程中,我们会发现 irr
中 R
中的混淆矩阵是:
我们可以发现顺序是错误的。标签的顺序应该从 irr
更改为 R
,就像在 Python 中一样。似乎 [0,1,14,3,4,53,54,6]
包使用了基于字符串的排序方法而不是基于整数的排序方法,这会将 [0,6,54]
放在 irr
的前面。这个错误可以而且应该很容易纠正。
第二个错误:R 中的混淆矩阵不完整
在我的 14
和 3
中,这些值不能涵盖从 0 到 100 的所有可能值。因此 pred_test.csv
中的 label_test.csv
中的默认混淆矩阵将错过那些未出现在数据中的值。这应该是固定的。
让我们看另一个例子。
在 irr
中,让我们将标签从 R
更改为 pred_test.csv
。然后,我们再次运行 54
和 99
。结果是:
script_r.R
我们可以发现 script_python.py
中来自 In R:
kappa: 0.245283
weighted_kappa: 0.443038
In Python:
kappa: 0.24528301886792447
weighted_kappa: 0.592891760904685
的 weighted_kappa
根本没有变化。但是irr
中R
的{{1}}从weighted_kappa
减少到sklearn
。所以我们知道Python
又犯了一个错误。
原因是0.83
可以让我们将0.59
传递给混淆矩阵,这样混淆矩阵的形状将是100 * 100,但是在irr
中,混淆矩阵是根据 sklearn
和 full labels
的唯一值计算的,这会遗漏很多其他可能的值。这个错误会为这里的 irr
和 label
分配相同的权重。因此最好在 pred
包中提供一个选项,让客户提供自定义 53
,就像他们在 99
中从 irr
所做的那样。
解决方法
我已经给包的作者发了邮件,他说他会在下一次更新中修复这个错误。
详情如下:
实际上,我知道 kappa2 函数的这种尴尬行为。 这是由于因子水平的转换和重新排序。这些 实际上不是两个错误,而只是一个导致错误的错误 混淆矩阵的生成(您已经发现了)。你 可以通过删除 kappa2 函数中的第一行轻松修复它 (“收视率
一般来说,我的函数需要知道因子水平才能 正确计算 kappa。因此,对于您的数据,您需要存储 值作为具有适当可能因子水平的因子。 例如
label
评级
当您现在运行修改后的 kappa2-function(即没有第一个 行),结果应该是正确的。
kappa2(ratings) # 未加权 kappa2(ratings,"equal") # 加权 kappa 等权重
下次更新我的包时,我会考虑到这一点。
,作者的解决方案是行不通的,因为在 kappa2 函数的 code 中,它将您的评分转换为矩阵,一旦将因子转换为矩阵,级别就会丢失,这是行:
ratings <- as.matrix(na.omit(ratings))
你可以在你的数据上试试,它被转换成一个字符:
lvl = 0:100
ratings = data.frame(label = factor(label[,1],levels=lvl),pred = factor(pred[,levels=lvl))
as.matrix(ratings)
label pred
[1,] "0" "0"
[2,] "1" "1"
[3,] "1" "1"
[4,] "1" "0"
[5,] "0" "3"
[6,] "14" "4"
[7,] "53" "54"
[8,] "3" "6"
相同的结果:
kappa2(ratings,weight="equal")
Cohen's Kappa for 2 Raters (Weights: equal)
Subjects = 8
Raters = 2
Kappa = 0.368
z = 1.79
p-value = 0.0742
我建议使用 DescTools
,您只需要在 R 中使用 table()
函数提供混淆矩阵,并正确声明上述因素:
library(DescTools)
CohenKappa(table(ratings$label,ratings$pred),weight="Unweighted")
[1] 0.245283
CohenKappa(table(ratings$label,weight="Equal-Spacing")
[1] 0.8359909