측정 오차와 랜덤 변동

Measurement Bias & Random Variability — 세 번째 편향과 유한 표본의 불확실성

측정 오차(measurement error)의 구조(독립/비독립, 차등/비차등), 교란 변수 오측정의 영향, 비인과적 화살표 문제, 식별(identification) vs. 추정(estimation), 초모집단 개념, 조건성 원리, 차원의 저주를 다룬다. Hernán & Robins (2020) Ch.9-10을 기반으로 작성하였다.

Experimentation
Causal Inference
저자

Kwangmin Kim

공개

2026년 03월 20일

1 정의

정의: 측정 편향 (Measurement Bias)

측정 편향(measurement bias, information bias)은 연구 데이터를 측정하는 과정에서 처리–결과 간 연관이 약화 또는 강화되는 체계적 편향이다.

  • 진짜 처리 \(A\)와 측정된 처리 \(A^*\), 진짜 결과 \(Y\)와 측정된 결과 \(Y^*\)의 괴리

  • 교란·선택 편향과 달리, 무작위 실험에서도 그리고 교란·선택 없이도 발생 가능

  • 이산 변수의 측정 오차를 오분류(misclassification)라 부른다

  • 역학: Measurement Bias, Information Bias, Misclassification

  • IT: Measurement Error, Label Noise, Data Quality Issue

정의: 랜덤 변동 (Random Variability)

유한한 표본 크기로 인해 추정값(estimate)이 모수(estimand)와 달라지는 비체계적 오차이다.

  • 체계적 편향(교란, 선택, 측정)과 질적으로 다름

  • 표본이 커질수록 감소하나, 체계적 편향은 표본 크기와 무관

  • 신뢰구간(confidence interval)으로 불확실성을 정량화

  • 역학: Random Error, Sampling Variability

  • IT: Statistical Noise, Sampling Uncertainty

역학 (Epidemiology) IT/비즈니스 비고
Measurement Error Data Quality Error 진짜 값과 측정 값의 괴리
Misclassification Label Noise 이산 변수의 측정 오차
Nondifferential Error Random Noise 처리/결과와 무관한 오차
Differential Error Systematic Mismeasurement 처리/결과에 따라 달라지는 오차
Identification Identification 무한 표본에서 인과 효과 계산 가능 여부
Estimation Estimation 유한 표본에서 추정값 도출
Confidence Interval Confidence Interval 랜덤 변동의 정량화

2 개념 및 원리

2.1 Part 1: 측정 오차 (Ch.9)

2.1.1 측정 오차의 분류

측정 오차는 두 가지 축으로 분류된다 (Hernán & Robins, 2020, Section 9.2):

비차등 (Nondifferential) 차등 (Differential)
독립 Figure 9.2: 가장 단순한 경우 Figure 9.4-9.5: 결과가 처리 측정에 영향 (또는 그 반대)
비독립 Figure 9.3: 공통 recall 능력 Figure 9.6-9.7: 가장 복잡한 경우

비차등 측정 오차 (Nondifferential):

  • 처리의 측정 오차 \(U_A\)가 진짜 결과 \(Y\)와 독립
  • 결과의 측정 오차 \(U_Y\)가 진짜 처리 \(A\)와 독립
  • 이분형 변수에서는 일반적으로 효과를 귀무 방향으로 감쇠(attenuation)

차등 측정 오차 (Differential):

  • 예: 회상 편향(recall bias) — 결과(질병)가 있으면 처리(노출) 기억이 달라짐
    • 치매(\(Y\)) → 약물 복용(\(A\)) 기억에 영향 → \(Y \rightarrow U_A\)
  • 예: 감시 편향(surveillance bias) — 처리를 받으면 결과 측정이 더 정밀
    • 약물 사용(\(A\)) → 의사가 더 자주 검사 → \(A \rightarrow U_Y\)
  • 차등 오차는 효과를 어느 방향으로든 편향시킬 수 있다

2.1.2 오측정된 교란 변수

Figure 9.8: \(A \leftarrow L \rightarrow Y\)에서 \(L\) 대신 \(L^*\)만 관찰 가능할 때

  • 진짜 뒷문 경로 \(A \leftarrow L \rightarrow Y\)\(L^*\)일반적으로 차단 불가
  • \(L^*\)로 보정하면 잔류 교란(residual confounding) 발생
  • 이를 “비측정 교란”으로 볼 수도 있고 “측정 편향”으로 볼 수도 있음
예외: 오측정이 문제 없는 경우

Figure 9.11: \(L^*\)\(L\)\(A\) 사이를 완전히 매개하는 경우 (즉, 의사결정자가 \(L\)이 아닌 \(L^*\)에 기반하여 처리를 결정)

\[L \rightarrow L^* \rightarrow A, \quad L \rightarrow Y\]

\(L^*\)로 보정해도 뒷문 경로가 차단된다. 핵심: 의사결정자가 가진 정보만큼의 데이터가 있으면 교란 보정이 가능하다.

2.1.3 비인과적 DAG의 문제 (Section 9.5)

많은 연구자가 그리는 DAG에는 비인과적 화살표가 포함된다:

  • 예: 비만 \(L\) → 사망 \(Y\)에서 \(L\)은 BMI > 30으로 정의
  • BMI는 체중/신장²이며, 체중과 신장은 \(Y\)의 실제 원인
  • \(L\)은 진짜 원인이 아니라 측정 지표 → DAG의 화살표는 비인과적

이런 경우 d-분리 규칙의 적용이 정확하지 않을 수 있다.

2.2 Part 2: 랜덤 변동 (Ch.10)

2.2.1 식별 vs. 추정

개념 정의 관심사
식별 (Identification) 무한 표본에서 인과 효과 계산 가능? 교란, 선택, 측정 편향
추정 (Estimation) 유한 표본에서 얼마나 정확한 값을 얻을 수 있나? 랜덤 변동, 표본 크기

Ch.1-9는 식별 문제, Ch.10부터는 추정 문제를 다룬다.

2.2.2 초모집단 (Super-population)

  • 표본 20명은 무한한 초모집단에서 무작위 추출된 것으로 간주
  • 추정량(estimand) \(\Pr[Y=1 \mid A=a]\): 초모집단의 모수
  • 추정자(estimator) \(\widehat{\Pr}[Y=1 \mid A=a] = 7/13\): 표본 통계량
  • 일치 추정자(consistent estimator): 표본 크기 → ∞ 일 때 추정량에 수렴

2.2.3 신뢰구간

\[ \text{95\% Wald CI}: \quad \hat{p} \pm 1.96 \times \sqrt{\frac{\hat{p}(1-\hat{p})}{n}} \]

신뢰구간의 올바른 해석
  • 올바름: “동일 연구를 반복하면 95%의 경우 구간이 모수를 포함한다”
  • 틀림: “이 구간에 모수가 있을 확률이 95%이다”
  • 신뢰구간은 랜덤 변동만 반영하며, 체계적 편향은 포함하지 않는다

2.2.4 조건성 원리 (Conditionality Principle)

Table 10.1-10.2 예시 (Section 10.4):

  • 240명 RCT에서 미보정 위험차 = -0.15 (처리 효과 있음)
  • 그런데 흡연 \(L\)이 처리군에 불균형하게 배분됨 (무작위 배정의 나쁜 운)
  • \(L\)로 보정하면 위험차 = 0 (효과 없음)

조건성 원리: 보조 통계량(ancillary statistic)에 조건화하여 추론해야 한다.

  • \(L\)\(A\)의 결합 분포는 보조 통계량 → 이에 조건화
  • 즉, 항상 보정된 추정량을 사용해야 함 (보정이 효율성을 높일 때)
  • 비보정 추정량은 보조 통계량에 조건부로 편향됨

2.2.5 차원의 저주

  • 교란 변수가 많아지면 층화 셀이 기하급수적으로 증가
  • 각 셀의 표본이 줄어 추정 정밀도 하락
  • 해결: 모형 기반 접근 (Ch.11 이후) — 회귀, 성향 점수 등으로 차원 축소

3 직관적 설명

3.1 “깨진 온도계” 비유

  1. 방 온도(\(A\))가 식물 성장(\(Y\))에 미치는 영향을 연구
  2. 온도계가 정확하지 않다: 측정 온도 \(A^* = A + \text{오차}\)
  3. 오차가 비차등적 (식물 성장과 무관): 효과가 약화되어 보임
  4. 오차가 차등적 (식물 상태에 따라 온도계 위치 변경): 어느 방향으로든 편향 가능

3.2 IT 비유: “로그 데이터의 측정 오차”

  1. 클릭 이벤트 측정: 일부 클릭이 서버 로그에 누락 (\(A^*\)\(A\))
  2. 전환 측정: 쿠키 만료로 일부 전환 미귀속 (\(Y^*\)\(Y\))
  3. 비차등 오차: 누락이 처리/대조군에 무관 → 효과 과소 추정
  4. 차등 오차: 처리군 페이지가 느려서 이벤트 손실 더 많음 → 방향 불확실

3.3 “동전 던지기의 운” 비유 (랜덤 변동)

  1. 공정한 동전을 4번 던져 모두 앞면 → “이 동전은 편향되었다”?
  2. 아니다, 표본이 너무 작아서 우연히 발생
  3. 10,000번 던지면 앞면 비율 ≈ 50%에 수렴
  4. 인과 추론도 마찬가지: 작은 표본의 RCT에서 불균형은 랜덤 변동일 수 있다

4 왜 필요한가

4.1 세 가지 편향의 통합적 이해

Ch.7-9는 인과 추론의 세 가지 체계적 편향을 완성한다:

편향 원인 무작위 실험에서 표본 크기와 관계
교란 (Ch.7) 공통 원인 제거됨 무관
선택 편향 (Ch.8) 공통 결과 조건화 발생 가능 무관
측정 편향 (Ch.9) 부정확한 측정 발생 가능 무관
랜덤 변동 (Ch.10) 유한 표본 발생 가능 표본↑ 시 감소
실무 상황 위험 대응
A/B 테스트의 짧은 실험 기간 랜덤 변동 → 거짓 양성/음성 검정력 분석, 최소 표본 크기
설문 기반 데이터 회상 편향 → 차등 측정 오차 객관적 측정 도구, 전향적 설계
로그 데이터 품질 이벤트 누락 → 비차등 측정 오차 데이터 검증 파이프라인
다수 교란 변수 보정 차원의 저주 → 추정 불안정 모형 기반 접근, 성향 점수
대규모 관찰 연구 표본 크지만 체계적 편향 잔존 CI가 좁아도 편향 존재 가능 → 민감도 분석

5 응용 분야

분야 측정 오차의 형태 보정 접근
역학/식이 연구 자가 보고 식이 → 비차등 오차 바이오마커 보정, 캘리브레이션
테크/이벤트 로깅 이벤트 누락, 중복 기록 로그 검증, AA 테스트
의료 기록 진단 코드 오분류 차트 리뷰 검증 표본
GWAS SNP genotyping 오류 품질 관리 (MAF, HWE 필터)
경제학/설문 응답 편향, 사회적 바람직성 간접 질문, 리스트 실험
NLP/레이블링 어노테이터 간 불일치 다수 어노테이터, 확률적 레이블

6 예시

6.1 수치 예시: 비차등 측정 오차의 감쇠 효과

진짜 효과는 \(\text{RR} = 2.0\)이지만 처리의 10% 오분류가 있을 때:

\(A=1\) (진짜) \(A=0\) (진짜)
\(A^*=1\) (측정) 진양성 90% 위양성 10%
\(A^*=0\) (측정) 위음성 10% 진음성 90%
\(\Pr[Y=1]\) 0.20 0.10
  • 진짜 RR = 0.20 / 0.10 = 2.0
  • 측정된 RR: \(A^*=1\)의 위험 = \(0.9 \times 0.20 + 0.1 \times 0.10 = 0.19\)
    • \(A^*=0\)의 위험 = \(0.1 \times 0.20 + 0.9 \times 0.10 = 0.11\)
    • RR* = 0.19 / 0.11 = 1.73 (귀무 방향으로 감쇠)

7 코드 예시

7.1 측정 오차의 감쇠 효과 시뮬레이션

import numpy as np
import pandas as pd

np.random.seed(42)
n = 100_000

# --- 진짜 효과: A → Y, RR ≈ 2.0 ---
A = np.random.binomial(1, 0.5, n)
Y = np.random.binomial(1, np.where(A == 1, 0.20, 0.10), n)

# --- 비차등 오분류 (10% 확률로 A 반전) ---
misclass_rate = 0.10
flip = np.random.binomial(1, misclass_rate, n)
A_star = np.where(flip, 1 - A, A)

df = pd.DataFrame({"A": A, "A_star": A_star, "Y": Y})

# 진짜 RR
true_rr = df.loc[df.A == 1, "Y"].mean() / df.loc[df.A == 0, "Y"].mean()
print(f"진짜 RR: {true_rr:.3f}")

# 오측정 RR (감쇠)
meas_rr = df.loc[df.A_star == 1, "Y"].mean() / df.loc[df.A_star == 0, "Y"].mean()
print(f"오측정 RR: {meas_rr:.3f}")
print(f"감쇠 비율: {(meas_rr - 1) / (true_rr - 1):.1%}")

7.2 차등 측정 오차 (회상 편향) 시뮬레이션

np.random.seed(7)
n = 100_000

# 진짜 효과 = 0 (A는 Y에 영향 없음)
A = np.random.binomial(1, 0.3, n)
Y = np.random.binomial(1, 0.15, n)  # A와 독립

# 차등 오분류: Y=1인 사람이 A=1로 잘못 기억할 확률 높음
A_star = A.copy()
recall_bias = (Y == 1) & (A == 0)
A_star[recall_bias] = np.random.binomial(
    1, 0.20, recall_bias.sum()  # 20%가 노출을 잘못 기억
)

df = pd.DataFrame({"A": A, "A_star": A_star, "Y": Y})

# 진짜 OR
from scipy.stats import contingency
true_table = pd.crosstab(df.A, df.Y)
true_or = (true_table.iloc[1, 1] * true_table.iloc[0, 0]) / \
          (true_table.iloc[1, 0] * true_table.iloc[0, 1])
print(f"진짜 OR: {true_or:.3f}")  # ≈ 1.0

# 오측정 OR (회상 편향)
meas_table = pd.crosstab(df.A_star, df.Y)
meas_or = (meas_table.iloc[1, 1] * meas_table.iloc[0, 0]) / \
          (meas_table.iloc[1, 0] * meas_table.iloc[0, 1])
print(f"오측정 OR (회상 편향): {meas_or:.3f}")  # > 1.0 (허위 연관!)

7.3 식별 vs. 추정: 신뢰구간과 검정력

from scipy import stats

np.random.seed(42)

# 진짜 인과 위험차 = -0.10
p_treat, p_control = 0.15, 0.25
true_rd = p_treat - p_control

sample_sizes = [50, 200, 1000, 5000]
print(f"{'n':>6} | {'추정 RD':>10} | {'95% CI':>20} | {'p-value':>10}")
print("-" * 60)

for n_per_group in sample_sizes:
    y1 = np.random.binomial(1, p_treat, n_per_group)
    y0 = np.random.binomial(1, p_control, n_per_group)

    p1_hat, p0_hat = y1.mean(), y0.mean()
    rd_hat = p1_hat - p0_hat
    se = np.sqrt(p1_hat * (1 - p1_hat) / n_per_group +
                 p0_hat * (1 - p0_hat) / n_per_group)
    ci = (rd_hat - 1.96 * se, rd_hat + 1.96 * se)
    z = rd_hat / se
    pval = 2 * (1 - stats.norm.cdf(abs(z)))

    print(f"{n_per_group:>6} | {rd_hat:>10.3f} | ({ci[0]:+.3f}, {ci[1]:+.3f}) | {pval:>10.4f}")

print(f"\n진짜 RD = {true_rd:.2f}")
print("표본이 커질수록 추정이 정확해지고 CI가 좁아진다")

7.4 조건성 원리: 보정의 중요성

np.random.seed(42)
n = 240

# RCT이지만 L과 A가 우연히 연관
L = np.random.binomial(1, 0.5, n)
# 나쁜 운: 흡연자가 처리군에 더 많이 배정됨
A = np.random.binomial(1, np.where(L == 1, 0.67, 0.33), n)
Y = np.random.binomial(1, np.where(L == 1, 0.50, 0.05), n)  # A 효과 = 0

df = pd.DataFrame({"L": L, "A": A, "Y": Y})

# 미보정
naive_rd = df.loc[df.A == 1, "Y"].mean() - df.loc[df.A == 0, "Y"].mean()
print(f"미보정 RD: {naive_rd:.3f}")  # ≠ 0 (우연한 교란)

# L로 보정 (표준화)
p_L = df.L.value_counts(normalize=True).sort_index()
std_risk = {}
for a in [0, 1]:
    r = 0
    for l in [0, 1]:
        sub = df[(df.A == a) & (df.L == l)]
        if len(sub) > 0:
            r += sub.Y.mean() * p_L[l]
    std_risk[a] = r

adj_rd = std_risk[1] - std_risk[0]
print(f"보정 RD: {adj_rd:.3f}")  # ≈ 0
print("→ 조건성 원리: 불균형한 보조 통계량에 조건화하면 편향 제거")

8 관련 주제

선행 지식

후속 주제

다른 카테고리 연결

Subscribe

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