適合不足と過学習

Beginner

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

はじめに

この実験では、機械学習におけるアンダーフィッティング(過小適合)とオーバーフィッティング(過剰適合)の問題、および多項式特徴量を用いた線形回帰を使って非線形関数を近似する方法を実証します。データの生成、モデルの適合、およびモデル性能の評価には scikit-learn を使用します。

VM のヒント

VM の起動が完了したら、左上隅をクリックして Notebook タブに切り替え、Jupyter Notebook を開いて練習を始めましょう。

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

学習中に問題が発生した場合は、いつでも Labby に質問してください。セッション終了後にフィードバックを提供していただければ、迅速に問題を解決します。

ライブラリのインポート

まず、この実験で必要なライブラリをインポートします。

import numpy as np
import matplotlib.pyplot as plt
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import cross_val_score

データの生成

コサイン関数から 30 個のサンプルを生成し、それにランダムなノイズを加えます。

def true_fun(X):
    return np.cos(1.5 * np.pi * X)

np.random.seed(0)

n_samples = 30

X = np.sort(np.random.rand(n_samples))
y = true_fun(X) + np.random.randn(n_samples) * 0.1

データの可視化

真の関数と生成したサンプルをプロットします。

plt.figure(figsize=(6, 4))
plt.plot(np.linspace(0, 1, 100), true_fun(np.linspace(0, 1, 100)), label="True function")
plt.scatter(X, y, edgecolor="b", s=20, label="Samples")
plt.xlabel("x")
plt.ylabel("y")
plt.legend(loc="best")
plt.show()

多項式特徴量を用いたモデルの適合

次数が 1、4、および 15 の多項式特徴量を用いてモデルを適合させ、結果をプロットします。

degrees = [1, 4, 15]

plt.figure(figsize=(14, 5))

for i in range(len(degrees)):
    ax = plt.subplot(1, len(degrees), i + 1)
    plt.setp(ax, xticks=(), yticks=())

    polynomial_features = PolynomialFeatures(degree=degrees[i], include_bias=False)
    linear_regression = LinearRegression()
    pipeline = Pipeline(
        [
            ("polynomial_features", polynomial_features),
            ("linear_regression", linear_regression),
        ]
    )
    pipeline.fit(X[:, np.newaxis], y)

    X_test = np.linspace(0, 1, 100)
    plt.plot(X_test, pipeline.predict(X_test[:, np.newaxis]), label="Model")
    plt.plot(X_test, true_fun(X_test), label="True function")
    plt.scatter(X, y, edgecolor="b", s=20, label="Samples")
    plt.xlabel("x")
    plt.ylabel("y")
    plt.xlim((0, 1))
    plt.ylim((-2, 2))
    plt.legend(loc="best")
    plt.title("Degree {}".format(degrees[i]))

plt.show()

モデルの性能評価

交差検証(cross-validation)を用いてモデルを評価し、検証セットでの平均二乗誤差(Mean Squared Error, MSE)を計算します。

degrees = [1, 4, 15]

plt.figure(figsize=(14, 5))

for i in range(len(degrees)):
    ax = plt.subplot(1, len(degrees), i + 1)
    plt.setp(ax, xticks=(), yticks=())

    polynomial_features = PolynomialFeatures(degree=degrees[i], include_bias=False)
    linear_regression = LinearRegression()
    pipeline = Pipeline(
        [
            ("polynomial_features", polynomial_features),
            ("linear_regression", linear_regression),
        ]
    )
    pipeline.fit(X[:, np.newaxis], y)

    ## Evaluate the models using crossvalidation
    scores = cross_val_score(
        pipeline, X[:, np.newaxis], y, scoring="neg_mean_squared_error", cv=10
    )

    X_test = np.linspace(0, 1, 100)
    plt.plot(X_test, pipeline.predict(X_test[:, np.newaxis]), label="Model")
    plt.plot(X_test, true_fun(X_test), label="True function")
    plt.scatter(X, y, edgecolor="b", s=20, label="Samples")
    plt.xlabel("x")
    plt.ylabel("y")
    plt.xlim((0, 1))
    plt.ylim((-2, 2))
    plt.legend(loc="best")
    plt.title(
        "Degree {}\nMSE = {:.2e}(+/- {:.2e})".format(
            degrees[i], -scores.mean(), scores.std()
        )
    )

plt.show()

まとめ

この実験では、多項式特徴量を用いた線形回帰を使って非線形関数を近似する方法と、交差検証(cross-validation)を用いてモデルの性能を評価する方法を示しました。線形関数では訓練サンプルに適合するのに不十分であり、次数 4 の多項式が真の関数をほぼ完全に近似することがわかりました。ただし、次数が高くなると、モデルは訓練データに過学習(overfitting)し、訓練データのノイズを学習してしまいます。交差検証と平均二乗誤差(Mean Squared Error, MSE)を使ってモデルの性能を評価し、過学習を回避することができます。