권세혁HOME
  • 강의노트
    • 기초수학·수리통계·조사방법
    • 기초통계·회귀·다변량분석
    • 머신러닝·딥러닝
    • AI·감성분석
  • 통계상담
  • 임업통계_인사이트
  • 놀이터_플랫폼
  • 통계이야기
  1. 【기초통계】
  2. 📄 적합성 검정
  • 【기초통계】
    • 📄 통계학의 개념
    • 📄 데이터와 통계
    • 📄 일변량 분석
    • 📄 교차표 분석
    • 📄 적합성 검정
    • 📄 정규성 검정
    • 📄 상관분석
    • 📄 분산분석(ANOVA)
    • 📄 시계열 분석
  • 【회귀분석】
    • 📄 개념·추정
    • 📄 변수선택
    • 📄 다중공선성
    • 📄 회귀진단
    • 📄 로지스틱회귀=예측분류
  • 【다변량분석】
    • 📄 다변량분석 개요
    • 📄 PCA주성분분석
    • 📄 FA요인분석
    • 📄 판별분석=예측분류
    • 📄 군집분석
    • 📄 다차원척도·대응분석
    • 📄 정준상관·MANOVA

목차

  • 1 적합성 검정
    • 1.1 개념
      • 1.1.1 필요이유
      • 1.1.2 적합성 검정 개념
      • 1.1.3 \(\chi^{2}\) 적합성 검정
    • 1.2 이산형 확률모형
    • 1.3 연속형 확률모형
      • 1.3.1 적합성 검정방법
  • 2 함수 적합
    • 2.1 함수적합 개념
    • 2.2 함수적합 원리
    • 2.3 선형함수 linear function 예제
    • 2.4 비선형함수 non-linear function 예제
  1. 【기초통계】
  2. 📄 적합성 검정

기초통계 | 5. 분포 적합성검정

Author

권세혁

1 적합성 검정

정의

분포 적합성 검정(Goodness-of-Fit Test)은 관측된 자료가 특정 이론적 분포를 따른다는 가설의 타당성을 평가함으로써, 통계적 모형의 전제가 충족되는지를 확인하고 추론 결과의 신뢰성을 확보하기 위해 수행된다.

1.1 개념

1.1.1 필요이유

적합성 검정이 필요한 이유
이유 내용
모형 전제 검토 회귀분석·ANOVA·MLE 등은 특정 분포(정규·포아송 등)를 전제 → 가정 충족 여부 확인 필수
이론 모형 타당성 평가 멘델 3:1 비율 등 이론적 분포가 실제 데이터에 부합하는지 검정
모수 추정 신뢰도 확보 잘못된 분포 가정은 편향·비효율적 추정량을 유도함
응용 분야 판단 기준 불량률(이항분포), 콜센터 수신량(포아송분포) 등 관리 기준의 전제

통계 모형의 전제 검토: 많은 통계 분석 기법(회귀분석, 분산분석, 최대우도법 등)은 특정한 확률 분포(정규분포, 포아송분포 등)를 전제로 한다. 이러한 가정이 충족되지 않으면 분석 결과는 왜곡되거나 신뢰할 수 없는 결론을 초래할 수 있다.

이론 모형의 타당성 평가: 통계적 실험이나 조사에서 수립한 이론적 분포 모델(예: 유전 비율, 고객 유입 패턴 등)이 실제 데이터에 적합한지 검정하는 것은 모형 자체의 타당성을 판단하는 데 필수적이다. 예를 들어, 멘델의 유전 법칙에 따라 3:1 비율이 예측된다면, 실제 결과가 이와 유의하게 다른지를 검정해야 한다.

모수 추정의 신뢰도 확보: 분포가 적절하게 지정되지 않은 상태에서 수행된 추정은 불편하거나 비효율적인 추정량을 유도할 수 있다. 분포 적합성 검정은 분석자가 설정한 분포 가정이 얼마나 정당한지를 사전 확인함으로써, 추정과 추론의 타당성을 보장해준다.

모의실험, 품질관리 등 응용 분야에서의 판단 기준

  • 산업 통계에서는 생산품의 불량률이 이항분포를 따른다고 가정하고 관리도를 구성함 → 이 분포 적합성이 무너지면 관리 기준 자체가 무의미하다.
  • 서비스센터의 전화 수신량이 포아송 분포를 따른다는 가정을 기반으로 인력 배치 → 적합성 검정이 필요하다.

1.1.2 적합성 검정 개념

분포 적합성 검정은 관측된 데이터가 특정한 이론적 분포(모형 분포)에 잘 부합하는지를 검정하는 통계적 방법이다. 즉, 어떤 모집단에서 추출된 표본이, 가정한 분포(예: 이항분포, 포아송분포, 정규분포 등)로부터 생성되었을 가능성을 평가한다.

이 검정은 다음과 같은 상황에 적용된다.

  • 주어진 자료가 특정 분포에 따르는지 검정하고자 할 때
  • 실험 결과가 이론적으로 기대되는 확률 분포와 일치하는지 검정할 때

귀무가설이 “설정한 이론 분포를 따른다”이므로 귀무가설이 기각되면 데이터가 어떤 분포를 따르는지 알 수 없다. 따라서 적합성 검정은 귀무가설이 채택되는 것이 추론의 관심이다.

1.1.3 \(\chi^{2}\) 적합성 검정

확률표본 데이터로부터 히스토그램을 구한다. 이산형 데이터는 가질 수 있는 개별 값이 구간이고 연속형은 데이터의 범위를 10~12개 구간 개수가 되도록 동일 폭으로 나눈 구간으로 정의된다.

확률표본 데이터로부터 빈도표(관측 빈도)를 만들고, 모집단이 따를 것 같은 이론적 분포로부터(예: 정규분포) 빈도표(기대 빈도)를 만들어 비교한다. 표본 분포가 설정한 모집단 분포와 동일하다면 관측빈도와 기대빈도는 동일할 것이다.

χ² 적합성 검정 절차
단계 내용
① 가설 설정 \(H_0\): 데이터가 이론 분포를 따른다
② 기대빈도 계산 \(E_i = n \times p_i\) (이론 분포 확률 × 표본 크기)
③ 검정통계량 \(\chi^2 = \sum\frac{(O_i-E_i)^2}{E_i} \sim \chi^2(k-1-m)\)
④ 판단 p값 > α → 귀무가설 채택 (분포 적합)

⚠️ 주의: 모든 기대빈도 \(E_i \geq 5\) 필요. 미만인 셀은 인접 셀과 병합 후 검정. \(m\)은 추정된 모수의 개수.

통계적 가설

  • 귀무가설: 확률표본 데이터는 가정된 이론분포를 따른다.
  • 대립가설: 확률표본 데이터는 가정 분포를 따르지 않는다.

검정통계량: \(\chi^{2}\) 통계량은 관측빈도와 기대빈도의 차이를 기대빈도로 나눈 값의 합이다.

\[\chi^{2} = \overset{k}{\sum_{i = 1}}\frac{(O_{i} - E_{i})^{2}}{E_{i}} \sim \chi^{2}(df = k - 1 - m)\]

여기서 \(O_{i}\)는 범주 \(i\)에서의 관측도수, \(E_{i}\)는 해당 범주에서의 이론적 분포로부터 계산되는 기대도수이며 \(k\)는 범주의 수이다. \(m\)은 모수 추정에 사용된 자유도 수이다.

1.2 이산형 확률모형

주사위는 공평한가? (균일분포): 보유한 주사위가 공정한지 fair 알아보기 위하여 1,000번을 던져 나온 결과를 정리한 것이다. 주사위가 공정한지 유의수준 5%에서 검정하시오.

주사위 눈금별 빈도
눈금 1 2 3 4 5 6
빈도 \(O_{i}\) 150 160 165 155 170 200
  • 귀무가설: 주사위는 공정하다. 각 눈금이 나올 확률은 \(\frac{1}{6}\)이다.
  • 대립가설: 주사위는 공정하지 않다.
  • 기대빈도 \(E_{i}\): 귀무가설이 옳다는 가정 하에 계산되는 빈도이다. 그러므로 1~6 각 눈금의 기대빈도는 1000/6 = 166.7으로 동일하다.
  • 검정통계량: \(ts = \sum_{i}\frac{(O_{i} - E_{i})^{2}}{E_{i}} \sim \chi^{2}(df = k - c - 1)\), \(k\) = 셀의 크기, \(c\) = 추정된 모수의 개수, \(TS = 9.49 \sim \chi^{2}(5)\)
  • 유의확률: 0.091이므로 귀무가설이 채택되어 주사위는 공평하다고 할 수 있다.
from scipy.stats import chisquare

# 관측 빈도
observed = [150, 160, 165, 155, 170, 200]

# 총 시행 횟수
n = sum(observed)

# 기대 확률: 공정한 주사위 → 각 면의 확률은 1/6
expected = [n / 6] * 6  # [166.67, 166.67, ..., 166.67]

# 카이제곱 적합성 검정 수행
chi2_stat, p_value = chisquare(f_obs=observed, f_exp=expected)

# 출력
print("카이제곱 통계량:", round(chi2_stat, 3))
print("p-value:", round(p_value, 4))
print(expected)

카이제곱 통계량: 9.5
p-value: 0.0907
[166.66666666666666, 166.66666666666666, 166.66666666666666, 166.66666666666666, 166.66666666666666, 166.66666666666666]

결론: 주사위 균일분포 적합성 검정
검정통계량 자유도 유의확률
9.50 5 0.091

유의확률(0.091) > 유의수준(0.05) → 귀무가설 채택: 주사위는 공정하다고 볼 수 있다.

성비는 동일한가? (이항분포): 우리나라 출생 아이의 성비가 동일한지 알아보기 위하여 자녀가 3인인 1,000 가구의 남아 수를 조사한 자료이다. 이를 이용하여 성비가 동일한지 검정하시오.

남자아이 수별 가구 수
남자아이 수 0 1 2 3
가구수 100 350 400 150
  • 귀무가설: 성비는 동일하다.
  • 대립가설: 성비는 동일하지 않다.

기대빈도: 성비가 동일하다면 남아 비율은 1/2이므로 남자아이 수(\(X\))는 이항분포(n=3, p=1/2)을 따르므로 기대확률에 \(n = 1000\)을 곱해 구하면 된다. [125, 375, 375, 125]

검정통계량: \(TS = 13.33 \sim \chi^{2}(4 - 1 = 3)\)

유의확률: 0.004로 유의수준 0.05보다 작으므로 귀무가설을 기각하여 남녀 아이 성비는 다르다. 남자아이 2명 가구가 기대빈도 375 < 관측빈도 400으로 많고 3명도 관측빈도가 많으므로 여자 아이보다 남자 아이가 더 많다.

from scipy.stats import chisquare

# 관측 도수: 남자아이 수에 따른 가구 수
observed = [100, 350, 400, 150]

# 기대 도수(이론빈도): 이항분포(B(n=3, p=0.5)) × 총 가구 수 (1000)
from scipy.stats import binom

n = 3
p = 0.5
total = 1000

# 이항분포 기반 기대도수 계산
expected = [binom.pmf(k, n, p) * total for k in range(4)]

# 카이제곱 적합성 검정 수행
chi2_stat, p_value = chisquare(f_obs=observed, f_exp=expected)

# 결과 출력
print("카이제곱 통계량:", round(chi2_stat, 3))
print("p-value:", round(p_value, 4))
print(expected)

카이제곱 통계량: 13.333
p-value: 0.004
[np.float64(125.0), np.float64(375.0), np.float64(375.0), np.float64(125.0)]

결론: 성비 이항분포 적합성 검정
검정통계량 자유도 유의확률
13.333 3 0.004

유의확률(0.004) < 유의수준(0.05) → 귀무가설 기각: 남녀 성비는 동일하지 않다. 남자아이 2명·3명 가구의 관측빈도가 기대빈도보다 많아 남아 출생이 더 높은 경향이 있다.

교통사고 건수는 포아송분포를 따르나?: D지역 1일 교통사고 건수를 알아보기 위하여 300일 동안 매일 교통사고 건수를 조사한 자료이다.

1일 교통사고 건수별 빈도
건수 0 1 2 3 4 5 6 7
요일수 20 54 74 67 45 25 11 4
  • 귀무가설: D 지역 1일 교통사건 건수는 포아송분포를 따른다.
  • 대립가설: 포아송분포를 따르지 않는다.

포아송 모수 추정: 포아송 분포는 평균을 모수로 가지고 있으므로 (건수×요일) 합을 300일로 나누면 하루 평균 교통사고 건수 추정치이다. \(\widehat{\lambda} = 2.673\)

기대빈도: \(\widehat{p(j)} = P(X = j|X \sim P(\lambda = 2.67))\), 단 건수=7일 때는 4개로 기대빈도가 5 미만이므로 6과 7을 합하여 셀의 개수는 7개이다. [20, 55, 74, 66, 44, 23, 14]

검정통계량: \(TS = 0.186 \sim \chi^{2}(7 - 1 - 1 = 5)\), 포아송 분포 모수를 1개 추정했으므로 자유도는 1 더 줄어든다.

유의확률은 0.99이므로 귀무가설을 채택되어 교통사고 건수는 모수가 2.67(건수/1일)인 포아송분포 따른다.

from scipy.stats import poisson, chisquare
import numpy as np

# 관측도수
observed = np.array([20, 54, 74, 67, 45, 25, 11, 4])
total_days = observed.sum()

# 평균 λ 추정: 포아송 분포의 모수는 관측된 평균과 같다고 가정
values = np.arange(len(observed))
lambda_hat = np.sum(values * observed) / total_days

# 기대도수 계산 (포아송분포 기반)
expected = poisson.pmf(values, mu=lambda_hat) * total_days

# 기대도수가 너무 작은 셀은 마지막에 병합 (R 규칙: 기대도수 < 5 합치기)
observed_adj = np.append(observed[:-2], observed[-2:].sum())
expected_adj = np.append(expected[:-2], expected[-2:].sum())

# Ensure that the sums of observed and expected frequencies match
expected_adj = expected_adj * observed_adj.sum() / expected_adj.sum()

# 카이제곱 검정
chi2_stat, p_value = chisquare(f_obs=observed_adj, f_exp=expected_adj)

# 결과 출력
print("추정된 λ (평균 사고 건수):", round(lambda_hat, 4))
print("카이제곱 통계량:", round(chi2_stat, 4))
print("p-value:", round(p_value, 4))

추정된 λ (평균 사고 건수): 2.6733
카이제곱 통계량: 0.186
p-value: 0.9999
[20.83690818 55.7040012 74.4576816 66.35006738 44.3439617 23.70923819 14.59814175]

결론: 교통사고 포아송분포 적합성 검정
추정 \(\hat\lambda\) 검정통계량 자유도 유의확률
2.673 0.186 5 0.999

유의확률(0.999) > 유의수준(0.05) → 귀무가설 채택: 교통사고 건수는 \(\lambda = 2.67\)인 포아송분포를 따른다.

1.3 연속형 확률모형

개념: 연속형 확률모형 적합성 검정은 관측된 연속형 데이터가 특정 이론적 확률분포(예: 정규분포, 지수분포, 감마분포 등)를 따르는지 여부를 검정하는 통계적 절차이다.

귀무가설과 대립가설

  • 귀무가설: 자료는 지정된 연속형 분포를 따른다.
  • 대립가설: 자료는 해당 분포를 따르지 않는다.
연속형 정규성 검정 방법 비교
검정 방법 통계량 특징 권장 상황
Shapiro-Wilk W (0~1) 소표본에서 강력 \(n \leq 50\) (1000까지도 사용)
Kolmogorov-Smirnov D (최대 거리) 모수 알고 있을 때 적합 모수 사전 지정 가능 시
Anderson-Darling \(A^2\) 꼬리 부분 더 민감 정규성 검정에 특화
Lilliefors D 모수 추정값 사용 시 모수 미지일 때 K-S 대안
Jarque-Bera JB 왜도·첨도 기반 회귀 잔차 정규성 검정

시각화 도구

연속형 확률분포의 적합성 검정에서는 수치 기반의 정량적 검정뿐 아니라, 분포 형태를 직관적으로 이해할 수 있는 시각화 기법도 중요하게 활용된다.

P-P 그래프 vs. Q-Q 그래프
구분 P-P 그래프 Q-Q 그래프
비교 기준 누적확률 (CDF) 분위수 (Quantile)
판단 기준 45도 대각선 근접 여부 45도 직선 근접 여부
장점 분포 전 구간 균형 있게 평가 꼬리 부분 적합성 차이에 민감
주로 사용 전반적 적합도 확인 이상값·꼬리 부분 파악

Probability-Probability plot: P-P plot은 관측값의 누적확률(경험누적분포)과 이론 누적분포함수의 값을 직접 비교하여 각 관측값에 대해 다음의 점을 그린다.

\((x_{i}:{\widehat{F}}_{n}(x_{i}) = \frac{i}{n + 1},F(x_{i}))\), 여기서 \({\widehat{F}}_{n}(x_{i})\)는 표본 누적분포, \(F(x_{i})\)는 이론 누적분포이다. 45도 대각선을 기준으로 점들이 근접해 있으면 분포 적합성 양호하다고 판단한다.

Q-Q Plot (Quantile-Quantile Plot): Q-Q plot은 표본 분위수와 이론 분위수를 직접 비교하는 도구이다.

\((\text{이론 분위수},\text{표본 분위수}) = (F^{- 1}(p_{i} = \frac{i - 0.5}{n}),x_{(i)})\), 여기서 \(F^{- 1}(p_{i})\)는 이론 분포(정규분포를 주로 사용함)의 \(p_{i}\) 분위수, \(x_{(i)}\)는 표본의 \(i\)-번째 순서통계량이다.

#P-P plot
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import scipy.stats as stats
import seaborn as sns

# 타이타닉 데이터 불러오기
titanic = sns.load_dataset("titanic")

# age 변수 추출 및 결측치 제거
age_data = titanic["age"].dropna()
age_sorted = np.sort(age_data)
n = len(age_sorted)

# 경험 누적확률 (empirical CDF)
empirical_cdf = np.arange(1, n + 1) / (n + 1)

# 이론 누적확률 (정규분포 기준 CDF)
mean_age = np.mean(age_sorted)
std_age = np.std(age_sorted, ddof=1)
theoretical_cdf = stats.norm.cdf(age_sorted, loc=mean_age, scale=std_age)

# P-P Plot 그리기
plt.figure(figsize=(6, 5))
plt.plot(empirical_cdf, theoretical_cdf, 'o', label='Data Points')
plt.plot([0, 1], [0, 1], 'r--', label='y = x')
plt.xlabel('Empirical CDF')
plt.ylabel('Theoretical CDF (Normal)')
plt.title('P-P Plot of Titanic Age (vs Normal)')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
#Q-Q plot
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import scipy.stats as stats
import seaborn as sns

# 타이타닉 데이터 불러오기 및 전처리
titanic = sns.load_dataset("titanic")
age_data = titanic["age"].dropna()

# Q-Q plot (정규분포와 비교)
plt.figure(figsize=(6, 5))
stats.probplot(age_data, dist="norm", plot=plt)
plt.title("Q-Q Plot of Titanic Age (vs Normal)")
plt.grid(True)
plt.tight_layout()
plt.show()

P-P plot 결과는 Titanic 승객의 나이(age) 변수가 정규분포보다 오른쪽으로 치우쳐져 있으며, 이는 양의 왜도 특성을 지닌 우로 치우진 분포임을 시사한다.

1.3.1 적합성 검정방법

Shapiro-Wilk W-통계량 (정규성 검정): Shapiro-Wilk 검정(Shapiro & Wilk, 1965)은 주어진 데이터가 정규분포를 따르는지를 검토하기 위한 방법으로, 특히 소표본(\(n \leq 50\))에서 강력한 검정력을 가지며, 현재는 1000개 이하의 표본에도 널리 사용된다.

\[W = \frac{\left( \sum_{i = 1}^{n}a_{i}x_{(i)} \right)^{2}}{\sum_{i = 1}^{n}(x_{i} - \overline{x})^{2}}\]

\(W\)값은 일반적으로 0과 1 사이의 값을 가지며, 값이 1에 가까울수록 데이터가 정규분포에 가깝다는 것을 의미한다.

  • 귀무가설: 데이터는 정규분포를 따른다.
  • 대립가설: 데이터는 정규분포를 따르지 않는다.
import seaborn as sns
from scipy.stats import shapiro
import matplotlib.pyplot as plt
# 데이터 불러오기
titanic = sns.load_dataset("titanic")
# age 변수에서 결측치 제거
age_data = titanic['age'].dropna()
# Shapiro-Wilk 검정 수행
w_stat, p_value = shapiro(age_data)
print(f"W-통계량 = {w_stat:.4f}, p-value = {p_value:.4f}")

W-통계량 = 0.9815, p-value = 0.0000

Kolmogorov-Smirnov 검정과 D-통계량: Kolmogorov-Smirnov(K-S) 검정은 관측된 누적분포함수가 주어진 이론적 누적분포함수와 일치하는지를 검정하는 방법이다.

\[D = \sup_{x}\left| F_{n}(x) - F(x) \right|\]

여기서, \(F_{n}(x)\)는 표본 누적분포함수, \(F(x)\)는 이론 누적분포함수, \(\sup_{x}\)는 모든 \(x\)에 대해 최대 절댓값을 취하는 것이다.

from scipy.stats import kstest, norm
import seaborn as sns
# Titanic 데이터셋에서 age 변수
titanic = sns.load_dataset("titanic")
age_data = titanic['age'].dropna()
# 평균과 표준편차로 정규분포 생성
mean = age_data.mean()
std = age_data.std()
# Kolmogorov-Smirnov 검정 수행
d_stat, p_value = kstest(age_data, 'norm', args=(mean, std))
print(f"D-통계량 = {d_stat:.4f}, p-value = {p_value:.4f}")

D-통계량 = 0.0646, p-value = 0.0050 → 정규분포를 따르지 않는다.

K-S 검정 적용 가능 분포 종류
분포 종류 설명 Python 함수 예시 (scipy.stats)
정규분포 평균과 표준편차로 정의되는 연속 분포 'norm', args=(μ, σ)
지수분포 사건 간의 시간 간격 모델링 'expon', args=(loc, scale)
균등분포 모든 구간에서 같은 확률 'uniform', args=(a, b-a)
감마분포 대기 시간이나 생존 분석에서 자주 사용 'gamma', args=(shape, loc, scale)
베타분포 0~1 사이 확률 변수 모델링에 적합 'beta', args=(α, β)
로지스틱분포 S자형 누적분포, 로지스틱 회귀와 관련 'logistic', args=(loc, scale)
카이제곱분포 분산 분석, 독립성 검정 등에서 사용 'chi2', args=(df,)
레이리분포 신호 처리, 물리학에서 사용 'rayleigh', args=(loc, scale)
로그정규분포 지수적으로 증가하는 변수에 적합 'lognorm', args=(σ, loc, scale)

Titanic 데이터셋의 age 변수는 정규성을 만족하지 않으며, K-S 검정 결과 로그정규분포나 감마분포에 가장 가까운 분포 특성을 보인다.

from scipy.stats import norm, expon, lognorm, gamma, kstest

# 데이터
data = age_data
# 정규분포
norm_params = norm.fit(data)
ks_norm = kstest(data, 'norm', args=norm_params)
# 지수분포
expon_params = expon.fit(data)
ks_expon = kstest(data, 'expon', args=expon_params)
# 로그정규분포
lognorm_params = lognorm.fit(data)
ks_lognorm = kstest(data, 'lognorm', args=lognorm_params)
# 감마분포
gamma_params = gamma.fit(data)
ks_gamma = kstest(data, 'gamma', args=gamma_params)

# 결과 출력
print(f"[정규분포]     D = {ks_norm.statistic:.4f}, p = {ks_norm.pvalue:.4f}")
print(f"[지수분포]     D = {ks_expon.statistic:.4f}, p = {ks_expon.pvalue:.4f}")
print(f"[로그정규분포] D = {ks_lognorm.statistic:.4f}, p = {ks_lognorm.pvalue:.4f}")
print(f"[감마분포]     D = {ks_gamma.statistic:.4f}, p = {ks_gamma.pvalue:.4f}")

[정규분포] D = 0.0646, p = 0.0050
[지수분포] D = 0.2964, p = 0.0000
[로그정규분포] D = 0.0565, p = 0.0202
[감마분포] D = 0.0575, p = 0.0172
모두 유의확률이 0.05보다 작아 최적의 이론분포는 발견하지 못했지만 로그정규분포가 가장 근접한 분포이다.

Anderson-Darling 검정과 AD 통계량: Anderson-Darling 검정은 표본 데이터가 특정 이론분포(주로 정규분포)를 따르는지 검정하는 정규성 검정 기법 중 하나로, Kolmogorov-Smirnov 검정의 일반화된 형태이다. 특히 K-S 검정보다 정규성 검정에서 더 강력한 검정력을 가지는 것으로 알려져 있다.

\[A^{2} = - n - \frac{1}{n}\overset{n}{\sum_{i = 1}}\left\lbrack (2i - 1) \cdot \left( \ln F(x_{(i)}) + \ln\left( 1 - F(x_{(n + 1 - i)}) \right) \right) \right\rbrack\]

from scipy.stats import anderson
import seaborn as sns
# Titanic 데이터셋에서 age 변수
titanic = sns.load_dataset("titanic")
age_data = titanic['age'].dropna()
# Anderson-Darling 검정 (정규성 기준)
result = anderson(age_data, dist='norm')

print(f"AD 통계량 = {result.statistic:.4f}")
for cv, sig in zip(result.critical_values, result.significance_level):
    print(f"유의수준 {sig}% →임계값: {cv:.4f}")

AD 통계량 = 3.8230
유의수준 15.0% →임계값: 0.5730
유의수준 10.0% →임계값: 0.6520
유의수준 5.0% →임계값: 0.7830
유의수준 2.5% →임계값: 0.9130
유의수준 1.0% →임계값: 1.0860 → 유의수준 1% 임계값보다 통계량이 3.823으로 크므로 정규성은 기각된다.

Anderson-Darling 검정 적용 가능 분포
함수 이름 설명 사용 예
'norm' 정규분포 (default) anderson(data, 'norm')
'expon' 지수분포 anderson(data, 'expon')
'logistic' 로지스틱분포 anderson(data, 'logistic')
'gumbel' 극값분포 I형 (Gumbel, 극단값 이론) anderson(data, 'gumbel')
'gumbel_l', 'gumbel_r' 왼쪽/오른쪽 Gumbel 분포 anderson(data, 'gumbel_r')

Lilliefors 검정 (정규성 검정): K-S 검정은 비교 대상 분포(예: 정규분포)의 모수, 즉 평균과 표준편차가 사전에 주어져 있어야 한다는 제약이 있다. 실제 분석에서는 대부분 모수를 알 수 없고 표본으로부터 추정하기 때문에, 이러한 상황을 반영한 검정 방법이 필요하다. 이러한 배경에서 Lilliefors 검정이 제안되었다.

\[D = \sup_{x}\left| F_{n}(x) - F(x;\widehat{\mu},\widehat{\sigma}) \right|\]

from statsmodels.stats.diagnostic import lilliefors
import seaborn as sns

# Titanic 데이터셋 중 age 변수
titanic = sns.load_dataset("titanic")
age_data = titanic['age'].dropna()

# Lilliefors 검정 (정규성 검정)
stat, p_value = lilliefors(age_data)

print(f"Lilliefors 통계량 D = {stat:.4f}, p-value = {p_value:.4f}")

Lilliefors 통계량 D = 0.0646, p-value = 0.0010

Lilliefors 검정은 Kolmogorov-Smirnov 검정을 기반으로 하면서, 정규분포의 모수(평균, 표준편차)를 표본에서 추정한 상황에 맞게 수정된 정규성 검정 방법이다. Shapiro-Wilk 검정보다 덜 민감하지만 모수 추정 상황에서는 더 현실적인 방법이다.

Jarque-Bera 검정 (JB 검정): 많은 통계적 추론과 회귀분석에서는 잔차항이 정규분포를 따른다는 가정이 필수적이다. Jarque-Bera 검정은 왜도와 첨도에 근거하여 정규성을 판단하는 모멘트 기반 검정이다.

\[\text{JB} = \frac{n}{6}\left( S^{2} + \frac{(K - 3)^{2}}{4} \right)\]

여기서 \(S\)는 표본 왜도, \(K\)는 표본 첨도이다. 정규분포일 경우 왜도는 0, 첨도는 3이 되어 JB 통계량이 0에 가까워진다. JB 통계량은 자유도 2인 카이제곱 분포를 따른다.

from scipy.stats import jarque_bera
import seaborn as sns

# Titanic 데이터셋에서 age 변수 사용
titanic = sns.load_dataset("titanic")
age_data = titanic['age'].dropna()

# Jarque-Bera 검정
stat, p_value = jarque_bera(age_data)

print(f"JB 통계량 = {stat:.4f}, p-value = {p_value:.4f}")

JB 통계량 = 18.7876, p-value = 0.0001

유의확률이 매우 작으므로, 귀무가설 기각 → 데이터는 정규분포를 따른다고 보기 어렵다.

타이타닉 age 변수 정규성 검정 결과 종합
검정 방법 통계량 유의확률 결론
Shapiro-Wilk W = 0.9815 p < 0.001 정규성 기각 ⚠
Kolmogorov-Smirnov D = 0.0646 p = 0.005 정규성 기각 ⚠
Anderson-Darling AD = 3.823 (임계값 1% = 1.086 초과) 정규성 기각 ⚠
Lilliefors D = 0.0646 p = 0.001 정규성 기각 ⚠
Jarque-Bera JB = 18.788 p < 0.001 정규성 기각 ⚠

결론: 모든 정규성 검정에서 귀무가설이 기각되어 age 변수는 정규분포를 따르지 않는다. P-P·Q-Q 플롯에서도 우측 편포(양의 왜도) 특성이 확인된다. 분석 시 비모수 검정 또는 로그 변환 고려 필요.

2 함수 적합

2.1 함수적합 개념

함수 적합(function fitting)은 주어진 데이터가 어떤 함수 형태를 따르는지를 분석하고, 그 함수를 가장 잘 설명할 수 있는 모수나 구조를 추정하는 과정을 말한다.

이론적으로 함수 적합은 다음과 같은 배경에 기반한다.

  • 모형 설정: 분석 대상이 되는 현상에 대해, 데이터가 따를 것으로 가정되는 함수 형태(선형, 비선형, 다항식, 지수함수, 로그함수 등)를 설정한다.
  • 모수 추정: 설정한 함수의 형태를 기준으로, 주어진 데이터와 함수 간의 오차를 최소화하는 모수(parameter)를 추정한다. 가장 널리 쓰이는 방법은 최소제곱법(least squares)이다.
  • 적합도 평가: 추정된 함수가 데이터를 얼마나 잘 설명하는지를 평가한다. 결정계수(R²), 평균제곱오차(MSE), 평균절대오차(MAE)와 같은 지표가 사용된다.
  • 통계적 가정과 한계: 함수 적합에는 오차의 독립성, 등분산성, 정규성 등의 가정이 포함되는 경우가 많다.
  • 활용과 확장: 적합된 함수는 예측(prediction), 보간(interpolation), 외삽(extrapolation), 변수 간 관계 해석 등에 활용된다.

2.2 함수적합 원리

함수 적합의 수학적 원리는 관측된 데이터가 특정한 함수 형태를 따른다고 가정하고, 해당 함수의 모수를 추정하여 데이터와 함수 간의 차이를 최소화하는 데 있다.

함수 적합 6단계 절차
단계 내용
① 모형 설정 선형·비선형·지수·로그 등 함수 형태 \(y = f(x;\theta)\) 가정
② 오차 정의 잔차 \(e_i = y_i - \hat{y}_i\) (관측값 - 예측값)
③ 목적 함수 잔차 제곱합 최소화: \(\min S(\theta) = \sum(y_i - f(x_i;\theta))^2\)
④ 모수 추정 선형: 닫힌 해 \(\hat\beta = (X^\top X)^{-1}X^\top y\); 비선형: 수치 최적화
⑤ 확률론적 해석 오차 정규분포 가정 → OLS = MLE
⑥ 적합도 평가 \(R^2\), MSE, MAE, 적합성 검정

1. 문제 설정: 관측된 데이터가 \(\{(x_{i},y_{i})|i = 1,2,\ldots,n\}\)와 같이 주어졌다고 하자. 우리는 어떤 함수 형태 \(y = f(x;\theta)\)를 가정한다. 여기서 \(\theta\)는 추정해야 하는 모수(parameter)들의 집합이다.

2. 오차 정의: 함수 적합에서는 모델이 예측한 값 \({\widehat{y}}_{i} = f(x_{i};\theta)\)와 실제 관측값 \(y_{i}\)의 차이를 오차(error) 또는 잔차(residual)라고 한다.

\[e_{i} = y_{i} - {\widehat{y}}_{i}\]

3. 목적 함수 설정: 가장 일반적인 접근법은 잔차의 제곱합을 최소화하는 최소제곱법(Least Squares Method)이다.

\[S(\theta) = \overset{n}{\sum_{i = 1}}\left( y_{i} - f(x_{i};\theta) \right)^{2}\]

최적의 모수 \(\widehat{\theta}\)는 다음을 만족한다. \(\widehat{\theta} = \arg\min_{\theta}S(\theta)\)

4. 모수 추정

  • 선형 함수 적합: \(f(x;\theta)\)가 \(\theta\)에 대해 선형이라면, 해를 닫힌 형태(closed form)로 구할 수 있다. 예) 단순 선형회귀 \(y = \beta_{0} + \beta_{1}x\)의 최적 해는 \(\widehat{\beta} = (X^{\top}X)^{- 1}X^{\top}y\)이다.
  • 비선형 함수 적합: \(f(x;\theta)\)가 모수에 대해 비선형이면, 수치적 최적화 기법(예: Gauss-Newton, Levenberg-Marquardt 알고리즘)을 사용한다.

5. 확률론적 해석: 만약 오차항 \(\varepsilon_{i}\)가 평균 0, 분산 \(\sigma^{2}\)인 독립 동일분포(\(iid\)) 정규분포를 따른다고 가정하면, 최소제곱법은 최대우도추정(MLE)와 동일한 해를 준다.

\[y_{i} = f(x_{i};\theta) + \varepsilon_{i},\quad\varepsilon_{i} \sim N(0,\sigma^{2})\]

6. 적합도 평가

  • 결정계수: \(R^{2} = 1 - \frac{SS_{\text{res}}}{SS_{\text{tot}}}\), \(SS_{\text{res}} = \overset{n}{\sum_{i = 1}}(y_{i} - {\widehat{y}}_{i})^{2}\), \(SS_{\text{tot}} = \overset{n}{\sum_{i = 1}}(y_{i} - \overline{y})^{2}\)
  • 평균제곱오차(MSE): \(\text{MSE} = \frac{1}{n}\overset{n}{\sum_{i = 1}}(y_{i} - {\widehat{y}}_{i})^{2}\)
  • 평균절대오차(MAE): \(\text{MAE} = \frac{1}{n}\overset{n}{\sum_{i = 1}}|y_{i} - {\widehat{y}}_{i}|\)
  • 적합성 검정(카이제곱 검정, Kolmogorov-Smirnov 검정 등)

2.3 선형함수 linear function 예제

모형 & 데이터: \(Y_{i} = \alpha + \beta X_{i} + e_{i}\)

#함수 설정
def func(x, a, b):
    return a*x + b

#설명변수 X [0~10] 정수를 100개 동일 구간으로 나누어 저장
import numpy as np
x = np.linspace(0, 10, 100)

y=func(x, 1, 2)+0.9*np.random.normal(size=len(x))

\(y=1+2 \times x\) 함수값에 난수 생성(\(0.9 \times N(0,1)\)) 값을 더한다.

가장 적합한 함수 구하는 규칙 Least Squares Methods: 관측치 \(y_i\)와 적합치 \(\hat y_i = \hat a + \hat b \times x\)의 차이의 제곱합이 최소가 되는 모수 \((\hat a, \hat b)\) 구하는 방법이다.

\[\min_{\alpha,\beta} \sum_i^n (y_i-\alpha-\beta x_i)^2\]

from scipy.optimize import curve_fit
beta, est_cov = curve_fit(func,x,y)

beta에는 OLS 추정값가 저장되고 est_cov에는 추정분산이 출력된다. 대각행렬이 각 모수의 추정분산이 된다.

회귀분석과 결과 비교

from scipy import stats
import numpy as np
slope, intercept, r_value, p_value, std_err=stats.linregress(x,y)

import statsmodels.api as sm
model=sm.OLS(y,sm.add_constant(x))
fit=model.fit()
fit.summary()

import matplotlib.pyplot as plt
plt.scatter(x, y, marker='.')
plt.plot(x, 2+1*x, linewidth=2)
plt.plot(x, func(x,*popt), color='red', linewidth=2)
plt.legend(['Original', 'Best Fit'], loc=2)
plt.show()

2.4 비선형함수 non-linear function 예제

추정함수: \(y_{i} = a\exp(\frac{- (x - b)^{2}}{2c^{2}})\)

from scipy.optimize import curve_fit

def func(x, a, b, c):
    return a*np.exp(-(x-b)**2/(2*c**2))
x = np.linspace(0, 10, 100)
y = func(x, 1, 5, 2) # 답인 y들과
y_gen = y + 0.2*np.random.normal(size=len(x)) # noise
beta,est_cov=curve_fit(func, x, y_gen)
beta

plt.scatter(x, y_gen, marker='.')
plt.plot(x, y, linewidth=2, color='blue')
plt.plot(x, func(x, *beta), color='red', linewidth=2)
plt.legend(['Original', 'Best Fit'], loc=2)
plt.show()