多項式とスプライン補間

Machine LearningMachine LearningBeginner
今すぐ練習

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

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

はじめに

この実験では、リッジ回帰を使ってある次数までの多項式で関数を近似する方法を学びます。1次元の点 x_in_samples が与えられたとき、これを行う2つの異なる方法を示します。

  1. PolynomialFeatures:指定された次数までのすべての単項式を生成します。これにより、n_samples 行と degree + 1 列のヴァンデルモンド行列が得られます。
  2. SplineTransformer:Bスプライン基底関数を生成します。Bスプラインの基底関数は、次数 degree の逐次多項式関数で、degree+1 個の連続するノットの間のみ非ゼロです。

非線形特徴を追加するために make_pipeline 関数を使い、線形モデルで非線形効果をモデル化するのにこれらの変換器がどのように適しているかを示します。関数、訓練点、および多項式特徴とBスプラインを使った補間を描画します。また、両方の変換器のすべての列を個別に描画し、スプラインのノットを表示します。最後に、周期スプラインの使用方法を示します。

VMのヒント

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

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

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


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL ml(("Machine Learning")) -.-> ml/FrameworkandSoftwareGroup(["Framework and Software"]) ml/FrameworkandSoftwareGroup -.-> ml/sklearn("scikit-learn") subgraph Lab Skills ml/sklearn -.-> lab-49248{{"多項式とスプライン補間"}} end

データの準備

近似しようとする関数を定義し、描画用に準備します。

def f(x):
    """Function to be approximated by polynomial interpolation."""
    return x * np.sin(x)

## whole range we want to plot
x_plot = np.linspace(-1, 11, 100)

## To make it interesting, we only give a small subset of points to train on.
x_train = np.linspace(0, 10, 100)
rng = np.random.RandomState(0)
x_train = np.sort(rng.choice(x_train, size=20, replace=False))
y_train = f(x_train)

## create 2D-array versions of these arrays to feed to transformers
X_train = x_train[:, np.newaxis]
X_plot = x_plot[:, np.newaxis]

多項式特徴による補間

多項式特徴を生成し、訓練データに対してリッジ回帰モデルを適合させるために PolynomialFeatures を使用します。そして、関数、訓練点、および多項式特徴を使った補間を描画します。

## plot function
lw = 2
fig, ax = plt.subplots()
ax.set_prop_cycle(
    color=["black", "teal", "yellowgreen", "gold", "darkorange", "tomato"]
)
ax.plot(x_plot, f(x_plot), linewidth=lw, label="ground truth")

## plot training points
ax.scatter(x_train, y_train, label="training points")

## polynomial features
for degree in [3, 4, 5]:
    model = make_pipeline(PolynomialFeatures(degree), Ridge(alpha=1e-3))
    model.fit(X_train, y_train)
    y_plot = model.predict(X_plot)
    ax.plot(x_plot, y_plot, label=f"degree {degree}")

ax.legend(loc="lower center")
ax.set_ylim(-20, 10)
plt.show()

Bスプライン補間

Bスプライン基底関数を生成し、訓練データに対してリッジ回帰モデルを適合させるために SplineTransformer を使用します。そして、関数、訓練点、およびBスプラインを使った補間を描画します。

## B-spline with 4 + 3 - 1 = 6 basis functions
model = make_pipeline(SplineTransformer(n_knots=4, degree=3), Ridge(alpha=1e-3))
model.fit(X_train, y_train)

y_plot = model.predict(X_plot)
ax.plot(x_plot, y_plot, label="B-spline")
ax.legend(loc="lower center")
ax.set_ylim(-20, 10)
plt.show()

変換器の描画

生成された特徴ベースをより深く理解するために、両方の変換器のすべての列を個別に描画します。

fig, axes = plt.subplots(ncols=2, figsize=(16, 5))
pft = PolynomialFeatures(degree=3).fit(X_train)
axes[0].plot(x_plot, pft.transform(X_plot))
axes[0].legend(axes[0].lines, [f"degree {n}" for n in range(4)])
axes[0].set_title("PolynomialFeatures")

splt = SplineTransformer(n_knots=4, degree=3).fit(X_train)
axes[1].plot(x_plot, splt.transform(X_plot))
axes[1].legend(axes[1].lines, [f"spline {n}" for n in range(6)])
axes[1].set_title("SplineTransformer")

## plot knots of spline
knots = splt.bsplines_[0].t
axes[1].vlines(knots[3:-3], ymin=0, ymax=0.8, linestyles="dashed")
plt.show()

周期スプライン

SplineTransformer を使用して結節を手動で指定することで、周期スプラインの使用方法を示します。訓練データに対してリッジ回帰モデルを適合させ、関数、訓練点、および周期スプラインを使った補間を描画します。

def g(x):
    """Function to be approximated by periodic spline interpolation."""
    return np.sin(x) - 0.7 * np.cos(x * 3)


y_train = g(x_train)

## Extend the test data into the future:
x_plot_ext = np.linspace(-1, 21, 200)
X_plot_ext = x_plot_ext[:, np.newaxis]

lw = 2
fig, ax = plt.subplots()
ax.set_prop_cycle(color=["black", "tomato", "teal"])
ax.plot(x_plot_ext, g(x_plot_ext), linewidth=lw, label="ground truth")
ax.scatter(x_train, y_train, label="training points")

for transformer, label in [
    (SplineTransformer(degree=3, n_knots=10), "spline"),
    (
        SplineTransformer(
            degree=3,
            knots=np.linspace(0, 2 * np.pi, 10)[:, None],
            extrapolation="periodic",
        ),
        "periodic spline",
    ),
]:
    model = make_pipeline(transformer, Ridge(alpha=1e-3))
    model.fit(X_train, y_train)
    y_plot_ext = model.predict(X_plot_ext)
    ax.plot(x_plot_ext, y_plot_ext, label=label)

ax.legend()
fig.show()

まとめ

この実験では、リッジ回帰を使ってある次数までの多項式で関数を近似する方法を学びました。1次元の点 x_in_samples が与えられた場合のこれを行う2つの異なる方法を示しました。非線形特徴を追加するために make_pipeline 関数を使用し、線形モデルで非線形効果をモデル化するのにこれらの変換器がどのように適しているかを示しました。多項式特徴とBスプラインを使って関数、訓練点、および補間を描画しました。また、両方の変換器のすべての列を個別に描画し、スプラインの結節を示しました。最後に、周期スプラインの使用方法を示しました。