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_size와 train_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()}") # Truerandom_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_size | float 또는 int | None | 테스트 세트의 비율(0.0-1.0) 또는 샘플 수 |
train_size | float 또는 int | None | 훈련 세트의 비율(0.0-1.0) 또는 샘플 수 |
random_state | int | None | 재현성을 위한 난수 시드 |
shuffle | bool | True | 분할 전에 데이터를 섞을지 여부 |
stratify | array-like | None | 계층화 분할에 사용할 데이터 |
불균형 데이터를 위한 계층화 분할
데이터셋에 불균형 클래스가 있는 경우(일부 클래스가 다른 클래스보다 훨씬 적은 샘플을 가짐) 무작위 분할은 전체 분포를 제대로 나타내지 못하는 훈련 또는 테스트 세트를 만들 수 있습니다. 이것은 분류 작업에서 특히 문제가 됩니다.
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 Split | 70-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)}")데이터 누출 방지
데이터 누출은 테스트 세트의 정보가 훈련 프로세스에 영향을 미칠 때 발생합니다. 일반적인 원인:
- 분할 전 전처리: 항상 먼저 분할한 다음 전처리
- 결합 데이터에서 특징 스케일링: 훈련 데이터에서만 스케일러 적합
- 결합 데이터에서 특징 선택: 훈련 데이터만 사용하여 특징 선택
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=True로 train_test_split을 사용해서는 안 됩니다. 시간적 순서를 파괴하고 데이터 누출(과거를 예측하기 위해 미래 데이터 사용)을 유발하기 때문입니다. 대신 간단한 시간순 분할을 위해 shuffle=False로 train_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 분할은 신뢰할 수 있는 머신러닝을 향한 첫 번째 단계입니다.