이 포스트는 밀도 함수와 질량 함수 의 심화편이다. PDF·PMF의 정의, 존재 조건, 지지 집합, 커널 표현을 먼저 학습한 뒤 읽는 것을 권장한다.
통계 모델링에서 모델을 선택한다 = 분포를 선택한다:
- 회귀 분석: 오차가 정규 분포를 따른다고 가정 → 정규 분포의 성질을 모르면 잔차 진단이 불가능하다
- GLM: 반응 변수의 분포(이항, 포아송, 감마 등)에 따라 링크 함수와 추정 방법이 달라진다
- 베이지안 추론: 사전 분포로 베타·감마 등을 선택하는 이유는 켤레(conjugate) 관계 때문이다
- 생존 분석: 지수·와이블 분포는 “고장까지의 시간”을 모델링하는 기본 도구다
- 이상 탐지: 데이터가 어떤 분포를 따르는지 알아야 “비정상적으로 극단적인 값”의 기준을 정할 수 있다
각 분포의 PDF·PMF, 지지 집합, 모수의 의미를 정확히 알면 올바른 모델을 선택하고, 모델의 한계를 이해할 수 있다.
1 주요 분포의 PDF·PMF 성질
1.1 이산 분포
\[ p_X(x) = p^x(1-p)^{1-x}, \quad x \in \{0,1\} \]
지지: \(\{0,1\}\), 커널: \(p^x(1-p)^{1-x}\)
\[ 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}\)
\[ 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 연속 분포
\[ f_X(x) = \frac{1}{b-a}\mathbf{1}_{[a,b]}(x) \]
지지: \([a,b]\), 커널: \(\mathbf{1}_{[a,b]}(x)\) (상수)
\[ 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)\)
\[ f_X(x) = \lambda e^{-\lambda x}\mathbf{1}_{[0,\infty)}(x) \]
지지: \([0,\infty)\), 커널: \(e^{-\lambda x}\)
\[ 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)\)
\[ 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 관련 주제
선행 지식
- 밀도 함수와 질량 함수 — PDF·PMF 정의, 지지 집합, 커널 표현 (기초편)
- 확률변수 — PMF·PDF 기본 소개
- 분포 함수 — CDF와 PDF의 관계, 분위수 함수
후속 주제
- 연속확률변수와 확률밀도함수 — 기댓값·분산·MGF
- Exponential Family — PDF의 통합 체계
- Transformation of Random Variables — 변수변환 후 PDF 계산
관련 개념
- MLE — 우도 함수 = PDF의 곱 (독립 표본)
- Bayes’ Rule — 커널 표현으로 사후 분포 도출
- Convergence in Probability — 밀도 함수의 수렴