重回帰分析
前回の記事では、単回帰分析について説明しました。これは1つの特徴量(説明変数)が1つの目標(目的変数)にどのように影響するかを理解するのに役立ちます。しかし、現実世界の問題はより複雑であることが多いです。例えば、住宅価格を予測する場合、床面積だけでなく、寝室の数、立地、築年数など複数の要因を考慮する必要があります。このようなとき、私たちは次が必要です。重回帰分析。
簡単に言うと、重回帰分析は単回帰分析を自然に拡張したもので、複数の説明変数が1つの目的変数に与える影響を同時に分析できます。本記事では、重回帰分析の中心概念、数学的原理、実装方法、実際の応用について、ゼロから包括的に理解していきます。
一、重回帰分析とは?
1.1 中心的概念
重回帰分析は、複数の説明変数(特徴量・説明変数とも呼ばれる)と1つの連続型目的変数(目的変数・応答変数とも呼ばれる)の間の線形関係を確立する統計手法です。
わかりやすい比喩:あなたがスープの味(目的変数)を調整している料理長だと想像してください。単回帰分析は、塩の量だけで塩加減を調整するようなものです。一方、重回帰分析は、塩、砂糖、唐辛子、醤油など複数の調味料(特徴量)の量を同時に調整して、スープの最終的な味を総合的に決めるようなものです。重回帰分析により、各調味料が味にどの程度貢献しているかを分析できます。
1.2 モデル式
重回帰モデルの数学的表現は以下の通りです:
y = β₀ + β₁x₁ + β₂x₂ + ... + βₙxₙ + ε
この式の各部分を分解してみましょう:
| 記号 | 名称 | 意味 |
|---|---|---|
y |
目的変数 | 予測したい目的の値(例:住宅価格)。 |
x₁, x₂, ..., xₙ |
説明変数 | 予測に用いるy特徴(例:面積、寝室数、築年数)。 |
β₀ |
切片項 | すべての説明変数が0のときyの予測基準値。 |
β₁, β₂, ..., βₙ |
回帰係数 | 各説明変数xᵢの重み。これは次のことを意味します:他の特徴が変わらない場合、xᵢその変数が1単位増加すると、y平均的にβᵢ単位変化します。これが重回帰分析の核心です。 |
ε |
誤差項 | モデルでは説明できないランダムな変動(例:測定誤差、未知の要因)。 |
式の解釈の例:住宅価格(y)を予測するモデルを仮定します:房价 = 50000 + 3000 * 面积 + 10000 * 卧室数 - 2000 * 房龄
β₀ = 50000:理論上、面積0、寝室0、築年数0の「住宅」の基準価格。β₁ = 3000:寝室数と築年数が同じ場合、面積が1平米増えるごとに、住宅価格は平均で3000元上昇します。β₂ = 10000:面積と築年数が同じ場合、寝室が1つ増えると、住宅価格は平均で10000元上昇します。β₃ = -2000:面積と寝室数が同じ場合、築年数が1年増えるごとに、住宅価格は平均で2000元下落します。
二、重回帰モデルを「訓練」するには?
モデルを「訓練」するとは、本質的には、既存のデータに基づいて最適な回帰係数のセットを見つけることであり、(β₀, β₁, ..., βₙ)モデルの予測値をできるだけ実際の値に近づけることです。このプロセスは通常、最小二乗法によって行われます。
2.1 目的:損失関数の最小化
私たちは残差平方和を損失関数として用い、モデルの予測誤差を評価します。RSS = Σ(yᵢ - ŷᵢ)²ここで、yᵢはi番目の実際の値、ŷᵢはモデルによるi番目のサンプルに対する予測値です。
訓練の目的は、RSSの値が最小になるような係数のセットを見つけることです。
2.2 解法プロセス(行列形式)
特徴量の数が多い場合、行列演算を使うとより効率的に表現・求解できます。モデルは次のように書けます:Y = Xβ + εここで:
Yはすべての目的変数値を含む列ベクトルです。Xは計画行列で、最初の列は通常すべて1です(切片項β₀に対応します)。後続の各列は1つの特徴量に対応します。βはすべての回帰係数を含む列ベクトルです。εは誤差項のベクトルです。
最小二乗法の導出により、係数βの最適解(閉形式解)は次のようになります:β = (XᵀX)⁻¹XᵀYこの式は理論的には非常に優れていますが、実際のプログラミングでは通常、数値最適化ライブラリ(例えばscikit-learn)を使用して、効率的かつ安定的に計算します。これにより、行列の逆行列などの複雑な操作が自動的に処理されます。
三、Python で重回帰分析を実装する
完全な例を通して、人気の機械学習ライブラリを使用してscikit-learn重回帰モデルを構築しましょう。
3.1 環境準備とデータ読み込み
まず、必要なライブラリがインストールされていることを確認し、サンプルデータセットを読み込みます。
例
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.datasets import fetch_california_housing # 古典的な多変量データセット
# カリフォルニア住宅価格データセットを読み込み
california = fetch_california_housing()
df = pd.DataFrame(california.data, columns=california.feature_names)
df['MedHouseVal'] = california.target # 目的列を追加:住宅価格の中央値
print("データセット形状:", df.shape)
print("\n"先頭5行のデータ:")
print(df.head())
print("\n"特徴量の説明:")
print(california.DESCR[:500]) # 説明の一部を表示
3.2 データ探索と前処理
モデル構築の前に、データの基本状況を把握することが非常に重要です。
例
print(df.info())
print("\n"基本統計量:")
print(df.describe())
# 2. 特徴量(X)と目的変数(y)に分割
X = df.drop('MedHouseVal', axis=1) # 特徴行列:住宅価格以外のすべての列を含む
y = df['MedHouseVal'] # 目的変数ベクトル:住宅価格
# 3. 訓練データとテストデータに分割(70%訓練、30%テスト)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
print(f"\n"訓練データのサンプル数: {X_train.shape)
3.3 モデルの作成、訓練、評価
次に、線形回帰モデルを作成し、訓練データで「フィット」させ、テストデータでその性能を評価します。
例
model = LinearRegression()
# 2. モデルを訓練(データにフィット)
model.fit(X_train, y_train)
# 3. 訓練したモデルで予測
y_train_pred = model.predict(X_train)
y_test_pred = model.predict(X_test)
# 4. モデル性能の評価
# 平均二乗誤差 (MSE) - 小さいほど良い
train_mse = mean_squared_error(y_train, y_train_pred)
test_mse = mean_squared_error(y_test, y_test_pred)
# 決定係数 (R²) - 1に近いほど良く、モデルの説明力が高いことを示す
train_r2 = r2_score(y_train, y_train_pred)
test_r2 = r2_score(y_test, y_test_pred)
print("=== モデル性能の評価 ===")
print(f"訓練データ MSE: {train_mse:.4f}, R²: {train_r2:.4f}")
print(f"テストデータ MSE: {test_mse:.4f}, R²: {test_r2:.4f}")
# 5. 学習されたモデルパラメータを確認
print("\n"=== モデルパラメータ ===")
print(f"切片 (β₀): {model.intercept_:.4f}")
print("回帰係数 (β₁, β₂, ...):")
for feature, coef in zip(X.columns, model.coef_):
print(f" {feature}: {coef:.4f}")
3.4 結果の解釈と可視化
係数と評価指標の意味を理解します。
例
plt.figure(figsize=(8, 6))
plt.scatter(y_test, y_test_pred, alpha=0.5)
plt.plot([y.min(), y.max()], [y.min(), y.max()], 'r--', lw=2) # 理想的な対角線を描画
plt.xlabel('実際の住宅価格')
plt.ylabel('予測住宅価格')
plt.title('重回帰分析:実測値 vs 予測値(テストデータ)')
plt.grid(True, linestyle='--', alpha=0.7)
plt.show()
# 可視化:特徴量の重要度(係数の絶対値の大きさで近似的に表す)
features = X.columns
coefs = model.coef_
plt.figure(figsize=(10, 6))
bars = plt.barh(features, np.abs(coefs)) # 絶対値を使って影響の大きさを比較
plt.xlabel('回帰係数の絶対値')
plt.title('住宅価格に対する特徴量の影響の大きさ(係数の絶対値に基づく)')
# 棒グラフに数値ラベルを追加する
for bar, coef in zip(bars, coefs):
width = bar.get_width()
plt.text(width + 0.01, bar.get_y() + bar.get_height()/2, f'{coef:.4f}', va='center')
plt.grid(True, axis='x', linestyle='--', alpha=0.7)
plt.tight_layout()
plt.show()
四、重回帰分析の注意点と課題
4.1 重要な仮定
線形回帰モデルの有効性は、いくつかの統計的仮定に基づいています:
- 線形関係:独立変数と従属変数の間に線形関係が存在する。
- 独立性:観測値は互いに独立である。
- 等分散性:誤差項の分散はすべての観測で一定である。
- 正規性:誤差項は正規分布に従う。
- 多重共線性がないこと:独立変数間に高い相関があってはならない。
4.2 よくある課題と対策
| 課題 | 説明 | 考えられる結果 | 対策方法 |
|---|---|---|---|
| 多重共線性 | 特徴量間の相関が高い。 | 係数の推定が不安定になり、個々の特徴量の影響を解釈することが難しくなる。 | 1. 相関行列を使用して高相関の特徴量を確認し、削除する。 2. 主成分分析(PCA)を使用して次元を削減する。 3. 正則化手法(リッジ回帰など)を使用する。 |
| 過学習 | モデルが複雑すぎて、トレーニングデータのノイズに完全に適合し、テストセットでの性能が悪い。 | テストセットの誤差がトレーニングセットの誤差よりもはるかに大きい。 | 1. より多くのデータを収集する。 2. より少ない特徴量を使用する(特徴選択)。 3. 正則化を使用する。 |
| 非線形関係 | データの関係性は本質的に非線形である。 | モデルの予測能力が低く、R² 値が低い。 | 1. 特徴量を変換する(多項式特徴量、対数変換など)。 2. 非線形モデル(決定木、ニューラルネットワークなど)を使用する。 |
五、実践演習:理解を深める
さあ、あなたが実際に手を動かしてみましょう!次の演習を順番に完了して、重回帰分析への理解を深めてください。
演習 1:モデルの解釈
上記のコードが出力したモデルの係数を使用して、以下の質問に答えなさい:
- どの特徴がカリフォルニアの住宅価格に対して正の影響が最も大きいか?(係数の値に基づいて判断)
- どの特徴がカリフォルニアの住宅価格に対して負の影響を与えるか??
- どのように解釈する?
AveRooms(平均部屋数)の係数について、完全な文で説明してください。
演習 2:多重共線性の診断
- 特徴量の
X相関行列を計算し(df.corr())。 - 相関の絶対値が0.7より大きい特徴量のペアを見つけなさい。それらは多重共線性を持つ可能性があります。
- (任意)モデルから高相関の特徴量を1つ削除して再トレーニングし、係数とR²スコアがどのように変化するかを観察しなさい。
演習 3:新しいデータセットへの挑戦
- から
sklearn.datasetsから別の回帰データセットを読み込み、例えばload_diabetes(糖尿病データセット)。 - この記事のモデリング手順を繰り返してください:データ探索、分割、トレーニング、評価、可視化。
- 2つのデータセットにおけるモデルの性能を比較し、考えられる原因を考察してください。