콘텐츠로 이동

자유도와 점근 이론

카이제곱 검정의 자유도

자유도는 \(H_0\) 아래 기준분포로 쓰이는 카이제곱 분포의 모양을 결정한다. 계산 방식은 어떤 카이제곱 검정을 하는지에 따라 달라진다.

적합도 검정

범주가 \(k\)개인 적합도 검정에서는

\[ \text{df} = k - 1 \]

이다. 제약이 하나 생기는 것은 관측도수의 합이 전체 표본크기 \(n\)이어야 하기 때문이다:

\[ \sum_{i=1}^{k} O_i = n = \sum_{i=1}^{k} E_i \]

따라서 편차 \(O_i - E_i\) 중 \(k - 1\)개만 자유롭게 변할 수 있고 마지막 하나는 나머지로 결정된다.

독립성 검정과 동질성 검정

\(r \times c\) 분할표에서는

\[ \text{df} = (r - 1) \times (c - 1) \]

이며, 여기서 \(r\)은 행의 수, \(c\)는 열의 수이다.

제약은 다음과 같다:

  • 행 합계가 일치해야 한다: 행에서 나오는 독립인 제약 \(r - 1\)개.
  • 열 합계가 일치해야 한다: 열에서 나오는 독립인 제약 \(c - 1\)개.
  • 제약 하나(총합)는 중복이다.

따라서 표에서 자유로운 칸의 수는

\[ rc - 1 - (r - 1) - (c - 1) = (r - 1)(c - 1) \]

이다.

자유로운 칸을 직접 세어 보자

적합도 검정에서는 마지막 한 칸이, 분할표에서는 마지막 행과 마지막 열이 주변합에 의해 결정된다

자유도 공식은 외울 것이 아니라 세는 것이다. 왼쪽 (가)에서 범주가 5개인 적합도 검정을 보자. 앞의 네 칸에는 어떤 값이든 넣을 수 있다. 그러나 \(O_1 + \dots + O_5 = n\)이 고정되어 있으므로 다섯 번째 칸은 \(n\)에서 앞의 넷을 뺀 값으로 결정된다. 고를 수 있는 칸이 4개, 즉 \(\text{df} = k - 1 = 4\)이다.

오른쪽 (나)의 3행 4열 분할표에서도 같은 일을 한다. 행 합 3개와 열 합 4개가 모두 고정되어 있다고 하자. 왼쪽 위 \(2 \times 3\) 구역의 파란 칸 6개를 자유롭게 채우고 나면, 각 행의 마지막 칸은 그 행의 합에서 채운 값들을 빼면 나오고, 마지막 행 전체는 각 열의 합에서 위의 값들을 빼면 나온다. 주황 칸 6개는 한 번도 고를 기회가 없다. 그래서 \(\text{df} = (r-1)(c-1) = 2 \times 3 = 6\)이다.

이 그림은 앞의 뺄셈식이 왜 맞는지도 보여 준다. 칸이 \(rc = 12\)개, 총합 제약으로 1개, 행 제약으로 \(r - 1 = 2\)개, 열 제약으로 \(c - 1 = 3\)개를 빼서 \(12 - 1 - 2 - 3 = 6\)이다. 행 제약이 \(r\)개가 아니라 \(r-1\)개인 이유가 그림에 그대로 있다. 행 합 3개와 열 합 4개를 모두 알면 총 7개의 수를 아는 것 같지만, 두 묶음의 합이 똑같이 \(n\)이어야 하므로 실제로 독립인 정보는 6개뿐이다. 오른쪽 아래 구석의 \(n\) 칸이 그 중복을 담당한다.

주의할 점은 이 세기가 "기대도수를 무엇으로부터 계산했는가"에 달려 있다는 것이다. 위의 분할표에서는 기대도수를 자료의 주변합으로 추정했기 때문에 주변합이 제약이 되었다. 만약 확률이 이론으로 완전히 주어져 아무것도 추정하지 않았다면 잃을 자유도는 총합 제약 하나뿐이고 \(\text{df} = rc - 1 = 11\)이 된다. 추정한 모수 하나마다 칸 하나가 주황색으로 바뀐다고 생각하면 된다.

점근 이론

핵심 결과

\(H_0\) 아래에서 표본크기가 크면 카이제곱 검정통계량

\[ \chi^2 = \sum \frac{(O_{ij} - E_{ij})^2}{E_{ij}} \]

은 적절한 자유도의 카이제곱 확률변수로 분포수렴한다. 이는 점근적 결과이다. 유한 표본에서는 근사적으로 성립하며 표본크기가 커질수록 근사가 좋아진다.

적합도 검정의 유도 개요

\[ \sum_{i=1}^k \frac{(O_i - E_i)^2}{E_i} = \sum_{i=1}^k \frac{\left(\left(\sum_{j=1}^{n} X_j\right) - np_i\right)^2}{np_i} = \sum_{i=1}^k \left(\frac{\left(\sum_{j=1}^{n} X_j\right) - np_i}{\sqrt{np_i}}\right)^2 \]

분모를 근사하면

\[ \approx \sum_{i=1}^k \left(\frac{\left(\sum_{j=1}^{n} X_j\right) - np_i}{\sqrt{np_i(1-p_i)}}\right)^2 \approx \sum_{i=1}^k Z_i^2 = \chi^2_{k-1} \]

이다. 마지막 단계는 \(Z_i\)들이 완전히 독립이 아니라는(선형 제약 하나를 만족한다는) 사실을 이용하며, 이 때문에 유효 자유도가 \(k\)에서 \(k-1\)로 줄어든다.

수렴 속도

카이제곱 근사는 다음 조건에서 좋아진다:

  • 전체 표본크기 \(n\)이 클수록.
  • 기대 칸 도수가 고르게 분포할수록.
  • 기대도수가 아주 작은 범주가 적을수록.

실무 지침으로는 모든 기대도수가 적어도 5 이상일 때 근사가 대체로 믿을 만하다.

연습문제

연습문제 1. 어떤 분할표가 4행 3열이다. 카이제곱 독립성 검정의 자유도는 얼마인가? 공식을 설명하라.

풀이

자유도는

\[ df = (r-1)(c-1) = (4-1)(3-1) = 3 \times 2 = 6 \]

이다. 이 공식이 나오는 것은 기대도수를 주변 합계로부터 계산하기 때문이다. \(r\)행 \(c\)열이면 주변 합계가 \(r + c\)개인데, 행 주변합과 열 주변합이 모두 \(n\)으로 합해져야 한다는 제약이 있어 제약은 \(r + c - 1\)개가 된다. 자유로운 모수의 수는 \((r \times c) - 1 - (r + c - 1) = rc - r - c + 1 = (r-1)(c-1)\)이다.

연습문제 2. 정규분포에 대한 적합도 검정에서 구간을 8개 쓰고 두 모수(\(\mu\)와 \(\sigma\))를 자료로부터 추정했다. 자유도는 얼마인가?

풀이

구간이 \(k\)개이고 추정한 모수가 \(p\)개인 적합도 검정에서는

\[ df = k - 1 - p = 8 - 1 - 2 = 5 \]

이다. 추정한 모수 하나마다 자유도가 1씩 줄어드는 것은 제약이 하나씩 더 생기기 때문이다. 기대도수를 (가설로 주어진 값이 아니라) 추정된 모수값으로 계산하므로 관측과 기대 사이의 어긋남이 줄어든다.

연습문제 3. 어떤 카이제곱 검정에서 관측값이 \(n = 50\)개이고 범주가 10개이며 기대도수가 모두 같다. 경험 법칙 조건(모든 기대도수가 적어도 5)이 만족되는지 확인하라.

풀이

\(n = 50\)이고 같은 크기의 범주가 \(k = 10\)개이면 각 기대도수는

\[ E_i = \frac{n}{k} = \frac{50}{10} = 5 \]

이다. 조건 \(E_i \geq 5\)가 (정확히 경계에서) 만족된다. 카이제곱 근사가 적절할 것이나, 일부 통계학자는 \(E_i \geq 5\)를 최소 기준으로 보고 더 안전하게는 \(E_i \geq 10\)을 권한다.

연습문제 4. 연습문제 3의 10개 범주 중 하나의 기대도수가 2뿐이라면 어떤 보완 조치를 취할 수 있는가?

풀이

기대도수가 너무 작을 때 흔히 쓰는 대처는 다음과 같다:

  1. 인접한 범주 병합: 도수가 낮은 범주를 이웃 범주와 합쳐 기대도수가 큰 범주를 만든다. \(k\)가 줄고 합쳐진 칸의 기대도수가 커진다.

  2. 정확검정 사용: Fisher의 정확검정이나 순열검정은 카이제곱 근사에 의존하지 않으므로 작은 기대도수도 다룰 수 있다.

  3. 자료 추가 수집: 가능하다면 \(n\)을 늘리면 모든 기대도수가 비례하여 커진다.

실무에서는 첫 번째 선택지(범주 병합)가 가장 흔하다. 다만 합치는 범주는 과학적으로 의미가 있어야 한다. 임의로 고르지 말고 인접하거나 성격이 비슷한 범주를 합쳐야 한다.

연습문제 5. "정리하며"는 모수를 추정하고도 자유도를 줄이지 않으면 \(p\) 값이 체계적으로 커진다고 했다. 포아송 적합도 검정으로 이를 확인하라.

풀이
import numpy as np
from scipy import stats

rng = np.random.default_rng(1010)
lam, n, M, K = 3.0, 200, 20_000, 8      # 범주: 0,1,...,6 그리고 7 이상

def chi2_stat(x):
    """λ를 자료에서 추정한 포아송 적합도 통계량."""
    obs = np.bincount(np.minimum(x, K - 1), minlength=K).astype(float)
    lam_hat = x.mean()                   # ← 모수를 추정했다
    p = stats.poisson.pmf(np.arange(K - 1), lam_hat)
    p = np.r_[p, 1 - p.sum()]
    exp = n * p
    return ((obs - exp)**2 / exp).sum(), exp.min()

stat = np.empty(M)
emin = np.empty(M)
for i in range(M):
    stat[i], emin[i] = chi2_stat(rng.poisson(lam, n))

print(f"기대도수 최솟값의 평균  {emin.mean():.3f}")
print(f"통계량의 평균          {stat.mean():.4f}")
print(f"  (자유도가 df 이면 평균이 df 여야 한다: k-1={K - 1}, k-2={K - 2})\n")
for df, label in [(K - 1, "df = k-1  (조정 안 함)"), (K - 2, "df = k-2  (올바름)")]:
    print(f"{label:24s} 기각률 {np.mean(stat > stats.chi2.ppf(0.95, df)):.4f}")
기대도수 최솟값의 평균  6.665
통계량의 평균          5.9963
  (자유도가 df 이면 평균이 df 여야 한다: k-1=7, k-2=6)

df = k-1  (조정 안 함)       기각률 0.0273
df = k-2  (올바름)          기각률 0.0471

통계량의 평균이 5.996으로 \(k-2=6\)에 정확히 맞는다. 카이제곱 분포의 평균이 자유도와 같으므로, 이 한 줄만으로도 올바른 자유도가 6임을 알 수 있다.

조정을 빠뜨리면 수준이 0.0273으로 떨어진다. 명목의 55%다. 자유도를 크게 잡으면 임계값도 커지므로 기각을 덜 하게 된다.

자유도 임계값 \(\chi^2_{0.95}\) 실제 수준
7 (잘못) 14.07 0.0273
6 (올바름) 12.59 0.0471

방향이 중요하다. 이 실수는 보수적이다. 즉 있지도 않은 이탈을 만들어 내지는 않지만, 진짜 이탈을 놓친다. 적합도 검정은 대개 "모형이 맞다"를 보이려는 목적이므로, 보수적인 검정은 모형을 통과시키기 쉽게 만든다. 그런 점에서는 오히려 위험한 방향이다.

왜 자유도가 하나 줄어드는가. \(\hat\lambda=\bar X\)로 기대도수를 맞추면 관측과 기대의 어긋남이 한 방향으로 더 줄어든다. 자료가 스스로에게 맞춰졌기 때문이다. 잃어버린 그 한 방향이 자유도 1에 해당한다.

일반 규칙. 적합도 검정에서 자료로 추정한 모수가 \(r\)개면

\[ \text{df}=k-1-r \]
  • 포아송(\(\lambda\) 하나) → \(k-2\)
  • 정규(\(\mu,\sigma\) 둘) → \(k-3\)
  • 이항(\(p\) 하나, \(n\)은 알려짐) → \(k-2\)

다만 이 규칙에도 조건이 있다. 다음 문제에서 본다.

연습문제 6. 연습문제 5의 규칙 \(\text{df}=k-1-r\)는 모수를 집단화된 도수로부터 추정했을 때만 정확하다. 원자료에서 추정하면 어떻게 되는지 확인하라.

풀이

문제의 소재. 정규성 적합도 검정에서 \(\mu,\sigma\)를 추정하는 방법이 둘이다.

방법 쓰는 정보 극한분포
집단화 자료의 최대가능도 각 구간의 도수만 정확히 \(\chi^2_{k-1-r}\)
원자료의 \(\bar x,\ s\) 관측값 전부 \(\chi^2_{k-1-r}\)와 \(\chi^2_{k-1}\) 사이

실무에서는 거의 언제나 뒤쪽을 쓴다. 더 많은 정보를 썼으므로 통계량이 더 커지고, 자유도 \(k-1-r\)짜리 분포보다 오른쪽으로 밀린다(체르노프·레만).

import numpy as np
from scipy import stats

rng = np.random.default_rng(4040)
M, n, K = 20_000, 200, 8
qs = np.linspace(0, 1, K + 1)[1:-1]      # 등확률 구간의 경계 분위수

stat = np.empty(M)
for i in range(M):
    x = rng.standard_normal(n)           # H0 가 참 (정규자료)
    mu, sd = x.mean(), x.std(ddof=1)     # ← 원자료에서 추정
    edges = np.r_[-np.inf, mu + sd * stats.norm.ppf(qs), np.inf]
    obs = np.histogram(x, bins=edges)[0].astype(float)
    exp = np.full(K, n / K)
    stat[i] = ((obs - exp)**2 / exp).sum()

print(f"통계량의 평균 {stat.mean():.4f}   "
      f"(k-1 = {K - 1},  k-1-2 = {K - 3})\n")
for df in [K - 1, K - 3]:
    print(f"  df={df} 를 쓰면 실제 수준 "
          f"{np.mean(stat > stats.chi2.ppf(0.95, df)):.4f}")
통계량의 평균 5.4538   (k-1 = 7,  k-1-2 = 5)

  df=7 를 쓰면 실제 수준 0.0195
  df=5 를 쓰면 실제 수준 0.0605

통계량의 평균 5.45가 5와 7 사이에 있다. 어느 쪽 자유도도 정확하지 않다.

자유도 실제 수준 판정
7 (\(k-1\)) 0.0195 지나치게 보수적
5 (\(k-1-r\)) 0.0605 과대기각(명목의 1.21배)

체르노프·레만 정리. 원자료의 최대가능도추정량을 쓰면 극한분포가

\[ \chi^2_{k-1-r}+\sum_{j=1}^{r}\lambda_j Z_j^2,\qquad 0\le\lambda_j\le1 \]

로, 두 카이제곱 분포 사이에 낀다. \(\lambda_j\)는 구간 나누기와 모형에 의존하므로 일반적인 임계값표를 만들 수 없다.

실무의 대처.

  1. 정규성 검정에는 카이제곱을 쓰지 않는다. 샤피로·윌크, 앤더슨·달링, 콜모고로프·스미르노프(릴리포스 보정)가 모두 낫다. 구간을 어떻게 나눌지 고민할 필요도 없다.
  2. 꼭 써야 한다면 모의실험으로 임계값을 얻는다. 위 코드가 그대로 그 작업이다.
  3. \(k-1-r\)를 쓰되 과대기각을 감수한다. 여기서는 0.06 정도로, 치명적이지는 않다.
  4. 집단화 자료만 있으면 집단화 최대가능도로 추정한다. 그러면 \(k-1-r\)가 정확하다.

이 문제가 주는 더 큰 교훈. "자유도는 제약의 개수"라는 직관적 규칙은 추정량이 무엇이냐에 따라 달라진다. 같은 모형, 같은 구간이라도 \(\mu,\sigma\)를 어떻게 추정했는지가 극한분포를 바꾼다.

연습문제 7. 연습문제 4는 기대도수가 작을 때 범주를 병합하라고 했다. 병합의 대가가 무엇인지 모의실험으로 재어라.

풀이
import numpy as np
from scipy import stats

rng = np.random.default_rng(3030)
M, n = 20_000, 100
p0 = np.array([.70, .10, .08, .07, .05])     # H0
p1 = np.array([.60, .10, .08, .12, .10])     # 대립: 작은 범주들이 커짐

def run(p_true, merge):
    obs = rng.multinomial(n, p_true, size=M).astype(float)
    if merge is None:
        exp = n * p0
    else:
        obs = np.column_stack([obs[:, s].sum(1) for s in merge])
        exp = n * np.array([p0[s].sum() for s in merge])
    k = len(exp)
    stat = ((obs - exp)**2 / exp).sum(1)
    return np.mean(stat > stats.chi2.ppf(0.95, k - 1)), exp.min(), k

plans = [
    ("병합 없음", None),
    ("뒤 2개 병합", [np.array([0]), np.array([1]), np.array([2]), np.array([3, 4])]),
    ("뒤 3개 병합", [np.array([0]), np.array([1]), np.array([2, 3, 4])]),
]
print(f"{'설정':>12s} {'k':>3s} {'E_min':>7s} {'수준':>8s} {'검정력':>8s}")
for label, merge in plans:
    lvl, emin, k = run(p0, merge)
    pw, _, _ = run(p1, merge)
    print(f"{label:>12s} {k:3d} {emin:7.2f} {lvl:8.4f} {pw:8.4f}")
          설정   k   E_min       수준      검정력
       병합 없음   5    5.00   0.0469   0.7053
     뒤 2개 병합   4    8.00   0.0505   0.7029
     뒤 3개 병합   3   10.00   0.0491   0.6034

적게 병합하면 거의 공짜다. 뒤 2개만 합치면 \(E_{\min}\)이 5에서 8로 올라가는데 검정력은 0.705에서 0.703으로 사실상 그대로다.

많이 병합하면 크게 잃는다. 뒤 3개를 합치면 검정력이 0.603으로 10%포인트 떨어진다.

왜 그런가 — 비중심 모수를 계산해 보면 분명하다.

\[ \lambda=n\sum_i\frac{(p_{1i}-p_{0i})^2}{p_{0i}} \]
설정 \(\lambda\)
병합 없음 \(100(\tfrac{0.01}{0.7}+\tfrac{0.0025}{0.07}+\tfrac{0.0025}{0.05})=10.00\)
뒤 3개 병합 \(100(\tfrac{0.01}{0.7}+\tfrac{0.01}{0.20})=6.43\)

병합하면 서로 다른 범주의 이탈이 한 칸에 뭉쳐진다. 여기서는 이탈이 모두 같은 방향(증가)이라 일부만 남았지만, 방향이 반대인 이탈을 합치면 서로 상쇄되어 아예 사라진다.

# 이탈의 방향이 반대인 경우
p2 = np.array([.70, .10, .08, .12, .00])     # 4번 ↑, 5번 ↓
for label, merge in plans:
    pw, _, k = run(p2, merge)
    print(f"{label:>12s} (k={k})  검정력 {pw:.4f}")
       병합 없음 (k=5)  검정력 0.5988
     뒤 2개 병합 (k=4)  검정력 0.0471
     뒤 3개 병합 (k=3)  검정력 0.0470

검정력이 0.599에서 0.047로 무너진다. 0.047은 곧 유의수준이므로, 검정이 아무것도 탐지하지 못하는 상태다.

4번 범주가 \(0.07\to0.12\), 5번이 \(0.05\to0.00\)이라 둘을 합치면 \(0.12\to0.12\)로 순변화가 정확히 0이 된다. 두 범주를 합치는 순간 이탈이 통째로 사라진다.

이것이 병합의 가장 큰 위험이다. 기대도수를 키우려다 탐지하려던 신호 자체를 지워 버릴 수 있다.

병합의 원칙 넷.

  1. 최소한으로 병합한다. \(E_{\min}\ge5\)를 겨우 넘기는 정도면 충분하다.
  2. 과학적으로 인접한 범주를 합친다. "기타"로 뭉뚱그리지 않는다.
  3. 자료를 보고 병합 방식을 고르지 않는다. 어느 칸이 이탈했는지 본 뒤 합치면 수준이 무너진다.
  4. 병합 계획을 사전에 정한다. 예: "기대도수가 5 미만이면 인접한 상위 범주와 합친다"를 미리 써 둔다.

연습문제 8. 연습문제 3의 "모든 기대도수가 5 이상" 규칙이 실제로 얼마나 잘 맞는지 모의실험으로 검증하라.

풀이
import numpy as np
from scipy import stats

rng = np.random.default_rng(2020)
M = 40_000
cases = [
    (np.ones(5) / 5, 25), (np.ones(5) / 5, 10),
    (np.array([.90, .05, .04, .01]), 50),
    (np.array([.90, .05, .04, .01]), 100),
    (np.array([.90, .05, .04, .01]), 500),
    (np.array([.97, .01, .01, .01]), 100),
    (np.array([.97, .01, .01, .01]), 500),
    (np.array([.50, .30, .15, .04, .01]), 100),
]
print(f"{'p0':>32s} {'n':>5s} {'E_min':>7s} {'실제 수준':>10s}")
for p, n in cases:
    k, exp = len(p), n * p
    obs = rng.multinomial(n, p, size=M).astype(float)
    stat = ((obs - exp)**2 / exp).sum(1)
    lvl = np.mean(stat > stats.chi2.ppf(0.95, k - 1))
    print(f"{str(np.round(p, 3)):>32s} {n:5d} {exp.min():7.2f} {lvl:10.4f}")
                              p0     n   E_min      실제 수준
           [0.2 0.2 0.2 0.2 0.2]    25    5.00     0.0481
           [0.2 0.2 0.2 0.2 0.2]    10    2.00     0.0394
           [0.9  0.05 0.04 0.01]    50    0.50     0.0524
           [0.9  0.05 0.04 0.01]   100    1.00     0.0526
           [0.9  0.05 0.04 0.01]   500    5.00     0.0498
           [0.97 0.01 0.01 0.01]   100    1.00     0.0658
           [0.97 0.01 0.01 0.01]   500    5.00     0.0491
      [0.5  0.3  0.15 0.04 0.01]   100    1.00     0.0556

규칙이 대체로 잘 맞지만, 이유는 생각과 다르다.

1 — \(E_{\min}\ge5\)이면 안전하다. 세 경우 모두 0.048~0.050이다. 충분조건으로서는 훌륭하다.

2 — 그러나 필요조건은 아니다. \(E_{\min}=0.5\)인 경우(둘째 묶음의 \(n=50\))에도 수준이 0.0524다. 균등 5범주 \(n=10\)(\(E_{\min}=2\))은 0.0394로 오히려 보수적이다.

3 — 문제는 최솟값이 아니라 치우침이다. 가장 나쁜 경우는 \(p_0=(0.97,0.01,0.01,0.01)\), \(n=100\)의 0.0658(명목의 1.32배)이다. \(E_{\min}\)은 1로 다른 경우와 같지만, 기대도수의 불균형(97 대 1)이 훨씬 심하다.

왜 치우침이 문제인가. 카이제곱 근사는 각 칸의 \((O_i-E_i)/\sqrt{E_i}\)가 정규에 가깝다는 데 기댄다. \(E_i\)가 작으면 이 양이 이산적이고 오른쪽으로 치우쳐 정규와 멀어진다. 그런 칸이 여럿이면 오차가 누적된다.

더 정교한 지침들.

제안 내용
코크런(1954) \(E_i<1\)인 칸이 없고, \(E_i<5\)인 칸이 20% 이하
로스코·박스 \(k>2\)이면 \(E_i\ge2\)로 충분
보수적 모든 \(E_i\ge5\)

위 결과는 코크런의 제안과 잘 맞는다. \((0.97,0.01,0.01,0.01)\)·\(n=100\)은 \(E_i<5\)인 칸이 75%로 코크런 기준을 위반하고, 실제로 수준이 어긋났다.

가장 안전한 실무 지침.

  1. 의심스러우면 모의실험으로 확인한다. 위 코드 열 줄이면 된다.
  2. 정확검정을 쓴다. scipy.stats.chisquare에 대응하는 다항 정확검정이나 순열검정을 쓰면 근사가 필요 없다.
  3. \(p\)가 경계 근처면(0.03~0.08) 특히 조심한다. 근사 오차가 결론을 바꿀 수 있는 구간이다.

연습문제 9. 자유도가 클수록 같은 통계량 값의 \(p\)가 커진다. 그렇다면 범주를 잘게 나눌수록 검정력이 떨어지는가? 모의실험으로 확인하라.

풀이
import numpy as np
from scipy import stats

rng = np.random.default_rng(5050)
M, n = 5_000, 200

print(f"{'범주 k':>7s} {'df':>4s} {'E_min':>7s} {'수준':>8s} "
      f"{'검정력(평균 이동)':>17s} {'검정력(두꺼운 꼬리)':>19s}")
for K in [2, 4, 8, 16, 32]:
    qs = np.linspace(0, 1, K + 1)[1:-1]
    edges = np.r_[-np.inf, stats.norm.ppf(qs), np.inf]   # 등확률 구간
    exp = np.full(K, n / K)
    crit = stats.chi2.ppf(0.95, K - 1)
    out = []
    for gen in [lambda: rng.standard_normal(n),                 # H0
                lambda: rng.standard_normal(n) + 0.3,           # 위치 이동
                lambda: rng.standard_t(4, n) / np.sqrt(2.0)]:   # 분산 1 로 맞춘 t(4)
        hit = 0
        for _ in range(M):
            obs = np.histogram(gen(), bins=edges)[0].astype(float)
            hit += ((obs - exp)**2 / exp).sum() > crit
        out.append(hit / M)
    print(f"{K:7d} {K - 1:4d} {n / K:7.2f} {out[0]:8.4f} "
          f"{out[1]:17.4f} {out[2]:19.4f}")
   범주 k   df   E_min       수준        검정력(평균 이동)         검정력(두꺼운 꼬리)
      2    1  100.00   0.0574            0.9190              0.0626
      4    3   50.00   0.0510            0.9174              0.7114
      8    7   25.00   0.0526            0.8690              0.6354
     16   15   12.50   0.0470            0.7708              0.4952
     32   31    6.25   0.0538            0.6234              0.3698

답은 "그렇다, 그러나 조건이 있다"이다.

1 — 범주를 늘리면 검정력이 떨어진다. 두 대립가설 모두에서 \(k\)가 커질수록 검정력이 단조 감소한다. 평균 이동에서는 0.919 → 0.623, 두꺼운 꼬리에서는 0.711 → 0.370이다.

왜. 비중심 모수 \(\lambda\)는 범주를 쪼개도 크게 늘지 않는데, 임계값은 자유도와 함께 계속 커진다. 신호는 그대로인데 기준만 높아지는 셈이다.

2 — 그러나 너무 적으면 아무것도 못 본다. \(k=2\)일 때 두꺼운 꼬리에 대한 검정력이 0.0626으로 수준과 다를 바 없다. 중앙값을 기준으로 둘로 나누면 대칭인 분포의 꼬리 차이가 완전히 사라진다.

3 — 최적은 대립가설에 달려 있다.

대립가설 최적 \(k\)
평균 이동 2(또는 4)
꼬리 두께 4

요약하면 "이탈을 담아낼 만큼만, 그러나 그 이상은 말라"다. 관례적으로 \(k\)를 \(n^{2/5}\) 정도로 잡는 규칙(만의 규칙)이 있는데, \(n=200\)이면 \(k\approx8\)이다. 위 표에서 \(k=8\)은 어느 대립가설에서도 최선은 아니지만 둘 다에서 나쁘지 않다. 목표 대립가설을 모를 때의 타협으로 합리적이다.

더 근본적인 교훈. 카이제곱 적합도 검정은 모든 방향의 이탈을 조금씩 본다. 특정 방향(위치, 산포, 꼬리)을 알고 있다면 그 방향에 맞춘 검정이 훨씬 강력하다.

관심 더 나은 검정
위치 \(t\) 검정, 부호검정
정규성 전반 샤피로·윌크
꼬리 앤더슨·달링
분포 전체 콜모고로프·스미르노프

카이제곱은 범주형 자료에 쓰는 검정이지, 연속형 자료를 억지로 구간화해 쓰는 도구가 아니다.

연습문제 10. 자유도 계산의 점검 목록을 만들어라.

풀이

계산 절차.

자유도 = (자유로운 칸의 수) - (자료로 추정한 모수의 수)
    │
    ├─ 적합도 검정 (범주 k 개)
    │      자유로운 칸 = k - 1        ← 합이 n 으로 고정
    │      모수 r 개 추정 → df = k - 1 - r
    │      ※ 원자료에서 추정했으면 이 값이 정확하지 않다 (연습문제 6)
    │
    ├─ 독립성·동질성 (r × c)
    │      df = (r-1)(c-1)
    │      ※ 행·열 합이 모두 고정되므로
    │
    ├─ 맥니마 검정 (2×2 대응)
    │      df = 1                     ← 불일치 쌍만 본다
    │
    └─ 코크런의 Q (k 개 조건, 대응)
           df = k - 1

점검 목록.

  • [ ] 모수를 자료에서 추정했는가? 추정한 개수만큼 뺀다.
  • [ ] 추정을 원자료에서 했는가, 집단화 도수에서 했는가? 전자면 \(k-1-r\)가 근사일 뿐이다.
  • [ ] 범주를 병합했는가? 병합 후의 \(k\)로 계산한다.
  • [ ] 기대도수가 0인 칸이 있는가? 그 행·열이 통째로 비었다면 표의 크기를 줄여 다시 센다.
  • [ ] 통계량의 평균이 자유도와 맞는가? 모의실험으로 확인할 수 있는 가장 쉬운 점검이다(연습문제 5).

자주 하는 실수 다섯.

실수 결과
모수 추정 후 \(k-1\) 사용 보수적 — 모형을 통과시키기 쉬워짐
병합 전의 \(k\) 사용 보수적
\(r\times c\)에서 \(rc-1\) 사용 크게 보수적
빈 행·열을 세어 넣음 보수적
자료를 보고 범주를 나눔 과대기각

네 개가 모두 보수적인 방향이라는 점이 흥미롭다. 자유도를 과대 계산하는 실수가 훨씬 흔하기 때문이다. 그래서 "카이제곱 검정이 유의하지 않다"는 결과를 볼 때 자유도를 먼저 확인하는 습관이 유용하다.

마지막 하나만 반대 방향이고, 이것이 가장 위험하다. 어느 칸이 튀는지 본 뒤에 범주를 나누거나 합치면 수준이 크게 부풀어 오른다.

자유도를 확인하는 가장 확실한 방법. \(H_0\)가 참인 자료를 모의로 만들어 통계량의 평균을 재 본다. 카이제곱 분포의 평균은 자유도와 같으므로, 평균이 5.996이면 자유도가 6이다. 이론을 못 믿겠으면 세어 보면 된다.


정리하며

자유도는 제약의 개수를 세어 정한다.

검정 자유도
적합도 (범주 \(k\)) \(k-1\)
적합도 (모수 \(r\) 개 추정) \(k-1-r\)
독립성·동질성 (\(r\times c\)) \((r-1)(c-1)\)
  • 적합도의 \(-1\) 은 합의 제약이다. \(\sum O_j=n\) 이므로 마지막 칸은 나머지로 정해진다.
  • 모수를 추정할 때마다 하나씩 더 잃는다. 포아송 적합도에서 \(\lambda\) 를 자료에서 추정했다면 \(k-2\) 다. 이 조정을 빠뜨리면 \(p\) 값이 체계적으로 커져 기각을 못 하게 된다.
  • \((r-1)(c-1)\) 도 같은 논리다. 행 합과 열 합이 고정되므로 자유롭게 채울 수 있는 칸이 그만큼이다. \(2\times2\) 표의 자유도가 \(1\) 인 것이 그래서다.
  • 자유도가 클수록 분포가 오른쪽으로 이동하고 넓어진다. 평균이 \(\text{df}\), 분산이 \(2\,\text{df}\) 이므로, 같은 통계량 값이라도 자유도에 따라 \(p\) 값이 크게 달라진다.
  • 점근 결과다. 3장에서 재어 보았듯 처음 두 적률은 소표본에서도 맞지만 꼬리는 그렇지 않다.

다음 절 적합도 검정부터 구체적인 검정으로 들어간다.