はじめに
この実験の目的は、scikit - learn のLearningCurveDisplayクラスを使用して学習曲線をプロットする方法を示すことです。学習曲線は、訓練プロセス中にサンプルを追加することの影響を示します。我々は、手書き数字データセットを使って、単純ベイズ分類器と RBF カーネルを持つ SVM 分類器の学習曲線を分析します。さらに、これらの予測モデルの計算コストだけでなく、統計的な精度を見ることで、それらの拡張性を調べます。
VM のヒント
VM の起動が完了したら、左上隅をクリックしてノートブックタブに切り替えて、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__}")
学習曲線を分析する
## 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 分類器の学習と評価時の複雑さはサンプル数とともに急速に増加します。対照的に、単純ベイズ分類器は学習と評価時の複雑さが低く、はるかに良好な拡張性を持っています。また、学習時間の増加と交差検証スコアのトレードオフも確認しました。