0Pricing
Machine Learning Academy · 강의

K겹 교차 검증: 누수 없이 분할하기

학습자는 cross_val_score를 사용해 5겹 CV를 구현하고, 학습 중 테스트 폴드를 절대 사용하지 않는 이유를 이해하며, CV 점수의 평균과 표준편차를 해석합니다.

K겹 교차 검증: 누수 없이 분할하기은(는) CoddyKit의 무료 Machine Learning Academy 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Machine Learning Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Machine Learning Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.

Why a Single Train-Test Split Is Risky

When you evaluate a model on a single held-out test set, the result depends heavily on which examples happened to end up in the test set. With a small dataset, 80 test examples might be unusually easy or hard, making your accuracy estimate misleading. K-Fold Cross-Validation solves this by averaging accuracy across multiple test folds, giving a more reliable estimate of how the model will perform on new data. It also uses the data more efficiently — every example is used for both training and testing across different folds.

How K-Fold CV Works Step by Step

K-Fold CV splits the dataset into k equally sized parts called folds. In each of k rounds, one fold is used as the test fold and the remaining k-1 folds form the training set. The model is trained from scratch on the training folds and evaluated on the test fold. This repeats until every fold has served as the test fold exactly once. The final performance estimate is the mean (and standard deviation) of the k scores. Common values: k=5 or k=10.

cross_val_score: One-Line Cross-Validation

scikit-learn's cross_val_score handles the entire K-Fold loop: it creates the folds, trains the model on each training portion, evaluates on the test fold, and returns an array of scores. The cv parameter sets the number of folds. The scoring parameter specifies the metric. You can also pass n_jobs=-1 to train all folds in parallel, dramatically reducing wall-clock time on multi-core machines.

from sklearn.linear_model import LogisticRegression
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import make_pipeline
import numpy as np

X, y = load_breast_cancer(return_X_y=True)
model = make_pipeline(StandardScaler(), LogisticRegression(max_iter=1000))
scores = cross_val_score(model, X, y, cv=5, scoring='accuracy', n_jobs=-1)
print('Fold scores:', np.round(scores, 4))
print('Mean:', round(scores.mean(), 4), 'Std:', round(scores.std(), 4))

The Test Fold Is Never Seen During Training

The critical rule of K-Fold CV is that the test fold must never influence the model or any preprocessing step. This means the scaler must be fitted only on the training folds and then applied to the test fold — never fitted on the combined data. Using a Pipeline with cross_val_score automatically enforces this: scikit-learn calls fit on the training portion of the pipeline and predict on the test portion inside each fold, preventing any leakage.

# WRONG: fitting scaler on all data before CV causes leakage
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
from sklearn.datasets import load_breast_cancer

X, y = load_breast_cancer(return_X_y=True)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)  # leaks test fold statistics!
wrong_score = cross_val_score(LogisticRegression(max_iter=1000), X_scaled, y, cv=5).mean()

# CORRECT: Pipeline ensures scaler is fitted only on training folds
from sklearn.pipeline import make_pipeline
correct_score = cross_val_score(make_pipeline(StandardScaler(), LogisticRegression(max_iter=1000)), X, y, cv=5).mean()
print('Wrong (leaky):', round(wrong_score, 4))
print('Correct (no leak):', round(correct_score, 4))

Setting the Random Seed for Reproducibility

By default, KFold does not shuffle the data and always creates the same splits for the same dataset, making results reproducible. If you set shuffle=True, pass a random_state integer so that the shuffle is deterministic: KFold(n_splits=5, shuffle=True, random_state=42). Shuffling is recommended when the dataset is sorted by class or time order, as sequential splits would create highly unrepresentative folds. Always document the random state in your experiments for reproducibility.

from sklearn.model_selection import KFold, cross_val_score
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_iris
import numpy as np

X, y = load_iris(return_X_y=True)
kf = KFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(DecisionTreeClassifier(random_state=42), X, y, cv=kf)
print('Shuffled 5-fold scores:', np.round(scores, 4))
print('Mean:', round(scores.mean(), 4))

Interpreting Mean and Standard Deviation

The mean CV score estimates your model's expected performance on new data. The standard deviation tells you how stable that performance is. A mean of 0.93 with std 0.01 is much more trustworthy than 0.93 with std 0.08. High standard deviation indicates that model performance is sensitive to which examples are in the training set — a sign of either a small dataset, high model variance, or an unrepresentative data split. When comparing two models, the one with lower variance (smaller std) is often preferred even if its mean is slightly lower.

Choosing K: 5-Fold vs 10-Fold vs LOOCV

The choice of k involves a bias-variance trade-off for the CV estimate itself. k=5: each training set is 80% of the data, fast to compute, slightly high bias. k=10: each training set is 90%, better estimate, more computation. Leave-One-Out CV (LOOCV): k=n, nearly unbiased but extremely slow for large datasets and has high variance between folds. The standard recommendation is k=5 or k=10. For very small datasets (<100 examples), LOOCV gives the most data-efficient estimate.

from sklearn.model_selection import cross_val_score, LeaveOneOut
from sklearn.neighbors import KNeighborsClassifier
from sklearn.datasets import load_iris
import numpy as np

X, y = load_iris(return_X_y=True)
knn = KNeighborsClassifier(n_neighbors=5)
for k in [5, 10]:
    scores = cross_val_score(knn, X, y, cv=k)
    print(f'{k}-fold CV: mean={scores.mean():.4f}, std={scores.std():.4f}')
# LOOCV is slow for large datasets; feasible here
loo_scores = cross_val_score(knn, X, y, cv=LeaveOneOut())
print(f'LOOCV: mean={loo_scores.mean():.4f}, std={loo_scores.std():.4f}')

cross_validate: Multiple Metrics at Once

cross_validate is a more powerful variant that can compute multiple metrics simultaneously and also return training scores and fit/score times. This is useful for comparing train vs test scores (to diagnose overfitting) or computing multiple metrics (accuracy, F1, AUC) in a single CV run instead of running CV separately for each metric.

from sklearn.model_selection import cross_validate
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_breast_cancer
import numpy as np

X, y = load_breast_cancer(return_X_y=True)
rf = RandomForestClassifier(n_estimators=100, random_state=42)
results = cross_validate(rf, X, y, cv=5,
                          scoring=['accuracy', 'f1', 'roc_auc'],
                          return_train_score=True)
for metric in ['test_accuracy', 'test_f1', 'test_roc_auc']:
    vals = results[metric]
    print(f'{metric}: {vals.mean():.4f} (+/- {vals.std():.4f})')

When K-Fold CV Can Be Misleading

K-Fold CV gives misleading estimates in several scenarios: (1) Time-series data — shuffling and splitting ignores temporal order, creating leakage where future data trains models used to predict the past; (2) Group data — if multiple rows belong to the same patient or user, splitting them into different folds leaks group-level patterns; (3) Highly imbalanced classes — random splits may put all positive examples in the training set. Use specialised CV variants: TimeSeriesSplit, GroupKFold, and StratifiedKFold for these cases.

Cross-Validation Is Evaluation, Not Training

A common misconception: K-Fold CV does not produce a deployable model. Each of the k model fits is discarded after evaluation. Cross-validation exists solely to estimate how a model trained with your chosen hyperparameters and pipeline will perform on unseen data. Once you are satisfied with the CV estimate, you retrain your final model on the complete training dataset (all folds combined) with those hyperparameters and deploy that model. The CV score is your honest estimate of its expected performance.

Reporting CV Results: Mean and Confidence Interval

When reporting cross-validation results, always report both the mean and the standard deviation: 0.932 ± 0.012. This conveys not just performance but stability. For publication or stakeholder reports, you can also compute a 95% confidence interval: mean ± 1.96 × std / sqrt(k). When comparing two models, check whether their confidence intervals overlap — overlapping intervals suggest the difference is not statistically meaningful and may just reflect random variation in the data split.

from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import cross_val_score
import numpy as np

X, y = load_breast_cancer(return_X_y=True)
scores = cross_val_score(RandomForestClassifier(n_estimators=100, random_state=42), X, y, cv=10)
mean, std = scores.mean(), scores.std()
ci95 = 1.96 * std / np.sqrt(len(scores))
print(f'CV Mean: {mean:.4f}')
print(f'CV Std:  {std:.4f}')
print(f'95% CI:  [{mean-ci95:.4f}, {mean+ci95:.4f}]')

Quick Check

Test your understanding of K-Fold Cross-Validation from this lesson.

Lesson Recap

In this lesson you learned: K-Fold CV estimates generalisation by averaging scores across k non-overlapping test folds, always use a Pipeline to prevent preprocessing from leaking test fold statistics into training, and CV is an evaluation tool — retrain on all data after selecting hyperparameters. Next up we explore Stratified and Time-Series cross-validation for specialised data types.

자주 묻는 질문

“K겹 교차 검증: 누수 없이 분할하기” 강의는 무료인가요?

네 — “K겹 교차 검증: 누수 없이 분할하기” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Machine Learning Academy 강의 전체를 잠금 해제할 수 있습니다. Machine Learning Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“K겹 교차 검증: 누수 없이 분할하기”에서 뭘 배우나요?

학습자는 cross_val_score를 사용해 5겹 CV를 구현하고, 학습 중 테스트 폴드를 절대 사용하지 않는 이유를 이해하며, CV 점수의 평균과 표준편차를 해석합니다. 브라우저에서 직접 실행하는 실습 코드로 Machine Learning Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Machine Learning Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Machine Learning Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.

“K겹 교차 검증: 누수 없이 분할하기” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Machine Learning Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Machine Learning Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. K겹 교차 검증: 누수 없이 분할하기
  2. 층화 및 시계열 교차 검증
  3. 그리드 탐색과 무작위 탐색 비교
  4. 중첩 교차 검증: 선택과 평가를 동시에 수행하기
← Machine Learning Academy(으)로 돌아가기