<!doctype html>
2026년 6월 21일 | 개발 공부
Brunner-Munzel 검정은 두 독립 표본에서 한쪽 값이 다른 쪽보다 클 확률이 같은지 보는 비모수 검정이다. 나는 처음에 이 이름을 Mann-Whitney U 검정의 낯선 변형 정도로만 봤는데, 실제로는 질문이 조금 더 정확하다. 평균이 같은지, 중앙값이 같은지, 순위합이 큰지보다 먼저 두 표본의 분포 모양과 흔들림이 서로 달라도 비교 질문을 유지할 수 있는가를 따진다.
실험 로그를 보다 보면 이런 표가 자주 나온다. A 모델은 대부분 안정적인데 가끔 낮은 점수가 나오고, B 모델은 평균은 비슷하지만 꼬리가 길다. 이때 단순 평균 차이만 보면 약해 보이고, Mann-Whitney U를 바로 걸면 두 그룹의 분포 모양이 비슷하다는 감각을 슬쩍 빌려 쓰게 된다. Brunner-Munzel은 그 지점에서 “한쪽에서 뽑은 값이 다른 쪽에서 뽑은 값보다 클 확률”이라는 더 직접적인 문장으로 돌아간다.
Mann-Whitney U와 같은 자리에 놓지 않기
Mann-Whitney U 검정은 여전히 좋은 기본 도구다. 독립 두 표본이고, 값의 순서가 의미 있으며, 두 분포가 대체로 비슷한 모양에서 위치만 밀린 것처럼 보이면 빠르고 익숙하다. 문제는 실무 데이터가 그렇게 얌전하지 않을 때다. 그룹별 표본 수가 다르고, 분산이 다르고, 한쪽에 outlier 꼬리가 길면 순위합 하나로 “어느 쪽이 낫다”라고 쓰기 애매해진다.
Brunner-Munzel은 이 상황에서 귀무가설을 조금 다르게 잡는다. SciPy 문서 표현을 빌리면, 두 그룹에서 값을 하나씩 뽑았을 때 더 큰 값을 얻을 확률이 양쪽에서 같다는 가설을 본다. tie를 반으로 나눠 생각하면 상대 처리 효과가 0.5인지 확인하는 셈이다. 그래서 이 검정은 분포가 완전히 같다고 가정하지 않은 채 stochastic dominance 신호를 확인하는 렌즈에 가깝다.
내가 먼저 확인하는 표 모양
이 검정을 꺼내기 전에 나는 표를 세 칸으로 나눈다. 첫째, 표본이 정말 독립인가. 같은 query, 같은 환자, 같은 seed를 두 모델이 함께 지나간 결과라면 독립 두 표본이 아니라 paired delta 문제다. 그때는 Wilcoxon signed-rank test나 paired permutation test가 더 자연스럽다. 둘째, 값의 순서가 의미 있는가. 성공/실패처럼 이진 결과라면 McNemar나 비율 비교가 먼저일 수 있다.
셋째, 분포 모양이 얼마나 다른가. boxplot이나 ECDF를 그렸을 때 한쪽만 tail이 길거나, 표본 수가 크게 다르거나, variance가 확연히 다르면 Brunner-Munzel 후보로 올린다. 반대로 표본 수가 작고 값이 많이 묶여 있으면 검정 이름을 고르는 것보다 원자료 점을 먼저 보여 주는 편이 낫다. p-value 하나가 그 모든 구조를 대신 설명하지는 못한다.
나는 특히 A/B 테스트형 로그보다 모델 평가 테이블에서 이 구분을 더 자주 만난다. 어떤 모델은 쉬운 샘플에서 조금씩 이기고 어려운 샘플에서 크게 지며, 다른 모델은 반대 모양을 보인다. 평균은 비슷해도 “무작위로 하나씩 뽑으면 어느 쪽이 더 자주 이기나”라는 질문은 남는다. Brunner-Munzel은 바로 그 질문을 통계 표 안으로 옮겨 적게 해 준다.
SciPy에서 쓸 때 남길 메모
Python에서는 scipy.stats.brunnermunzel을 바로 쓸 수 있다. 결과는 W statistic과 p-value로 나온다. 여기서 중요한 건 함수 호출보다 기록 방식이다. 나는 결과 표에 검정명, alternative, p-value, 각 그룹의 n, 요약 통계, 그리고 왜 Mann-Whitney U가 아니라 Brunner-Munzel을 골랐는지를 한 줄로 같이 둔다. 나중에 표만 다시 보면 “그때 왜 이걸 썼지?”가 제일 먼저 헷갈리기 때문이다.
from scipy import stats
w, p = stats.brunnermunzel(group_a, group_b, alternative="two-sided")
print(w, p)
SciPy 문서는 작은 표본에서 p-value 근사를 조심하라고 적는다. 데이터 크기가 50 이하일 때는 t distribution 쪽을 권장하고, 10 미만이면 permutation variant를 검토하는 편이 낫다는 메모가 붙어 있다. 이 문장은 꽤 중요하다. 작은 표본일수록 검정 이름이 멋져 보여도, 실제로는 점 하나가 결론을 흔드는 일이 더 많다.
또 하나 남길 것은 alternative 방향이다. two-sided로 돌렸는지, A가 B보다 큰 쪽을 보려 했는지, 반대로 작은 쪽을 보려 했는지를 결과 표에 적어야 한다. 방향을 나중에 다시 추측하면 해석이 쉽게 꼬인다. 특히 모델 점수가 클수록 좋은 metric인지, latency처럼 작을수록 좋은 metric인지도 같은 줄에 붙여 두면 검정 결과를 읽는 사람이 덜 헤맨다.
결론 대신 inspection queue를 줄이기
내가 이 검정을 좋아하는 지점은 “A가 B보다 낫다”를 바로 말해 주기 때문이 아니다. 오히려 반대다. Brunner-Munzel은 분포 모양이 다른 두 표본을 볼 때, 평균 차이와 rank 차이를 섞어 말하지 않도록 질문을 좁혀 준다. pairwise 우위 확률이 흔들리는지 본 뒤, 그 옆에 Cliff's delta 같은 효과 크기와 bootstrap confidence interval을 붙이면 해석이 훨씬 덜 둥둥 뜬다.
그래서 내 노트에서는 Brunner-Munzel을 최종 판정 도장으로 두지 않는다. “독립 표본인가”, “paired로 다시 만들 수 없는가”, “분포 모양이 달라 Mann-Whitney 가정을 빌리기 불편한가”, “효과 크기와 원자료 그림을 같이 남겼는가”를 확인하는 체크포인트로 둔다. 통계 검정이 하나 더 늘어난 것 같지만, 실제로는 잘못된 비교를 하나 줄이는 쪽에 가깝다.
다음에 같은 표를 다시 만나면 나는 평균표 바로 아래에 작은 decision note를 붙일 생각이다. paired 가능 여부, 분포 모양 차이, 선택한 검정, 같이 본 효과 크기를 네 줄로 남기면 충분하다. 검정 결과보다 그 네 줄이 더 오래 쓸모 있다. 나중에 데이터가 늘어났을 때 같은 기준으로 다시 비교할 수 있기 때문이다. 이렇게 적어 두면 다음 실험의 표본 설계도 덜 흔들린다.
'[개발 공부]' 카테고리의 다른 글
| Glass's Delta: 기준군 표준편차로 읽는 평균 차이 (0) | 2026.06.23 |
|---|---|
| Vargha-Delaney A12: 두 독립 표본의 승률 효과 크기 (0) | 2026.06.22 |
| HTTP 204 응답: 성공인데 본문이 없는 상태 (0) | 2026.06.19 |
| Games-Howell 사후검정: 분산이 다른 그룹의 쌍별 비교 (0) | 2026.06.18 |
| Welch ANOVA: 분산이 다른 세 그룹 비교 (0) | 2026.06.17 |