교차검증으로 KDE 대역폭을 선택하는 방법
커널 밀도 추정의 대역폭을 교차검증으로 선택하는 방법과 계산 가속, 경계 보정, 운영 시 진단 기준을 정리한다.
2026-08-14 · 최초 발행 2024-04-29
밀도 추정의 결과를 바꾸는 대역폭
KDE(Kernel Density Estimation)는 유한 표본에서 연속 분포의 밀도를 추정하는 비모수 방식이다. 각 관측치 주변에 커널 함수를 놓고 이를 합산하며, 평활화 매개변수인 대역폭으로 결과의 매끄러운 정도를 조절한다.
커널은 가우시안이나 Epanechnikov처럼 여러 선택지가 있지만, 성능에 대한 영향은 대역폭보다 작다. 대역폭이 작으면 고분산으로 과적합하기 쉽고, 너무 크면 고바이어스 상태로 분포의 구조가 사라진다. 다변량 KDE에서는 스칼라 대역폭 h 또는 대역폭 행렬 H를 사용하며, 공분산 스케일링과 비등방성도 함께 고려해야 한다.
교차검증은 데이터 분할을 통해 일반화 성능을 기준으로 h를 고르는 절차다. LOO 로그우도와 Least-Squares CV(LSCV, ISE 근사)가 대표 지표다. Silverman/Scott 규칙이나 Sheather–Jones 플러그인 방법과 비교하면, 데이터 분포에 맞춰 대역폭을 조정할 수 있다는 점이 특징이다.
커널보다 먼저 정리할 선택 기준
가우시안 커널은 범용적으로 쓰기 좋고 미분이 가능하며 FFT나 FGT 가속과도 잘 맞는다. Epanechnikov 커널은 이론적 최적성을 가지지만 구현 복잡도가 커질 수 있다.
다변량 데이터에서는 Mahalanobis 거리를 적용해 변수 간 스케일 차이를 보정할 수 있다. 공분산을 정규화한 뒤 스칼라 h를 선택하는 방식은 운영 관점에서 다루기 쉬운 절충안이다.
규칙기반 방법은 빠르게 초기 후보를 마련하는 데 적합하다. 다만 Silverman/Scott 규칙은 비정상 분포나 다봉형 분포에서 과평활될 수 있다. 초기값을 규칙기반으로 만들고, LSCV·LOO 우도 CV·K-폴드 CV·플러그인(SJ) 방법으로 후보를 좁히는 구성이 가능하다.
순진하게 계산하면 복잡도는 O(n^2)다. 데이터가 커지면 이산화(bin)/FFT, KD/Ball-Tree, Fast Gauss Transform, Nystrom 근사를 검토한다. 배치 또는 스트리밍 환경에서는 미니배치 근사 업데이트와 샘플 가중치를 적용할 수 있고, 파티션별로 계산한 부분 KDE를 합성하는 접근도 가능하다.
경계 근처에서는 바운더리 바이어스가 생길 수 있다. 반사(reflection), 경계 커널, logit 등의 변수 변환이 보정 수단이 된다. 과평활과 과소평활은 유효 모드 수, 점별 LOO 스코어, 퍼플렉시티 변화를 통해 진단하며, 시각화는 공통 스케일로 비교해야 한다.
후보 생성부터 운영 재학습까지
입력으로는 관측치 X, 차원 d, 선택 지표(LOO 로그우도 또는 LSCV), 후보 대역폭 집합 H가 필요하다. 샘플 가중치와 경계 정의는 선택 사항이다.
처리는 다음 흐름으로 진행한다.
- 표준편차 또는 Robust scaler를 사용해 스케일을 표준화하고 공분산을 정규화한다.
- Silverman/Scott 초기값에서 로그스페이스로 ±1~2 오더 범위의
H후보를 만든다. - 각
h에 KDE를 적합하고 검증 스코어를 계산하는 K-폴드 CV를 반복해 폴드 평균을 구한다. - 최적
h*를 선택한 뒤 전체 데이터로 최종 모델을 적합한다.
결과로는 추정 밀도 함수, 포인트별 로그우도, 모드/HPD 구간, 상위 95% 등고선 같은 임계값을 얻는다. h<=0이거나 분산이 0인 특성이 있으면 예외 처리가 필요하며, 소규모 노이즈를 추가할 수 있다. 수치 언더플로우는 로그-합-지수 안정화로 방지한다. CV가 실패하면 규칙기반 값으로 폴백하고 후보 범위를 넓힌다.
대역폭 선택 방식이 다른 지점
| 방법 | 성능 | 확장성 | 일관성(추정) | 안정성 | 운영 편의 |
|---|---|---|---|---|---|
| Silverman/Scott 규칙 | 초기값 양호, 복잡 분포 과평활 가능 | 매우 우수 | 중간 | 높음 | 매우 우수 |
| 플러그인(Sheather–Jones) | 실전 성능 우수, 다봉형 대응 | 우수 | 높음 | 중간 | 우수 |
| LSCV(최소제곱 CV) | ISE 근사 최소화, 노이즈 민감 | 중간 | 높음 | 중간 | 보통 |
| LOO 로그우도 CV | 이상치 견고성 우수, 모델 적합도 직접 최적화 | 중간 | 높음 | 중간~높음 | 보통 |
| K-폴드 그리드/베이즈 탐색 | 구현 단순·유연, 후보 의존 | 우수 | 높음 | 높음 | 우수 |
분포 모양이 의사결정에 연결되는 곳
이상치 탐지에서는 KDE 등고선을 이용해 밀도 하위 q 분위 영역을 이상치로 정의할 수 있다. 대역폭을 CV로 선택하고 밀도를 추정한 뒤, 유효 임계값을 정해 운영 ROC로 검증한다.
고객 세분화와 캠페인 타깃팅에서는 구매 금액·빈도의 2D KDE로 다봉형 구조를 파악한다. 공분산을 정규화하고 대역폭 행렬을 근사한 다음, 모드를 기준으로 세그먼트를 추출한다.
금융 리스크의 비모수 VaR/ES 추정에서는 수익률 KDE로 꼬리 확률을 직접 추정한다. Heavy-tail에 대비해 로그우도 CV를 적용하고, 바운더리 변환 없이 백테스트로 적합성을 검증한다.
제조 공정에서는 공정 특성값의 KDE를 이용해 공정변동을 감지할 수 있다. 윈도우 기반 재학습, HPD 변화 감시, 경보 임계 재조정이 운영 절차가 된다.
규칙기반 방식과 비교해 LOO-CV 최적화는 평균 로그우도를 520% 개선할 수 있다. LSCV 기준으로는 MISE가 1030% 감소할 수 있으며, 이는 데이터 구조와 샘플 수에 의존한다. 분포 가정을 제거하면 모델의 견고성이 높아지고, 다봉형·비대칭 분포를 포착해 의사결정 품질을 높일 수 있다.
교차검증으로 대역폭을 고르는 Python 예시
환경은 Python 3.10+, numpy 1.26+, scikit-learn 1.4+, matplotlib 3.8+를 가정한다. 연속형 변수를 대상으로 한 소규모 2D 시각화 예시다.
# pip install numpy scikit-learn matplotlib
import numpy as np
from sklearn.model_selection import KFold
from sklearn.neighbors import KernelDensity
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
# 1) 데이터 생성: 다봉형 분포
rng = np.random.default_rng(42)
n = 2000
X = np.vstack([
rng.normal(loc=[0, 0], scale=[0.5, 0.8], size=(n//2, 2)),
rng.normal(loc=[3, 2], scale=[0.6, 0.4], size=(n//2, 2)),
])
# 2) 전처리: 스케일 정규화
scaler = StandardScaler().fit(X)
Xs = scaler.transform(X)
# 3) 대역폭 후보군(로그스페이스)
h0 = 1.06 * np.min(Xs.std(axis=0)) * Xs.shape[0] ** (-1.0 / (Xs.shape[1] + 4)) # Scott/Silverman 혼합 초기값
candidates = np.logspace(np.log10(h0/4), np.log10(h0*4), 15)
# 4) K-폴드 CV로 로그우도 최대화
def cv_kde_bandwidth(X, candidates, k=5, kernel='gaussian'):
kf = KFold(n_splits=k, shuffle=True, random_state=42)
scores = []
for h in candidates:
fold_scores = []
for train_idx, val_idx in kf.split(X):
Xtr, Xval = X[train_idx], X[val_idx]
kde = KernelDensity(kernel=kernel, bandwidth=max(h, 1e-3))
kde.fit(Xtr)
# 평균 LOO 근사: 검증 폴드 로그우도
s = kde.score(Xval) / len(Xval)
fold_scores.append(s)
scores.append(np.mean(fold_scores))
best = int(np.argmax(scores))
return candidates[best], scores
h_star, scores = cv_kde_bandwidth(Xs, candidates)
print(f"Best bandwidth (CV): {h_star:.4f}")
# 5) 최종 KDE 적합
kde = KernelDensity(kernel='gaussian', bandwidth=h_star).fit(Xs)
# 6) 시각화: 등고선
xx, yy = np.meshgrid(np.linspace(Xs[:,0].min()-3, Xs[:,0].max()+3, 200),
np.linspace(Xs[:,1].min()-3, Xs[:,1].max()+3, 200))
grid = np.c_[xx.ravel(), yy.ravel()]
zz = np.exp(kde.score_samples(grid)).reshape(xx.shape)
plt.figure(figsize=(5,4))
plt.contourf(xx, yy, zz, levels=15, cmap='mako')
plt.scatter(Xs[:,0], Xs[:,1], s=5, alpha=0.3, color='white')
plt.title("KDE with CV-selected bandwidth")
plt.tight_layout()
plt.show()
고차원 데이터에서는 d>4 상황을 피하고, PCA/UMAP으로 차원을 줄인 뒤 KDE를 적용하는 방식을 고려할 수 있다. 후보 탐색은 로그-하이퍼밴드나 베이지안 최적화로 자동화할 수 있다.
[0,1] 구간의 1D 데이터에서는 반사 샘플링으로 경계 편향을 완화할 수 있다.
def reflect_01(x):
# [0,1] 구간 반사
xr = np.concatenate([x, -x, 2 - x])
return np.clip(xr, 0, 1)
# 사용: xr = reflect_01(x.reshape(-1,1))
계산 비용과 추정 품질의 균형
대역폭 탐색은 데이터 스케일을 정규화한 뒤 수행한다. 규칙기반으로 시작하고 CV로 정밀화한 뒤, 재분할·재시드를 통한 로버스트 점검을 더하는 흐름이 적합하다. LOO 로그우도와 LSCV를 동시에 모니터링하면 과평활과 과소평활의 균형을 점검할 수 있다.
교차검증 비용은 일반화 성능 향상과 맞바꿔야 한다. 대용량 환경에서는 이산화/FFT와 부분샘플링을 병행한다. 커널 종류의 영향은 상대적으로 작고 대역폭의 영향이 크므로, 구현 단순성을 위해 가우시안 기본 설정을 선택할 수 있다. 다변량에서 정밀한 H 행렬을 추정하는 난이도와 스칼라 h의 운영 편의 사이에서는 공분산 정규화와 스칼라 h 조합이 실무 절충안이 된다.
KDE를 안정적으로 운영하려면 규칙기반 초기값만으로 멈추지 않고 K-폴드 또는 LOO 교차검증으로 대역폭을 데이터에 맞춰 조정해야 한다. 계산 가속과 경계 보정을 함께 적용하고, 재학습과 진단 지표를 운영 흐름에 포함한다.