결측 데이터와 트리 기반 모델의 도전 과제
현실 세계의 데이터셋에서는 거의 언제나 일부 값이 누락되는 경우가 발생한다. 특히 고차원일수록, 혹은 관측이 복잡할수록 결측 확률은 증가한다. 전통적으로 결측치는 평균 대치, 회귀 대치, 또는 완전한 사례만 사용함으로써 처리되곤 한다. 그러나 이러한 방법들은 편향을 유발하거나 분산을 과대추정할 수 있으며, 이론적 근거가 부족한 경우가 많다.
트리 기반 모델, 특히 랜덤 포레스트(Random Forest)는 결측치에 대해 독특한 해결책을 제공할 수 있다. 그 핵심은
MIA (Missingness Incorporated in Attributes)라 불리는 기법이다. 이 방법은 결측 자체를 정보로 간주하며, 별도의 대치 없이 트리 분할 과정에 직접 통합한다.
MIA의 작동 원리
표준 결정 트리에서는 각 분할 노드에서 특정 변수 \(X_j\)에 대해 임계값 \(S\)를 선택하고, \(X_{ij} < S\) 인 샘플은 왼쪽 자식 노드로, 그렇지 않은 경우는 오른쪽 자식 노드로 보낸다. 그러나 \(X_{ij}\)가 결측인 경우, MIA는 다음 세 가지 후보 규칙 중 최적의 것을 선택한다:
- 규칙 A: 관측된 값에 대해 일반적인 분할을 수행하고, 결측 샘플은 모두 왼쪽 노드로 보냄.
- 규칙 B: 관측된 값에 대해 일반적인 분할을 수행하고, 결측 샘플은 모두 오른쪽 노드로 보냄.
- 규칙 C: 결측 여부 자체를 분할 기준으로 삼음 — 즉, 결측이면 왼쪽, 관측이면 오른쪽.
각 규칙은 목적 함수(예: CART 기준)를 기반으로 평가되며, 가장 정보 이득이 큰 규칙이 채택된다. 이 방식은 결측 패턴이 예측 변수와 관련이 있을 때 유의미한 신호로 작용할 수 있도록 해준다.
분포형 랜덤 포레스트(DRF)를 활용한 실습 예제
MIA는 Generalized Random Forests(GRF) 프레임워크 내에서 구현되어 있으며, 이를 기반으로 한
drf 패키지에서도 활용 가능하다. 아래 예제는 조건부 분포 추정을 목적으로 하는 DRF에 MIA를 적용한 사례다.
먼저, 이변량 정규분포에서 공분산 구조를 가진 설계변수 \(X\)와 선형 종속관계를 따르는 반응변수 \(Y\)를 생성한다:
library(mvtnorm)
set.seed(2)
n <- 2000
beta1 <- 1
beta2 <- -1.8
# 공분산 행렬을 가진 X 생성
X <- rmvnorm(n, mean = c(0, 0), sigma = matrix(c(1, 0.7, 0.7, 1), 2, 2))
u <- rnorm(n, sd = sqrt(exp(X[, 1]))) # X₁에 의존하는 이분산성
Y <- beta1 * X[, 1] + beta2 * X[, 2] + u
이제 \(X_1\)에 대해 MAR(Missing at Random) 메커니즘을 적용하여 일부 값을 결측 처리한다:
# X₂ ≤ -0.2인 경우에만 X₁이 30% 확률로 결측
prob_na <- 0.3
X[ , 1] <- ifelse(X[ , 2] <= -0.2 & runif(n) < prob_na, NA, X[ , 1])
결측이 단순 무작위(MCAR)가 아니라 \(X_2\)에 의존하므로, 삭제 기법은 편향을 초래할 수 있다. 이제 MIA 기반 DRF를 적합하고, 특정 입력 \(x = (1, 1)\)에서의 조건부 기댓값과 분산을 추정한다:
library(drf)
x_query <- matrix(c(1, 1), ncol = 2)
alpha <- 0.05
# 결측치를 자연스럽게 처리하는 DRF 적합
drf_model <- drfCI(
X = X,
Y = Y,
min.node.size = 5,
splitting.rule = 'FourierMMD',
num.features = 10,
B = 100
)
# 예측 가중치 계산
pred_result <- predictdrf(drf_model, x = x_query)
weights <- pred_result$weights[1, ]
조건부 기댓값 추정
가중치를 이용해 \( \mathbb{E}[Y|X=x] \)을 점추정하고, 부트스트랩 가중치로부터 신뢰구간을 구성한다:
# 점추정
cond_mean <- sum(weights * Y)
# 부트스트랩 기반 분포 생성
boot_means <- sapply(pred_result$weightsb, function(wb) sum(wb[1, ] * Y))
var_est <- var(boot_means - cond_mean)
# 95% 신뢰구간 (정규근사 사용)
z <- qnorm(1 - alpha / 2)
ci_lower <- cond_mean - z * sqrt(var_est)
ci_upper <- cond_mean + z * sqrt(var_est)
round(c(ci_lower, cond_mean, ci_upper), 2)
# 출력 예시: [-1.15, -0.67, -0.19]
결측 처리 전의 결과([-1.00, -0.69, -0.37])와 비교하면 중심점은 유사하지만, 분산이 약 2.4배 증가함을 확인할 수 있다. 이는 결측으로 인한 정보 손실을 반영한다.
조건부 분산 추정
비슷한 방식으로 조건부 분산도 추정 가능하다:
cond_var <- sum(weights * Y^2) - cond_mean^2
boot_vars <- sapply(pred_result$weightsb, function(wb) {
mu_boot <- sum(wb[1, ] * Y)
sum(wb[1, ] * Y^2) - mu_boot^2
})
var_of_var <- var(boot_vars - cond_var)
se <- sqrt(var_of_var)
ci_lower_v <- cond_var - z * se
ci_upper_v <- cond_var + z * se
c(ci_lower_v, cond_var, ci_upper_v)
# 출력 예시: [1.79, 2.74, 3.69]
기존 결과([1.89, 2.65, 3.42])와 비교 시 추정값은 오히려 더 진실값에 가까울 수 있으나, 이는 표본 변동성의 영향일 수 있음을 유의해야 한다.
논의 및 주의사항
MIA는 결측 치환 없이도 트리 기반 모델을 효과적으로 운용할 수 있게 해주는 실용적인 접근법이다. 특히 결측 패턴이 정보를 포함할 때, 이 기법은 오히려 성능을 향상시킬 수 있다. GRF 계열의 패키지에서 네이티브 지원되며, 범주형 변수와 연속형 변수 모두에 적용 가능하다.
그러나 다음과 같은 제한점을 인지해야 한다:
- 현재로서는 대수적 일관성(consistency)이나 신뢰구간의 유효성에 대한 이론적 보장이 부족하다.
- MAR 이외의 메커니즘(예: MNAR)에서는 편향이 심화될 수 있다.
- 모델 복잡도가 증가할 수 있으며, 해석이 직관적이지 않을 수 있다.
결론적으로, MIA는 결측치 문제에 대한 빠르고 강건한 타당한 타협안이며, 특히 탐색적 분석이나 빠른 프로토타이핑에서 유용하다. 다만, 공식 보고서나 정책 결정에는 추가적인 민감도 분석이 필요하다.