多评估者数据的评估者间可靠性计算
Inter-rater reliability calculation for multi-raters data
我有以下列表:
[[1, 1, 1, 1, 3, 0, 0, 1],
[1, 1, 1, 1, 3, 0, 0, 1],
[1, 1, 1, 1, 2, 0, 0, 1],
[1, 1, 0, 2, 3, 1, 0, 1]]
在我想计算 inter-rater 可靠性分数的地方,有多个评分者(行)。我不能使用 Fleiss 的 kappa,因为行的总和不等于相同的数字。在这种情况下,什么是好的方法?
这里的基本问题是您没有正确应用所提供的数据。有关正确的组织,请参阅 here。您有四个类别(评分 0-3)和八个科目。因此,无论审稿人的数量有多少,您的 table 必须有八行和四列。例如,第一行是对第一项的评分统计:
[0, 4, 0, 0] ... since everyone rated it a `1`.
您的 -inf
值来自倒数第二列的 P[j] 分数除以 0。
我之前的回答,标准化分数,是基于 我 对 Fleiss 的误解;我有不同的可靠性。
有很多方法可以计算这样的指标;一个是相对评分的一致性(可以通过归一化获得);另一种是将每个评分者的行转换为相对排名的图表,并计算这些图表之间的相似度。
请注意,Fleiss 不 完全适用于具有相对指标的 rating 情况:它假定这是分类任务,而不是排名。 Fleiss 对收视率的差距并不敏感。它只知道评级不同:(0,1) 配对与 (0,3) 配对一样具有破坏性。
这个问题的一个答案是使用 krippendorff alpha 分数:
import krippendorff
arr = [[1, 1, 1, 1, 3, 0, 0, 1],
[1, 1, 1, 1, 3, 0, 0, 1],
[1, 1, 1, 1, 2, 0, 0, 1],
[1, 1, 0, 2, 3, 1, 0, 1]]
res = krippendorff.alpha(arr)
是的,数据准备是这里的关键。让我们一起走过它。
虽然 Krippendorff 的 alpha 可能出于多种原因而更优越,但 numpy 和 statsmodels 提供了从上述 table 中获取 Fleiss kappa 所需的一切。 Fleiss 的 kappa 在医学研究中更为普遍,尽管 Krippendorff alpha 提供的结果基本相同如果使用得当。如果它们提供的结果大不相同,这可能是由于许多用户错误造成的,最重要的是 输入数据的格式和测量级别(例如,序数与标称) – 跳过解决方案(转置和聚合):Fleiss kappa 0.845
密切注意哪个轴代表 主题、评分者或类别!
弗莱斯河童
statsmodels.stats import inter_rater as irr
原始数据的行是评分者,列是受试者,整数代表分配的类别(如果我没记错的话)。
我删除了一行,因为有 4 行和 4 个类别,这可能会混淆情况 – 所以现在我们有 4 [0,1,2,3] 个类别和 3 行。
orig = [[1, 1, 1, 1, 3, 0, 0, 1],
[1, 1, 1, 1, 3, 0, 0, 1],
[1, 1, 1, 1, 2, 0, 0, 1]]
来自 aggregate_raters() 函数的文档
"将形状为 (subject, rater) 的原始数据转换为 (subject, cat_counts)"
irr.aggregate_raters(orig)
这个returns:
(array([[2, 5, 0, 1],
[2, 5, 0, 1],
[2, 5, 1, 0]]),
array([0, 1, 2, 3]))
现在……orig 数组中的行数等于第一个返回数组 (3) 中的行数。列数现在等于类别数 ([0,1,2,3] -> 4)。每行的内容加起来为 8,等于 orig 输入数据中的列数 - 假设每个评分者都对每个主题进行评分。此聚合显示评分者如何分布在每个主题(行)的类别(列)中。 (如果在类别 2 上达成一致,我们将看到 [0,0,8,0];或类别 0 [8,0,0,0]。
该函数需要行作为主题。查看受试者数量如何没有变化(3 行)。对于每个主题,它计算每个类别被分配的次数 'looking' 在行中找到类别(数字)的次数。对于第一行或类别,0 被分配了两次,1 分配了五次,2 none,3 分配了一次
[1, 1, 1, 1, 3, 0, 0, 1] -> [2, 5, 0, 1]
第二个数组returns类别值。如果我们将输入数组中的两个 3 都替换为 9,则分布看起来相同,但最后一个类别已更改。
ori9 = [[1, 1, 1, 1, 9, 0, 0, 1],
[1, 1, 1, 1, 9, 0, 0, 1],
[1, 1, 1, 1, 2, 0, 0, 1]]
(array([[2, 5, 0, 1],
[2, 5, 0, 1],
[2, 5, 1, 0]]),
array([1, 2, ,3, 9])) <- categories
aggregate_raters() returns ([data], [categories])
的元组
在 [data] 中,行保持主题。 aggregate_raters() 将评分者的列转换为类别。 Fleiss 期望 'table' 数据采用这种(主题、类别)格式:https://en.wikipedia.org/wiki/Fleiss'_kappa#Data
现在开始解决问题:
如果我们将原始数据插入 Fleiss kappa 会发生什么:
(我们只使用数据 'dats' 而不是类别列表 'cats')
dats, cats = irr.aggregate_raters(orig)
irr.fleiss_kappa(dats, method='fleiss')
-0.12811059907834096
但是……为什么?好吧,看看 orig 数据 – aggregate_raters() 假设 raters 作为列 !这意味着我们 完全不一致 例如在第一列和倒数第二列之间——Fleiss 认为:“第一个评分者总是评分为“1”,倒数第二个评分者总是评分为“0”-> 在所有三个主题上完全不一致。
所以我们需要做的是(抱歉我是菜鸟——可能不是最优雅的):
giro = np.array(orig).transpose()
giro
array([[1, 1, 1],
[1, 1, 1],
[1, 1, 1],
[1, 1, 1],
[3, 3, 2],
[0, 0, 0],
[0, 0, 0],
[1, 1, 1]])
现在我们将主题作为行,将评估者作为列(三个评估者分配 4 个类别)。如果我们将其插入 aggregate_raters() 函数并将结果数据输入 fleiss 会发生什么? (使用索引 0 获取返回元组的第一部分)
irr.fleiss_kappa(irr.aggregate_raters(giro)[0], method='fleiss')
0.8451612903225807
最后......这更有意义,如果除了主题 5 [3, 3, 2] 之外,所有三位评分者都完全同意。
Krippendorff 的阿尔法
当前的 krippendorff 实现需要 orig 格式的数据,其中评估者作为行,列作为主题——准备数据不需要聚合函数。所以我可以看到这是一个更简单的解决方案。 Fleiss 在医学研究中仍然非常普遍,所以让我们看看它的比较:
import krippendorff as kd
kd.alpha(orig)
0.9359
哇……比 Fleiss 的 kappa 高很多……好吧,我们需要告诉 Krippendorff ”史蒂文对变量的测量水平。它必须是 'nominal' 之一, 'ordinal', 'interval', 'ratio' 或可调用的。 – 这是 Krippendorff 阿尔法的 'difference function'。 https://repository.upenn.edu/cgi/viewcontent.cgi?article=1043&context=asc_papers
kd.alpha(orig, level_of_measurement='nominal')
0.8516
希望这对您有所帮助,我在写这篇文章时学到了很多东西。
我有以下列表:
[[1, 1, 1, 1, 3, 0, 0, 1],
[1, 1, 1, 1, 3, 0, 0, 1],
[1, 1, 1, 1, 2, 0, 0, 1],
[1, 1, 0, 2, 3, 1, 0, 1]]
在我想计算 inter-rater 可靠性分数的地方,有多个评分者(行)。我不能使用 Fleiss 的 kappa,因为行的总和不等于相同的数字。在这种情况下,什么是好的方法?
这里的基本问题是您没有正确应用所提供的数据。有关正确的组织,请参阅 here。您有四个类别(评分 0-3)和八个科目。因此,无论审稿人的数量有多少,您的 table 必须有八行和四列。例如,第一行是对第一项的评分统计:
[0, 4, 0, 0] ... since everyone rated it a `1`.
您的 -inf
值来自倒数第二列的 P[j] 分数除以 0。
我之前的回答,标准化分数,是基于 我 对 Fleiss 的误解;我有不同的可靠性。 有很多方法可以计算这样的指标;一个是相对评分的一致性(可以通过归一化获得);另一种是将每个评分者的行转换为相对排名的图表,并计算这些图表之间的相似度。
请注意,Fleiss 不 完全适用于具有相对指标的 rating 情况:它假定这是分类任务,而不是排名。 Fleiss 对收视率的差距并不敏感。它只知道评级不同:(0,1) 配对与 (0,3) 配对一样具有破坏性。
这个问题的一个答案是使用 krippendorff alpha 分数:
import krippendorff
arr = [[1, 1, 1, 1, 3, 0, 0, 1],
[1, 1, 1, 1, 3, 0, 0, 1],
[1, 1, 1, 1, 2, 0, 0, 1],
[1, 1, 0, 2, 3, 1, 0, 1]]
res = krippendorff.alpha(arr)
是的,数据准备是这里的关键。让我们一起走过它。
虽然 Krippendorff 的 alpha 可能出于多种原因而更优越,但 numpy 和 statsmodels 提供了从上述 table 中获取 Fleiss kappa 所需的一切。 Fleiss 的 kappa 在医学研究中更为普遍,尽管 Krippendorff alpha 提供的结果基本相同如果使用得当。如果它们提供的结果大不相同,这可能是由于许多用户错误造成的,最重要的是 输入数据的格式和测量级别(例如,序数与标称) – 跳过解决方案(转置和聚合):Fleiss kappa 0.845
密切注意哪个轴代表 主题、评分者或类别!
弗莱斯河童
statsmodels.stats import inter_rater as irr
原始数据的行是评分者,列是受试者,整数代表分配的类别(如果我没记错的话)。
我删除了一行,因为有 4 行和 4 个类别,这可能会混淆情况 – 所以现在我们有 4 [0,1,2,3] 个类别和 3 行。
orig = [[1, 1, 1, 1, 3, 0, 0, 1],
[1, 1, 1, 1, 3, 0, 0, 1],
[1, 1, 1, 1, 2, 0, 0, 1]]
来自 aggregate_raters() 函数的文档
"将形状为 (subject, rater) 的原始数据转换为 (subject, cat_counts)"
irr.aggregate_raters(orig)
这个returns:
(array([[2, 5, 0, 1], [2, 5, 0, 1], [2, 5, 1, 0]]), array([0, 1, 2, 3]))
现在……orig 数组中的行数等于第一个返回数组 (3) 中的行数。列数现在等于类别数 ([0,1,2,3] -> 4)。每行的内容加起来为 8,等于 orig 输入数据中的列数 - 假设每个评分者都对每个主题进行评分。此聚合显示评分者如何分布在每个主题(行)的类别(列)中。 (如果在类别 2 上达成一致,我们将看到 [0,0,8,0];或类别 0 [8,0,0,0]。
该函数需要行作为主题。查看受试者数量如何没有变化(3 行)。对于每个主题,它计算每个类别被分配的次数 'looking' 在行中找到类别(数字)的次数。对于第一行或类别,0 被分配了两次,1 分配了五次,2 none,3 分配了一次
[1, 1, 1, 1, 3, 0, 0, 1] -> [2, 5, 0, 1]
第二个数组returns类别值。如果我们将输入数组中的两个 3 都替换为 9,则分布看起来相同,但最后一个类别已更改。
ori9 = [[1, 1, 1, 1, 9, 0, 0, 1],
[1, 1, 1, 1, 9, 0, 0, 1],
[1, 1, 1, 1, 2, 0, 0, 1]]
(array([[2, 5, 0, 1], [2, 5, 0, 1], [2, 5, 1, 0]]), array([1, 2, ,3, 9])) <- categories
aggregate_raters() returns ([data], [categories])
的元组在 [data] 中,行保持主题。 aggregate_raters() 将评分者的列转换为类别。 Fleiss 期望 'table' 数据采用这种(主题、类别)格式:https://en.wikipedia.org/wiki/Fleiss'_kappa#Data
现在开始解决问题:
如果我们将原始数据插入 Fleiss kappa 会发生什么: (我们只使用数据 'dats' 而不是类别列表 'cats')
dats, cats = irr.aggregate_raters(orig)
irr.fleiss_kappa(dats, method='fleiss')
-0.12811059907834096
但是……为什么?好吧,看看 orig 数据 – aggregate_raters() 假设 raters 作为列 !这意味着我们 完全不一致 例如在第一列和倒数第二列之间——Fleiss 认为:“第一个评分者总是评分为“1”,倒数第二个评分者总是评分为“0”-> 在所有三个主题上完全不一致。
所以我们需要做的是(抱歉我是菜鸟——可能不是最优雅的):
giro = np.array(orig).transpose()
giro
array([[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1], [3, 3, 2], [0, 0, 0], [0, 0, 0], [1, 1, 1]])
现在我们将主题作为行,将评估者作为列(三个评估者分配 4 个类别)。如果我们将其插入 aggregate_raters() 函数并将结果数据输入 fleiss 会发生什么? (使用索引 0 获取返回元组的第一部分)
irr.fleiss_kappa(irr.aggregate_raters(giro)[0], method='fleiss')
0.8451612903225807
最后......这更有意义,如果除了主题 5 [3, 3, 2] 之外,所有三位评分者都完全同意。
Krippendorff 的阿尔法
当前的 krippendorff 实现需要 orig 格式的数据,其中评估者作为行,列作为主题——准备数据不需要聚合函数。所以我可以看到这是一个更简单的解决方案。 Fleiss 在医学研究中仍然非常普遍,所以让我们看看它的比较:
import krippendorff as kd
kd.alpha(orig)
0.9359
哇……比 Fleiss 的 kappa 高很多……好吧,我们需要告诉 Krippendorff ”史蒂文对变量的测量水平。它必须是 'nominal' 之一, 'ordinal', 'interval', 'ratio' 或可调用的。 – 这是 Krippendorff 阿尔法的 'difference function'。 https://repository.upenn.edu/cgi/viewcontent.cgi?article=1043&context=asc_papers
kd.alpha(orig, level_of_measurement='nominal')
0.8516
希望这对您有所帮助,我在写这篇文章时学到了很多东西。