import numpy as np
import matplotlib.pyplot as plt
# 1. Sample Data (Hours studied vs Test Score)
x = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
y = np.array([35, 45, 50, 55, 60, 65, 70, 75, 85])
# 2. Visualize the Data
plt.scatter(x, y)
plt.show()
回帰分析(regression analysis)とは、ある変数 \(Y\) を他の変数 \(X_1, X_2, \ldots, X_p\) を用いて予測・説明するための統計的手法である。\(Y\) を目的変数、\(X_1, X_2, \ldots, X_p\) を説明変数と呼ぶ。回帰分析は、経済学、社会学、医学、工学など様々な分野で応用されている。
例えば、以下のような例がある。
| 説明変数 \(X\) | 目的変数 \(Y\) |
|---|---|
| 気温 | アイスクリームの売上 |
| 広告費 | 商品の売上 |
| 勉強時間 | 試験の点数 |
| 面積、築年数 | 住宅価格 |
\(X = (X_1, X_2, \ldots, X_p)\) とすると、説明変数 \(X\) と目的変数 \(Y\) の関係は以下のように表される。
\[ Y = f(X) + \epsilon \]
ここで、\(f\) は説明変数 \(X\) と目的変数 \(Y\) の関係を表す関数、\(\epsilon\) は誤差項である。
単回帰分析(simple regression analysis)は、1つの説明変数 \(X\) を用いて目的変数 \(Y\) を予測・説明する手法である。単回帰分析では、\(X\) と \(Y\) の関係を線形モデルで表す。数学的には、以下のように表される。
\[ Y = \beta_0 + \beta_1 X + \epsilon \]
\(n\) 組の観測データ
\[ \mathcal{D} = \{(x_1, y_1), (x_2, y_2), \ldots, (x_n, y_n)\} \]
が与えられたとき、データからパラメータ \(\beta_0\) と \(\beta_1\) を推定する。推定されたパラメータをそれぞれ \(\hat{\beta}_0\) と \(\hat{\beta}_1\) と表す。これらのパラメータを用いて、\(x_i\) に対する予測値 \(\hat{y}_i\) は
\[ \hat{y} = \hat{\beta}_0 + \hat{\beta}_1 x \]
と計算される。\(x_i\) に対する予測値 \(\hat{y}_i\) と実際の観測値 \(y_i\) の差を残差(residual)と呼び、以下のように定義される。
\[ e_i = y_i - \hat{y}_i \]
残差平方和(residual sum of squares, RSS)は残差の二乗の和であり、以下のように定義される。
\[ \text{RSS} = \sum_{i=1}^{n} e_i^2 = \sum_{i=1}^{n} (y_i - \hat{y}_i)^2 \]
これを展開すると、
\[ \text{RSS} = (y_1 - \hat{\beta}_0 - \hat{\beta}_1 x_1)^2 + (y_2 - \hat{\beta}_0 - \hat{\beta}_1 x_2)^2 + \ldots + (y_n - \hat{\beta}_0 - \hat{\beta} x_n)^2 \]
となる。RSS を最小化する \(\hat{\beta}_0\) と \(\hat{\beta}_1\) を求める方法を最小二乗法(least squares method)と呼ぶ。
計算より、最小二乗法により求められる \(\hat{\beta}_0\) と \(\hat{\beta}_1\) は以下のように表される。
\[ \hat{\beta}_1 = \frac{\sum_{i=1}^{n}(x_i - \bar{x})(y_i - \bar{y})}{\sum_{i=1}^{n}(x_i - \bar{x})^2} \]
\[ \hat{\beta}_0 = \bar{y} - \hat{\beta}_1 \bar{x} \]
ここで、\(\bar{x} = \frac{1}{n} \sum_{i=1}^{n} x_i\), \(\bar{y} = \frac{1}{n} \sum_{i=1}^{n} y_i\) をそれぞれ \(x\) および \(y\) の平均とする。
架空のデータセット \(\mathcal{D}\) を用いて、勉強時間と試験の点数の関係を分析する。
\[ \mathcal{D} = \{(1, 35), (2, 45), (3, 50), (4, 55), (5, 60), (6, 65), (7, 70), (8, 75), (9, 85)\} \]
勉強時間を説明変数 \(X\)、試験の点数を目的変数 \(Y\) とする。次のコードは、データの可視化を行う。
import numpy as np
import matplotlib.pyplot as plt
# 1. Sample Data (Hours studied vs Test Score)
x = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
y = np.array([35, 45, 50, 55, 60, 65, 70, 75, 85])
# 2. Visualize the Data
plt.scatter(x, y)
plt.show()
与えられた \(\mathcal{D}\) から \(\hat{\beta}_0\) と \(\hat{\beta}_1\) を計算する関数を以下に示す。
import numpy as np
def simple_linear_regression(x, y):
n = len(x)
x_mean = np.mean(x)
y_mean = np.mean(y)
# Calculate beta_1
numerator = np.sum((x - x_mean) * (y - y_mean))
denominator = np.sum((x - x_mean) ** 2)
beta_1 = numerator / denominator
# Calculate beta_0
beta_0 = y_mean - beta_1 * x_mean
return beta_0, beta_1最後に、上記の関数を用いて \(\hat{\beta}_0\) と \(\hat{\beta}_1\) を計算してみる。
# Calculate coefficients
beta_0, beta_1 = simple_linear_regression(x, y)
print(f"Intercept (β0): {beta_0}")
print(f"Slope (β1): {beta_1}")Intercept (β0): 31.666666666666664
Slope (β1): 5.666666666666667
これで,与えられた勉強時間 \(x\) に対する試験の点数の予測値 \(\hat{y}\) を次のように計算できる。
\[ \hat{y} \approx 31.6667 + 5.6667 x \]
例えば、勉強時間が 4 時間のとき、試験の点数の予測値は
\[ \hat{y} \approx 31.6667 + 5.6667 \times 4 \approx 54.3335 \]
となる。この予測値は、実際の観測値 \(y = 55\) に近いことがわかる。
最後に、回帰直線をデータとともにプロットする。
# Plot the regression line
plt.scatter(x, y, color="blue", label="Data points")
plt.plot(x, beta_0 + beta_1 * x, color="red", linewidth=2, label="Regression line")
plt.xlabel("X (Hours studied)")
plt.ylabel("y (Test Score)")
plt.title("Simple Linear Regression")
plt.legend()
plt.show()
Python では、scikit-learn ライブラリを用いて回帰分析を簡単に実装できる。以下に、単回帰分析の例を示す。
次に、線形回帰モデルを作成し、\(\hat{\beta}_0\) と \(\hat{\beta}_1\) を計算する。データからパラメータを推定することを学習(learning)、フィッティング(fitting)、トレーニング(training)と呼ぶ。
LinearRegression() からモデルを作成し、fit() にデータ X と y を与えて、\hat{\beta}_0 と \hat{\beta}_1 を計算する。
from sklearn.linear_model import LinearRegression
# 1. Sample Data (Hours studied vs Test Score)
X = np.array([[1], [2], [3], [4], [5], [6], [7], [8], [9]])
y = np.array([35, 45, 50, 55, 60, 65, 70, 75, 85])
# 2. Create and Fit the Model
model = LinearRegression()
model.fit(X, y)
# 3. Print the coefficients
print(f"Intercept (β0): {model.intercept_}")
print(f"Slope (β1): {model.coef_[0]}")Intercept (β0): 31.666666666666664
Slope (β1): 5.666666666666667
load_diabetes 関数を用いて糖尿病データセットを読み込み、BMIを説明変数、糖尿病の進行度を目的変数として単回帰分析を行う。ここでは,BMIが標準化されていることに注意 1。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.datasets import load_diabetes
# 糖尿病データセットの読み込み
diabetes = load_diabetes(as_frame=True)
# BMI を説明変数、糖尿病の進行度を目的変数とする
X = diabetes.data[["bmi"]]
y = diabetes.target
# 線形回帰モデルの作成と学習
model = LinearRegression()
model.fit(X, y)
# 回帰直線の描画
plt.scatter(X, y, color="blue", label="Data points")
plt.plot(X, model.predict(X), color="red", linewidth=2, label="Regression line")
plt.xlabel("X (BMI)")
plt.ylabel("y (Diabetes Progression)")
plt.title("Simple Linear Regression")
plt.legend()
plt.show()
# 回帰係数の表示
print(f"Intercept (β0): {model.intercept_}")
print(f"Slope (β1): {model.coef_[0]}")
Intercept (β0): 152.13348416289617
Slope (β1): 949.4352603840388
回帰分析は、変数間の関係性をモデル化する手法であり、必ずしも因果関係を示すものではない。例えば、アイスクリームの売上と水難事故の発生件数には正の相関があるが、これは両者が夏季に増加するという共通の要因によるものであり、アイスクリームの売上が水難事故を引き起こすわけではない。このように、回帰分析の結果を解釈する際には、因果関係と相関関係を区別することが重要である。
カリフォルニア州の住宅価格データセットを用いて、収入を説明変数、住宅価格を目的変数として単回帰分析を行い、回帰直線を描画せよ。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.datasets import fetch_california_housing
# カリフォルニア州の住宅価格データセットの読み込み
housing = fetch_california_housing(as_frame=True)
# 収入を説明変数、住宅価格を目的変数とする
X = housing.data[["MedInc"]] # 所得を説明変数とする
y = housing.target # 住宅価格を目的変数とする
# 線形回帰モデルの作成と学習
model = LinearRegression()
model.fit(X, y)
# ここにコードを書くhttps://www4.stat.ncsu.edu/~boos/var.select/diabetes.html↩︎