Является ли Fleiss Kappa надежной мерой для заключения межведомственного соглашения? Следующие результаты смущают меня, есть ли какие-либо предположения при его использовании?
У меня есть матрица аннотаций со следующим описанием: 3 аннотатора, 3 категории, 206 предметов
Данные хранятся в переменной numpy.ndarray z:
array([[ 0., 2., 1.],
[ 0., 2., 1.],
[ 0., 2., 1.],
[ 0., 2., 1.],
[ 1., 1., 1.],
[ 0., 2., 1.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.],
[ 0., 3., 0.]])
Как можно видеть, 200 из 206 аннотаций относятся к одним и тем же категориям всех трех аннотаторов. Сейчас внедряем капельницу Fleiss:
from statsmodels.stats.inter_rater import fleiss_kappa
fleiss_kappa(z)
0.062106000466964177
Почему оценка настолько низкая, несмотря на то, что большинство субъектов (200/206) аннотированы для той же категории?
4 ответа
Я использую «рейтер» вместо «аннотатор». Помните, что это меры согласия выше случайности между оценщиками.
Каппа Флейса
Для каппы Fleiss вам нужно сначала агрегатировать_raters(): это приведет вас от предметов в виде строк и оценщиков в виде столбцов (субъекты, оценщики) к -> субъектам в виде строк и категорий в виде столбцов (субъекты, категории)
from statsmodels.stats import inter_rater as irr
agg = irr.aggregate_raters(arr) # returns a tuple (data, categories)
agg
Значения каждой строки будут в сумме равны количеству оценщиков (3), если каждый оценщик назначил одну категорию для каждого предмета. Теперь столбцы представляют категории, как показано здесь https://en.wikipedia.org/wiki/Fleiss'_kappa#Data .
(array([[1, 1, 1, 0], # all three raters disagree [1, 1, 1, 0], # again [1, 1, 1, 0], # and again [1, 1, 1, 0], # and again [0, 3, 0, 0], # all three raters agree on 1 [1, 1, 1, 0], [2, 0, 0, 1], # two raters agree on 0, third picked 3 [2, 0, 0, 1], # perfect disagreement [2, 0, 0, 1], # for the rest of the dataset. [2, 0, 0, 1], . . . ), array([0, 1, 2, 3])) # categories
совершенное несогласие: «каждый раз, когда я выбираю 0, вы выбираете 3»
… ваши данные говорят, что у вас есть 4 категории [0, 1, 2, 3]
Для первых 4 предметов каждый оценщик кодировал свою категорию! Затем для остальных испытуемых первая и третья оценки соглашаются на категорию 0, а вторая оценивает на 3. Теперь это совершенное несоответствие для большей части набора данных, поэтому я не удивлюсь, увидев отрицательную альфу или каппа! Давайте посмотрим... нам нужны только агрегированные данные agg[0] (первая часть кортежа).
irr.fleiss_kappa(agg[0], method='fleiss')
-0,44238 … что имеет смысл, учитывая разногласия по большинству вопросов
Криппендорф альфа
Текущая реализация криппендорфа предполагает, что оценщики будут строками, а субъекты — столбцами (оценщики, субъекты). Поэтому нам нужно транспонировать исходные данные. Если мы этого не сделаем, то предполагается, что 206 оценщиков оценили 3 предмета в четырех категориях [0,1,2,3], что дает ответ, данный ранее (0,98). Криппендорф не ожидает агрегированного формата!
import numpy as np
import krippendorff as kd
arrT = np.array(arr).transpose() #returns a list of three lists, one per rater
kd.alpha(arrT, level_of_measurement='nominal') #assuming nominal categories
-0,4400 … что имеет смысл, потому что оно должно быть близко к каппе Флейсса или равно ему.
Я думаю, что оценка statsmodels в полном порядке. Проблема вашего примера в том, что почти все время выбирается вторая категория. Это подразумевает, по определению Флейсса Каппы, что два случайных оценщика выбирают вторую категорию очень высоко. Математически, следуя обозначениям статьи в Википедии ( которая точно соответствует статье), Флейсс Каппа определяется как:
k=(\bar{P}-\bar{P_e})/(1-\bar{P_e})
где
- \bar{P} - фактическая вероятность того, что оценки двух случайных оценщиков совпадают
- bar{P_e} — вероятность того, что рейтинги двух случайных оценщиков случайно совпадут.
В вашем случае \bar{P} и (и в этом проблема) \bar{P_e} близки к 1.
Решением вашей проблемы было бы то, что оценщики пришли к согласию и по двум другим категориям. Так, например, измените свой пример таким образом, чтобы у вас было 306 предметов, с еще 3 категориями и 3 оценщиками. Предположим, что аннотации первых 6 тем аналогичны вашему примеру. Затем для следующих 100 предметов все 3 оценщика согласны с категорией 1. Для следующих 100 предметов все 3 оценщика согласны с категорией 2. Соответственно, все оценщики согласны с категорией 3 для последних 100 предметов. Теперь вероятность того, что два оценщика случайно получат одинаковую оценку, намного ниже, поскольку общее количество оценок в каждой категории гораздо более сбалансировано. В этом точном примере Каппа Флейсса составляет 0,9787.
from statsmodels.stats.inter_rater import fleiss_kappa
import numpy as np
firstSixAnnotations=np.array([[ 0., 2., 1.],
[ 0., 2., 1.],
[ 0., 2., 1.],
[ 0., 2., 1.],
[ 1., 1., 1.],
[ 0., 2., 1.]])
allRatersAgreeOnFirstCategory=np.tile(np.array([3.,0.,0.]), (100,1))
allRatersAgreeOnSecondCategory=np.tile(np.array([0.,3.,0.]), (100,1))
allRatersAgreeOnThirdCategory=np.tile(np.array([0.,0.,3.]), (100,1))
z=np.concatenate([firstSixAnnotations,allRatersAgreeOnFirstCategory,allRatersAgreeOnSecondCategory,allRatersAgreeOnThirdCategory])
print(fleiss_kappa(z))
Я также хочу вычислить каппу или криппендорф Флейсса. но значение криппендорфа ниже, чем у Fleiss, намного ниже, это 0,032, а у моего Fleiss - 0,49.
У меня 3 категории, каждую оценивают по 3 аннотатора. В 52% случаев 3 аннотатора согласились по одной и той же категории, в 43% два аннотатора согласились по одной категории, и только в 5% случаев каждый аннотатор выбрал другую категорию. Разве соглашение не слишком низкое, особенно при использовании криппендорфа?
Это решение может служить вашей цели. Вот фрагмент кода, который дает оценку каппа0.98708
.
import krippendorff
arr = [[ 0, 2, 1],
[ 0, 2, 1],
[ 0, 2, 1],
[ 0, 2, 1],
[ 1, 1, 1],
[ 0, 2, 1],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0],
[ 0, 3, 0]]
kappa = krippendorff.alpha(arr)
print(kappa)
Он работает с Python 3.4+, и вот зависимости, которые вам нужно установить
pip install numpy krippendorff