Skip to content
주제
Python
Sklearn Train Test Split: Python에서 데이터 분할을 위한 완벽 가이드

Sklearn Train Test Split: Python에서 데이터 분할을 위한 완벽 가이드

Updated on

전체 데이터셋에서 머신러닝 모델을 학습시킨 다음 동일한 데이터에서 평가하면 중대한 문제가 발생합니다. 모델은 잘 작동하는 것처럼 보이지만 패턴을 학습하는 대신 데이터를 단순히 암기했을 뿐입니다. 이러한 과적합은 모델이 새로운 미확인 데이터를 만났을 때 처참하게 실패할 것임을 의미합니다. 데이터 과학자는 학습 중에 모델이 한 번도 본 적이 없는 데이터에서 모델 성능을 평가할 수 있는 신뢰할 수 있는 방법이 필요합니다.

해결책은 훈련-테스트 분할입니다. 평가를 위해 데이터의 일부를 보류하면 실제 세계에서 모델이 어떻게 수행될지에 대한 정직한 평가를 얻을 수 있습니다. sklearn의 train_test_split 함수는 이 프로세스를 간단하게 만들지만 잘못 사용하면 여전히 데이터 누출, 일반화 성능 저하 및 오해의 소지가 있는 성능 메트릭으로 이어질 수 있습니다.

이 가이드는 기본 사용법부터 시계열 데이터, 불균형 클래스 및 다중 출력 문제를 위한 고급 기술까지 sklearn의 train_test_split에 대해 알아야 할 모든 것을 다룹니다.

📚

Train Test Split이란?

Train test split은 머신러닝 모델을 평가하기 위한 기본 기술입니다. 데이터셋을 두 부분으로 나눕니다. 모델을 적합시키는 데 사용되는 훈련 세트와 미확인 데이터에서 모델 성능을 평가하는 데 사용되는 테스트 세트입니다.

scikit-learn(sklearn)의 train_test_split 함수는 이 프로세스를 자동화하여 단 한 줄의 코드로 무작위 셔플링 및 분할을 처리합니다.

from sklearn.model_selection import train_test_split
 
# 기본 사용법
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

이 예에서 X는 특징(입력 변수)을 포함하고 y는 목표 변수(예측하려는 것)를 포함합니다. 함수는 네 개의 배열을 반환합니다: 훈련 특징, 테스트 특징, 훈련 레이블 및 테스트 레이블.

기본 train_test_split 구문

train_test_split의 가장 간단한 사용법은 두 개의 인수만 필요합니다: 특징과 목표 변수입니다.

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_iris
 
# 샘플 데이터 로드
iris = load_iris()
X = iris.data
y = iris.target
 
# 데이터 분할(80% 훈련, 20% 테스트)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
 
print(f"Training samples: {len(X_train)}")
print(f"Test samples: {len(X_test)}")

이것은 데이터를 무작위로 분할하여 80%는 훈련에, 20%는 테스트에 사용됩니다. 그러나 이 기본 사용법에는 중대한 결함이 있습니다. 코드를 실행할 때마다 분할이 달라져서 결과를 재현할 수 없습니다.

필수 매개변수

test_size와 train_size

test_size 매개변수는 테스트 세트에 들어가는 데이터의 양을 제어합니다. 다음과 같이 지정할 수 있습니다:

  • 0.0과 1.0 사이의 float(데이터셋의 비율)
  • 정수(테스트 샘플의 절대 수)
# 30% 테스트 세트
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)
 
# 테스트 세트에 50개 샘플
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=50)
 
# 또는 train_size 지정
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=0.8)

test_sizetrain_size를 모두 지정하는 경우 1.0(또는 정수를 사용하는 경우 총 데이터셋 크기)이 되어야 합니다. 대부분의 경우 test_size만 지정하면 충분합니다.

재현성을 위한 random_state

random_state 매개변수는 재현 가능한 결과에 중요합니다. 이것이 없으면 코드를 실행할 때마다 다른 분할을 얻게 되어 디버깅이나 실험 비교가 불가능해집니다.

# random_state 없음 - 매번 다른 분할
X_train1, X_test1, y_train1, y_test1 = train_test_split(X, y, test_size=0.2)
X_train2, X_test2, y_train2, y_test2 = train_test_split(X, y, test_size=0.2)
 
print(f"Same split? {(X_train1 == X_train2).all()}")  # False
 
# random_state 있음 - 매번 동일한 분할
X_train1, X_test1, y_train1, y_test1 = train_test_split(X, y, test_size=0.2, random_state=42)
X_train2, X_test2, y_train2, y_test2 = train_test_split(X, y, test_size=0.2, random_state=42)
 
print(f"Same split? {(X_train1 == X_train2).all()}")  # True

random_state에는 어떤 정수든 사용하세요. 특정 숫자는 중요하지 않습니다. 중요한 것은 프로젝트 전체에서 동일한 숫자를 일관되게 사용하는 것입니다.

shuffle 매개변수

기본적으로 train_test_split은 분할하기 전에 데이터를 섞습니다. 대부분의 머신러닝 작업에서 이것은 정확히 원하는 것입니다. 그러나 시계열 데이터나 순서가 중요한 경우 섞기를 비활성화해야 합니다.

# 섞기 활성화(기본값)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=True)
 
# 섞기 비활성화(시계열용)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False)

shuffle=False일 때 함수는 단순히 처음 부분을 훈련용으로, 마지막 부분을 테스트용으로 가져와서 원래 순서를 유지합니다.

매개변수 참조 표

매개변수타입기본값설명
test_sizefloat 또는 intNone테스트 세트의 비율(0.0-1.0) 또는 샘플 수
train_sizefloat 또는 intNone훈련 세트의 비율(0.0-1.0) 또는 샘플 수
random_stateintNone재현성을 위한 난수 시드
shuffleboolTrue분할 전에 데이터를 섞을지 여부
stratifyarray-likeNone계층화 분할에 사용할 데이터

불균형 데이터를 위한 계층화 분할

데이터셋에 불균형 클래스가 있는 경우(일부 클래스가 다른 클래스보다 훨씬 적은 샘플을 가짐) 무작위 분할은 전체 분포를 제대로 나타내지 못하는 훈련 또는 테스트 세트를 만들 수 있습니다. 이것은 분류 작업에서 특히 문제가 됩니다.

stratify 매개변수는 훈련 및 테스트 세트의 클래스 분포가 원래 데이터셋과 일치하도록 보장합니다.

import numpy as np
from sklearn.model_selection import train_test_split
 
# 불균형 데이터셋 생성(90% 클래스 0, 10% 클래스 1)
X = np.random.randn(1000, 5)
y = np.array([0] * 900 + [1] * 100)
 
# 계층화 없음
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
print(f"Train distribution: Class 0: {sum(y_train == 0)}, Class 1: {sum(y_train == 1)}")
print(f"Test distribution: Class 0: {sum(y_test == 0)}, Class 1: {sum(y_test == 1)}")
 
# 계층화 있음
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)
print(f"\nStratified train distribution: Class 0: {sum(y_train == 0)}, Class 1: {sum(y_train == 1)}")
print(f"Stratified test distribution: Class 0: {sum(y_test == 0)}, Class 1: {sum(y_test == 1)}")

계층화를 사용하면 훈련 및 테스트 세트 모두 90/10 클래스 분포를 유지합니다. 계층화 없이는 운이 좋으면 대표적인 분할을 얻을 수 있지만 클래스 1이 5%만 있는 테스트 세트로 끝날 수 있어 신뢰할 수 없는 평가 메트릭으로 이어집니다.

여러 배열 분할

여러 배열을 한 번에 분할할 수 있으며 sklearn은 모든 배열에 대해 동일한 방식으로 분할되도록 보장합니다(모든 배열에 대해 동일한 인덱스).

import numpy as np
 
X = np.random.randn(100, 5)
y = np.random.randint(0, 2, 100)
sample_weights = np.random.rand(100)
 
# 세 배열 모두 분할
X_train, X_test, y_train, y_test, weights_train, weights_test = train_test_split(
    X, y, sample_weights, test_size=0.2, random_state=42
)
 
print(f"X_train shape: {X_train.shape}")
print(f"y_train shape: {y_train.shape}")
print(f"weights_train shape: {weights_train.shape}")

이것은 샘플 가중치, 여러 목표 변수 또는 일관되게 분할해야 하는 추가 메타데이터가 있을 때 특히 유용합니다.

Train/Test Split vs 교차 검증 vs 홀드아웃

다양한 검증 전략은 다양한 목적에 사용됩니다. 비교는 다음과 같습니다:

방법데이터 사용계산 비용최적 용도제한 사항
Train/Test Split70-80% 훈련, 20-30% 테스트낮음빠른 모델 평가, 대규모 데이터셋단일 평가, 분할에서 운이 좋거나 나쁠 수 있음
교차 검증100% 훈련/테스트에 사용(k-fold)높음(k배 느림)소규모 데이터셋, 신뢰할 수 있는 성능 추정계산 비용이 높음, 시계열에는 부적합
Train/Val/Test (홀드아웃)60% 훈련, 20% 검증, 20% 테스트중간하이퍼파라미터 튜닝, 최종 평가더 많은 데이터 필요, 더 복잡한 워크플로
from sklearn.model_selection import cross_val_score, train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
 
iris = load_iris()
X, y = iris.data, iris.target
model = RandomForestClassifier(random_state=42)
 
# 방법 1: 간단한 train/test 분할
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
model.fit(X_train, y_train)
print(f"Train/Test Split Score: {model.score(X_test, y_test):.3f}")
 
# 방법 2: 5-fold 교차 검증
scores = cross_val_score(model, X, y, cv=5)
print(f"Cross-Validation Score: {scores.mean():.3f} (+/- {scores.std():.3f})")
 
# 방법 3: Train/Val/Test 분할
X_temp, X_test, y_temp, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
X_train, X_val, y_train, y_val = train_test_split(X_temp, y_temp, test_size=0.25, random_state=42)
model.fit(X_train, y_train)
print(f"Validation Score: {model.score(X_val, y_val):.3f}")
print(f"Test Score: {model.score(X_test, y_test):.3f}")

대부분의 프로젝트에서는 간단한 train/test 분할로 시작하세요. 데이터가 제한되어 있거나 더 강력한 성능 추정이 필요한 경우 교차 검증을 사용하세요. 하이퍼파라미터를 조정해야 하는 경우 train/val/test를 사용하세요.

고급 분할 기술

시계열 분할

시계열 데이터의 경우 무작위 섞기는 시간적 순서를 파괴하여 데이터 누출(과거를 예측하기 위해 미래 정보 사용)로 이어질 수 있습니다. 대신 TimeSeriesSplit을 사용하세요:

from sklearn.model_selection import TimeSeriesSplit
import numpy as np
 
X = np.random.randn(100, 5)
y = np.random.randn(100)
 
tscv = TimeSeriesSplit(n_splits=5)
 
for train_index, test_index in tscv.split(X):
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]
    print(f"Train size: {len(train_index)}, Test size: {len(test_index)}")

TimeSeriesSplit은 각 훈련 세트가 특정 시점까지의 모든 과거 데이터를 포함하고 테스트 세트가 바로 다음 기간을 포함하는 여러 train/test 분할을 생성합니다. 이것은 미래를 예측하기 위해 과거 데이터만 있는 실제 예측을 시뮬레이션합니다.

그룹화된 데이터를 위한 GroupShuffleSplit

데이터에 그룹이 있는 경우(예: 동일한 환자의 여러 측정값, 동일한 고객의 여러 거래) 데이터 누출을 피하기 위해 전체 그룹이 훈련 세트 또는 테스트 세트에 함께 유지되도록 해야 합니다.

from sklearn.model_selection import GroupShuffleSplit
import numpy as np
 
X = np.random.randn(100, 5)
y = np.random.randint(0, 2, 100)
groups = np.array([0] * 25 + [1] * 25 + [2] * 25 + [3] * 25)  # 4개 그룹
 
gss = GroupShuffleSplit(n_splits=1, test_size=0.2, random_state=42)
 
for train_idx, test_idx in gss.split(X, y, groups):
    X_train, X_test = X[train_idx], X[test_idx]
    y_train, y_test = y[train_idx], y[test_idx]
    print(f"Train groups: {np.unique(groups[train_idx])}")
    print(f"Test groups: {np.unique(groups[test_idx])}")

이것은 주어진 그룹의 모든 샘플이 훈련 세트 또는 테스트 세트 중 하나에만 있고 둘 다에는 없도록 보장합니다.

Train Test Split 모범 사례

올바른 분할 비율 선택

가장 일반적인 분할 비율은 다음과 같습니다:

  • 80/20: 중대형 데이터셋(10,000개 이상 샘플)의 표준 선택
  • 70/30: 더 강력한 테스트 평가를 위한 소규모 데이터셋(1,000-10,000개 샘플)에 더 좋음
  • 90/10: 10%만으로도 충분한 테스트 샘플을 제공하는 매우 대규모 데이터셋(100,000개 이상 샘플)의 경우
  • 60/20/20: 하이퍼파라미터 조정 시 train/validation/test용
import numpy as np
 
def recommend_split_ratio(n_samples):
    if n_samples < 1000:
        return "Consider cross-validation instead of simple split"
    elif n_samples < 10000:
        return "70/30 split recommended"
    elif n_samples < 100000:
        return "80/20 split recommended"
    else:
        return "90/10 or 80/20 split recommended"
 
sample_sizes = [500, 5000, 50000, 500000]
for size in sample_sizes:
    print(f"{size} samples: {recommend_split_ratio(size)}")

데이터 누출 방지

데이터 누출은 테스트 세트의 정보가 훈련 프로세스에 영향을 미칠 때 발생합니다. 일반적인 원인:

  1. 분할 전 전처리: 항상 먼저 분할한 다음 전처리
  2. 결합 데이터에서 특징 스케일링: 훈련 데이터에서만 스케일러 적합
  3. 결합 데이터에서 특징 선택: 훈련 데이터만 사용하여 특징 선택
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
import numpy as np
 
X = np.random.randn(1000, 10)
y = np.random.randint(0, 2, 1000)
 
# 잘못됨: 분할 전 스케일링(데이터 누출!)
scaler_wrong = StandardScaler()
X_scaled_wrong = scaler_wrong.fit_transform(X)
X_train, X_test, y_train, y_test = train_test_split(X_scaled_wrong, y, test_size=0.2)
 
# 올바름: 먼저 분할한 다음 스케일링
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)  # 훈련 데이터에 적합
X_test_scaled = scaler.transform(X_test)  # 훈련 통계를 사용하여 테스트 데이터 변환

잘못된 접근 방식은 전체 데이터셋(테스트 샘플 포함)의 정보를 사용하여 스케일링 매개변수를 계산하므로 테스트 세트에 대한 정보가 훈련 프로세스로 누출됩니다.

가능한 한 계층화하기

분류 문제의 경우 특정 이유가 없는 한 항상 계층화 분할을 사용하세요. 이것은 특히 다음의 경우 중요합니다:

  • 불균형 데이터셋
  • 소규모 데이터셋
  • 희귀 클래스가 있는 다중 클래스 문제
from sklearn.model_selection import train_test_split
import numpy as np
 
# 희귀 질병 데이터셋: 1% 양성 사례
X = np.random.randn(1000, 20)
y = np.array([0] * 990 + [1] * 10)
 
# 계층화 없음 - 테스트 세트에 양성 사례가 없을 수 있음!
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=123)
print(f"Non-stratified test positives: {sum(y_test)}")
 
# 계층화 있음 - 비례 표현 보장
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.1, random_state=123, stratify=y
)
print(f"Stratified test positives: {sum(y_test)}")

피해야 할 일반적인 실수

1. random_state 잊기

random_state 없이는 코드를 실행할 때마다 결과가 변경됩니다. 이로 인해 디버깅이 불가능하고 실험을 재현할 수 없게 됩니다.

# 나쁨: random_state 없음
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
 
# 좋음: random_state 설정
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

2. 불균형 클래스를 계층화하지 않음

불균형 데이터셋의 경우 무작위 분할은 매우 비대표적인 테스트 세트를 생성하여 신뢰할 수 없는 성능 메트릭으로 이어질 수 있습니다.

# 나쁨: 불균형 데이터에 대한 계층화 없음
X_train, X_test, y_train, y_test = train_test_split(X, y_imbalanced, test_size=0.2)
 
# 좋음: 계층화 사용
X_train, X_test, y_train, y_test = train_test_split(
    X, y_imbalanced, test_size=0.2, stratify=y_imbalanced, random_state=42
)

3. 섞기를 사용한 시계열 데이터 분할

시계열 모델은 시간적 순서에 의존합니다. 섞기는 이 구조를 파괴하고 심각한 데이터 누출로 이어질 수 있습니다.

# 나쁨: 시계열 데이터 섞기
X_train, X_test, y_train, y_test = train_test_split(
    X_timeseries, y_timeseries, test_size=0.2, shuffle=True
)
 
# 좋음: 섞기 비활성화 또는 TimeSeriesSplit 사용
X_train, X_test, y_train, y_test = train_test_split(
    X_timeseries, y_timeseries, test_size=0.2, shuffle=False
)

4. 분할 전 전처리

분할하기 전에 전체 데이터셋에서 전처리기(스케일러, 대치기, 인코더)를 적합시키면 데이터 누출이 발생합니다.

# 나쁨: 분할 전 전처리
X_scaled = StandardScaler().fit_transform(X)
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2)
 
# 좋음: 먼저 분할한 다음 전처리
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

5. 하이퍼파라미터 튜닝에 테스트 세트 사용

테스트 세트는 최종 평가에만 사용해야 합니다. 하이퍼파라미터를 선택하는 데 사용하면 본질적으로 테스트 데이터에서 훈련하는 것입니다.

# 나쁨: 테스트 세트에서 튜닝
from sklearn.ensemble import RandomForestClassifier
 
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
 
best_score = 0
best_params = None
for n_estimators in [10, 50, 100]:
    model = RandomForestClassifier(n_estimators=n_estimators)
    model.fit(X_train, y_train)
    score = model.score(X_test, y_test)  # 테스트 세트 사용!
    if score > best_score:
        best_score = score
        best_params = n_estimators
 
# 좋음: 검증 세트 또는 교차 검증 사용
X_temp, X_test, y_temp, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
X_train, X_val, y_train, y_val = train_test_split(X_temp, y_temp, test_size=0.25, random_state=42)
 
best_score = 0
best_params = None
for n_estimators in [10, 50, 100]:
    model = RandomForestClassifier(n_estimators=n_estimators)
    model.fit(X_train, y_train)
    score = model.score(X_val, y_val)  # 검증 세트 사용
    if score > best_score:
        best_score = score
        best_params = n_estimators

실전 예제: 완전한 워크플로

train_test_split을 올바르게 사용한 완전한 머신러닝 워크플로는 다음과 같습니다:

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import classification_report, confusion_matrix
 
# 데이터 로드
np.random.seed(42)
X = np.random.randn(1000, 10)
y = (X[:, 0] + X[:, 1] > 0).astype(int)  # 이진 분류
 
# 단계 1: 데이터 분할(균형 잡힌 테스트 세트를 위한 계층화)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)
 
# 단계 2: 전처리(훈련 데이터에만 적합)
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
 
# 단계 3: 모델 훈련
model = RandomForestClassifier(n_estimators=100, random_state=42)
model.fit(X_train_scaled, y_train)
 
# 단계 4: 평가
y_pred = model.predict(X_test_scaled)
print("Classification Report:")
print(classification_report(y_test, y_pred))
print("\nConfusion Matrix:")
print(confusion_matrix(y_test, y_pred))
 
# 단계 5: 과적합 확인
train_score = model.score(X_train_scaled, y_train)
test_score = model.score(X_test_scaled, y_test)
print(f"\nTrain accuracy: {train_score:.3f}")
print(f"Test accuracy: {test_score:.3f}")
print(f"Overfitting gap: {train_score - test_score:.3f}")

대화형 데이터 분할을 위한 RunCell 사용

Jupyter 노트북에서 작업할 때 다양한 분할 비율과 매개변수를 실험하는 것은 번거로울 수 있습니다. RunCell (opens in a new tab)은 Jupyter의 데이터 과학 워크플로를 위해 특별히 설계된 AI 에이전트를 제공합니다. 다음을 도와줍니다:

  • 여러 분할 비율을 자동으로 테스트하고 결과 비교
  • 전처리 파이프라인의 데이터 누출 감지
  • 특정 데이터셋에 대한 최적의 계층화 전략 제안
  • 올바른 train/test 비율을 선택하기 위한 검증 곡선 생성

RunCell은 Jupyter 환경에 직접 통합되어 반복적인 코드를 작성하지 않고도 데이터 분할 전략을 쉽게 반복할 수 있습니다.

PyGWalker로 데이터 시각화

데이터를 분할한 후 훈련 및 테스트 세트가 유사한 분포를 가지고 있는지 확인하는 것이 중요합니다. PyGWalker (opens in a new tab)는 pandas DataFrame을 Tableau 스타일의 대화형 시각화로 변환하여 다음을 쉽게 만듭니다:

  • 훈련 및 테스트 세트 간의 특징 분포 비교
  • 분할에서 잠재적인 샘플링 편향 식별
  • 클래스 불균형 시각화 및 계층화가 올바르게 작동했는지 확인
  • 훈련 데이터의 특징 간 관계 탐색
import pygwalker as pyg
import pandas as pd
 
# 시각화를 위해 DataFrame으로 변환
train_df = pd.DataFrame(X_train, columns=[f'feature_{i}' for i in range(X_train.shape[1])])
train_df['dataset'] = 'train'
test_df = pd.DataFrame(X_test, columns=[f'feature_{i}' for i in range(X_test.shape[1])])
test_df['dataset'] = 'test'
 
combined = pd.concat([train_df, test_df])
 
# 대화형 시각화 생성
pyg.walk(combined)

이를 통해 훈련 및 테스트 분포가 일치하는지 대화형으로 탐색할 수 있으며 이는 신뢰할 수 있는 모델 평가에 중요합니다.

FAQ

80/20 분할과 70/30 분할 중 어떻게 선택하나요?

10,000개 이상의 샘플이 있는 데이터셋의 경우 80/20을 사용하고, 더 작은 데이터셋(1,000-10,000개 샘플)의 경우 70/30을 사용하세요. 중요한 것은 테스트 세트에 신뢰할 수 있는 평가를 위한 충분한 샘플이 있는지 확인하는 것입니다. 일반적으로 분류 문제의 경우 최소 200-500개의 샘플입니다. 매우 대규모 데이터셋(100,000개 이상의 샘플)의 경우 5%만으로도 수천 개의 테스트 샘플을 제공하므로 90/10 또는 95/5를 사용할 수 있습니다.

random_state는 무엇이며 왜 중요한가요?

random_state는 분할하기 전에 데이터를 섞는 난수 생성기의 시드입니다. 동일한 random_state 값을 사용하면 코드를 실행할 때마다 동일한 분할을 얻을 수 있으며 이는 재현성과 디버깅에 필수적입니다. 이것이 없으면 매번 다른 train/test 분할을 얻게 되어 성능 변화가 모델 개선 때문인지 아니면 단순히 운이 좋거나 나쁜 데이터 분할 때문인지 판단할 수 없습니다.

stratify 매개변수는 언제 사용해야 하나요?

불균형 클래스나 소규모 데이터셋이 있는 경우 특히 모든 분류 문제에 stratify=y를 사용하세요. 계층화는 훈련 및 테스트 세트의 클래스 분포가 전체 분포와 일치하도록 보장합니다. 예를 들어 데이터의 10%가 양성 사례인 경우 계층화는 훈련 및 테스트 세트 모두 약 10%의 양성 사례를 갖도록 보장하여 비대표적인 분할로 인한 평가 편향을 방지합니다.

시계열 데이터에 train_test_split을 사용할 수 있나요?

아니요, 시계열 데이터에 shuffle=Truetrain_test_split을 사용해서는 안 됩니다. 시간적 순서를 파괴하고 데이터 누출(과거를 예측하기 위해 미래 데이터 사용)을 유발하기 때문입니다. 대신 간단한 시간순 분할을 위해 shuffle=Falsetrain_test_split을 사용하거나 시간적 순서를 존중하는 교차 검증을 위해 TimeSeriesSplit을 사용하세요. 시계열의 경우 항상 훈련 데이터가 시간순으로 테스트 데이터 이전에 오도록 하세요.

train_test_split은 교차 검증과 어떻게 다른가요?

train_test_split은 단일 train/test 파티션(일반적으로 80/20)을 생성하여 하나의 성능 추정값을 제공합니다. 교차 검증(k-fold와 같은)은 여러 train/test 분할을 생성하고 결과를 평균하여 더 강력한 성능 추정값을 제공합니다. 빠른 평가와 대규모 데이터셋에는 train_test_split을 사용하세요. 소규모 데이터셋(1,000개 미만의 샘플) 또는 더 신뢰할 수 있는 성능 추정이 필요한 경우 교차 검증을 사용하세요. 교차 검증은 k배 느리지만(예: 5-fold는 5배 느림) 성능 메트릭의 분산을 줄입니다.

결론

sklearn의 train_test_split은 머신러닝 모델을 평가하기 위한 기본 도구입니다. 데이터를 올바르게 분할하면 실제 모델 동작을 예측하는 정직한 성능 추정값을 얻을 수 있습니다. 핵심 원칙을 기억하세요: 재현성을 위해 항상 random_state를 설정하고, 분류 문제에는 stratify를 사용하고, 분할 전 전처리를 피하고, 데이터셋 크기에 따라 분할 비율을 선택하세요.

이러한 기본 사항을 마스터하면 과적합 모델과 오해의 소지가 있는 성능 메트릭으로 이어지는 가장 일반적인 함정을 피할 수 있습니다. 간단한 분류기를 구축하든 복잡한 딥러닝 시스템을 구축하든 적절한 train-test 분할은 신뢰할 수 있는 머신러닝을 향한 첫 번째 단계입니다.

📚