「精度」と「モデルの複雑さ」に注力しながら、線形回帰をpythonで実装。


目次


  • 線形モデル

  • 線形モデルによる回帰

  • 線形回帰(通常最小二乗法)

  • 一次元データに対しての線形回帰

  • 高次元データに対しての線形回帰


参考文献


線形モデル

線形モデルは、入力特徴量の線形関数(Linear function)を用いて予測を行う。


線形モデルによる回帰

回帰問題で使われる線形モデルの予測式は、以下のようになる。

$$y = w(0) \times x(0) + w(1) \times x(1) + w(2) \times x(2) + ・・・ + w(p) \times x(p)$$

ここでの$x(0)~x(p)$は、ある1サンプルの特徴量を示す。また、$w$と$b$は、学習されたモデルのパラメータであり、$y$はモデルからの予測である。

特徴量が1つの場合、傾き$w(0)$、切片が$b$の直線になる。

回帰における線形モデルにおいての予測は、特徴量が1つの場合は直線に、特徴量が2つの場合は平面に、高次元の場合は超平面になる。

回帰モデルを用いた回帰には、様々なアルゴリズムが存在する。

それらの異なる点は2つ。


  • パラメータwとbを訓練データから学習する方法

  • モデルの複雑さを制御する方法


線形回帰(通常最小二乗法)

線形回帰(または、通常最小二乗法 ordinary least squares: OLS)は、最も単純な線形回帰手法である。

線形回帰は、訓練データにおいて、予測と真の回帰ターゲットyとの平均二乗誤差(mean squared error: MSE)が最小になるような$w$と$b$を求める。

平均二乗誤差は、

$$MSE = \frac{1}{n} \sum_{n=0}^{p} (y − \hat{y})^2$$

誤差をイメージできない人もいると思います(僕は頭に描けなかった)。なので、誤差を図示してみました。

線形回帰は、ハイパーパラメータがない。よって、モデルの複雑さを制御できない。


下準備

$ pip install scikit-learn

$ pip install mglearn


一次元データに対しての線形回帰

from sklearn.linear_model import LinearRegression

from sklearn.model_selection import train_test_split
import mglearn

X, y = mglearn.datasets.make_wave(n_samples=60)
print("(サンプル数, 特徴量数): ", X.shape)
# => (サンプル数, 特徴量数): (60, 1)

X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)

lr = LinearRegression().fit(X_train, y_train)

print(f"training dataに対しての精度: {lr.score(X_train, y_train):.2}")
print(f"test dataに対しての精度: {lr.score(X_test, y_test):.2}")
# => training dataに対しての精度: 0.67
# => test dataに対しての精度: 0.66


考察:

training dataに対しても、test dataに対しても、精度は低い。よって、過剰適合はなく、適合不足である可能性が高い。

下の「精度とモデルの複雑さ」の図でいうと、スイートスポット左側に位置しているのだろう。

線形回帰は、一次元データに対しては、モデルの複雑さが低く、適合不足に陥りやすい。


高次元データに対しての線形回帰

X, y = mglearn.datasets.load_extended_boston()

print("(サンプル数, 特徴量数): ", X.shape)
# => (サンプル数, 特徴量数): (506, 104)

X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)

lr = LinearRegression().fit(X_train, y_train)
print(f"training dataに対しての精度: {lr.score(X_train, y_train):.2}")
print(f"test dataに対しての精度: {lr.score(X_test, y_test):.2}")
# => training dataに対しての精度: 0.95
# => test dataに対しての精度: 0.61


考察:

training dataに対しての精度は非常に良いが、test dataに対しての精度は良くない。これは、過剰適合の可能性が高い。

上記の「精度とモデルの複雑さ」の図でいうと、スイートスポットの右側に来ているのだろう。

よって、汎化性能(test dataに対しての精度)を上げるためには、モデルの複雑度を制御する必要がある。

その手法に、リッジ回帰Lassoがある。


おまけ

次の記事で、モデルの複雑さを制御する手法であるリッジ回帰Lassoについての記事を書く予定です。