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
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にします。
これも重回帰のほうが精度が良い結果になりました。
まとめ
今回は単回帰、重回帰、多項式回帰を解説しました。
直線関係であるとわかっているデータなら単回帰や重回帰がおススメです。
ただし直線関係がないデータにはうまく機能しません。
コメント