회귀 모델의 샘플 수 추정

파라미터당 10개 규칙, 효과 크기, 다중공선성, 로지스틱 EPV — 경험칙과 검정력 분석의 통합

선형 회귀에서 “파라미터당 10개”라는 경험칙이 어디서 나오는지를 F-검정 자유도, 잔차 분산 안정성, 검정력 분석의 세 관점에서 유도한다. 효과 크기에 따른 비중심 분포 기반 샘플 수 계산, 다중공선성(VIF) 보정, 로지스틱 회귀 EPV 규칙, 경험칙과 검정력 분석의 관계, 그리고 실무 4단계 파이프라인을 다룬다.

Statistics
저자

Kwangmin Kim

공개

2026년 04월 12일

1 개요

가설 검정에서 표본 크기를 결정하는 일반론은 표본 크기 결정에서 다루었다. 그 포스트는 단일/이표본 정규 검정, ANOVA, 비율 검정처럼 닫힌 형태의 공식이 존재하는 경우를 중심으로 한다.

회귀 분석에서는 상황이 달라진다. 파라미터 수 \(p\) , 효과 크기, 다중공선성, 클래스 불균형 등 여러 요인이 곱셈으로 결합되기 때문에 단순한 공식 하나로 끝나지 않는다. 이 포스트는 다음 질문에 답한다:

  • “파라미터 1개당 10개”라는 규칙은 어디서 나오는가?
  • 효과 크기가 작으면 왜 더 많은 샘플이 필요한가?
  • 다중공선성이 있으면 필요 샘플 수는 어떻게 변하는가?
  • 로지스틱 회귀에서는 왜 선형 회귀보다 더 많은 샘플이 필요한가?
  • 경험칙과 검정력 분석 중 어느 것을 따라야 하는가?

2 파라미터당 10개 규칙의 유도

2.1 OLS 추정량의 분산 구조

회귀 모델 \(y = X\beta + \epsilon\) 에서 OLS 추정량의 공분산 행렬은 다음과 같다:

\[\text{Var}(\hat{\beta}) = \sigma^2 (X^\top X)^{-1}\]

파라미터가 \(p\) 개이고 샘플이 \(n\) 개이면, \(X\)\(n \times p\) 행렬이다. \((X^\top X)^{-1}\) 의 대각 원소 — 각 추정량의 분산 — 이 안정적으로 추정되려면 \(n \gg p\) 이어야 한다.

직관적으로 이해하면: \(n = p\) 이면 \((X^\top X)\) 가 정방 행렬이 되어 데이터의 모든 자유도를 파라미터 추정에 소모한다. 잔차를 추정할 여유가 없으므로 과적합이 발생한다. \(n < p\) 이면 아예 역행렬이 존재하지 않는다.


2.2 F-검정 관점: 왜 “10”인가

회귀 전체 유의성의 F-통계량은 다음과 같다:

\[F = \frac{R^2 / p}{(1 - R^2) / (n - p - 1)}\]

분자 자유도는 \(p\) , 분모 자유도는 \(n - p - 1\) 이다. 분모 자유도가 충분히 커야 F-분포의 꼬리가 안정되고 검정이 검정력을 갖는다.

경험적으로 분모 자유도 \(\geq 10p\) 가 되려면:

\[n - p - 1 \geq 10p \implies n \geq 11p + 1 \approx 10p\]

여기서 “파라미터당 10개” 기준이 등장한다. 이 수치는 엄밀한 수학적 상수가 아니라, 자유도 기반 안정성 조건이 수렴하는 실용적 근사값이다.


2.3 잔차 분산의 안정성

각 계수 \(\hat{\beta}_j\) 의 표준오차는 다음과 같다:

\[\text{SE}(\hat{\beta}_j) = \sigma \sqrt{[(X^\top X)^{-1}]_{jj}}\]

실제 추정에 쓰이는 잔차 분산 \(\hat{\sigma}^2 = \frac{RSS}{n - p - 1}\) 은 자유도 \(n - p - 1\) 의 카이제곱 분포를 따른다. 이 자유도가 작을수록 \(\hat{\sigma}^2\) 추정이 불안정해지고, 그 불확실성이 \(\text{SE}(\hat{\beta}_j)\) 로 직접 전파된다.

\(n = 10p\) 이면 \(n - p - 1 \approx 9p\) 자유도다. \(p = 10\) 이면 자유도 90 — 카이제곱 분포의 분산 \(\text{Var}(\chi^2_\nu) = 2\nu\) 에 의해 상대적 변동이 \(\sqrt{2/90} \approx 15\%\) 수준으로, 실무적으로 안정적이다.


2.4 검정력 관점의 교차 확인

t-검정으로 \(H_0: \beta_j = 0\) 을 검정할 때, 통계량은 자유도 \(n - p - 1\) 의 t-분포를 따른다. \(\alpha = 0.05\) , 검정력 \(1 - \beta = 0.80\) 을 원하면 최소 자유도가 요구되며, 이를 역산하면 대략 \(n \approx 10p\) 에 해당하는 조건이 나온다.

관점 근거 결론
F-검정 분모 자유도 \(n - p - 1 \geq 10p\) \(n \approx 10p\)
\(\hat{\sigma}^2\) 안정성 잔차 자유도가 충분해야 함 \(n \gg p\) 경험칙
검정력 \(\alpha = 0.05\) , power \(= 0.8\) 달성 \(n \approx 10p\) 수준

세 관점이 독립적으로 같은 영역에 수렴한다는 사실이 이 경험칙의 근거다.


3 효과 크기와 비중심 분포

“파라미터당 10개”는 추정의 안정성만 보장한다. 추정이 안정적이라는 것은 “계수 값이 제대로 나온다”는 뜻이지, “효과가 있다는 결론을 내릴 수 있다”는 뜻이 아니다. 실제로 존재하는 효과를 탐지할 수 있는가는 별개의 질문이며, 이는 효과 크기에 의존한다.

3.1 비중심 t-분포와 검정력

\(H_1\) 하에서 t-통계량은 비중심 t-분포를 따른다:

\[T = \frac{\hat{\beta}_j}{\text{SE}(\hat{\beta}_j)} \sim t_{n-p-1,\;\lambda}\]

비중심 모수:

\[\lambda = \frac{\beta_j}{\text{SE}(\hat{\beta}_j)} = \frac{\beta_j \sqrt{n \cdot \text{Var}(x_j)}}{\sigma}\]

\(n\) 이 클수록 \(\text{SE}\) 가 작아지고 \(\lambda\) 가 커지며, 비중심 분포가 귀무 분포에서 멀어져 검정력이 올라간다. 이 관계가 “샘플이 많을수록 작은 효과도 탐지 가능”의 수학적 실체다.

검정력은 비중심 분포의 임계값 바깥 면적이다:

\[1 - \beta = P(|T| > t_{\alpha/2,\;\nu} \mid \lambda)\]


3.2 Cohen의 \(f^2\) 와 필요 샘플 수

다중 회귀에서 효과 크기를 표준화한 지표가 Cohen의 \(f^2\) 다:

\[f^2 = \frac{R^2}{1 - R^2}\]

직관적으로 \(f^2\) 는 “설명된 분산 대 설명되지 않은 분산의 비율”이다. \(R^2 = 0.13\) 이면 \(f^2 = 0.15\) 로, 잔차 분산 1 단위당 모델이 0.15 단위의 분산을 설명한다는 뜻이다. 이 비율이 작을수록 신호가 잡음에 묻혀 있어 탐지가 어렵다.

F-검정의 비중심 모수가 \(\lambda_F = f^2 \cdot n\) 이므로, 목표 검정력을 달성하는 데 필요한 비중심 모수 \(\lambda_F^*\) 가 상수이면:

\[n^* = \frac{\lambda_F^*}{f^2}\]

\(f^2\)분모에 있으므로 효과 크기가 절반으로 줄면 필요 \(n\) 이 두 배가 된다. 이것이 효과 크기와 샘플 수의 역비례 관계다.

\(p = 10\) , \(\alpha = 0.05\) , 검정력 0.80 기준으로 구체적 수치를 보면:

Cohen의 \(f^2\) \(R^2\) 해석 필요 \(n\)
0.02 작은 효과 ( \(R^2 \approx 0.02\) ) 547
0.15 중간 효과 ( \(R^2 \approx 0.13\) ) 89
0.35 큰 효과 ( \(R^2 \approx 0.26\) ) 45

\(f^2 = 0.02\) 이면 \(n = 100\) 에서 실제 검정력은 약 0.30이다. 70%의 확률로 실제 존재하는 효과를 놓친다. “파라미터당 10개 = 100”으로 안심하면 작은 효과는 탐지하지 못한다.

from statsmodels.stats.power import FTestPower

def required_n(f2, alpha=0.05, power=0.80, num_params=10):
    """Cohen의 f²로부터 필요 샘플 수를 계산한다."""
    analysis = FTestPower()
    n = analysis.solve_power(
        effect_size=f2**0.5,
        alpha=alpha,
        power=power,
        df_num=num_params,
    )
    return int(n) + 1

print(required_n(f2=0.02))   # 547
print(required_n(f2=0.15))   # 89
print(required_n(f2=0.35))   # 45

4 다중공선성과 VIF 보정

4.1 VIF가 분산에 미치는 영향

다중공선성이 있으면 \((X^\top X)^{-1}\) 의 대각 원소가 팽창한다. 이것이 분산 팽창 인수(Variance Inflation Factor, VIF)로 정확히 표현된다:

\[\text{Var}(\hat{\beta}_j) = \frac{\sigma^2}{n \cdot \text{Var}(x_j)} \cdot \text{VIF}_j\]

\[\text{VIF}_j = \frac{1}{1 - R_j^2}\]

여기서 \(R_j^2\)\(x_j\) 를 나머지 예측변수들로 회귀했을 때의 결정계수다.

직관적으로: VIF는 유효 샘플 수를 줄이는 효과를 낸다. VIF = 5 이면 1000개의 샘플 중 실질적으로 200개만 해당 변수의 독립적 추정에 기여하는 셈이다.

\[n_{\text{effective}} = \frac{n}{\text{VIF}_j}\]


4.2 VIF가 검정력에 미치는 영향

비중심 t-모수를 VIF로 다시 쓰면:

\[\lambda_j = \frac{\beta_j \sqrt{n \cdot \text{Var}(x_j)}}{\sigma \cdot \sqrt{\text{VIF}_j}}\]

\(\text{VIF}_j\) 가 분모 루트 안에 있으므로, 같은 검정력을 유지하려면:

\[n_{\text{required}} = n_{\text{no-collinearity}} \times \text{VIF}_j\]

\(f^2 = 0.15\) , \(p = 10\) , 검정력 0.80 기준:

VIF 해석 필요 \(n\)
1 다중공선성 없음 89
2 약한 상관 ( \(R_j^2 = 0.50\) ) 178
5 중간 상관 ( \(R_j^2 = 0.80\) ) 445
10 강한 상관 ( \(R_j^2 = 0.90\) ) 890
25 심각한 상관 ( \(R_j^2 = 0.96\) ) 2,225

VIF = 10이면 \(n\) 의 90%가 공선성을 보완하는 데 소모되고, 10%만 실제 추정에 기여한다. 이것이 “같은 신호를 탐지하는 데 더 많은 관측이 필요해진다”의 정확한 의미다.


4.3 VIF 보정 공식

\[\boxed{n_{\text{required}} = n_{\text{base}} \times \text{VIF}_{\max}}\]

def required_n_with_vif(f2, vif_max, alpha=0.05, power=0.80, num_params=10):
    """VIF 보정을 포함한 필요 샘플 수를 계산한다."""
    from statsmodels.stats.power import FTestPower
    analysis = FTestPower()
    n_base = analysis.solve_power(
        effect_size=f2**0.5,
        alpha=alpha,
        power=power,
        df_num=num_params,
    )
    n_adjusted = n_base * vif_max
    return int(n_adjusted) + 1

print(required_n_with_vif(f2=0.15, vif_max=1))   # 89
print(required_n_with_vif(f2=0.15, vif_max=5))   # 445
print(required_n_with_vif(f2=0.15, vif_max=10))  # 890

이 공식은 최악의 경우(가장 큰 VIF를 가진 변수)를 기준으로 하는 보수적 추정이다. 변수마다 VIF가 다를 때는 시뮬레이션이 더 정확하다.


4.4 시뮬레이션 기반 검정력 확인

import numpy as np
from scipy import stats

def simulate_power(n, p, beta, sigma, corr_matrix, alpha=0.05, n_sim=1000):
    """상관 구조가 있는 예측변수에서 F-검정의 시뮬레이션 검정력을 계산한다."""
    reject_count = 0
    for _ in range(n_sim):
        X = np.random.multivariate_normal(
            mean=np.zeros(p),
            cov=corr_matrix,
            size=n
        )
        y = X @ beta + np.random.normal(0, sigma, n)
        XtX_inv = np.linalg.inv(X.T @ X)
        beta_hat = XtX_inv @ X.T @ y
        residuals = y - X @ beta_hat
        RSS_full = residuals @ residuals
        y_mean = y.mean()
        SST = ((y - y_mean)**2).sum()
        F = ((SST - RSS_full) / p) / (RSS_full / (n - p - 1))
        f_crit = stats.f.ppf(1 - alpha, p, n - p - 1)
        if F > f_crit:
            reject_count += 1
    return reject_count / n_sim

# VIF ~= 5 구조 (r = 0.8 상관관계)
p = 10
r = 0.8
corr = np.full((p, p), r)
np.fill_diagonal(corr, 1.0)

beta = np.array([0.3] * p)
sigma = 1.0

power_89  = simulate_power(n=89,  p=p, beta=beta, sigma=sigma, corr_matrix=corr)
power_445 = simulate_power(n=445, p=p, beta=beta, sigma=sigma, corr_matrix=corr)

print(f"n=89  검정력: {power_89:.2f}")   # ~0.30
print(f"n=445 검정력: {power_445:.2f}")  # ~0.80

4.5 다중공선성 심각도별 전략

VIF 보정으로 샘플을 늘리는 것이 항상 최선은 아니다. VIF가 일정 수준을 넘으면 모델 변경이 샘플 증가보다 효율적이다.

VIF 범위 해석 권장 전략
1 – 2 무시 가능 기본 \(n\) 사용
2 – 5 주의 VIF 보정 \(n\) 계산 후 수집 가능성 확인
5 – 10 심각 Ridge 회귀 전환 검토
10 이상 매우 심각 PCA 변환 후 주성분 회귀, 또는 변수 제거

왜 VIF가 커지면 전략이 바뀌는가? VIF = 2 – 5 범위에서는 샘플을 2 – 5배 늘리는 것이 현실적으로 가능하다. 그러나 VIF = 10이면 샘플을 10배 늘려야 하므로, 데이터 수집 비용이 급격히 증가한다. 이 시점에서는 Ridge의 \(\ell_2\) 패널티로 \((X^\top X + \lambda I)^{-1}\) 을 안정화하는 편이 현실적이다. Ridge는 대각에 \(\lambda\) 를 더해 조건수를 낮추므로, 공선성에 의한 분산 팽창을 직접 억제한다. VIF가 10을 넘으면 변수 자체에 중복 정보가 과다하다는 신호이므로, PCA로 독립 성분을 추출하거나 변수를 제거하는 것이 근본적 해결이다.


5 로지스틱 회귀: EPV 규칙과 두 패널티의 결합

5.1 Events Per Variable (EPV)

로지스틱 회귀에서는 소수 클래스의 사건 수가 추정 안정성을 결정한다. 선형 회귀와 달리 로지스틱 회귀는 이산적 결과(0/1)를 다루기 때문에, 각 파라미터가 안정적으로 추정되려면 소수 클래스에 속하는 관측치(event)가 충분해야 한다. “Events Per Variable”이라는 이름은 바로 이것을 가리킨다 — 파라미터 하나당 소수 클래스의 사건이 몇 개 있는가.

Peduzzi et al. (1996)의 시뮬레이션에 따르면, EPV < 10이면 MLE가 수렴하지 않거나, 계수 추정값의 편향이 커지거나, complete separation(완전 분리 — 예측변수의 특정 조합이 결과를 완벽하게 구분하여 MLE가 무한대로 발산하는 현상)이 발생한다.

기본 EPV 규칙:

\[n_{\text{EPV}} = \frac{10 \cdot p}{\text{소수 클래스 비율}}\]

\(p = 10\) , 1:1 비율이면 \(n_{\text{EPV}} = 200\) 이다.


5.2 두 패널티의 곱셈 결합

로지스틱 회귀에서 다중공선성이 존재하면 두 개의 독립적 패널티가 동시에 작용한다:

\[n_{\text{required}} = \underbrace{\frac{10 \cdot p}{\text{소수 클래스 비율}}}_{\text{EPV 패널티}} \times \underbrace{\text{VIF}_{\max}}_{\text{다중공선성 패널티}}\]

왜 더하기가 아니라 곱하기인가? 비유로 설명하면: EPV 패널티는 “신호의 총 에너지를 줄이는” 효과이고, VIF 패널티는 “특정 채널의 잡음을 키우는” 효과다. 총 에너지가 반으로 줄고(\(\times 0.5\)), 동시에 특정 채널의 잡음이 5배 커지면(\(\times 5\)), 그 채널의 신호 대 잡음비는 \(0.5 \times \frac{1}{5} = 0.1\) 로 떨어진다. 두 효과가 서로 다른 경로로 작용하므로 곱셈으로 결합된다. 이것을 Fisher 정보행렬의 구조에서 확인할 수 있다:

\[\text{Var}(\hat{\beta}) \approx (X^\top W X)^{-1}\]

문제 영향 경로 결과
클래스 불균형 / 로지스틱 구조 \(W = \text{diag}(\pi_i(1 - \pi_i))\) 값이 작아짐 정보행렬 전체가 스케일다운
다중공선성 \(X^\top X\) 가 ill-conditioned 특정 계수의 분산만 선택적으로 팽창

\(W\) 는 모든 계수에 균등하게 작용하고, VIF는 공선성에 연루된 계수에 선택적으로 작용한다. 서로 다른 메커니즘이므로 곱셈으로 결합된다.


5.3 \(p = 10\) , 1:1 비율, VIF별 수치

VIF 해석 필요 \(n\) 파라미터당
1 다중공선성 없음 200 20
2 약한 상관 400 40
5 중간 상관 1,000 100
10 강한 상관 2,000 200
25 심각한 상관 5,000 500

VIF = 10이면 파라미터당 200개다. 선형 회귀에서 다중공선성 없는 경우(파라미터당 10개) 대비 20배이며, 이 수준이면 샘플 증가보다 Ridge 로지스틱 회귀나 변수 제거를 먼저 검토하는 것이 현실적이다.


5.4 로지스틱 시뮬레이션

import numpy as np
from scipy import stats

def logistic_simulate_power(n, p, beta, corr_matrix, alpha=0.05, n_sim=1000):
    """로지스틱 회귀에서 Wald 카이제곱 검정의 시뮬레이션 검정력을 계산한다."""
    from sklearn.linear_model import LogisticRegression

    reject_count = 0
    for _ in range(n_sim):
        X = np.random.multivariate_normal(np.zeros(p), corr_matrix, size=n)
        log_odds = X @ beta
        prob = 1 / (1 + np.exp(-log_odds))
        y = np.random.binomial(1, prob)

        model = LogisticRegression(fit_intercept=False, max_iter=1000, C=1e6)
        model.fit(X, y)
        beta_hat = model.coef_[0]

        pi_hat = model.predict_proba(X)[:, 1]
        W = np.diag(pi_hat * (1 - pi_hat))
        info_matrix = X.T @ W @ X

        try:
            chi2_stat = beta_hat @ info_matrix @ beta_hat
            chi2_crit = stats.chi2.ppf(1 - alpha, df=p)
            if chi2_stat > chi2_crit:
                reject_count += 1
        except np.linalg.LinAlgError:
            pass

    return reject_count / n_sim

p = 10
beta = np.array([0.3] * p)

# 다중공선성 없음
corr_none = np.eye(p)

# VIF ~= 5 (r = 0.8)
r = 0.8
corr_high = np.full((p, p), r)
np.fill_diagonal(corr_high, 1.0)

power_200_none  = logistic_simulate_power(n=200,  p=p, beta=beta, corr_matrix=corr_none)
power_200_high  = logistic_simulate_power(n=200,  p=p, beta=beta, corr_matrix=corr_high)
power_1000_high = logistic_simulate_power(n=1000, p=p, beta=beta, corr_matrix=corr_high)

print(f"n=200,  VIF=1: {power_200_none:.2f}")    # ~0.80
print(f"n=200,  VIF=5: {power_200_high:.2f}")    # ~0.30
print(f"n=1000, VIF=5: {power_1000_high:.2f}")   # ~0.80

5.5 세 요인의 통합 공식

\[\boxed{n_{\text{required}} = \frac{10 \cdot p}{\text{소수 클래스 비율}} \times \text{VIF}_{\max}}\]

요인 역할 \(p = 10\) 기준 예시
\(p\) 추정 파라미터 수 \(\times 10\)
소수 클래스 비율 분모 — 비율이 낮을수록 \(n\) 증가 1:1이면 \(\div 0.5 = \times 2\)
\(\text{VIF}_{\max}\) 다중공선성 패널티 VIF = 5이면 \(\times 5\)

세 요인이 모두 곱셈으로 작용하므로, VIF = 5 + 1:9 클래스 불균형이면:

\[n = \frac{10 \times 10}{0.1} \times 5 = 5{,}000\]

파라미터당 500개다.


6 경험칙 vs 검정력 분석: 두 기준의 관계

지금까지 경험칙(파라미터당 10개, EPV, VIF 보정)과 검정력 분석(비중심 분포 기반)을 각각 다루었다. 실무에서는 이 두 기준이 서로 다른 \(n\) 을 제시하는 경우가 흔하다. 어느 쪽을 따라야 하는가? 이를 이해하려면 두 기준이 애초에 다른 질문에 답한다는 점을 인식해야 한다.

6.1 목적 자체가 다르다

경험칙 (EPV, \(p \times 10\) , VIF 보정) 검정력 기반 샘플 수 계산
목적 추정의 안정성 보장 특정 효과 탐지 확률 보장
질문 “계수를 신뢰할 수 있게 추정할 수 있는가?” “존재하는 효과를 탐지할 확률이 충분한가?”
효과 크기 고려 안 함 명시적으로 지정
근거 점근 이론 + 시뮬레이션 경험칙 비중심 분포 이론
출력 최소 안정성 조건 목표 검정력을 보장하는 \(n\)

6.2 경험칙이 보장하는 것

EPV \(\geq 10\) , \(n \geq 10p\) 류의 규칙은 추정 가능성(estimability)을 보장한다. 이 조건 미만에서 발생하는 문제:

  • MLE가 수렴하지 않거나 complete separation 발생
  • 계수 추정값의 편향이 커짐 (Peduzzi et al., 1996)
  • 신뢰구간이 너무 넓어 실용적으로 무의미
  • Wald 검정의 점근 정규 근사가 성립하지 않음

경험칙은 “이 \(n\) 이하면 통계 결과 자체를 믿을 수 없다”는 최소 조건이다. 비유하면 자동차의 최소 연료량과 같다 — 연료가 부족하면 출발 자체가 불가능하지만, 연료가 충분하다고 해서 목적지에 도착할 수 있는 것은 아니다.


6.3 검정력 분석이 보장하는 것

\[1 - \beta = P(\text{reject } H_0 \mid \beta = \delta)\]

추정이 완벽하게 안정적이더라도 효과가 작으면 검정력이 낮아 탐지에 실패한다. 이것은 경험칙과 독립적인 질문이다.


6.4 같은 \(n\) 에서 두 기준이 엇갈리는 경우

Case 1: 경험칙 통과, 검정력 부족

\(p = 10\) , 1:1 비율, 다중공선성 없음이면 EPV 기준 \(n = 200\) 으로 충분하다. 그러나 효과 크기가 작으면 ( \(f^2 = 0.02\) ):

\[n_{\text{power}} = \frac{\lambda^*}{f^2} \approx \frac{12.4}{0.02} \approx 620\]

\(n = 200\) 에서 실제 검정력 \(\approx 0.30\) 이다. 추정은 안정적이지만 효과를 탐지하지 못한다.

Case 2: 검정력 충족, 경험칙 미달

효과가 매우 크면 ( \(f^2 = 1.0\) ):

\[n_{\text{power}} \approx 25\]

검정력 분석은 \(n = 25\) 로 충분하다고 하지만, EPV 기준은 \(n \geq 200\) 을 요구한다. \(n = 25\) 에서 MLE 편향과 수렴 문제가 발생할 수 있다.


6.5 두 조건의 관계

\[n_{\text{final}} = \max(n_{\text{경험칙}},\ n_{\text{power}})\]

경험칙은 필요조건 (이 이하면 결과를 믿을 수 없음), 검정력 분석은 충분조건 (이 이상이면 목표 검정력 달성)이다. 최종 샘플 수는 두 조건 중 더 큰 값을 취한다.

상황 구속 기준 이유
효과 크기 크다 ( \(f^2 \geq 0.35\) ) 경험칙 검정력은 소수 샘플로도 충족, 추정 안정성이 병목
효과 크기 작다 ( \(f^2 \leq 0.05\) ) 검정력 추정은 안정적이어도 신호가 약해 탐지 실패
다중공선성 심각 (VIF \(\geq 5\) ) 경험칙 VIF 보정이 검정력 요건보다 빠르게 증가
클래스 불균형 심각 (1:19 이상) 경험칙 EPV 패널티가 지배적
def final_n(p, f2=None, minority_ratio=0.5, vif_max=1.0,
            model='logistic', alpha=0.05, power=0.80):
    """경험칙과 검정력 분석 중 더 큰 값을 반환한다."""
    if model == 'logistic':
        n_heuristic = (10 * p / minority_ratio) * vif_max
    else:
        n_heuristic = 10 * p * vif_max

    if f2 is not None:
        from statsmodels.stats.power import FTestPower
        n_power = FTestPower().solve_power(
            effect_size=f2**0.5, alpha=alpha,
            power=power, df_num=p
        ) * vif_max
    else:
        n_power = 0

    n_final = max(n_heuristic, n_power)
    binding = '경험칙' if n_heuristic >= n_power else '검정력'
    return int(n_final) + 1, binding

# 효과 크기 큰 경우 -- 경험칙이 구속
print(final_n(p=10, f2=0.35, model='logistic'))
# (200, '경험칙')

# 효과 크기 작은 경우 -- 검정력이 구속
print(final_n(p=10, f2=0.02, model='logistic'))
# (621, '검정력')

7 실무 4단계 파이프라인

7.1 Step 1: 효과 크기 추정

가장 어렵고 가장 중요한 단계다. 효과 크기의 추정 방법을 신뢰도 순으로 나열하면:

방법 신뢰도 설명
자체 Pilot Study 높음 동일 모집단, 동일 측정
Meta-analysis 높음 여러 연구의 효과 크기 풀링
유사 선행 연구 중간 모집단/측정 차이로 편향 가능
MDES (Minimum Detectable Effect Size) 중간 의미 있는 최소 효과를 역산
Cohen 관행값 낮음 최후 수단

MDES 접근은 “이 효과가 실무적으로 의미 있으려면 최소 얼마여야 하는가?”를 먼저 정의하고, 그 값을 효과 크기로 사용한다. Cohen 관행값(small/medium/large)은 분야와 무관한 일반적 기준이라 특정 연구의 맥락을 반영하지 못한다. 반면 MDES는 “이 크기 이하의 효과는 발견해도 실무적 의미가 없다”는 도메인 지식에 기반하므로, 연구 설계에 더 적합한 근거를 제공한다. 예: 로지스틱 회귀에서 OR \(= 1.5\) 이상이면 임상적으로 유의미하다고 판단하면, \(\beta_{\min} = \log(1.5)\) 를 효과 크기로 설정한다.

7.2 Step 2: 공식 검정력 분석

선형 회귀:

from statsmodels.stats.power import FTestPower

n = FTestPower().solve_power(
    effect_size=f2**0.5,
    alpha=0.05,
    power=0.80,
    df_num=p,
)

로지스틱 회귀 — 닫힌 형태 공식이 없으므로 시뮬레이션을 권장한다:

import numpy as np
from sklearn.linear_model import LogisticRegression
from scipy import stats

def logistic_power_by_simulation(n, p, beta_true, prev=0.5,
                                  alpha=0.05, n_sim=2000):
    """로지스틱 회귀 검정력을 시뮬레이션으로 추정한다."""
    reject = 0
    intercept = np.log(prev / (1 - prev))

    for _ in range(n_sim):
        X = np.random.randn(n, p)
        log_odds = intercept + X @ np.array([beta_true] * p)
        prob = 1 / (1 + np.exp(-log_odds))
        y = np.random.binomial(1, prob)

        if y.sum() < 5 or (1 - y).sum() < 5:
            continue

        model = LogisticRegression(max_iter=1000, C=1e6)
        model.fit(X, y)
        beta_hat = model.coef_[0]
        pi_hat = model.predict_proba(X)[:, 1]
        W = np.diag(pi_hat * (1 - pi_hat))
        info = X.T @ W @ X

        try:
            chi2 = beta_hat @ info @ beta_hat
            if chi2 > stats.chi2.ppf(1 - alpha, df=p):
                reject += 1
        except np.linalg.LinAlgError:
            pass

    return reject / n_sim

# n을 바꿔가며 검정력 0.80 달성 지점 탐색
for n in [100, 200, 300, 400, 500]:
    pw = logistic_power_by_simulation(n=n, p=10, beta_true=0.3)
    print(f"n={n:4d} -> power={pw:.2f}")

7.3 Step 3: 경험칙 교차 확인

Step 2의 결과와 경험칙을 비교하여 \(\max\) 를 취한다.

7.4 Step 4: 민감도 분석 + 여유분

효과 크기 추정이 틀렸을 때를 대비해 비관적 시나리오로 재계산한다:

f2_estimated = 0.15
for ratio in [0.50, 0.75, 1.00]:
    f2_scenario = f2_estimated * ratio
    n, binding = final_n(p=10, f2=f2_scenario, model='logistic')
    print(f"효과 크기 {ratio*100:.0f}%: f2={f2_scenario:.3f} -> n={n} ({binding})")

여유분 가이드라인:

상황 여유분
탈락/결측 예상 +10 – 20%
측정 오류 가능성 높음 +15 – 25%
규제 제출용 (FDA/EMA) 검정력 0.90 이상 사용
탐색적 연구 검정력 0.80으로 충분

8 도메인별 실무 관행

분야 주된 방법 특이사항
임상시험 공식 검정력 분석 필수 FDA/EMA 규정상 프로토콜에 명시
역학 연구 EPV 기준 + 검정력 교차 확인 로지스틱 회귀가 주류
사회과학 G*Power Cohen 관행값 남용 주의
산업 ML 시뮬레이션 대용량 데이터로 커버하는 경우가 많다
A/B 테스트 MDE 역산 + 검정력 비즈니스 임팩트 기반 MDES 정의

9 요약

효과 크기는 MDES 또는 Pilot Study로 추정하고, 검정력 분석과 경험칙의 최댓값을 취한 뒤, 비관적 시나리오로 민감도 분석을 거쳐 10 – 20% 여유분을 더한다.

\[n_{\text{final}} = \max\!\left(\underbrace{\frac{10p}{\text{minority ratio}} \times \text{VIF}}_{\text{경험칙}},\quad \underbrace{\frac{\lambda^*}{f^2} \times \text{VIF}}_{\text{검정력}}\right) \times (1 + \text{여유분})\]


10 관련 주제

선행 지식

관련 개념

Subscribe

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