学習曲線の描画

Machine LearningMachine LearningBeginner
今すぐ練習

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

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

はじめに

この実験の目的は、scikit - learnのLearningCurveDisplayクラスを使用して学習曲線をプロットする方法を示すことです。学習曲線は、訓練プロセス中にサンプルを追加することの影響を示します。我々は、手書き数字データセットを使って、単純ベイズ分類器とRBFカーネルを持つSVM分類器の学習曲線を分析します。さらに、これらの予測モデルの計算コストだけでなく、統計的な精度を見ることで、それらの拡張性を調べます。

VMのヒント

VMの起動が完了したら、左上隅をクリックしてノートブックタブに切り替えて、Jupyter Notebookを使った練習にアクセスします。

時々、Jupyter Notebookが読み込み終了するまで数秒待つ必要があります。Jupyter Notebookの制限により、操作の検証を自動化することはできません。

学習中に問題に直面した場合は、Labbyにお問い合わせください。セッション後にフィードバックを提供してください。すぐに問題を解決いたします。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL sklearn(("Sklearn")) -.-> sklearn/ModelSelectionandEvaluationGroup(["Model Selection and Evaluation"]) sklearn(("Sklearn")) -.-> sklearn/UtilitiesandDatasetsGroup(["Utilities and Datasets"]) ml(("Machine Learning")) -.-> ml/FrameworkandSoftwareGroup(["Framework and Software"]) sklearn(("Sklearn")) -.-> sklearn/CoreModelsandAlgorithmsGroup(["Core Models and Algorithms"]) sklearn/CoreModelsandAlgorithmsGroup -.-> sklearn/naive_bayes("Naive Bayes") sklearn/CoreModelsandAlgorithmsGroup -.-> sklearn/svm("Support Vector Machines") sklearn/ModelSelectionandEvaluationGroup -.-> sklearn/model_selection("Model Selection") sklearn/UtilitiesandDatasetsGroup -.-> sklearn/datasets("Datasets") ml/FrameworkandSoftwareGroup -.-> ml/sklearn("scikit-learn") subgraph Lab Skills sklearn/naive_bayes -.-> lab-49195{{"学習曲線の描画"}} sklearn/svm -.-> lab-49195{{"学習曲線の描画"}} sklearn/model_selection -.-> lab-49195{{"学習曲線の描画"}} sklearn/datasets -.-> lab-49195{{"学習曲線の描画"}} ml/sklearn -.-> lab-49195{{"学習曲線の描画"}} end

データセットの読み込み

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__}")

学習曲線を分析する

## Interpret the learning curves

単純ベイズ分類器の学習曲線を分析することができます。その形状は、より複雑なデータセットでは非常に頻繁に見られます:訓練に使用するサンプルが少ない場合、訓練スコアは非常に高くなり、サンプル数を増やすと低下します。一方、テストスコアは最初は非常に低く、サンプルを追加すると上昇します。すべてのサンプルを訓練に使用すると、訓練スコアとテストスコアがより現実的になります。

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],
    )
):
    ## scalability regarding the fit time
    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("Fit time (s)")
    ax[0, ax_idx].set_title(
        f"Scalability of the {estimator.__class__.__name__} classifier"
    )

    ## scalability regarding the score time
    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("Score time (s)")
    ax[1, ax_idx].set_xlabel("Number of training samples")

学習時間の増加と交差検証スコアのトレードオフを確認する

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("Accuracy")
    ax[ax_idx].set_xlabel("Fit time (s)")
    ax[ax_idx].set_title(
        f"Performance of the {estimator.__class__.__name__} classifier"
    )

plt.show()

まとめ

この実験では、scikit - learnのLearningCurveDisplayクラスを使用して学習曲線を描画する方法を示しました。ディジットデータセットを使って、単純ベイズ分類器とRBFカーネルを持つSVM分類器の学習曲線を分析しました。さらに、これらの予測モデルの拡張性を、それらの計算コストだけでなく統計的精度も見ることで調べました。SVMと単純ベイズ分類器の拡張性が大きく異なることがわかりました。SVM分類器の学習と評価時の複雑さはサンプル数とともに急速に増加します。対照的に、単純ベイズ分類器は学習と評価時の複雑さが低く、はるかに良好な拡張性を持っています。また、学習時間の増加と交差検証スコアのトレードオフも確認しました。