본문 바로가기
Artificial Intelligence/60. Python

[PYTHON] 시계열 데이터 Cross-Validation의 3가지 데이터 누수 해결 방법과 방지 대책

by Papa Martino V 2026. 4. 28.
728x90

Cross-Validation
Cross-Validation

 

머신러닝 모델의 일반화 성능을 평가할 때 가장 널리 사용되는 기법은 교차 검증(Cross-Validation)입니다. 하지만 우리가 다루는 데이터가 '시간'의 흐름을 가진 시계열 데이터(Time-series)라면 이야기는 완전히 달라집니다. 일반적인 K-Fold 교차 검증을 시계열 데이터에 무심코 적용하는 순간, 모델은 미래의 정보를 이용해 과거를 예측하는 '미래 읽기' 오류, 즉 데이터 누수(Data Leakage)에 빠지게 됩니다. 본 포스팅에서는 시계열 데이터의 특수성을 고려하여 데이터 누수를 원천 차단하는 3가지 핵심 검증 전략과 파이썬(Python)을 활용한 실무적인 해결 방법을 심층적으로 다룹니다.


1. 시계열 데이터 누수의 발생 원인과 일반 CV와의 차이

시계열 데이터의 핵심 가정은 "과거의 사건이 미래에 영향을 미친다"는 것입니다. 데이터 간의 독립성(IID)이 보장되지 않기 때문에 검증 세트가 훈련 세트보다 시간적으로 앞서게 되면 모델은 현실 세계에서 불가능한 정보를 학습하게 됩니다.

항목 일반적인 K-Fold CV 시계열(Time-series) CV
데이터 샘플링 무작위 셔플링 (Random Shuffle) 시간 순서 유지 (Chronological Order)
데이터 독립성 각 폴드가 독립적이라고 가정 자기상관성(Autocorrelation) 존재
데이터 누수 위험 낮음 매우 높음 (Look-ahead Bias)
주요 검증 전략 Stratified, Group K-Fold Expanding/Rolling Window, Blocking

2. 데이터 누수를 방지하는 3가지 핵심 검증 전략

전략 1: Expanding Window (Time Series Split)

훈련 세트를 시간에 따라 점진적으로 확장하며 다음 시점의 데이터를 검증하는 방식입니다. Scikit-learn의 TimeSeriesSplit이 사용하는 표준 방식이며, 과거의 모든 정보를 활용한다는 장점이 있습니다.

전략 2: Rolling Window (Sliding Window)

훈련 세트의 크기를 고정하고 시간 축을 따라 이동시키는 방식입니다. 모델이 최신 트렌드에 더 민감하게 반응해야 하거나, 너무 오래된 데이터가 현재의 예측에 방해가 될 때 효과적인 해결 방법입니다.

전략 3: Blocked Cross-Validation (Gap-based)

훈련 데이터와 검증 데이터 사이에 의도적인 간격(Gap)을 두는 방식입니다. 시계열 데이터의 관성(Lag)으로 인해 인접한 데이터가 유사한 값을 가지는 경우 발생할 수 있는 '근접 누수'를 방지하기 위해 사용됩니다.


3. 실무 적용을 위한 Python 샘플 예제 (Example 7선)

실제 금융 데이터나 센서 데이터를 처리할 때 즉시 적용 가능한 시계열 검증 코드 예제입니다.

Ex 1. Scikit-learn TimeSeriesSplit 기본 사용 방법

from sklearn.model_selection import TimeSeriesSplit
import numpy as np

X = np.array([[1], [2], [3], [4], [5], [6], [7], [8]])
y = np.array([1, 2, 3, 4, 5, 6, 7, 8])

# n_splits를 통해 폴드 수 지정 (데이터 순서 엄격 준수)
tscv = TimeSeriesSplit(n_splits=3)

for train_index, test_index in tscv.split(X):
    print("Train:", train_index, "Validation:", test_index)

Ex 2. 훈련/검증 사이의 Gap(간격) 설정으로 누수 해결

# gap 파라미터를 사용하여 훈련 종료 시점과 검증 시작 시점 사이를 띄움
tscv_with_gap = TimeSeriesSplit(n_splits=3, gap=1)

for train_index, test_index in tscv_with_gap.split(X):
    print(f"Train end: {train_index[-1]}, Val start: {test_index[0]}")

Ex 3. Rolling Window (Sliding) 구현 방법

# max_train_size를 지정하여 훈련 데이터의 윈도우 크기를 고정
rolling_cv = TimeSeriesSplit(n_splits=5, max_train_size=2)

for train_index, test_index in rolling_cv.split(X):
    print("Fixed Window Train:", train_index)

Ex 4. Pandas를 활용한 날짜 기준 시계열 분할

import pandas as pd

df = pd.DataFrame({'date': pd.date_range('2026-01-01', periods=10), 'val': range(10)})

# 특정 날짜를 기준으로 수동 분할하여 테스트 세트의 시간적 격리 보장
train = df[df['date'] < '2026-01-08']
test = df[df['date'] >= '2026-01-08']

Ex 5. Purged K-Fold (금융 시계열 특화) 개념 구현

def get_purged_indices(data, train_idx, val_idx, pct_purge=0.01):
    # 검증 데이터 직전의 일부 데이터를 삭제하여 오염 방지
    purge_size = int(len(data) * pct_purge)
    new_train_idx = train_idx[:-purge_size]
    return new_train_idx, val_idx

Ex 6. 타겟 변수의 Lagging 처리를 통한 누수 방지 대책

# 현재 시점(t)의 예측을 위해 t-1, t-2의 정보만 피처로 사용하도록 오프셋 조정
df['target'] = df['val'].shift(-1) # 예측 타겟
df['feature_lag1'] = df['val'].shift(1) # 과거 데이터
df.dropna(inplace=True)

Ex 7. GroupTimeSeriesSplit (다변량/다수 개체 시계열)

from sklearn.model_selection import LeaveOneGroupOut
# 동일 시간대에 여러 상점/ID가 있는 경우 시간을 그룹으로 묶어 순서대로 분할
groups = df['date'].dt.month
# 시간 그룹을 유지하며 시계열 순서로 검증 진행

4. 결론: 시계열 검증의 골든 룰

시계열 데이터에서 교차 검증을 수행할 때 가장 위험한 것은 "이미 벌어진 일을 알고 있는 모델"을 만드는 것입니다. 이를 방지하기 위해서는 다음 3가지를 반드시 기억해야 합니다.

  1. 무작위 셔플링을 절대 사용하지 마십시오. (shuffle=False)
  2. 검증 데이터는 항상 훈련 데이터보다 미래의 시점이어야 합니다.
  3. 데이터 간의 자기상관성이 강하다면 Gap(완충 지대)을 두어 모델이 근접 데이터를 외우지 못하게 하십시오.

시계열 데이터 누수는 초기 단계에서 발견하기 매우 어렵지만, 실전 배포 시 모델 성능이 급락하는 가장 큰 원인이 됩니다. 엄격한 검증 설계를 통해 신뢰할 수 있는 AI 모델을 구축하시기 바랍니다.


참고 문헌 (Sources)

  • Hyndman, R. J., & Athanasopoulos, G. (2021). Forecasting: Principles and Practice. OTexts.
  • Lopez de Prado, M. (2018). Advances in Financial Machine Learning. Wiley.
  • Scikit-learn documentation: "Visualizing Cross-Validation Behavior in Time Series".
  • Bergmeir, C., & Benítez, J. M. (2012). "On the use of cross-validation for time series predictor evaluation". Information Sciences.
728x90