AI

[시계열 데이터] Sequential Data의 Validation(Sequential Data의 Cross-Validation)

lungjae 2024. 12. 12. 04:04

Ref : https://gmnam.tistory.com/230

 

시계열 모델의 교차검증 (cross-validation) 전략 (파이썬 코드 포함)

두 가지 time series 교차검증 (cross-validation) 방법 교차검증 cross validataion (CV) 은 데이터 모델링에 있어 모델의 정확도를 확인할 수 있는 효율적인 방법이다. 이것은 데이터를 훈련용과 테스트용을

gmnam.tistory.com

 

일반적인 Validation의 경우, Train데이터의 일부를 랜덤하게 샘플링하여 Validation Set을 만든다.

 

시계열 데이터와 같은 순서가 있는 데이터는 랜덤하게 샘플링할 경우 Sequence 정보를 무시하는것이 되므로, 조금 다른Cross Validation을 고려해야한다.


 

1. 순서를 망가뜨리지 않고, Train의 연속적인 일부를 잘라내어 Validation으로 사용하기

예를 들면 1900년 ~ 2020년 까지의 어떤 데이터가 있다고 할 때, 1900~1990년까지의 데이터를 train데이터로 쓰고, 1990~2020년까지의 데이터를 Validation데이터로 사용하는 것이다. (단순히 슬라이싱으로 만들어줄 수 있음)

 


2. sklearn의 TimeSeriesSplit 이용

from sklearn.model_selection import TimeSeriesSplit

tscv = TimeSeriesSplit(n_splits=5)
for train_index, val_index in tscv.split(data):
    train_data, val_data = data[train_index], data[val_index]

sklearn에서 제공해주는 대표적인 Cross Validation 기법인, TimeSeriesSplit을 사용해볼 수 있다.

 

예를 들어, 데이터가 아래와 같다고 하자.

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10] (순서 고려)

 

n_splits=4일 때, 아래와 같은 식으로 Split한다.

Split 1.

Train : [1, 2]

Val : [3, 4]

Split 2:

Train : [1, 2, 3, 4]

Val : [5, 6]

Split 3:

Train : [1, 2, 3, 4, 5, 6]

Val : [7, 8]

Split 4:

Train : [1, 2, 3, 4, 5, 6, 7, 8]

Val: [9, 10]

 

그림으로 나타내보면 아래와 같다.

https://gmnam.tistory.com/230


3. Blocked Cross Validation

아래 그림과 같은 식으로 Split하는 방식이다.

Ref : https://www.packtpub.com/en-us/learning/how-to-tutorials/cross-validation-strategies-for-time-series-forecasting-tutorial/

예를 들어, 다음과 같은 식으로 Split된다.

 

데이터: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Gap 크기 = 2, Fold = 3인 경우:

 

Split 1:

Train : [1, 2, 3]

Val : [6, 7] (4, 5는 Gap)

Split 2:

Train : [1, 2, 3, 4, 5]

Val : [8, 9] (6, 7은 Gap)

Split 3:

Train : [1, 2, 3, 4, 5, 6, 7]

Val : [10] (8, 9는 Gap)

 

TimeSeriesSplit과 달리, 어느 정도 Gap을 두고 Split되기 때문에, Train 데이터와 Validation 데이터 사이에 있는 시간적인 의존성을 최대한 없애준다.


4. Sliding Window 방식 활용

Validation Set 사이즈를 고정해두고, Sliding Window방식으로 Validation Set을 Split하는 방식도 생각해볼 수 있다.

window_size = 20  # 훈련 데이터 크기
val_size = 10     # 검증 데이터 크기
for i in range(len(data) - window_size - val_size):
    train_data = data[i:i + window_size]
    val_data = data[i + window_size:i + window_size + val_size]

 


 

그 외에도, 라벨 분포까지 고려하여 Stratified Split을 해본다거나.. 다른 여러 기준으로도 Split할 수 있을 것이다.

 

어쨌든 핵심은, Sequential 데이터는 Sequential 정보를 유지해야하기 때문에, Validation Set을 만들때는 연속적인 일부분을 떼어내야하므로 어떤식으로 Split하는지가 조금씩 다를 뿐이다. 큰 차이는 없어보임.