Skip to main content
확률분포(Probability Distribution)는 확률변수가 가질 수 있는 값과 그 확률을 나타내는 함수입니다. 데이터가 어떤 분포를 따르는지 이해하면, 이상치 판단, 가설검정, 모델 선택의 이론적 근거를 확보할 수 있습니다.

학습 목표

  • 이산형과 연속형 확률분포의 차이를 이해한다
  • 정규분포의 성질과 68-95-99.7 규칙을 설명할 수 있다
  • 이항분포와 포아송분포를 적절한 상황에 적용할 수 있다
  • 중심극한정리의 의미와 실무적 중요성을 설명할 수 있다
  • QQ-plot으로 데이터의 정규성을 시각적으로 판단할 수 있다

왜 중요한가

많은 통계 기법과 머신러닝 알고리즘은 데이터가 특정 분포를 따른다고 가정합니다. 예를 들어, 선형회귀는 잔차가 정규분포를 따른다고 가정하고, 로지스틱회귀는 이항분포를 기반으로 합니다. 분포를 이해하면 이런 가정의 타당성을 검증할 수 있습니다.

정규분포

정규분포(Normal Distribution)는 평균을 중심으로 좌우 대칭인 종 모양(bell curve)의 분포입니다.
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats

# 정규분포 생성
mu, sigma = 170, 10  # 평균 170cm, 표준편차 10cm
x = np.linspace(mu - 4*sigma, mu + 4*sigma, 1000)
pdf = stats.norm.pdf(x, mu, sigma)

fig, ax = plt.subplots(figsize=(10, 5))
ax.plot(x, pdf, 'b-', linewidth=2, label='PDF')

# 68-95-99.7 규칙 시각화
for n_sigma, alpha, label in [(1, 0.3, '68.3%'), (2, 0.2, '95.4%'), (3, 0.1, '99.7%')]:
    ax.fill_between(x, pdf, where=(x >= mu - n_sigma*sigma) & (x <= mu + n_sigma*sigma),
                    alpha=alpha, color='#4a9eca', label=f'{label} (+-{n_sigma}σ)')

ax.set_title('정규분포와 68-95-99.7 규칙')
ax.set_xlabel('키 (cm)')
ax.set_ylabel('확률 밀도')
ax.legend()
plt.tight_layout()
plt.show()

정규분포의 주요 성질

# 표준정규분포 (Z-분포): 평균=0, 표준편차=1
z = stats.norm(0, 1)

# 확률 계산
print(f"P(Z < 1.96) = {z.cdf(1.96):.4f}")        # 누적분포함수
print(f"P(-1.96 < Z < 1.96) = {z.cdf(1.96) - z.cdf(-1.96):.4f}")  # 95% 구간

# Z-score 변환: 원래 데이터 → 표준정규분포
heights = np.array([165, 170, 175, 180, 190])
z_scores = (heights - mu) / sigma
print(f"키 190cm의 Z-score: {z_scores[-1]:.1f}")
print(f"상위 {(1 - z.cdf(z_scores[-1]))*100:.1f}%에 해당")

# 역함수: 확률 → 값 (분위수)
print(f"상위 5% 기준: {stats.norm.ppf(0.95, mu, sigma):.1f}cm")
함수설명사용 예
pdf(x)확률밀도함수특정 값의 상대적 가능성
cdf(x)누적분포함수 P(X ≤ x)특정 값 이하의 확률
ppf(q)CDF의 역함수주어진 확률에 해당하는 값
rvs(size)난수 생성시뮬레이션 데이터 생성

이항분포

이항분포(Binomial Distribution)는 n번의 독립 시행에서 성공 횟수의 분포입니다.
# 불량률 5%인 제품 100개 중 불량품 수
n, p = 100, 0.05
binom = stats.binom(n, p)

x = np.arange(0, 20)
pmf = binom.pmf(x)

fig, ax = plt.subplots(figsize=(8, 5))
ax.bar(x, pmf, color='#4a9eca', alpha=0.7)
ax.set_title(f'이항분포 (n={n}, p={p})')
ax.set_xlabel('불량품 수')
ax.set_ylabel('확률')
plt.tight_layout()
plt.show()

# 확률 계산
print(f"평균 불량품 수: {binom.mean():.1f}개")
print(f"불량품이 정확히 5개일 확률: {binom.pmf(5):.4f}")
print(f"불량품이 10개 이상일 확률: {1 - binom.cdf(9):.4f}")

포아송분포

포아송분포(Poisson Distribution)는 단위 시간/공간에서 사건이 발생하는 횟수의 분포입니다.
# 하루 평균 3건의 고객 불만 접수
lam = 3
poisson = stats.poisson(lam)

x = np.arange(0, 15)
pmf = poisson.pmf(x)

fig, ax = plt.subplots(figsize=(8, 5))
ax.bar(x, pmf, color='#4a9e4a', alpha=0.7)
ax.set_title(f'포아송분포 (λ={lam})')
ax.set_xlabel('불만 건수')
ax.set_ylabel('확률')
plt.tight_layout()
plt.show()

print(f"하루 불만이 0건일 확률: {poisson.pmf(0):.4f}")
print(f"하루 불만이 7건 이상일 확률: {1 - poisson.cdf(6):.4f}")
분포유형적용 상황파라미터
정규분포연속형키, 시험 점수, 오차평균(mu), 표준편차(sigma)
이항분포이산형합격/불합격, 클릭/미클릭시행 수(n), 성공 확률(p)
포아송분포이산형시간당 사건 수평균 발생률(lambda)

중심극한정리

중심극한정리(Central Limit Theorem, CLT)는 모집단의 분포에 관계없이, 표본 평균의 분포는 표본 크기가 충분히 크면 정규분포에 근사한다는 정리입니다.
np.random.seed(42)

# 원래 분포: 균등분포 (정규분포가 아님)
population = np.random.uniform(0, 100, 100000)

fig, axes = plt.subplots(2, 3, figsize=(15, 8))

# 원래 분포
axes[0, 0].hist(population, bins=50, color='#e6a23c', alpha=0.7)
axes[0, 0].set_title('모집단 (균등분포)')

# 표본 크기별 표본 평균의 분포
sample_sizes = [2, 5, 10, 30, 100]
for i, n in enumerate(sample_sizes):
    row, col = (i + 1) // 3, (i + 1) % 3
    sample_means = [np.mean(np.random.choice(population, n)) for _ in range(5000)]
    axes[row, col].hist(sample_means, bins=50, color='#4a9eca', alpha=0.7)
    axes[row, col].set_title(f'표본 평균 분포 (n={n})')
    axes[row, col].axvline(np.mean(sample_means), color='red', linestyle='--')

plt.suptitle('중심극한정리: 표본 크기가 커질수록 정규분포에 근사')
plt.tight_layout()
plt.show()
표본 크기가 30 이상이면 중심극한정리가 일반적으로 적용됩니다. 원래 분포가 극단적으로 비대칭인 경우 더 큰 표본이 필요합니다.

QQ-plot — 정규성 검정

from scipy.stats import probplot

np.random.seed(42)
# 정규분포 데이터
normal_data = np.random.normal(100, 15, 200)
# 오른쪽 치우침 데이터
skewed_data = np.random.exponential(10, 200)

fig, axes = plt.subplots(1, 2, figsize=(12, 5))

# 정규분포 QQ-plot
probplot(normal_data, dist="norm", plot=axes[0])
axes[0].set_title('정규분포 데이터 QQ-Plot')

# 편향된 데이터 QQ-plot
probplot(skewed_data, dist="norm", plot=axes[1])
axes[1].set_title('편향된 데이터 QQ-Plot')

plt.tight_layout()
plt.show()

# 정규성 검정 (Shapiro-Wilk test)
stat, p_value = stats.shapiro(normal_data)
print(f"정규분포 데이터 — Shapiro-Wilk p-value: {p_value:.4f}")

stat, p_value = stats.shapiro(skewed_data)
print(f"편향된 데이터 — Shapiro-Wilk p-value: {p_value:.4f}")
# p < 0.05이면 정규분포가 아니라고 판단
QQ-plot에서 점들이 대각선에 가까울수록 정규분포에 가깝습니다. 꼬리 부분이 벗어나면 두꺼운 꼬리(heavy tail)를, S자 형태면 편향을 의미합니다.

AI/ML에서의 활용

  • 피처 정규화: 정규분포 가정이 필요한 모델(선형회귀, LDA)에서 피처의 정규성을 확인합니다
  • 이상치 판단: 정규분포에서 3시그마(sigma) 밖의 값을 이상치로 판단합니다
  • A/B 테스트: 중심극한정리를 이용하여 두 그룹의 평균 차이를 검정합니다
  • 확률 모델링: 이항분포로 분류 문제의 확률을, 포아송분포로 이벤트 발생을 모델링합니다
  1. 히스토그램으로 시각적 확인, 2) QQ-plot으로 정규성 검정, 3) Shapiro-Wilk 또는 Kolmogorov-Smirnov 검정으로 통계적 확인. 실무에서는 시각적 확인과 통계 검정을 함께 사용합니다.
표본 크기가 너무 작거나(n < 30), 분포의 분산이 무한한 경우(코시 분포 등)에는 CLT가 잘 적용되지 않습니다. 극단적으로 편향된 분포에서는 더 큰 표본이 필요합니다.

체크리스트

  • 이산형과 연속형 확률분포의 차이를 설명할 수 있다
  • 정규분포의 68-95-99.7 규칙을 이해한다
  • Z-score를 계산하고 확률을 구할 수 있다
  • 이항분포와 포아송분포를 적절한 상황에 적용할 수 있다
  • 중심극한정리의 의미를 설명할 수 있다
  • QQ-plot으로 정규성을 시각적으로 판단할 수 있다

다음 문서

가설검정

t-test, chi-square, ANOVA로 통계적 유의성을 검정합니다

기술통계

중심경향과 산포도를 복습합니다