乱数の固定
現象が再現するように乱数を固定します。
# ランダムシードを設定する(乱数を固定する) np.random.seed(1)
入力空間と特徴空間
今回のプログラムでは入力空間は1次元です。
その入力空間の元 を非線形写像 で写した特徴空間で回帰します。
目標値 と入力値 の関係は で は平均が 、標準偏差が の正規分布に従います。
計画行列 は以下の式で表されます。
ですが、プログラムでは、以下の図1のようにしています。
図1
プログラムで最初に作成する Phi は であることに注意してください。
sklearn.linear_model.LinearRegression に仕様を合わせているため、計画行列から、成分が1の列を抜いています。
LinearRegression 内で、計画行列は となります。
# 訓練データxの列ベクトル(入力空間) x = np.linspace(0, 1, N).reshape(-1, 1) # 特徴空間作成のためのインスタンスを作成(※成分が1のみの列は作成しないため、M-1を渡す) dm = DesignMatrix(M-1) # 入力空間から特徴空間へ写す # 行列Phi(特徴空間)を作成(※成分が1のみの列は作成していない) Phi = dm.transform(x) # 訓練データt=sin(x)の列ベクトルに正規分布に従うノイズを加える t = true_func(x) + np.random.normal(0, 0.2, N).reshape(-1, 1)
特徴空間で予測する
予測は特徴空間で行います。
# 訓練データt=sin(x)の列ベクトルに正規分布に従うノイズを加える t = true_func(x) + np.random.normal(0, 0.2, N).reshape(-1, 1) # 線形回帰のモデルを作成 model = LinearRegression() # 学習する model.fit(Phi, t)
コード
import matplotlib.pyplot as plt import numpy as np # 計画行列クラス(※成分が1の列は作成しない) class DesignMatrix: def __init__(self, degree): self.degree = degree def transform(self, x): return np.hstack([x**(m+1) for m in range(self.degree)]) # 線形回帰クラス class LinearRegression: def __init__(self): pass def fit(self, x, t): X = self._add_ones(x) self.w = np.linalg.inv(X.T @ X) @ X.T @ t def predict(self, x): X = self._add_ones(x) return X @ self.w def score(self, x, t): t_pred = self.predict(x) t_mean = t.mean() return 1 - np.sum((t - t_pred) ** 2) / np.sum((t - t_mean) ** 2) def _add_ones(self, x): ones = np.ones((x.shape[0], 1)) return np.hstack((ones, x)) # 訓練データ作成のための真の関数 def true_func(x): return np.sin(2 * np.pi * x) # ランダムシードを設定する(乱数を固定する) np.random.seed(1) # 訓練データ数 N = 10 # 特徴空間の次元(モデルのパラメータ数) M = 4 # 訓練データxの列ベクトル(入力空間) x = np.linspace(0, 1, N).reshape(-1, 1) # 特徴空間作成のためのインスタンスを作成(※成分が1のみの列は作成しないため、M-1を渡す) dm = DesignMatrix(M-1) # 入力空間から特徴空間へ写す # 行列Phi(特徴空間)を作成(※成分が1のみの列は作成していない) Phi = dm.transform(x) # 訓練データt=sin(x)の列ベクトルに正規分布に従うノイズを加える t = true_func(x) + np.random.normal(0, 0.2, N).reshape(-1, 1) # 線形回帰のモデルを作成 model = LinearRegression() # 学習する model.fit(Phi, t) # 係数、切片、決定係数を表示 print('係数', model.w[1:]) print('切片', model.w[0]) r2 = model.score(Phi, t) print('決定係数', r2) # 予測直線表示のためのxを作成 予測するために行列にする(reshape) x2 = np.linspace(0, 1, 100).reshape(-1,1) # 行列Phi2(特徴空間)を作成(※成分が1のみの列は作成していない) Phi2 = dm.transform(x2) # 予測する y2 = model.predict(Phi2) # グラフ表示 plt.scatter(x, t, marker ='+') plt.plot(x2, y2, color='orange') plt.show()
偉人の名言
新しいことを勉強してると世の中は怖くありません。
何もしないで、じっとしているから、怖くなるんです。
林家彦六
動画
なし