주석자 간 신뢰도 — Cohen’s Kappa와 ICC

Gold Standard는 얼마나 믿을 수 있는가

AI 모델 평가, 임상시험, 의료기기 규제 검증에서 gold standard는 인간 전문가의 판단으로 만들어진다. 이 gold standard 자체가 얼마나 일관된지를 정량화하는 것이 주석자 간 신뢰도(inter-rater reliability)이다. Cohen’s Kappa(명목 범주형 2인), Fleiss’ Kappa(3인 이상), ICC(연속형)의 수학적 정의, 해석 기준, 언제 어떤 지표를 쓰는지, R·Python 구현을 다룬다.

Statistics
Measurement
FDA
Data Science
저자

Kwangmin Kim

공개

2026년 04월 05일

1 왜 Gold Standard의 신뢰도를 측정해야 하는가

머신러닝 모델이나 의료 알고리즘을 평가할 때 우리는 반드시 정답 레이블(gold standard)이 필요하다. 그런데 이 정답은 어디서 오는가? 대부분은 인간 전문가가 직접 판정한다.

가령 AI 피부암 분류 모델을 검증한다면:

  • 피부과 전문의 5명이 각 이미지를 독립적으로 판독
  • 다수결 또는 합의로 gold standard를 결정
  • AI 모델의 판정을 이 gold standard와 비교

여기서 결정적인 질문이 생긴다: 전문의 5명이 얼마나 서로 동의하는가?

전문의들이 서로 엇갈린 판정을 내렸다면, 그 합의 결과는 진짜 ’정답’이라고 할 수 없다. 불확실한 gold standard로 모델을 평가한다면, 모델의 성능 수치 자체가 신뢰할 수 없게 된다.

이것이 주석자 간 신뢰도(inter-rater reliability, IRR)를 반드시 보고해야 하는 이유다.

FDA 규제 맥락

FDA는 의료기기 소프트웨어(SaMD) 검증 시 gold standard의 신뢰도 보고를 요구한다. 일반적으로 Cohen’s \(\kappa \geq 0.70\) (substantial agreement) 이상을 수용 가능한 기준으로 본다. 이보다 낮으면 gold standard의 질 자체를 의심해야 하며, 추가적인 합의 프로세스가 필요하다.


2 두 가지 다른 개념: 상관성 vs 일치성

주석자 신뢰도를 측정하기 전에 두 개념을 구분해야 한다.

개념 의미 적합한 지표
일치성 (Agreement) 두 판정자가 동일한 판정을 내렸는가 Cohen’s \(\kappa\), ICC (agreement형)
일관성 (Consistency) 두 판정자의 판정이 같은 방향으로 변화하는가 ICC (consistency형), Spearman \(\rho\)

판정자 A는 항상 판정자 B보다 점수를 5점 높게 준다고 하자. 상관계수는 1.0이지만 일치도는 낮다. 규제 검증에서는 일치성(agreement)이 요구된다. “두 판정자가 같은 답을 냈는가”가 중요하기 때문이다.


3 Cohen’s Kappa (\(\kappa\)) — 명목형 범주, 2명

3.1 정의

정의: Cohen’s Kappa

두 판정자 A, B가 \(n\)개 항목에 대해 \(k\)개 범주 중 하나를 독립적으로 부여할 때, 관측 일치율 \(P_o\)와 우연에 의한 기대 일치율 \(P_e\)를 사용하여 정의한다.

\[ \kappa = \frac{P_o - P_e}{1 - P_e} \]

여기서: - \(P_o = \sum_{i=1}^{k} \frac{n_{ii}}{n}\) (대각 원소의 합 / 전체) - \(P_e = \sum_{i=1}^{k} \frac{n_{i+} \cdot n_{+i}}{n^2}\) (주변 확률의 곱 합) - \(n_{ii}\): 두 판정자 모두 \(i\)로 분류한 항목 수 - \(n_{i+}\): 판정자 A가 \(i\)로 분류한 항목 수, \(n_{+i}\): 판정자 B가 \(i\)로 분류한 항목 수

3.2 직관적 이해

\(P_e\)는 “두 판정자가 무작위로 독립적으로 판정했을 때 우연히 일치할 확률”이다. \(\kappa\)는 이 우연을 제거하고 나서 얼마나 더 일치하는지를 측정한다.

  • \(\kappa = 1\): 완벽한 일치
  • \(\kappa = 0\): 우연 수준의 일치 (정보 없음)
  • \(\kappa < 0\): 우연보다 더 자주 불일치 (드물지만 가능)

3.3 수치 예시

이진 분류(양성/음성)에서 두 병리학자 A, B가 100개 슬라이드를 판독한 결과:

B: 양성 B: 음성
A: 양성 40 10 50
A: 음성 5 45 50
45 55 100

\[P_o = \frac{40 + 45}{100} = 0.85\]

\[P_e = \frac{50 \times 45}{100^2} + \frac{50 \times 55}{100^2} = 0.225 + 0.275 = 0.50\]

\[\kappa = \frac{0.85 - 0.50}{1 - 0.50} = \frac{0.35}{0.50} = 0.70\]

관측 일치율은 85%이지만, 우연 일치율이 50%이므로 \(\kappa = 0.70\)이 나온다. 단순 일치율(85%)보다 훨씬 보수적이고 신뢰할 수 있는 지표다.


4 Fleiss’ Kappa — 명목형 범주, 3명 이상

Cohen’s Kappa는 2명 판정자에 한정된다. 3명 이상에는 Fleiss’ Kappa를 사용한다.

정의: Fleiss’ Kappa

\(n\)개 항목, \(k\)개 범주, \(m\)명 판정자인 경우:

\[ \kappa_F = \frac{\bar{P} - \bar{P}_e}{1 - \bar{P}_e} \]

여기서: - \(\bar{P} = \frac{1}{n \cdot m(m-1)} \sum_{i=1}^{n} \sum_{j=1}^{k} n_{ij}(n_{ij}-1)\) (평균 관측 일치율) - \(\bar{P}_e = \sum_{j=1}^{k} p_j^2\), \(p_j = \frac{\text{범주 } j \text{의 총 판정 수}}{n \cdot m}\)

Fleiss’ Kappa는 판정자 조합에 관계없이 전체 집합의 일치도를 하나의 수치로 요약한다.


5 ICC (급내 상관계수, Intraclass Correlation Coefficient) — 연속형

Kappa는 명목 범주형 데이터에 사용하지만, 판정이 숫자 점수(예: 1-10점 통증 척도, CT 병변 크기 mm)일 때는 ICC를 사용한다.

5.1 Mixed Models 맥락의 ICC vs 신뢰도 맥락의 ICC

용어 주의

ICC는 문맥에 따라 두 가지 다른 의미로 쓰인다.

맥락 의미 공식
혼합 모형 (Mixed Model) 집단 내 분산 비율 — 군집화 정도 측정 \(ICC = \frac{\tau^2}{\tau^2 + \sigma^2}\)
신뢰도 측정 (여기서 다루는 것) 판정자 간 일치도 — 반복 측정의 안정성 ANOVA 기반 공식

이 포스트는 신뢰도 측정 맥락의 ICC를 다룬다.

5.2 ICC의 ANOVA 기반 정의

판정자를 무작위 효과(random effect)로 보는 ANOVA 분해:

\[ X_{ij} = \mu + \alpha_i + \beta_j + \varepsilon_{ij} \]

  • \(\alpha_i\): 항목 \(i\)의 무작위 효과 (\(\sigma^2_\alpha\))
  • \(\beta_j\): 판정자 \(j\)의 무작위 효과 (\(\sigma^2_\beta\))
  • \(\varepsilon_{ij}\): 오차 (\(\sigma^2_\varepsilon\))

Agreement 형 ICC (판정자 간 절대 일치, FDA에서 요구되는 형태):

\[ ICC_{agreement} = \frac{\sigma^2_\alpha}{\sigma^2_\alpha + \sigma^2_\beta + \sigma^2_\varepsilon} \]

Consistency 형 ICC (판정자 간 상대적 일관성):

\[ ICC_{consistency} = \frac{\sigma^2_\alpha}{\sigma^2_\alpha + \sigma^2_\varepsilon} \]

Agreement 형은 판정자 편향(\(\sigma^2_\beta\))까지 오차에 포함하므로 더 엄격하다. 규제 검증에서는 절대 일치가 필요하므로 Agreement 형을 사용한다.

5.3 ICC의 6가지 모형 (Shrout & Fleiss, 1979)

모형 판정자 측정 표기 언제 사용
ICC(1,1) 무작위 선택, 1회 측정 단일 One-way random 판정자마다 서로 다른 항목을 봄
ICC(1,k) 무작위 선택, k회 평균 평균 One-way random 위와 같지만 k명 평균 보고
ICC(2,1) 무작위 선택, 1회 측정 단일 Two-way random 모든 판정자가 모든 항목을 봄, 판정자를 일반화
ICC(2,k) 무작위 선택, k회 평균 평균 Two-way random 위와 같지만 k명 평균 보고
ICC(3,1) 고정 집합, 1회 측정 단일 Two-way mixed 특정 판정자 집단에만 일반화
ICC(3,k) 고정 집합, k회 평균 평균 Two-way mixed 위와 같지만 k명 평균 보고

임상·규제 검증에서 가장 흔히 사용하는 것: ICC(2,1) — Agreement 형. 모든 판정자가 모든 항목을 독립 판독하고, 이 판정자들 이상의 모집단으로 결과를 일반화하는 상황에 해당한다.


6 어떤 지표를 쓸 것인가

조건 지표
이진 분류 (양성/음성), 판정자 2명 Cohen’s \(\kappa\)
다범주 명목형, 판정자 2명 Cohen’s \(\kappa\) (다범주)
명목형 (범주), 판정자 3명 이상 Fleiss’ \(\kappa\)
연속형 또는 순서형 점수, 2명 이상 ICC
절대 일치 필요 (규제, 임상) ICC — Agreement 형
상대적 순위 일관성만 확인 ICC — Consistency 형 또는 Spearman \(\rho\)

7 해석 기준

Landis & Koch (1977)의 기준이 가장 널리 사용된다:

\(\kappa\) 또는 ICC 범위 해석 실무적 의미
< 0.00 Poor 우연보다 못함 — gold standard 폐기
0.00 – 0.20 Slight 거의 우연 수준
0.21 – 0.40 Fair 보통 미만
0.41 – 0.60 Moderate 보통
0.61 – 0.80 Substantial 충분한 일치 — FDA 최소 기준
0.81 – 1.00 Almost Perfect 우수한 일치
FDA 기준

일반적으로 \(\kappa \geq 0.70\) 이상이어야 gold standard로 인정된다. \(0.61 \leq \kappa < 0.70\)이면 조건부 수용 가능하나 추가 합의 과정 문서화가 필요하다. \(\kappa < 0.61\)이면 gold standard 재설계를 권고한다.


8 응용 분야

분야 상황 사용 지표
의료 AI CT/MRI 병변 어노테이션 일치도 ICC (연속형 크기)
임상시험 임상의 평가척도(MMSE, NIHSS) 신뢰도 ICC 또는 Weighted Kappa
FDA 의료기기 알고리즘 검증용 gold standard 신뢰도 Cohen’s \(\kappa\) (이진)
LLM 평가 인간 평가자 간 응답 품질 일치도 Cohen’s \(\kappa\) 또는 Fleiss’ \(\kappa\)
병리 조직검사 병리학자 간 종양 등급 판독 Weighted Kappa
신용 심사 심사원 간 대출 승인 일치도 Cohen’s \(\kappa\)

9 코드 예시

9.1 Step 1: 순수 구현 (원리 이해)

# R — Cohen's Kappa 수동 계산
compute_kappa <- function(mat) {
  n  <- sum(mat)
  po <- sum(diag(mat)) / n
  
  row_marginals <- rowSums(mat) / n
  col_marginals <- colSums(mat) / n
  pe <- sum(row_marginals * col_marginals)
  
  kappa <- (po - pe) / (1 - pe)
  list(po = po, pe = pe, kappa = kappa)
}

# 예시: 2×2 혼동 행렬
mat <- matrix(c(40, 10, 5, 45), nrow = 2, byrow = TRUE,
              dimnames = list(c("A:Pos", "A:Neg"), c("B:Pos", "B:Neg")))
result <- compute_kappa(mat)
cat(sprintf("Po = %.3f, Pe = %.3f, κ = %.3f\n",
            result$po, result$pe, result$kappa))
# Po = 0.850, Pe = 0.500, κ = 0.700
# Python — Cohen's Kappa 수동 계산
import numpy as np

def compute_kappa(mat):
    mat = np.array(mat)
    n   = mat.sum()
    po  = np.trace(mat) / n
    
    row_m = mat.sum(axis=1) / n
    col_m = mat.sum(axis=0) / n
    pe    = np.dot(row_m, col_m)
    
    kappa = (po - pe) / (1 - pe)
    return {"po": po, "pe": pe, "kappa": kappa}

mat = [[40, 10], [5, 45]]
result = compute_kappa(mat)
print(f"Po={result['po']:.3f}, Pe={result['pe']:.3f}, κ={result['kappa']:.3f}")
# Po=0.850, Pe=0.500, κ=0.700

9.2 Step 2: 라이브러리 활용 (실무)

# R — Cohen's Kappa (2인), Fleiss' Kappa (3인+), ICC
library(irr)

# ── Cohen's Kappa (2인, 명목형) ───────────────────────────────
rater_a <- c("Pos", "Pos", "Neg", "Neg", "Pos")
rater_b <- c("Pos", "Neg", "Neg", "Neg", "Pos")
raters  <- data.frame(A = rater_a, B = rater_b)

kappa2(raters)
# κ = 0.60 등 출력 (Kappa statistic, z, p-value)

# ── Fleiss' Kappa (3인 이상, 명목형) ─────────────────────────
# n개 항목 × m명 판정자 행렬 (각 셀에 부여된 범주)
ratings <- matrix(c(
  1, 1, 2,
  2, 2, 2,
  1, 1, 1,
  2, 1, 2
), nrow = 4, byrow = TRUE)

kappam.fleiss(ratings)

# ── ICC (연속형, 신뢰도 맥락) ────────────────────────────────
# 4명 판정자가 10개 항목에 대해 연속형 점수 부여
set.seed(42)
scores <- matrix(round(rnorm(40, mean = 5, sd = 1), 1), nrow = 10, ncol = 4)

# ICC(2,1) Agreement 형 — 규제 검증 권장
icc(scores, model = "twoway", type = "agreement", unit = "single")
# ICC, 95% CI, F-value, p-value 출력

# ICC(2,k) Agreement 형 — k명 평균 보고 시
icc(scores, model = "twoway", type = "agreement", unit = "average")
# Python — Cohen's Kappa (sklearn), ICC (pingouin)
from sklearn.metrics import cohen_kappa_score
import pingouin as pg
import pandas as pd
import numpy as np

# ── Cohen's Kappa ─────────────────────────────────────────────
y1 = [1, 1, 0, 0, 1]
y2 = [1, 0, 0, 0, 1]
kappa = cohen_kappa_score(y1, y2)
print(f"Cohen's κ = {kappa:.3f}")

# ── ICC (pingouin) ─────────────────────────────────────────────
np.random.seed(42)
data = pd.DataFrame({
    "Subject": np.repeat(range(1, 11), 4),
    "Rater":   list(range(1, 5)) * 10,
    "Score":   np.random.normal(loc=5, scale=1, size=40).round(1)
})

# ICC(2,1) Agreement 형
icc_result = pg.intraclass_corr(data     = data,
                                 targets  = "Subject",
                                 raters   = "Rater",
                                 ratings  = "Score")
# ICC2 (two-way random, single, absolute agreement) 행 선택
print(icc_result[icc_result["Type"] == "ICC2"])

9.3 Step 3: 결과 해석 출력 함수

# 결과를 Landis & Koch 기준으로 자동 해석
interpret_kappa <- function(k) {
  if      (k < 0)    "Poor (worse than chance)"
  else if (k < 0.20) "Slight"
  else if (k < 0.40) "Fair"
  else if (k < 0.60) "Moderate"
  else if (k < 0.80) "Substantial"
  else               "Almost Perfect"
}

k_val <- 0.70
cat(sprintf("κ = %.3f → %s\n", k_val, interpret_kappa(k_val)))
# κ = 0.700 → Substantial

10 자주 발생하는 오류

10.1 단순 일치율(Percent Agreement)로 보고

WRONG: "두 판정자의 일치율은 85%로 높다"
CORRECT: "관측 일치율은 85%이지만 우연 일치율이 50%이므로 κ = 0.70이다"

단순 일치율은 범주 분포가 불균형할 때 매우 높게 나올 수 있다. 예를 들어 99%가 음성인 데이터셋에서 두 판정자 모두 “항상 음성”으로 판정해도 일치율은 99%가 된다. Kappa는 이 문제를 \(P_e\) 보정으로 해결한다.

10.2 연속형 데이터에 Kappa 사용

WRONG: 통증 점수(1-10)에 Cohen's Kappa 적용
CORRECT: 통증 점수(1-10)에 ICC(2,1) Agreement 형 적용

순서형·연속형 데이터에 Kappa를 쓰면 인접 범주 불일치(3점 vs 4점)와 극단 불일치(1점 vs 10점)를 동일하게 취급하는 문제가 생긴다. 이를 부분적으로 해결하는 Weighted Kappa도 있지만, 이 경우 ICC가 더 자연스럽다.

10.3 ICC Agreement 형과 Consistency 형 혼동

규제 문서에서 “ICC = 0.85”만 보고하면 어떤 모형인지 알 수 없다. 반드시 ICC(2,1) agreement 또는 ICC(3,k) consistency 형태로 명시한다.


11 관련 주제

선행 지식

후속 주제

Subscribe

Enjoy this blog? Get notified of new posts by email: