複数の説明変数を組み合わせて目的変数を予測するのが、重回帰分析(multiple linear regression)です。本記事では、行列形式での定式化、Python での実装、よく踏む落とし穴(多重共線性など)を整理します。
目次
- 重回帰のモデル
- 株式分析でのよくある使い方
- Python で計算する
- 決定係数と自由度調整
- 多重共線性
- カテゴリ変数(ダミー変数)
- 残差診断
重回帰のモデル
説明変数を 個用意して、目的変数を直線(超平面)で表します。
行列で書くと、
最小二乗法の解は次のとおりです( が可逆なとき)。
行列演算で求まることが、単回帰との大きな違いです。
株式分析でのよくある使い方
| 目的変数 | 説明変数の例 |
|---|---|
| 個別銘柄の月次リターン | 市場リターン、業種ダミー、サイズ要因 |
| 翌期 EPS | 売上成長率、営業利益率、過去 EPS |
| ボラティリティ | 出来高、前期ボラ、業種 |
学術的には Fama-French 3 ファクターモデルなどが知られています(本記事ではモデル詳細は扱いません)。
Python で計算する
statsmodels で重回帰を組む例です。
import numpy as npimport pandas as pdimport statsmodels.api as sm
rng = np.random.default_rng(2)n = 300
# 説明変数 3 つx1 = rng.normal(0.0, 1.0, size=n)x2 = rng.normal(0.0, 1.0, size=n)x3 = rng.normal(0.0, 1.0, size=n)
# 目的変数: y = 0.5 + 0.8*x1 - 0.3*x2 + 0.0*x3 + noisey = 0.5 + 0.8 * x1 - 0.3 * x2 + 0.0 * x3 + rng.normal(0.0, 0.5, size=n)
df = pd.DataFrame({"x1": x1, "x2": x2, "x3": x3, "y": y})
X = sm.add_constant(df[["x1", "x2", "x3"]])model = sm.OLS(df["y"], X).fit()print(model.summary())coef 列で係数の推定値、P>|t| 列で各係数の有意性を確認します。
決定係数と自由度調整
説明変数を増やすと、 は機械的に上がります。本当に説明力が増えたかを見るには、自由度を考慮した 自由度調整済み決定係数 を使います。
statsmodels の出力では Adj. R-squared の行に表示されます。説明変数を 1 つ追加して R^2 だけが上がり Adj. R-squared が下がる場合、その変数は実質的な情報を持っていない可能性があります。
多重共線性
重回帰で最も注意すべき落とし穴が 多重共線性(multicollinearity) です。説明変数同士の相関が強いと、各係数の推定値が不安定になります。
判定の目安として、VIF(Variance Inflation Factor、分散拡大係数) が使われます。
ここで は、変数 を他の説明変数で回帰したときの決定係数です。慣例的には次のラインを使います。
| VIF の値 | 解釈 |
|---|---|
| 1〜5 | 大きな問題なし |
| 5〜10 | 注意 |
| 10 以上 | 多重共線性が疑わしい |
from statsmodels.stats.outliers_influence import variance_inflation_factor
X_no_const = df[["x1", "x2", "x3"]]vif = pd.DataFrame({ "feature": X_no_const.columns, "VIF": [variance_inflation_factor(X_no_const.values, i) for i in range(X_no_const.shape[1])],})print(vif)VIF が高い変数があれば、変数を削るか、主成分分析(PCA)などで合成変数に置き換える対処が一般的です。
カテゴリ変数(ダミー変数)
業種・市場区分のようなカテゴリ変数は、ダミー変数(0/1 の列)に展開してから回帰に入れます。pandas の get_dummies が手軽です。
sample = pd.DataFrame({ "sector": ["IT", "金融", "製造", "IT", "金融"], "x": [1.0, 2.0, 3.0, 4.0, 5.0], "y": [1.1, 1.9, 3.2, 4.0, 5.1],})
dummies = pd.get_dummies(sample["sector"], drop_first=True)features = pd.concat([sample[["x"]], dummies], axis=1)
X = sm.add_constant(features.astype(float))model = sm.OLS(sample["y"], X).fit()print(model.params)drop_first=True で 1 つのカテゴリを基準にして、係数を「基準カテゴリとの差分」として読みます。
残差診断
単回帰と同様、残差プロットで仮定を確認します。
- 残差と予測値の散布図 → 0 を中心に均等な散らばりが理想
- QQ プロット → 残差の正規性を確認
- 残差の自己相関(時系列データの場合) → Durbin-Watson 統計量
statsmodels の summary には Durbin-Watson 値が表示されます。2 付近なら自己相関は小さい、0 や 4 に近いと正・負の自己相関があるサインです。
注意点
- 説明変数の単位が桁違いだと、係数の大きさを直感で比べられません(必要に応じて標準化する)
- 過去の関係が将来も続く保証はないため、サンプル外検証 が必須
- 説明変数の選び方によっては、データに過剰に適合する オーバーフィット に陥ります(分割検証や正則化が対策)
- 株式リターンでは、リーク(将来情報の混入)に特に注意します
生成AI へのプロンプト例
要因モデルを汎用的に組む例です。
目的変数 y(pandas Series)と、説明変数の DataFrame X(列が要因)を受け取り、重回帰の結果を整理して返す関数 fit_factor_model(y, X) を書いてください。
戻り値: dict- params(係数の Series)、p_values(Series)- r_squared、adj_r_squared- vif(各説明変数の VIF を入れた DataFrame)- residuals(残差の Series)
要件:- statsmodels の OLS を使う- 切片を自動で追加- pandas 2.2 系の API を使う- docstring を日本語で書くまとめ
- 重回帰は複数の説明変数を線形に組み合わせるモデル
- 自由度調整済み で「変数を増やした効果」を評価する
- 多重共線性は VIF で確認、5〜10 以上は要注意
- カテゴリ変数はダミー変数に展開、係数は「基準カテゴリとの差」として読む
- オーバーフィットを避けるため、サンプル外検証を組み合わせる