Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
6
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

「精度」と「モデルの複雑さ」に注力しながら、線形回帰を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$$
誤差をイメージできない人もいると思います(僕は頭に描けなかった)。なので、誤差を図示してみました。

image.png

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

下準備

$ 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に対しても、精度は低い。よって、過剰適合はなく、適合不足である可能性が高い。
下の「精度とモデルの複雑さ」の図でいうと、スイートスポット左側に位置しているのだろう。

width=70

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

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

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についての記事を書く予定です。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
6
Help us understand the problem. What are the problem?