데이터 분할: 특성·목표값 나누기부터 평가지표까지

데이터 분할이 필요한 이유부터 특성·목표값 분리, train_test_split과 교차 검증, 평가지표(Accuracy·Precision·Recall·F1)와 신용평가·이미지분류 적용 사례까지 정리한다.

2026-08-14 · 최초 발행 2025-05-23

학습하지 않은 데이터로 평가해야 하는 이유

머신러닝과 데이터 과학에서 데이터 분할(Splitting Data)은 모델 개발과 평가 과정의 핵심 단계다. 모델이 학습 데이터에만 최적화되어 새로운 데이터에 대한 예측 성능이 떨어지는 과적합(Overfitting)을 막고, 학습에 쓰지 않은 데이터로 모델의 실제 성능을 측정해 일반화 능력을 평가하며, 독립적인 테스트 데이터로 모델 성능을 객관적으로 판단하기 위해 데이터를 나눈다.

데이터 분할의 기본 원칙은 전체 데이터를 학습용과 테스트용으로 나누는 것이다. 학습 데이터(Training Data)는 모델을 학습시키는 데 쓰이는 데이터로 '문제지'에 비유할 수 있고, 테스트 데이터(Test Data)는 모델의 성능을 평가하는 데 쓰이는 데이터로 '시험지'에 비유할 수 있다. 이러한 분리는 모델이 학습하지 않은 새로운 데이터에 대한 일반화 능력을 측정하기 위해 필수적이다.

정확도만으로는 부족하다

테스트 데이터를 사용하면 모델의 성능을 다양한 지표로 측정할 수 있다. 정확도(Accuracy)는 전체 예측 중 맞은 예측의 비율이고, 정밀도(Precision)는 양성으로 예측한 것 중 실제 양성인 비율, 재현율(Recall)은 실제 양성 중 양성으로 예측한 비율이며, F1 점수는 정밀도와 재현율의 조화평균이다.

from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score

# 예측값과 실제값 비교
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)

print(f"Accuracy: {accuracy:.4f}")
print(f"Precision: {precision:.4f}")
print(f"Recall: {recall:.4f}")
print(f"F1 Score: {f1:.4f}")

분할하기 전에, 특성과 목표값부터 갈라야 한다

머신러닝 모델을 구축하려면 데이터셋에서 특성(feature)과 목표값(target)을 먼저 분리해야 한다. 특성은 모델의 입력값(X)이고, 목표값은 모델이 예측해야 하는 출력값(y)이다.

zip 함수로 나누기

# 예시 데이터
data = [(1, 2, 0), (3, 4, 1), (5, 6, 0)]

# 특성과 타겟 분리
X, y = zip(*[(features[0:2], features[2]) for features in data])

print(f"X: {X}")  # X: ((1, 2), (3, 4), (5, 6))
print(f"y: {y}")  # y: (0, 1, 0)

Pandas DataFrame으로 나누기

import pandas as pd

# DataFrame 생성
df = pd.DataFrame({
    'feature1': [1, 3, 5],
    'feature2': [2, 4, 6],
    'target': [0, 1, 0]
})

# 특성과 타겟 분리
X = df[['feature1', 'feature2']]
y = df['target']

print(f"X:\n{X}")
print(f"y:\n{y}")

NumPy 배열로 나누기

import numpy as np

# 예시 데이터 배열
data = np.array([
    [1, 2, 0],
    [3, 4, 1],
    [5, 6, 0]
])

# 특성과 타겟 분리
X = data[:, 0:2]  # 모든 행의 0~1 열 선택
y = data[:, 2]    # 모든 행의 2 열 선택

print(f"X:\n{X}")
print(f"y:\n{y}")

학습·테스트 세트를 나누는 방법

Scikit-learn의 train_test_split 함수

가장 널리 쓰이는 방법으로, 데이터를 무작위로 학습 및 테스트 세트로 분할한다.

from sklearn.model_selection import train_test_split

# 특성과 타겟 데이터 준비
X = df[['feature1', 'feature2']]
y = df['target']

# 학습 데이터와 테스트 데이터 분리 (테스트 데이터 비율 20%)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

print(f"학습 데이터 크기: {X_train.shape}, {y_train.shape}")
print(f"테스트 데이터 크기: {X_test.shape}, {y_test.shape}")

주요 매개변수는 다음과 같다.

  • test_size: 테스트 데이터 비율 (0~1 사이 값)
  • random_state: 재현 가능한 결과를 위한 랜덤 시드 값
  • stratify: 계층화 샘플링을 위한 매개변수 (클래스 분포를 유지)

NumPy로 수동 분리하기

import numpy as np

# 데이터 준비
data = np.array([
    [1, 2, 0],
    [3, 4, 1],
    [5, 6, 0],
    [7, 8, 1],
    [9, 10, 0]
])

# 데이터 셔플
np.random.shuffle(data)

# 분할 지점 계산 (전체 데이터의 80%를 학습 데이터로 사용)
split_idx = int(len(data) * 0.8)

# 학습 데이터와 테스트 데이터 분리
train_data = data[:split_idx]
test_data = data[split_idx:]

# 특성과 타겟 분리
X_train = train_data[:, 0:2]
y_train = train_data[:, 2]
X_test = test_data[:, 0:2]
y_test = test_data[:, 2]

print(f"학습 데이터 크기: {X_train.shape}, {y_train.shape}")
print(f"테스트 데이터 크기: {X_test.shape}, {y_test.shape}")

한 번의 분할보다 여러 번 나눠 검증하면

단순한 학습/테스트 분할보다 더 강력한 평가 방법인 교차 검증은 데이터를 여러 폴드(fold)로 나누고, 각 반복에서 다른 폴드를 테스트 세트로 사용한다.

from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression

# 모델 초기화
model = LogisticRegression()

# 5-폴드 교차 검증 수행
scores = cross_val_score(model, X, y, cv=5)

print(f"교차 검증 점수: {scores}")
print(f"평균 점수: {scores.mean():.4f}")
전체 데이터셋학습 데이터 80%테스트 데이터 20%특성 X_train타겟 y_train특성 X_test타겟 y_test모델 학습모델성능 평가

분할할 때 놓치기 쉬운 것들

테스트 데이터가 학습 과정에 영향을 미치지 않도록 데이터 누수(Data Leakage)를 방지해야 하고, 학습 및 테스트 데이터가 전체 데이터의 특성을 잘 반영하도록 대표성을 확보해야 한다. 클래스 불균형이 있다면 stratify 매개변수로 클래스 분포를 유지하고, 시계열 데이터라면 시간 순서를 고려한 분할 방법을 적용해야 한다. 통계적으로 유의미한 결과를 얻으려면 충분한 테스트 데이터 크기도 필요하다.

신용 평가와 이미지 분류에 적용하면

신용 평가 모델 개발

금융 기관에서 고객의 대출 상환 가능성을 예측하는 모델을 개발할 때는 과거 고객 데이터를 학습/테스트로 분리해 모델의 정확도와 신뢰성을 평가한다.

# 신용 평가 데이터 불러오기
credit_data = pd.read_csv('credit_data.csv')

# 특성과 타겟 분리
X = credit_data.drop('default', axis=1)
y = credit_data['default']

# 학습/테스트 분리 (계층화 샘플링 적용)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42, stratify=y
)

# 모델 학습 및 평가
model = RandomForestClassifier()
model.fit(X_train, y_train)
y_pred = model.predict(X_test)

# 성능 지표 계산
print(f"정확도: {accuracy_score(y_test, y_pred):.4f}")
print(f"ROC AUC: {roc_auc_score(y_test, model.predict_proba(X_test)[:, 1]):.4f}")

이미지 분류 모델

컴퓨터 비전 문제에서는 이미지 데이터를 학습/검증/테스트 세트로 분할해 모델의 성능을 최적화한다.

# 학습/검증/테스트 세트로 3단계 분할
X_temp, X_test, y_temp, y_test = train_test_split(
    images, labels, test_size=0.2, random_state=42, stratify=labels
)

X_train, X_val, y_train, y_val = train_test_split(
    X_temp, y_temp, test_size=0.25, random_state=42, stratify=y_temp
)  # 0.25 * 0.8 = 0.2, 전체의 20%가 검증 데이터

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

train_test_split 하나로 끝나지 않는 이유

데이터 분할은 머신러닝 모델 개발 과정에서 필수적인 단계다. 특성과 목표값을 먼저 분리하고, 적절한 지표로 성능을 측정하며, 데이터 누수와 대표성을 점검하는 과정이 함께 맞물려야 모델의 일반화 능력을 제대로 평가할 수 있다. Scikit-learn의 train_test_split 함수는 간편하고 강력한 기능을 제공하지만, 교차 검증 같은 고급 평가 방법을 함께 활용해야 모델의 안정성과 신뢰성을 높일 수 있다.

데이터 분할train_test_split교차 검증평가지표머신러닝