학습 곡선 시각화

Beginner

This tutorial is from open-source community. Access the source code

소개

이 실험의 목적은 scikit-learn 의 LearningCurveDisplay 클래스를 사용하여 학습 곡선을 그리는 방법을 보여주는 것입니다. 학습 곡선은 훈련 과정에서 더 많은 샘플을 추가하는 효과를 보여줍니다. 우리는 손글씨 숫자 데이터셋을 사용하여 나이브 베이즈 분류기와 RBF 커널을 사용한 SVM 분류기의 학습 곡선을 분석할 것입니다. 또한, 예측 모델의 계산 비용을 살펴봄으로써 통계적 정확도뿐만 아니라 그들의 확장성을 살펴볼 것입니다.

VM 팁

VM 시작이 완료되면 왼쪽 상단 모서리를 클릭하여 Notebook 탭으로 전환하여 연습을 위한 Jupyter Notebook에 접근할 수 있습니다.

때때로 Jupyter Notebook 이 완전히 로드되기까지 몇 초 정도 기다려야 할 수 있습니다. Jupyter Notebook 의 제한으로 인해 작업의 유효성 검사를 자동화할 수 없습니다.

학습 중 문제가 발생하면 Labby 에게 문의하십시오. 세션 후 피드백을 제공하면 문제를 신속하게 해결해 드리겠습니다.

데이터셋 로드

from sklearn.datasets import load_digits

X, y = load_digits(return_X_y=True)

모델 정의

from sklearn.naive_bayes import GaussianNB
from sklearn.svm import SVC

naive_bayes = GaussianNB()
svc = SVC(kernel="rbf", gamma=0.001)

학습 곡선 플롯

import matplotlib.pyplot as plt
import numpy as np
from sklearn.model_selection import LearningCurveDisplay, ShuffleSplit

fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(10, 6), sharey=True)

common_params = {
    "X": X,
    "y": y,
    "train_sizes": np.linspace(0.1, 1.0, 5),
    "cv": ShuffleSplit(n_splits=50, test_size=0.2, random_state=0),
    "score_type": "both",
    "n_jobs": 4,
    "line_kw": {"marker": "o"},
    "std_display_style": "fill_between",
    "score_name": "Accuracy",
}

for ax_idx, estimator in enumerate([naive_bayes, svc]):
    LearningCurveDisplay.from_estimator(estimator, **common_params, ax=ax[ax_idx])
    handles, label = ax[ax_idx].get_legend_handles_labels()
    ax[ax_idx].legend(handles[:2], ["Training Score", "Test Score"])
    ax[ax_idx].set_title(f"Learning Curve for {estimator.__class__.__name__}")

학습 곡선 분석

## 학습 곡선 해석

나이브 베이즈 분류기의 학습 곡선을 분석해 볼 수 있습니다. 복잡한 데이터셋에서 자주 관찰되는 형태입니다. 훈련 샘플 수가 적을 때 훈련 점수는 매우 높지만, 샘플 수가 증가함에 따라 감소하는 경향을 보입니다. 반면, 테스트 점수는 처음에는 매우 낮지만 샘플을 추가함에 따라 증가합니다. 모든 샘플을 훈련에 사용하면 훈련 및 테스트 점수가 더 현실적인 수준으로 수렴합니다.

RBF 커널을 사용하는 SVM 분류기의 또 다른 일반적인 학습 곡선을 볼 수 있습니다. 훈련 세트의 크기에 관계없이 훈련 점수는 높은 수준을 유지합니다. 반면, 테스트 점수는 훈련 데이터셋의 크기가 커짐에 따라 증가합니다. 실제로, 증가하다가 어느 지점에서 플랫폼에 도달합니다. 이러한 플랫폼을 관찰하는 것은 모델의 일반화 성능이 더 이상 향상되지 않기 때문에 새로운 데이터를 추가로 학습시키는 것이 더 이상 유용하지 않을 수 있음을 나타냅니다.

모델의 확장성 확인

from sklearn.model_selection import learning_curve

common_params = {
    "X": X,
    "y": y,
    "train_sizes": np.linspace(0.1, 1.0, 5),
    "cv": ShuffleSplit(n_splits=50, test_size=0.2, random_state=0),
    "n_jobs": 4,
    "return_times": True,
}

train_sizes, _, test_scores_nb, fit_times_nb, score_times_nb = learning_curve(
    naive_bayes, **common_params
)
train_sizes, _, test_scores_svm, fit_times_svm, score_times_svm = learning_curve(
    svc, **common_params
)

모델 확장성 시각화

fig, ax = plt.subplots(nrows=2, ncols=2, figsize=(16, 12), sharex=True)

for ax_idx, (fit_times, score_times, estimator) in enumerate(
    zip(
        [fit_times_nb, fit_times_svm],
        [score_times_nb, score_times_svm],
        [naive_bayes, svc],
    )
):
    ## 적합 시간에 따른 확장성
    ax[0, ax_idx].plot(train_sizes, fit_times.mean(axis=1), "o-")
    ax[0, ax_idx].fill_between(
        train_sizes,
        fit_times.mean(axis=1) - fit_times.std(axis=1),
        fit_times.mean(axis=1) + fit_times.std(axis=1),
        alpha=0.3,
    )
    ax[0, ax_idx].set_ylabel("적합 시간 (초)")
    ax[0, ax_idx].set_title(
        f"{estimator.__class__.__name__} 분류기의 확장성"
    )

    ## 예측 시간에 따른 확장성
    ax[1, ax_idx].plot(train_sizes, score_times.mean(axis=1), "o-")
    ax[1, ax_idx].fill_between(
        train_sizes,
        score_times.mean(axis=1) - score_times.std(axis=1),
        score_times.mean(axis=1) + score_times.std(axis=1),
        alpha=0.3,
    )
    ax[1, ax_idx].set_ylabel("예측 시간 (초)")
    ax[1, ax_idx].set_xlabel("훈련 샘플 수")

훈련 시간 증가와 교차 검증 점수 간의 트레이드오프 확인

fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(16, 6))

for ax_idx, (fit_times, test_scores, estimator) in enumerate(
    zip(
        [fit_times_nb, fit_times_svm],
        [test_scores_nb, test_scores_svm],
        [naive_bayes, svc],
    )
):
    ax[ax_idx].plot(fit_times.mean(axis=1), test_scores.mean(axis=1), "o-")
    ax[ax_idx].fill_between(
        fit_times.mean(axis=1),
        test_scores.mean(axis=1) - test_scores.std(axis=1),
        test_scores.mean(axis=1) + test_scores.std(axis=1),
        alpha=0.3,
    )
    ax[ax_idx].set_ylabel("정확도")
    ax[ax_idx].set_xlabel("적합 시간 (초)")
    ax[ax_idx].set_title(
        f"{estimator.__class__.__name__} 분류기의 성능"
    )

plt.show()

요약

이 실험에서는 scikit-learn 의 LearningCurveDisplay 클래스를 사용하여 학습 곡선을 그리는 방법을 보여주었습니다. 손글씨 숫자 데이터셋 (digits dataset) 을 사용하여 나이브 베이즈 분류기와 RBF 커널을 사용한 SVM 분류기의 학습 곡선을 분석했습니다. 또한, 예측 모델의 계산 비용을 고려하여 통계적 정확도뿐만 아니라 모델의 확장성을 살펴보았습니다. SVM 분류기의 확장성은 나이브 베이즈 분류기에 비해 매우 다르다는 것을 확인했습니다. SVM 분류기의 적합 (fit) 및 예측 (score) 시간 복잡도는 샘플 수가 증가함에 따라 급격히 증가하는 반면, 나이브 베이즈 분류기는 적합 및 예측 시간 복잡도가 낮아 샘플 수 증가에 따른 영향이 적었습니다. 마지막으로, 훈련 시간 증가와 교차 검증 점수 간의 트레이드오프를 확인했습니다.