【Python】scikit-learn ~ 線形回帰 ~

■ はじめに

https://dk521123.hatenablog.com/entry/2020/03/02/233902
https://dk521123.hatenablog.com/entry/2020/03/08/113356
https://dk521123.hatenablog.com/entry/2020/04/04/021413

の続き。
今回は、scikit-learn で 線形回帰(Linear Regression)を行う

■ サンプル

例1:Hello world

import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression

# 特徴量x (2次元)
x = [[1], [2], [3], [5], [6], [7], [8], [10], [12], [15]]
# y (1次元)
y = [1, 4, 6, 9, 12, 13, 15, 20, 24, 31]

# 線形回帰モデルを作成
model = LinearRegression()
model.fit(x, y)

print('傾き: %.2f' % model.coef_)
print('切片: %.2f' % model.intercept_)
x_value = 41
y_value = model.predict([[x_value]])
print('x: {}, predicted y : {}'.format(
  x_value, y_value))

plt.figure(figsize=(8, 4))
y_pred = model.predict(x)

# 散布図
plt.scatter(x, y, color='blue', label='sample data')
plt.plot(x, y_pred, color='red', linestyle='-', label='prediction model')
plt.ylabel('y')
plt.xlabel('x')
plt.ylim(0, 40)
plt.title('Hello World')
plt.legend(loc='lower right')
plt.show()

出力結果

傾き: 2.08
切片: -0.86
x: 41, predicted y : [84.47097844]

例2:バネの伸びと力の関係

使用データ
https://raw.githubusercontent.com/ibm-et/jupyter-samples/master/elasticity/springData.txt

を改変。
~~~~~~
Distance(m) Mass(kg)
0.0865 0.1
0.1015 0.15
0.1106 0.2
・・・略・・・
0.4304 0.95
0.437 1.0
~~~~~~

プログラム

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression

# データの読み込み
df = pd.read_csv("springData.txt", sep=" ")

# F[N] = m(重さ) * 9.81(重力加速度)
df['Force(N)'] = df['Mass(kg)'] * 9.81

# バネの伸び切ったデータを削除するために、
# 7(N)より小さいデータは除外
df = df[df['Force(N)'] < 7]

df.plot('Distance(m)', 'Force(N)', kind='scatter')

# fit_intercept=False => 切片を求める計算を含めない。
# 原点を必ず通る性質のデータを扱うときに利用
liner_reg = LinearRegression(fit_intercept=False)
liner_reg.fit(
  df['Force(N)'].values.reshape(-1, 1),
  df['Distance(m)'])

# 関数を定義. liner_reg.coef_ : 傾き
function = lambda x: x * liner_reg.coef_

figure = df.plot('Force(N)', 'Distance(m)', kind='scatter')
x = np.linspace(0, 8, num=50)
y = function(x)
figure.plot(x, y, c='r')
plt.show()

例3:勾配降下法

同じデータセットで、勾配降下法(Gradient descent)について、
学べたらのでメモ。

プログラム

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

def residual(k, data_frame):
  x = data_frame['Force(N)']
  y = data_frame['Distance(m)']
  return 2 * np.sum(x * (x * k - y))

# データの読み込み
df = pd.read_csv("springData.txt", sep=" ")

# F[N] = m(重さ) * 9.81(重力加速度)
df['Force(N)'] = df['Mass(kg)'] * 9.81

# バネの伸び切ったデータを削除するために、
# 7(N)より小さいデータは除外
df = df[df['Force(N)'] < 7]

# 最急降下法による算出
a = 0.0001
k = 0.0
while np.abs(residual(k, df)) > 1e-5:
  k -= a * residual(k, df)

print(k)

出力結果

0.06540842097379776

参考文献

https://qiita.com/nanairoGlasses/items/084b7656c285b4a41e03
https://pythondatascience.plavox.info/scikit-learn/%E7%B7%9A%E5%BD%A2%E5%9B%9E%E5%B8%B0

関連記事

scikit-learn ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2020/03/02/233902
scikit-learn ~ 基本編 ~
https://dk521123.hatenablog.com/entry/2020/03/08/113356
scikit-learn ~ 重回帰/リッジ回帰 ~
https://dk521123.hatenablog.com/entry/2020/04/25/174503
scikit-learn ~ 決定木 / ランダムフォレスト ~
https://dk521123.hatenablog.com/entry/2020/04/04/021413
Pandas ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2019/10/22/014957
NumPy ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2018/03/28/224532
TensorFlow ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2018/02/16/103500
Keras ~ 深層学習用ライブラリ ~
https://dk521123.hatenablog.com/entry/2020/03/03/235302
PyTorch ~ 深層学習ライブラリ ~
https://dk521123.hatenablog.com/entry/2020/07/05/000000
Matplotlib ~ グラフ描画ライブラリ ~
https://dk521123.hatenablog.com/entry/2020/03/01/000000