본문 바로가기
[파이썬]/머신러닝

[머신러닝] 훈련·검증·테스트 데이터로 분리하는 이유(+분리 비율)

by sung min_Kim 2023. 12. 27.


 이번 글에서는 "왜 데이터를 훈련, 검증, 테스트 데이터로 분리해야 하는지, 그리고 이를 어떻게 체계적으로 분리할 수 있는지"에 대해 자세히 알아보려 한다.
차례와 사용 툴 및 라이브러리는 아래와 같다.

 [차례]
첫 번째, 훈련 · 검증 · 테스트 데이터
두 번째, random_state 매개변수 역할

세 번째, 데이터를 분리하는 이유
네 번째, 데이터 분리 방법

 [사용 툴]

- Jupyter notebook(웹 기반 대화형 코딩 환경)
 
 [사용 라이브러리 및 모듈]

  • 머신러닝 라이브러리 및 모델: scikit-learn
    - sklearn.model_selection.train_test_split: 훈련 및 테스트 데이터 세트 분리

 


훈련 · 검증 · 테스트 데이터


 데이터 기반 모델링에서 성공적인 모델을 구축하기 위해서는 데이터를 훈련, 검증, 테스트로 나누는 과정이 필수적이다. 이 세 종류의 데이터 세트는 모델 개발의 각기 다른 단계에 필요하며, 모델이 학습한 바를 평가하고 실제 환경에서의 적용 가능성을 파악하는 데 중요한 역할을 한다.

훈련 데이터(Traing Data)


 훈련 데이터 세트는 모델을 '학습(훈련)'시키는 데 사용된다. 모델은 이 데이터를 기반으로 패턴을 인식하고, 파라메터를 조정하며 학습한다. 주로 훈련 데이터 세트에 사용되는 변수명은 다음과 같다:

  • 독립변수: train_input, train_x, X_train
  • 종속변수: train_target, train_y, y_train

 

검증 데이터(Validation Data)


 검증 데이터 세트는 훈련 과정 중 모델 성능을 주기적으로 평가하는 데 사용된다. 이를 통해, 모델이 훈련 데이터에 과적합되는지 여부를 파악하며, 하이퍼파라메터의 조정이나 모델 구조 변경과 같은 결정을 내리는 데 필수적이다. 주로 검증 데이터 세트에 사용되는 변수명은 다음과 같다:

  • 독립변수: val_input, val_x, X_val
  • 종속변수: val_target, val_y, y_val

 

테스트 데이터(Test Data)

 
 테스트 데이터 세트는 모델 학습이 완료되고 검증 과정이 끝난 후 모델의 최종 성능을 평가하는 데 사용된다. 테스트 데이터는 학습 과정에서는 전혀 사용되지 않으며, 모델이 실제 환경에서 얼마나 잘 작동하는지를 평가하는 데 사용된다. 주로 테스트 데이터 세트에 사용되는 변수명은 다음과 같다:

  • 독립변수: test_input, test_x, X_test
  • 종속변수: test_target, test_y, y_test

 


random_state 매개변수 역할


 'random_state'를 설정하는 이유는 데이터를 분리할 때 일관된 결과를 얻기 위함이다. 즉, 이 값을 설정하면 코드를 여러 번 실행하더라도 데이터가 동일한 방식으로 분리되어, 결과의 재현성이 보장된다.

 'random_state=42' 같은 특정 값은 임의로 선택된 것으로, 특별한 의미를 가지는 것은 아니다. 이 값은 랜덤 한 데이터 생성 과정에 규칙성을 부여하기 위해 사용되며, 다른 숫자를 사용해도 상관없다. 주요한 점은 동일한 'random_state' 값을 사용하면 동일한 결과를 얻을 수 있다는 것이다.


데이터를 분리하는 이유

 

 

  1. 모델 훈련과 평가의 분리
    모델을 훈련하는 데 사용되는 훈련 데이터와 모델의 성능을 평가하는 데 사용되는 검증 및 테스트 데이터를 분리함으로써, 모델이 학습데이터에만 특화되어 성능을 과대평가하는 과적합(overfitting)을 방지할 수 있다.


  2. 하이퍼파라메터 튜닝
    검증 데이터는 모델의 하이퍼파라메터를 조정하는 데 사용된다. 훈련 세트에서 모델을 학습한 후, 검증 세트를 사용하여 모델의 설정을 조정하고, 이 조정이 실제로 모델의 성능을 향상시키는지를 평가한다.


  3. 최종 성능 평가
    테스트 데이터는 모든 모델 훈련 및 검증 절차가 끝난 후, 모델의 최종 성능을 평가하는 데 사용된다. 테스트 데이터는 모델 개발 과정에서 한 번도 사용되지 않으며, 모델이 실제로 새로운 데이터에 얼마나 잘 일반화되는지를 평가하는 데 중요하다.

 


데이터 분리 방법

 

1. 단계적 분리
1.1 훈련 대 테스트 분리


 데이터 분리의 첫 단계에서는 주로 전체 데이터 세트를 훈련 세트와 테스트 세트로 '7:3' 비율로 나눈다. 이는 전체 데이터의 약 70%를 훈련에 사용하고, 나머지 30%를 테스트에 사용하는 것을 의미하며, 이 경우 'test_size=0.3'으로 설정한다. 그러나, 데이터의 양이나 특성에 따라 유동적으로 조정될 수 있다. 예를 들어, '75:25(7.5:2.5)' 또는 '80:20(8:2)'의 비율을 적용하는 경우도 있다.

from sklearn.model_selection import train_test_split

# 전체 데이터를 훈련 데이터와 테스트 데이터로 나누기 (비율 7:3)
X_train, X_temp, y_train, y_temp = train_test_split(X, y, 
                                                    test_size=0.3,
                                                    random_state=42)

print(f"훈련 데이터 : {X_train.shape}, {y_train.shape}")
print(f"테스트 데이터 : {X_test.shape}, {y_test.shape}")

훈련:테스트 = 7:3


1.2 훈련 대 검증 분리


 다음 단계로, 훈련 세트를 추가로 세분화하여 검증 세트를 만든다. 이때 일반적으로 훈련 세트의 60~80%를 훈련 데이터로 계속 사용하고, 나머지를 검증 데이터로 사용한다. 주로 사용하는 비율은 '4:2' 또는 '6:4'이다. 예를 들어, '4:2' 비율을 적용하려면 'test_size=0.33'을 설정하여 훈련 데이터의 약 2/3을 훈련에, 약 1/3을 검증에 사용하게 된다. 이런 방법을 통해 모델을 학습하는 동시에 성능 검증 과정도 병행할 수 있다.

# 훈련 데이터를 훈련 데이터와 검증 데이터로 나누기 (비율 4:2)
X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, 
                                                  test_size=0.33, 
                                                  random_state=42)

print(f"훈련 데이터 : {X_train.shape}, {y_train.shape}")
print(f"검증 데이터 : {X_val.shape}, {y_val.shape}")
print(f"테스트 데이터 : {X_test.shape}, {y_test.shape}")

훈련:검증 = 4:2


 데이터를 훈련, 검증, 테스트 세트로 단계적으로 분할하는 방법은 일반적으로 사용되는 방법이지만, 이 방법에는 문제점이 있다. 특히, 각 단계에서 데이터를 분리할 때마다 해당 비율을 일일이 계산해야 하는 번거로움이 있다. 이를 해결하기 위해 전체 데이터를 한 번에 훈련, 검증, 테스트 세트로 나누는 방법을 사용하면, 이러한 문제점을 줄일 수 있다.


2. 통합적 분리
2.1 훈련 - 검증 - 테스트 분리


  가장 많이 사용되는 비율은 '훈련:검증:테스트 = 6:2:2'이다. 이는 전체 데이터의 60%를 훈련에, 20%를 검증에, 그리고 나머지 20%를 테스트에 사용하는 것을 의미한다. 첫 번째, train_test_split 함수는 데이터를 훈련 데이터와 (검증+테스트) 데이터로 분리한다. 여기서 test_size=0.4는 전체 데이터의 40%를 (검증+테스트) 데이터로 할당하라는 뜻이다. 따라서 이 단계 이후에 훈련 데이터는 전체 데이터의 60%를 차지하게 된다.

from sklearn.model_selection import train_test_split

X_train, X_temp, y_train, y_temp = train_test_split(X, y, 
                                                    test_size=0.4,
                                                    random_state=42)
print(f"{X_train.shape} : {y_train.shape}")
print(f"{X_temp.shape} : {y_temp.shape}")

훈련:(검증+테스트) = 6:4


 두 번째 train_test_split 함수는 (검증+테스트) 데이터를 다시 검증 데이터와 테스트 데이터로 분리한다. 여기서 test_size=0.5는 (검증+테스트) 데이터의 50%를 테스트 데이터로 할당하라는 뜻이다. 따라서, 이 단계 이후에 검증 데이터와 테스트 데이터는 각각 전체 데이터의 20%를 차지하게 된다.

X_val, X_test, y_val, y_test = train_test_split(X_temp, y_temp,
                                                test_size=0.5,
                                                random_state=42)
print(f"{X_train.shape} : {y_train.shape}")
print(f"{X_val.shape} : {y_val.shape}")
print(f"{X_test.shape} : {y_test.shape}")

훈련:검증:테스트 = 6:2:2


 이 방법은 전체 데이터를 한 번에 원하는 비율로 훈련, 검증, 테스트 세트로 나누는 데 효과적이다. 그렇지 않으면, 훈련/검증, 훈련/테스트로 두 번에 걸쳐 나누는 방식을 사용해야 하며, 이 경우 각 단계에서의 비율을 계산하는 것이 복잡해질 수 있다.

 따라서, 먼저 전체 데이터를 훈련 세트와 (검증+테스트) 세트로 나눈 후, (검증+테스트) 세트를 다시 검증 세트와 테스트 세트로 분리하는 방식은 코드의 간결성과 편의성을 제공한다. 이 방식을 통해 원하는 비율로 정확하게 데이터를 분리할 수 있으며, 각 단계에서의 복잡한 계산을 줄일 수 있다.