【Python】線形回帰(Ridge, Lasso)の作り方

Python
スポンサーリンク

Pythonで線形回帰モデルを作成することができます。

from sklearn.linear_model import LinearRegression
model = LinearRegression()
model.fit(X, y)

データセット

import pandas as pd
from sklearn.datasets import load_diabetes

data = load_diabetes()
df = pd.DataFrame(data["data"], columns = data["feature_names"])
df["target"] = data["target"]
df

“load_diabetes”のデータを呼び出しました。

特徴量”age” ~ “s6″を使って”target”を予測するモデルを作りましょう。

データ分割

from sklearn.model_selection import train_test_split

train, test = train_test_split(df, test_size = 0.1)
print(df.shape, train.shape, test.shape)

# ========== output ==========
# (442, 11) (397, 11) (45, 11)

モデルに学習させるデータと、検証に使うデータとに分けます。

train_test_splitで分割しましょう。test_size = 0.1にすると10%が検証データになります。

単回帰

from sklearn.linear_model import LinearRegression

#学習用データ
X_train = train["bmi"].values.reshape(-1, 1)
y_train = train["target"].values
#検証用データ
X_test = test["bmi"].values.reshape(-1, 1)
y_test = test["target"].values

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

単回帰は、1つの特徴量からデータを予測します。

まず、LinearRegressionをインポートしましょう。

今回は”bmi”を特徴量に使用しました。

LinearRegressionを呼び出してfitに特徴量と答えを渡すだけでOKです。

print(model.coef_, model.intercept_)

# ========== output ==========
# [935.83555314] 153.18883110145993
coef_ : 勾配
intercept_ : 切片

この2つの値を使って”bmi”から”target”が予測できるようになりました。

import matplotlib.pyplot as plt

plt.scatter(X_train, y_train, alpha = 0.8)
plt.plot(X_train, X_train * 935 + 153, "r-") #coef_とintercept_から予測する式
plt.xlabel("bmi")
plt.ylabel("target")
plt.show()

こんな感じで”bmi”を使って直線をフィットさせることができました。

しかし、学習データではモデルが答えを知っているので、検証データでも確かめましょう。

plt.scatter(X_test, y_test, alpha = 0.8)
plt.plot(X_test, X_test * 935 + 153, "r-") #coef_とintercept_から予測する式
plt.xlabel("bmi")
plt.ylabel("target")
plt.show()

検証データでもおおよそフィットしていますね。

誤差も計算してみましょう。

import numpy as np
from sklearn.metrics import mean_squared_error
print(np.sqrt(mean_squared_error(y_test, X_test * 935 + 153)))

# ========== output ==========
# 54.93980529280439

平均二乗誤差が54.9でした。

以上が、1つの特徴量から予測する単回帰モデルの作り方です。

重回帰

features = [c for c in df.columns if c != "target"]
print(features)

#学習用データ
X_train = train[features]
y_train = train["target"].values
#検証用データ
X_test = test[features]
y_test = test["target"].values

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

# ========== output ==========
# ['age', 'sex', 'bmi', 'bp', 's1', 's2', 's3', 's4', 's5', 's6']

重回帰は、複数の特徴量から予測します。

featuresに”target”以外の列名を入れました。

これらを使ってfitし、モデルを学習させます。

rint(model.coef_, model.intercept_)

# ========== output ==========
# [ -26.4221349  -225.29507502  518.14034363  344.07207154 -843.66182221
# 516.48702141  111.29241525  169.98211205  773.65137366   58.41894004] 151.56933753368102

このように、特徴量の数だけcoef_(勾配)が得られます。

col = features[2]
plt.scatter(X_train[col], y_train, alpha = 0.8)
plt.plot(X_train[col], X_train[col] * model.coef_[0] + model.intercept_, "r-") #coef_とintercept_から予測する式
plt.xlabel(col)
plt.ylabel("target")
plt.show()

重回帰では複数の特徴量を考慮しているので、単回帰とは違う結果になります。

2次元だと直線、3次元だと平面でフィットさせることになるからです。

plt.scatter(X_test[col], y_test, alpha = 0.8)
plt.plot(X_test[col], X_test[col] * model.coef_[0] + model.intercept_, "r-") #coef_とintercept_から予測する式
plt.xlabel(col)
plt.ylabel("target")
plt.show()

このように検証データでも違う結果になっています。

ただし、これだけで精度が悪くなっていると決めつけるのは良くありません。

全特徴量を使って誤差を検証してみましょう。

pred = np.sum([X_test[c] * model.coef_[i] for i, c in enumerate(features)], axis = 0) + model.intercept_
print(np.sqrt(mean_squared_error(y_test, pred)))

# ========== output ==========
# 53.614109763354776

平均二乗誤差が53.6なので、単回帰よりも精度がよくなっていますね。

Ridge回帰

from sklearn.linear_model import Ridge

features = [c for c in df.columns if c != "target"]

#学習用データ
X_train = train[features]
y_train = train["target"].values
#検証用データ
X_test = test[features]
y_test = test["target"].values

model = Ridge()
model.fit(X_train, y_train)

pred = np.sum([X_test[c] * model.coef_[i] for i, c in enumerate(features)], axis = 0) + model.intercept_
print(np.sqrt(mean_squared_error(y_test, pred)))

# ========== output ==========
# 56.668581514308066

Ridge回帰は過学習を抑制した線形モデルです。

今回は重回帰よりも精度が落ちていますが、不要な特徴量を考慮したくない場合に使われたりします。

Lasso回帰

from sklearn.linear_model import Lasso

features = [c for c in df.columns if c != "target"]

#学習用データ
X_train = train[features]
y_train = train["target"].values
#検証用データ
X_test = test[features]
y_test = test["target"].values

model = Lasso()
model.fit(X_train, y_train)

pred = np.sum([X_test[c] * model.coef_[i] for i, c in enumerate(features)], axis = 0) + model.intercept_
print(np.sqrt(mean_squared_error(y_test, pred)))

# ========== output ==========
# 59.80286708492358

Lasso回帰も過学習を抑制したモデルで、不要な特徴量の勾配を0にします。

これも重回帰のほうが精度が良い結果になりました。

まとめ

今回は単回帰、重回帰、多項式回帰を解説しました。

直線関係であるとわかっているデータなら単回帰や重回帰がおススメです。

ただし直線関係がないデータにはうまく機能しません。

>>【無料説明会あり】キカガクのAI人材育成コースで勉強する

コメント

タイトルとURLをコピーしました