주요 분포의 밀도 함수 (Distribution Families)

이산·연속 분포의 PDF·PMF, 정규화 증명, 혼합 분포

밀도 함수와 질량 함수의 심화편. 베르누이·이항·포아송·균등·정규·지수·감마·베타 분포의 PDF·PMF를 체계적으로 정리하고, 합/적분이 1임을 증명한다. 혼합 분포(GMM)와 응용 코드도 포함한다.

Statistics
저자

Kwangmin Kim

공개

2026년 03월 27일

선행 지식

이 포스트는 밀도 함수와 질량 함수 의 심화편이다. PDF·PMF의 정의, 존재 조건, 지지 집합, 커널 표현을 먼저 학습한 뒤 읽는 것을 권장한다.


왜 주요 분포를 알아야 하는가

통계 모델링에서 모델을 선택한다 = 분포를 선택한다:

  • 회귀 분석: 오차가 정규 분포를 따른다고 가정 → 정규 분포의 성질을 모르면 잔차 진단이 불가능하다
  • GLM: 반응 변수의 분포(이항, 포아송, 감마 등)에 따라 링크 함수와 추정 방법이 달라진다
  • 베이지안 추론: 사전 분포로 베타·감마 등을 선택하는 이유는 켤레(conjugate) 관계 때문이다
  • 생존 분석: 지수·와이블 분포는 “고장까지의 시간”을 모델링하는 기본 도구다
  • 이상 탐지: 데이터가 어떤 분포를 따르는지 알아야 “비정상적으로 극단적인 값”의 기준을 정할 수 있다

각 분포의 PDF·PMF, 지지 집합, 모수의 의미를 정확히 알면 올바른 모델을 선택하고, 모델의 한계를 이해할 수 있다.

1 주요 분포의 PDF·PMF 성질

1.1 이산 분포

베르누이 분포 \(\text{Bernoulli}(p)\)

\[ p_X(x) = p^x(1-p)^{1-x}, \quad x \in \{0,1\} \]

지지: \(\{0,1\}\), 커널: \(p^x(1-p)^{1-x}\)

이항 분포 \(\text{Binomial}(n,p)\)

\[ p_X(k) = \binom{n}{k}p^k(1-p)^{n-k}, \quad k \in \{0,1,\ldots,n\} \]

지지: \(\{0,1,\ldots,n\}\), 커널: \(\binom{n}{k}p^k(1-p)^{n-k}\)

포아송 분포 \(\text{Poisson}(\lambda)\)

\[ p_X(k) = \frac{e^{-\lambda}\lambda^k}{k!}, \quad k \in \{0,1,2,\ldots\} \]

지지: \(\mathbb{Z}_{\geq 0}\), 커널: \(\frac{\lambda^k}{k!}\)

1.2 연속 분포

균등 분포 \(\text{Uniform}(a,b)\)

\[ f_X(x) = \frac{1}{b-a}\mathbf{1}_{[a,b]}(x) \]

지지: \([a,b]\), 커널: \(\mathbf{1}_{[a,b]}(x)\) (상수)

정규 분포 \(N(\mu, \sigma^2)\)

\[ f_X(x) = \frac{1}{\sigma\sqrt{2\pi}}\exp\!\left(-\frac{(x-\mu)^2}{2\sigma^2}\right) \]

지지: \(\mathbb{R}\), 커널: \(\exp\!\left(-\frac{(x-\mu)^2}{2\sigma^2}\right)\)

지수 분포 \(\text{Exp}(\lambda)\)

\[ f_X(x) = \lambda e^{-\lambda x}\mathbf{1}_{[0,\infty)}(x) \]

지지: \([0,\infty)\), 커널: \(e^{-\lambda x}\)

감마 분포 \(\text{Gamma}(\alpha,\beta)\)

\[ f_X(x) = \frac{1}{\beta^\alpha\Gamma(\alpha)}x^{\alpha-1}e^{-x/\beta}\mathbf{1}_{(0,\infty)}(x) \]

지지: \((0,\infty)\), 커널: \(x^{\alpha-1}e^{-x/\beta}\)

특수 경우: \(\text{Exp}(\lambda) = \text{Gamma}(1, 1/\lambda)\), 카이제곱: \(\chi^2(k) = \text{Gamma}(k/2, 2)\)

베타 분포 \(\text{Beta}(\alpha,\beta)\)

\[ f_X(x) = \frac{x^{\alpha-1}(1-x)^{\beta-1}}{B(\alpha,\beta)}\mathbf{1}_{(0,1)}(x) \]

\(B(\alpha,\beta) = \frac{\Gamma(\alpha)\Gamma(\beta)}{\Gamma(\alpha+\beta)}\) (베타 함수)

지지: \((0,1)\), 커널: \(x^{\alpha-1}(1-x)^{\beta-1}\)


2 분포 검증: 합·적분이 1인지 확인

2.1 포아송 합이 1임을 증명

\[ \sum_{k=0}^\infty \frac{e^{-\lambda}\lambda^k}{k!} = e^{-\lambda} \sum_{k=0}^\infty \frac{\lambda^k}{k!} = e^{-\lambda} \cdot e^{\lambda} = 1 \quad\blacksquare \]

(테일러 급수: \(e^\lambda = \sum_{k=0}^\infty \lambda^k / k!\))

2.2 지수 분포 적분이 1임을 증명

\[ \int_0^\infty \lambda e^{-\lambda x}\,dx = \lambda \cdot \left[-\frac{1}{\lambda}e^{-\lambda x}\right]_0^\infty = \lambda \cdot \frac{1}{\lambda} = 1 \quad\blacksquare \]

2.3 정규 분포 적분이 1임을 증명 (가우스 적분)

\[ \int_{-\infty}^\infty e^{-x^2/2}\,dx = \sqrt{2\pi} \]

증명: \(I = \int_{-\infty}^\infty e^{-x^2/2}dx\) 라 하면:

\[ I^2 = \int_{-\infty}^\infty\int_{-\infty}^\infty e^{-(x^2+y^2)/2}dx\,dy = \int_0^{2\pi}\int_0^\infty e^{-r^2/2} r\,dr\,d\theta = 2\pi \cdot 1 = 2\pi \]

따라서 \(I = \sqrt{2\pi}\), \(\int_{-\infty}^\infty \frac{1}{\sigma\sqrt{2\pi}}e^{-(x-\mu)^2/(2\sigma^2)}dx = 1\). \(\quad\blacksquare\)


3 혼합 분포의 밀도

정의: 혼합 분포

\(K\) 개의 성분 분포 \(f_1, \ldots, f_K\) 와 혼합 가중치 \(\pi_k > 0\), \(\sum \pi_k = 1\):

\[ f_X(x) = \sum_{k=1}^K \pi_k\,f_k(x) \]

검증: \(\int f_X(x)dx = \sum_k \pi_k \int f_k(x)dx = \sum_k \pi_k = 1\)

예시: 2-성분 가우시안 혼합 (Gaussian Mixture Model)

\[ f_X(x) = 0.4 \cdot N(x;\,-2, 1) + 0.6 \cdot N(x;\,3, 4) \]

이 분포는 단일 분포 가족에 속하지 않지만, 유효한 PDF다.

활용
  • EM 알고리즘: GMM의 모수 추정
  • 군집 분석: 각 성분이 클러스터에 대응
  • 생존 분석: 치료 반응이 다른 두 그룹 혼합

4 응용 분야

분야 PDF·PMF 역할 구체적 예시
베이지안 추론 사전·사후 분포의 커널 \(p(\theta \mid \mathbf{x}) \propto p(\mathbf{x} \mid \theta)p(\theta)\)
최대우도추정 우도 함수 = PDF의 곱 \(L(\theta) = \prod_i f(x_i \mid \theta)\)
정보이론 엔트로피 \(H = -\int f\log f\,dx\) 미분 엔트로피 (연속 분포)
커널 밀도 추정 PDF를 데이터로부터 추정 KDE: \(\hat{f}(x) = \frac{1}{nh}\sum K\!\left(\frac{x-x_i}{h}\right)\)
딥러닝 출력 분포 모델링 소프트맥스 = 카테고리 PMF
A/B 테스트 검정 통계량의 귀무분포 \(t\)-분포 PDF로 p-value 계산

5 코드 예시

5.1 Step 1: 순수 Python — PDF·PMF 검증과 커널 구현

import math

# ── PDF 조건 검증 (수치 적분) ────────────────────────────────────
def riemann_integral(f, a, b, n=100_000):
    """단순 구분구적법으로 f를 [a,b]에서 적분"""
    dx = (b - a) / n
    return sum(f(a + (i + 0.5) * dx) for i in range(n)) * dx

# 정규 분포 N(0,1)
def norm_pdf(x, mu=0, sigma=1):
    return math.exp(-0.5*((x-mu)/sigma)**2) / (sigma * math.sqrt(2*math.pi))

integral_norm = riemann_integral(norm_pdf, -10, 10)
print(f"N(0,1) PDF 적분 = {integral_norm:.8f}")  # ≈ 1.0

# 베타 분포 Beta(2,3)
def gamma_func(n):
    return math.factorial(n-1) if isinstance(n, int) else math.gamma(n)

def beta_pdf(x, a=2, b=3):
    if not 0 < x < 1: return 0
    B = gamma_func(a) * gamma_func(b) / gamma_func(a+b)
    return x**(a-1) * (1-x)**(b-1) / B

integral_beta = riemann_integral(beta_pdf, 0, 1)
print(f"Beta(2,3) PDF 적분 = {integral_beta:.8f}")  # ≈ 1.0

# ── PMF 검증 ─────────────────────────────────────────────────────
def poisson_pmf(k, lam=3):
    return math.exp(-lam) * lam**k / math.factorial(k)

def binomial_pmf(k, n=10, p=0.3):
    return math.comb(n, k) * p**k * (1-p)**(n-k)

total_poisson  = sum(poisson_pmf(k)    for k in range(50))   # 무한합 근사
total_binomial = sum(binomial_pmf(k)   for k in range(11))

print(f"\nPoisson(3) PMF 합  = {total_poisson:.10f}")
print(f"Binomial(10,0.3) 합 = {total_binomial:.10f}")

# ── 커널 표현: 정규화 상수 계산 ─────────────────────────────────────
# f(x) ∝ x^(α-1) * exp(-x/β) on (0,∞): Gamma(α,β)
alpha, beta = 3, 2
kernel = lambda x: x**(alpha-1) * math.exp(-x/beta)

# 수치 적분으로 정규화 상수 계산
Z = riemann_integral(kernel, 1e-6, 50)
print(f"\nGamma({alpha},{beta}) 커널 정규화 상수 Z = {Z:.6f}")
print(f"  이론값 β^α * Γ(α) = {beta**alpha * gamma_func(alpha):.6f}")

# PDF = kernel / Z
gamma_pdf_approx = lambda x: kernel(x) / Z
print(f"  검증: ∫f(x)dx = {riemann_integral(gamma_pdf_approx, 1e-6, 50):.8f}")

# ── 혼합 분포 ────────────────────────────────────────────────────
def gmm_pdf(x, mus=[-2, 3], sigmas=[1, 2], weights=[0.4, 0.6]):
    return sum(w * norm_pdf(x, mu, sigma)
               for w, mu, sigma in zip(weights, mus, sigmas))

integral_gmm = riemann_integral(gmm_pdf, -10, 15)
print(f"\n2-성분 GMM PDF 적분 = {integral_gmm:.8f}")  # ≈ 1.0

# 모드 찾기 (수치적)
x_vals = [i/100 - 5 for i in range(2000)]
mode = max(x_vals, key=gmm_pdf)
print(f"GMM 최빈값(mode) ≈ {mode:.2f}")

5.2 Step 2: scipy·numpy — 분포 비교·KDE·혼합 분포

import numpy as np
from scipy import stats
from scipy.integrate import quad

# ── 주요 분포 PDF 비교 ──────────────────────────────────────────────
distributions = {
    "Uniform(0,1)":   stats.uniform(0, 1),
    "Normal(0,1)":    stats.norm(0, 1),
    "Exp(1)":         stats.expon(1),
    "Gamma(2,1)":     stats.gamma(2, scale=1),
    "Beta(2,3)":      stats.beta(2, 3),
}

print("주요 분포 PDF 값 (x=0.5):")
for name, dist in distributions.items():
    pdf_val = dist.pdf(0.5)
    print(f"  {name:<18} f(0.5) = {pdf_val:.6f}")

# 적분 검증
print("\nPDF 정규화 검증 (수치 적분):")
for name, dist in distributions.items():
    if "Exp" in name:
        integral, _ = quad(dist.pdf, 0, 100)
    elif "Beta" in name or "Uniform" in name:
        integral, _ = quad(dist.pdf, 0, 1)
    else:
        integral, _ = quad(dist.pdf, -10, 10)
    print(f"  {name:<18} ∫f(x)dx = {integral:.8f}")

# ── 커널 밀도 추정 (KDE) ──────────────────────────────────────────
np.random.seed(42)
true_dist = stats.norm(3, 1.5)
data = true_dist.rvs(200)

# KDE
kde = stats.gaussian_kde(data, bw_method='silverman')

x_range = np.linspace(-2, 8, 300)
true_pdf  = true_dist.pdf(x_range)
kde_pdf   = kde(x_range)

# KL divergence (근사)
eps = 1e-10
kl_div = np.trapz(true_pdf * np.log((true_pdf + eps) / (kde_pdf + eps)), x_range)
print(f"\nKDE vs 이론 PDF:")
print(f"  KDE 적분 ≈ {np.trapz(kde_pdf, x_range):.6f}")
print(f"  KL(true||KDE) ≈ {kl_div:.6f}")

# ── 혼합 정규 분포 (GMM) ──────────────────────────────────────────
class GaussianMixture:
    def __init__(self, mus, sigmas, weights):
        self.components = [stats.norm(m, s) for m, s in zip(mus, sigmas)]
        self.weights = np.array(weights) / sum(weights)

    def pdf(self, x):
        return sum(w * c.pdf(x) for w, c in zip(self.weights, self.components))

    def rvs(self, size):
        labels = np.random.choice(len(self.weights), size=size, p=self.weights)
        return np.array([self.components[k].rvs() for k in labels])

gmm = GaussianMixture(mus=[-2, 3], sigmas=[1, 2], weights=[0.4, 0.6])

# 정규화 검증
x_vals = np.linspace(-8, 12, 1000)
integral_gmm = np.trapz([gmm.pdf(x) for x in x_vals], x_vals)
print(f"\nGMM PDF 적분 = {integral_gmm:.6f}")

# 표본 생성 및 KDE로 검증
gmm_samples = gmm.rvs(5000)
kde_gmm = stats.gaussian_kde(gmm_samples)

print(f"GMM 표본 평균 = {gmm_samples.mean():.4f}")
print(f"이론 평균 = {0.4*(-2) + 0.6*3:.4f}")  # = 1.0

# ── PMF 시각화: 여러 이산 분포 비교 ─────────────────────────────────
discrete_dists = {
    "Bernoulli(0.3)": stats.bernoulli(0.3),
    "Binomial(10,0.3)": stats.binom(10, 0.3),
    "Poisson(3)": stats.poisson(3),
    "Geometric(0.3)": stats.geom(0.3),
}

print("\n이산 분포 PMF (k=0,1,2,3,4,5):")
header = f"{'k':>4}"
for name in discrete_dists:
    header += f" {name:>18}"
print(header)
print("-" * (4 + 19 * len(discrete_dists)))
for k in range(6):
    row = f"{k:>4}"
    for name, dist in discrete_dists.items():
        try:
            row += f" {dist.pmf(k):>18.6f}"
        except:
            row += f" {'N/A':>18}"
    print(row)

6 관련 주제

선행 지식

후속 주제

관련 개념

Subscribe

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