論文一覧に戻る 📚 用語解説(ジャストインタイム型データサイエンス教育)
多重共線性
Multicollinearity
説明変数同士が強く相関している状態。回帰係数の推定が不安定になり、p値が大きくなる。
回帰モデル多重共線性multicollinearity
📍 文脈💡 30秒結論📖 詳しく

📍 あなたが今見ているもの

論文中に 「多重共線性」として登場する用語。

多重共線性 とは:説明変数同士が強く相関している状態。回帰係数の推定が不安定になり、p値が大きくなる。

💡 30秒で分かる結論

🔖 キーワード索引

多重共線性 VIF 条件数 相関ヒートマップ 標準誤差 係数の符号反転 Ridge 回帰 PCA 主成分回帰 直交化 VIF と R²j 変数選択

📖 もっと詳しく

多重共線性(multicollinearity)は、 重回帰で説明変数同士が強く相関している状態。 これがあると、 「個々の係数は信用できないが、 予測自体はそこそこ正しい」という厄介な状況になります。

症状(あるある)

原因:説明変数同士が強く相関していると、 OLS の解 $(X^\top X)^{-1}$ で逆行列が不安定になります。 「x1 と x2 が一緒に動くので、 どっちが効いているか分けられない」状態。

検出

  1. 相関ヒートマップ:|r| > 0.7 のペアは要警戒
  2. VIF(Variance Inflation Factor):VIF > 10 で深刻、 > 5 で注意
  3. 条件数:cond(X) > 30 で問題ありの目安

対処法

覚えておくべき真実:多重共線性は「モデルが悪い」ではなく「係数の解釈ができない」状態。 予測精度には影響しない。 「個別の変数の効果」を主張したいときだけ深刻になる。

🎮 触って理解する

2つの説明変数 X1・X2 の相関 r をスライダーで変え、 目的変数 Y への重回帰 Y = β₁X1 + β₂X2 + 誤差閉形式の2変数OLSで正確に推定します。 真の値は β₁ = β₂ = 1.0。 相関を高めると、 推定される係数の 標準誤差が膨張し、 データを僅かに揺らすだけで係数が大きく振れる様子(=多重共線性)を体感できます。

👉 グラフの上を ドラッグ(スマホは指でスワイプ)すると、 同じ真の関係のまま「別の標本を引き直し」ます。 相関が高いほど、 少し揺らすだけで推定点(●)が対角線上を大きく行き来します。

VIF
-
= 1/(1−r²)
SE(β₁)
-
係数の標準誤差
SE(β₂)
-
係数の標準誤差
今の推定 β̂₁
-
真値 1.0
今の推定 β̂₂
-
真値 1.0
β̂₁ の95%CI幅
-
±1.96·SE の全幅

-

🧠 直感 — なぜ係数が分離できないのか

X1 と X2 が「似た動き」をすると、 OLS は「Y の増加分を X1 のおかげにするか X2 のおかげにするか」を決められません。 右パネルの推定点(●)の散らばりが 対角線(右下↘)方向に伸びた楕円になるのはこのためで、 「β̂₁ を大きくすれば β̂₂ を小さくしても当てはまりはほぼ同じ」=両者を足した効果 (β₁+β₂) はよく決まるのに、 個別には決まらないことを表します。 相関を r → 0 に下げると楕円は丸くなり、 推定は安定します。

🕳️ よくある落とし穴

🚀 発展 — 正則化と主成分回帰

関連ページ:

👁️ 直感 — 多重共線性は「説明変数同士の強い相関」

多重共線性(multicollinearity)は、 重回帰モデルで説明変数同士が強く相関する状態。 係数の推定が不安定になり、 解釈が困難に。

典型例

🔍 多重共線性の検出

① 相関行列ヒートマップ

|r| > 0.7 のペアは要注意。

② VIF(分散拡大因子)

$$ \text{VIF}_j = \frac{1}{1 - R_j^2} $$

③ 条件数(condition number)

X^T X の最大固有値/最小固有値。 30 を超えると多重共線性の疑い。

⚠️ 多重共線性の影響

🛠️ 多重共線性への対策

  1. 変数を削除:VIF が高い変数の一方を除外
  2. PCA で次元削減:主成分に置き換えて独立に
  3. Ridge 回帰:係数を縮小して安定化
  4. LASSO:自動的に変数選択
  5. 変数を合成:「BMI = 体重/身長²」のように1変数化
  6. サンプルを増やす:n を増やせば SE が小さくなり改善

🐍 Python での VIF 計算

🎯 解説: SSDSE-B-2026 で多重共線性を診断。 説明変数間の強相関(r>0.8)や VIF>10 で多重共線性を判定し、 回帰係数の不安定化リスクを評価。
📥 入力例: data/raw/SSDSE-B-2026.csv X = df[['総人口','出生数','転入','婚姻']] 相関行列 + VIF
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
from statsmodels.stats.outliers_influence import variance_inflation_factor
import pandas as pd

# SSDSE-B-2026(2023年、47都道府県)の実在列で VIF を計算
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]
X = df[['A1101', 'A4101', 'A5101', 'A9101']].rename(columns={
    'A1101': '総人口', 'A4101': '出生数', 'A5101': '転入', 'A9101': '婚姻'
}).astype(float)
X = (X - X.mean()) / X.std()  # 標準化

vif_df = pd.DataFrame({
    'feature': X.columns,
    'VIF': [variance_inflation_factor(X.values, i) for i in range(X.shape[1])]
})
print(vif_df.sort_values('VIF', ascending=False).round(2))
📤 実行例: 相関 r 行列 総人口-出生数: 0.995(深刻) 総人口-婚姻: 0.989 VIF: 総人口=113.20, 出生数=163.72
💬 読み方: r>0.8 で要注意、 r>0.95 で深刻。 VIF>10 で深刻。 人口系変数は強く相関し、 1 つだけ残すべき。

🚧 落とし穴と注意点

🔬 数式を言葉で読み解く

VIF の式 $\text{VIF}_j = 1 / (1 - R_j^2)$ を言葉に直すと: R²_j は「説明変数 x_j を、 残りの説明変数すべてで回帰したときの当てはまり」。 つまり「x_j は他の x で何 % 説明できるか」。 これが 0 なら VIF=1(独立、 問題なし)、 0.9 なら VIF=10(x_j の 90% は他の変数で説明可能、 多重共線性が深刻)、 1 に近づくと VIF は無限大に発散。 「分散がどれだけ膨らむか」の倍率なので、 VIF=10 は「係数の分散が独立時の 10 倍に膨張」と読める。

「多重共線性」を深く理解する

多重共線性の歴史

Ragnar Frisch(1934)が経済学で問題提起。 「経済データの多くは互いに相関しており、 回帰係数を一意に推定できない」。 1969年にノーベル経済学賞受賞時の主要業績。

完全共線性 vs 近似共線性

実務での経験則

📝 練習問題 — 理解度チェック

  1. この用語の基本定義を、 自分の言葉で説明できますか?
  2. この手法が使われる典型的なシナリオを3つ挙げられますか?
  3. この手法の前提条件・仮定を確認できますか?
  4. 結果を解釈する際の注意点は何ですか?
  5. 類似手法との違いを説明できますか?
  6. Python(または他言語)で実装できますか?
  7. SSDSE データで応用例を作成できますか?

📚 参考文献・さらなる学習

古典的教科書

実践書

オンラインリソース

💼 実務応用ガイド

データサイエンスプロジェクトでの位置づけ

  1. 探索的分析(EDA):基本統計量・可視化でデータを理解
  2. 前処理:標準化・正規化・欠損値処理
  3. モデリング:回帰・分類・クラスタリング
  4. 評価:CV、 指標計算、 統計的検定
  5. 解釈・報告:効果量・信頼区間・可視化

業界別ユースケース

📖 完全ガイド — 統計学習の参照表

分析の流れ — 8ステップ

  1. 問題定義:何を知りたいのか、 目的を明確に
  2. データ収集:信頼できるソースから(SSDSEなど公的データ)
  3. データクリーニング:欠損値、 外れ値、 入力ミスの確認
  4. 探索的分析(EDA):要約統計量、 ヒストグラム、 散布図
  5. 変数変換:標準化、 対数変換、 カテゴリのエンコード
  6. モデリング:適切な手法を選び、 学習
  7. 評価:CV、 指標、 統計的検定
  8. 解釈・報告:効果量、 信頼区間、 可視化

統計手法の選び方マトリクス

目的 1変数 2変数 多変量
記述平均, 中央値, 分散相関, 共分散PCA, 因子分析
可視化ヒストグラム, 箱ひげ散布図, ヒートマップ散布図行列, バイプロット
予測時系列モデル単回帰重回帰, Ridge, LASSO
分類ロジスティック回帰判別分析SVM, RF, NN
グループ化階級分け2次元クラスタリングk-means, 階層クラスタリング
検定1標本t検定2標本t検定, χ²ANOVA, MANOVA

サンプル数別の手法ガイド

n 推奨手法
n < 10記述統計のみ、 ノンパラ検定、 ベイズ統計
10 ≤ n < 30t検定, ブートストラップ, 単回帰
30 ≤ n < 200重回帰, ANOVA, 階層クラスタリング
200 ≤ n < 10000複雑な回帰, RF, GBM, k-means
n ≥ 10000深層学習, 大規模分散学習

Python 主要ライブラリ早見表

ライブラリ 用途
numpy数値計算の基礎、 行列演算
pandasデータフレーム、 表操作
scipy統計関数、 最適化、 線形代数
statsmodels古典統計、 検定、 回帰分析の詳細
scikit-learn機械学習、 前処理、 評価
matplotlib基本可視化
seaborn統計的可視化(高級)
plotlyインタラクティブ可視化
xgboost / lightgbm勾配ブースティング
PyTorch / TensorFlow深層学習

よくある質問(FAQ)

📓 用語のまとめ — 30秒で理解

このページで扱った概念を、 学習効率のためにまとめます。 これを毎日見ることで、 統計の基礎が体に染み込みます。

必ず押さえるべき記号

記号 意味 読み方
μ母平均ミュー
σ母標準偏差シグマ
σ²母分散シグマ二乗
標本平均エックスバー
s標本標準偏差エス
n標本サイズエヌ
pp値、 比率ピー
α有意水準アルファ
β回帰係数、 第二種誤り率ベータ
r相関係数アール
決定係数アール二乗
Σ総和記号、 共分散行列シグマ大文字
N(μ, σ²)正規分布ノーマル ミュー シグマ二乗
t(df)t分布ティー
χ²(df)カイ二乗分布カイ二乗
F(d1, d2)F分布エフ
H₀, H₁帰無仮説、 対立仮説エイチゼロ、 エイチワン
E[X]期待値エクスペクタンス
Var(X)分散バリアンス
Cov(X, Y)共分散カバリアンス

💡 統計学・データサイエンスは「記号の意味を理解する」ことが最初の壁。 各記号が何を表すか、 公式の中での役割を覚えてしまえば、 後はパターンの組合せで様々な手法が理解できます。

🌐 データサイエンス全体像での位置づけ

データサイエンスのワークフロー

  1. ビジネス理解:何を解決したいか
  2. データ理解:どんなデータがあるか
  3. データ準備:前処理、 特徴量エンジニアリング
  4. モデリング:手法選択、 学習
  5. 評価:性能、 解釈性、 ビジネス価値
  6. 展開:実装、 運用、 監視

(CRISP-DM プロセスより)

💡 この 6 工程はデータ分析全般の流れで、 この用語だけの話ではない。 多重共線性は「データ理解」で気づき、 「モデリング」で対処する。 VIF はデータ理解の段階で計算できる

主要分野のマッピング

分野 主要技術 代表ツール
記述統計要約量、 可視化pandas, matplotlib
推測統計検定、 信頼区間scipy.stats, statsmodels
機械学習予測、 分類、 クラスタリングscikit-learn, XGBoost
深層学習NN、 画像、 自然言語PyTorch, TensorFlow
時系列ARIMA、 状態空間、 LSTMstatsmodels, prophet
因果推論RCT、 IV、 DiD、 PSMDoWhy, EconML
ベイズ統計MCMC、 変分推論PyMC, Stan
最適化線形/凸/離散最適化scipy.optimize, cvxpy

キャリアパス

💎 良いデータ分析のための10のコツ

  1. 必ず可視化から始める:散布図、 ヒストグラム、 箱ひげ図
  2. 外れ値を意識する:除く前にドメイン的に理解
  3. 仮定を確認する:正規性、 独立性、 等分散性
  4. サンプルサイズに見合う複雑性:n=10 で深層学習はしない
  5. 効果量も併記する:p値だけでは不十分
  6. 信頼区間で不確実性を示す:点推定だけでは誤解の元
  7. 多重比較を補正する:探索的解析でも誠実に
  8. ホールドアウト or CV で評価する:訓練データの精度は意味がない
  9. 解釈可能性も重視する:ブラックボックスより white-box
  10. 再現可能なコードを書く:random_seed、 バージョン管理

🔗 用語間の関係 — 統計概念のネットワーク

記述統計の基本セット

これらは互いに深く関連します:

推測統計の基本セット

回帰モデルファミリー

クラスタリング・次元削減ファミリー

検定ファミリー

🧮 SSDSE-B-2026 実値計算 — 多重共線性を VIF で診断

SSDSE-B-2026 の実在列では、 「総人口」「出生数」「転入」「婚姻」のような規模系列が強く相関しており、 一緒に重回帰に入れると VIF が大きくなる典型例です。

🎯 解説: 相関行列を pandas で計算。 SSDSE-B-2026 の数値変数全組み合わせの Pearson 相関を一覧表示し、 多重共線性ペアを特定。
① 目的: SSDSE-B-2026 の実在列で、 説明変数同士の共線性を確認します。 ② 橋渡し: CSV は cp932/skiprows=[1] で読み、 2023 年の 47 都道府県に絞ります。 ③ コード: 下の Python で VIF を計算します。
📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 A1101(総人口) A4101(出生数) A5101(転入者数(日本人移動者)) A9101(婚姻件数) 北海道 5,092,000 24,430 47,388 17,281 東京都 14,086,000 86,348 406,749 71,774 沖縄県 1,468,000 12,549 26,410 6,316 …(全 47 行)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import pandas as pd
import numpy as np
from statsmodels.stats.outliers_influence import variance_inflation_factor

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]
X = df[['A1101', 'A4101', 'A5101', 'A9101']].rename(columns={
    'A1101': '総人口', 'A4101': '出生数', 'A5101': '転入', 'A9101': '婚姻'
}).astype(float)
X = (X - X.mean()) / X.std()  # 標準化
vif = pd.Series(
    [variance_inflation_factor(X.values, i) for i in range(X.shape[1])],
    index=X.columns)
print(vif.round(2))
📤 実行例(実測) 総人口 113.20 出生数 163.72 転入 30.03 婚姻 143.44 dtype: float64
💬 読み方: 対角は 1.0、 非対角がペア相関。 0.95 以上は深刻な共線性。 SSDSE は人口関連変数が多く、 共線性の塊。 PCA や変数選択で対処。
変数VIF判定
総人口113.20深刻
出生数163.72深刻
転入30.03深刻
婚姻143.44深刻

「総人口」「出生数」「転入」「婚姻」を同時に入れると、 全変数で VIF が 10 を超えました。 代表変数を 1 つに絞るか、 これら 4 変数から主成分を 1 つ作って代用する解決法が定石です。

🐍 Python 実装バリエーション

A. statsmodels.stats.outliers_influence.variance_inflation_factor(標準)

🎯 解説: statsmodels の variance_inflation_factor で VIF を計算。 SSDSE-B-2026 の実在列4変数について、 どの変数が共線性に強く関与するかを確認。
📥 入力例: data/raw/SSDSE-B-2026.csv X = 標準化済みの4列(総人口・出生数・転入・婚姻) variance_inflation_factor(X.values, i)
1
2
3
4
5
import pandas as pd
from statsmodels.stats.outliers_influence import variance_inflation_factor as vif_fn

vifs = pd.Series([vif_fn(X.values, i) for i in range(X.shape[1])], index=X.columns)
print(vifs.round(2))
📤 実行例: VIF 総人口 113.20 出生数 163.72 転入 30.03 婚姻 143.44
💬 読み方: VIF>10 で深刻。 ここでは4変数すべてが閾値を超え、 特に出生数・婚姻・総人口が強い共線性を示す。

B. numpy.linalg による条件数

🎯 解説: 条件数で設計行列全体の悪条件度を確認。 SSDSE-B-2026 の実在列を標準化し、 cond(X)>30 を多重共線性の警告として判断。
📥 入力例: data/raw/SSDSE-B-2026.csv X = 標準化済みの4列(総人口・出生数・転入・婚姻) X.shape=(47,4)
1
2
cond_num = np.linalg.cond(X.values)
print(f'条件数 = {cond_num:.1f}')  # > 30 で多重共線性疑い
📤 実行例: 条件数 条件数 = 33.4(30 超で多重共線性疑い)
💬 読み方: 条件数が 30 を超えると、 説明変数行列全体が悪条件化しているサイン。 VIF と併用して、 どの変数群を整理するかを決める。

C. sklearn.linear_model.Ridge(多重共線性に強い回帰)

🎯 解説: 多重共線性が回帰係数の安定性に与える影響を実演。 SSDSE-B-2026 で変数を 1 つ追加するだけで係数が大きく変動する例。
📥 入力例: data/raw/SSDSE-B-2026.csv Model1: 一般診療所 ~ 総人口(β=0.000909) Model2: 一般診療所 ~ 総人口 + 出生数
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import pandas as pd
from sklearn.linear_model import Ridge
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]
features = ['A1101', 'A4101', 'A5101', 'A9101']
labels = ['総人口', '出生数', '転入', '婚姻']
X = StandardScaler().fit_transform(df[features].astype(float))
y = df['I5102'].astype(float).values
ridge = Ridge(alpha=10.0).fit(X, y)
coef = {label: float(value) for label, value in zip(labels, ridge.coef_.round(2))}
print('coef =', coef)
print(f'R² = {ridge.score(X, y):.4f}')
📤 実行例: Ridge(α=10.0) {'総人口': 548.88, '出生数': 604.45, '転入': 578.77, '婚姻': 702.55} R² = 0.9646
💬 読み方: Ridge は係数を縮小して極端な符号反転を抑える。 ここでは R² を 0.9802 から 0.9646 に少し落とす代わりに、 4 変数の係数が同じ向きに安定する。

D. sklearn.decomposition.PCA → 主成分回帰

🎯 解説: 主成分分析(PCA)で多重共線性を解消。 SSDSE-B-2026 の相関変数を主成分に変換し、 直交変数として回帰。
📥 入力例: data/raw/SSDSE-B-2026.csv from sklearn.decomposition import PCA PCA().fit(StandardScaler().fit_transform(X))
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import pandas as pd
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]
X = StandardScaler().fit_transform(df[['A1101', 'A4101', 'A5101', 'A9101']].astype(float))
pca = PCA(n_components=4).fit(X)
print('PC 寄与率', pca.explained_variance_ratio_.round(4))
print('累積寄与率', pca.explained_variance_ratio_.cumsum().round(4))
📤 実行例(実測) PC 寄与率 [9.84e-01 1.34e-02 1.70e-03 9.00e-04] 累積寄与率 [0.984 0.9974 0.9991 1. ]
💬 読み方: PCA は変数を直交化。 主成分は元変数の線形結合で解釈に注意。 累積寄与率 90% 以上を採用が目安。 主成分回帰(PCR)として活用。

E. 相関ヒートマップで一目で確認

🎯 解説: 相関ヒートマップで多重共線性を視覚的に確認。 SSDSE-B-2026 の実在列(総人口・出生数・転入・婚姻)の相関を色で把握。
📥 入力例: data/raw/SSDSE-B-2026.csv sns.heatmap(X.corr(), annot=True, cmap='RdBu_r')
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]
X = df[['A1101', 'A4101', 'A5101', 'A9101']].rename(columns={
    'A1101': '総人口', 'A4101': '出生数', 'A5101': '転入', 'A9101': '婚姻'
}).astype(float)
sns.heatmap(X.corr(), annot=True, cmap='RdBu_r', vmin=-1, vmax=1)
plt.show()
📤 実行例(実測) このブロックは標準出力を出さない(図を描く・変数を定義するだけ)。
💬 読み方: 濃い赤のセルほど正の強相関。 4 変数は同じ人口規模を強く反映するため、 そのまま同時投入すると VIF が大きくなる。

⚠️ 多重共線性の落とし穴 7 連発

1. VIF だけで判断する。VIF は他の説明変数で当該変数を回帰したときの R²j から作られる単一指標です。 サンプルサイズが小さいと不安定になりがちで、 ペア相関ヒートマップ・条件数(cond(X))・固有値分解(最小固有値が 0 近い)と併用するのが正攻法です。

2. 「予測精度が落ちる」と誤解する。多重共線性は個別係数の標準誤差を膨らませますが、 X 全体の予測力(R², MSE)はほぼ影響を受けません。 予測が目的なら気にせず投入してよく、 むしろ「変数を捨てて bias を増やす」方が損です。

3. ダミー変数の罠(perfect multicollinearity)。カテゴリ変数を全水準でダミー化(drop_first しない)すると、 合計が 1 になり完全共線。 多くのライブラリでは特異行列でエラー、 もしくは警告も出さず怪しい結果を返します。 必ず参照カテゴリを 1 つ落としましょう。

4. 「Ridge を使えば安心」と過信する。Ridge は係数を 0 に縮める正則化で、 多重共線性下でも安定した解を返しますが、 縮められた係数の解釈は「介入効果」ではなくバイアスを含んだ予測重みです。 因果推論の文脈では別の戦略(DAG・IV)が必要です。

5. 標準化を忘れる。VIF と Ridge は、 説明変数の単位スケールに敏感です。 「所得は千円」「人口は万人」など桁が異なるまま入力すると、 結果が解釈不能になります。 必ず StandardScaler で z スコア化してから計算しましょう。

6. 「相関 0.7 未満なら安心」という基準を信じる。ペア相関では検出できない「線形結合の共線性」(x3 ≒ 0.5 x1 + 0.5 x2)が存在します。 必ず VIF や条件数の追加診断も組み合わせてください。

7. 多重共線性を理由に説明変数を機械的に削除する。「VIF 10 以上を全部消す」と理論的に重要な変数まで落としてしまいます。 ドメイン知識と「これは仮説検証に必要か / 予測のための補助か」の区別を行ったうえで削除や合成を決めましょう。

🗺️ 概念マップ — 3つの視点で体系を理解する

多重共線性 がデータサイエンスの体系の中でどこに位置するかを、 3つの異なる視点で可視化します。 同じ情報でも見方を変えると気付きが変わります。

📍 体系階層のパス

🌐 統計・データサイエンス前処理変換多重共線性

① 🔗 関係マップ — 「他の手法とどう繋がっているか」

中心に 多重共線性 を置き、 そこから Ridge回帰・LASSO・相関係数・重回帰・PCA・Elastic Net など 計 12 個の用語へ、 前提・兄弟・発展形といった関係を矢印で結んでいます。 線がどちら向きかを見れば、 先に読むべき用語あとから読む用語が分かります。 ノードはドラッグで動かせ、 ホイールでズーム、 クリックでその用語のページへ遷移します。

凡例:現在の用語上位カテゴリ兄弟(並列)前提発展形応用先2階層先

② ⭕ 包含マップ — 「どのカテゴリに含まれているか」

大きな円が小さな円を包含する Circle Packing 図。 「多重共線性」は緑色でハイライト

📍現在地:統計・データサイエンス

③ 🌳 ツリーマップ — 「面積で見るボリューム比較」

長方形を入れ子に分割した Treemap 図。 各分野の規模感を面積で比較。 「多重共線性」は緑色でハイライト

🎯 3つのマップの使い分け

マップ 分かること こんな時に見る
🔗 関係マップ手法間の横の関係(前提→発展→応用)「次に何を学べばよい?」 学習順序の判断
⭕ 包含マップ分類体系の入れ子構造(上位⊃下位)「この手法はどんなジャンルに属する?」
🌳 ツリーマップ分野の規模比較(面積=ボリューム)「データサイエンス全体の俯瞰像」

💡 ジャストインタイム学習のヒント:3つの視点を行き来することで、 概念を多角的に理解できます。 包含マップやツリーマップはズーム/ドリルダウンで大分類から細部まで探索できます。

🧭 深掘り(追記)— 「予測 vs 推論」の非対称性という別角度

👁️ 直感(別角度):同じ現象でも「予測」と「推論」で毒性が真逆

多重共線性の本質は、 説明変数が「束」で動くため、 束全体の効きは分かるが、 個々への配分が決まらないことにあります。 ここから 予測(当てる)推論(各変数の効果を語る) で毒性が非対称になります。

つまり「モデルが悪い」のではなく「問いが分不相応」なのです。 データが答えられる問い(束の効き)と答えられない問い(各変数の分離)を混同すると事故になります。

⚠️ 落とし穴(別角度・重要)

  1. 「予測目的なら無害」は条件付き:無害なのは 訓練時と同じ相関構造で内挿する限り。 相関を崩す外挿(例:ふだん一緒に動く2変数の一方だけ将来大きく変える施策評価)では、 束に頼った係数配分が破綻し予測も崩れる。 反実仮想(もしこの変数だけ動かしたら)は推論であって予測ではない。
  2. VIF 閾値(5 や 10)は恣意的な慣習:VIF は $1/(1-R_j^2)$ に過ぎず、 10 は $R_j^2=0.9$ という一つの目安。 サンプル数・効果量・目的次第で、 VIF 3 でも致命的にも、 20 でも実害皆無にもなる。 閾値は「診断のトリガー」であって「合否ライン」ではない。
  3. 標準化しても解決しない:標準化は各列のスケールを揃えるだけで、 列同士の相関は変えない。 VIF も条件数(相関行列ベース)もほぼ不変。 「標準化したから大丈夫」は誤解。 中心化が効くのは後述の交互作用・多項式項という特殊ケースのみ。
  4. 完全共線性=ダミー変数トラップ:全カテゴリのダミーを入れ切片も置くと $\sum=1$ で完全共線となり $X^\top X$ が特異化。 drop_first=True で基準カテゴリを1つ落とすのが定石。 「合計=各内訳の和」を同時投入するのも同じ罠。
  5. 時系列での「見せかけの共線」:多くの経済・人口系列は共通のトレンドで一斉に増減するため、 水準どうしは高相関になりやすい。 これは真の因果的重複ではなく共通トレンド由来のことが多く、 階差・成長率・per capita 化で相関が大きく下がることがある。
  6. 「VIF が高い変数を消す」の隠れたバイアス:削った変数が真に効いていれば、 残した変数の係数はその効果を吸い込み欠落変数バイアスを負う。 共線性(分散が大きい)を消す代償にバイアス(推定が偏る)を買う——分散とバイアスのトレードオフそのもの。 「消せば解決」ではない。

🚀 発展(別角度):束を「作り替える/縮める」アプローチ

📊 SSDSE-B-2026(2023年・47都道府県)実測で確認

総人口・出生数・転入者数・婚姻件数を同時に説明変数にした例(いずれも人口規模で一斉に動く「束」)。 実データでの数値です。

💡 この節の要点:多重共線性は「予測には概ね無害・推論には有害」という非対称性が核心。 VIF 閾値は目安に過ぎず、 標準化では解決せず、 変数削除もバイアスと引き換え。 目的(予測か推論か)を先に決めてから対処法を選ぶ。

🔗 関連ページ

📌 補足セクション — 多重共線性を SSDSE-B-2026 で確かめる

本セクションは「多重共線性」を 47都道府県データ(SSDSE-B-2026)で具体的に確認するための追加教材です。 例として総人口・出生数・転入・婚姻を同時に説明変数に入れる場合を扱います。

🎨 直感で掴む — 多重共線性

多重共線性を 47都道府県データで直感的に捉えるには、 まず「総人口・出生数・転入・婚姻を同時に説明変数に入れる場合」を思い浮かべます。 東京都・大阪府・神奈川県のように総人口が大きい都道府県ほど、 出生数や婚姻件数も大きくなる傾向があり、 こうしたデータの「形」を 多重共線性 は要約します。

たとえば 47都道府県を散布図にすると、 右肩上がりの帯状にデータが並びます。 この「帯の傾き」「帯のばらつき」「帯から外れる外れ値」を表現する道具が、 ここで扱う 多重共線性 だとイメージしてください。

📐 数式または定義

多重共線性の中心的な数式は次のとおりです( SSDSE-B-2026 の 47 都道府県 \(n=47\) を想定):

$$ \hat{y}_i = \hat{\beta}_0 + \hat{\beta}_1 x_i, \quad i = 1, 2, \dots, 47 $$ $$ \hat{\beta}_1 = \frac{\sum_{i=1}^{47} (x_i - \bar{x})(y_i - \bar{y})}{\sum_{i=1}^{47} (x_i - \bar{x})^2}, \quad \hat{\beta}_0 = \bar{y} - \hat{\beta}_1 \bar{x} $$

ここで \(x_i\) は総人口、 \(y_i\) は一般診療所数、 \(\bar{x}, \bar{y}\) はそれぞれの標本平均を表します。 多重共線性の解釈は、 上式で得られる係数や残差から導かれます。

🧮 実値で計算してみる — 多重共線性

SSDSE-B-2026 の 47都道府県データから、 「総人口・出生数・転入・婚姻を同時に説明変数に入れる場合」を Python で再現します。 まず一行で読み込めるよう、 引数を直書きしたシンプル版を示します:

📥 入力例(SSDSE-B-2026 全体:564 行 × 112 列 = 47 都道府県 × 2012〜2023 年) 年度 地域コード 都道府県 A1101(総人口) A1303(65歳以上人口) A4101(出生数) … 2023 R01000 北海道 5,092,000 1,681,000 24,430 … 2023 R13000 東京都 14,086,000 3,205,000 86,348 … 2023 R47000 沖縄県 1,468,000 350,000 12,549 … …(残り 112 列は住宅・家計・教育・医療など)
1
2
3
# 最小コード(直書き)
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]

続いて、 列名はリポジトリ準拠(A1101 総人口、 A4101 出生数、 A5101 転入、 A9101 婚姻、 I5102 一般診療所)の本番コードです。

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 A1101(総人口) I5102(一般診療所数) 北海道 5,092,000 3,403 東京都 14,086,000 14,894 沖縄県 1,468,000 928 …(全 47 行)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import pandas as pd
import numpy as np

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])

# 2023 年の 47都道府県スナップショット
sub = df[df['SSDSE-B-2026'] == 2023].copy()
x = sub['A1101'].astype(float)   # 総人口
y = sub['I5102'].astype(float)   # 一般診療所

# 多重共線性の基礎統計
x_mean, y_mean = x.mean(), y.mean()
beta1 = ((x - x_mean) * (y - y_mean)).sum() / ((x - x_mean) ** 2).sum()
beta0 = y_mean - beta1 * x_mean

print(f'n = {len(x)}')             # 47
print(f'beta1 = {beta1:,.6f}')     # 0.000909
print(f'beta0 = {beta0:,.4f}')     # -174.4478
print(f'相関係数 = {x.corr(y):.4f}')  # 0.9717

# 残差・決定係数も計算
y_hat = beta0 + beta1 * x
resid = y - y_hat
ss_res = (resid ** 2).sum()
ss_tot = ((y - y_mean) ** 2).sum()
r2 = 1 - ss_res / ss_tot
print(f'R^2 = {r2:.4f}')
📤 実行例(実測) n = 47 beta1 = 0.000909 beta0 = -174.4478 相関係数 = 0.9717 R^2 = 0.9442

このコードを実行すると、 47都道府県データから 多重共線性に関連する係数・指標が直接得られます。 SSDSE-B-2026 が手元にない場合は、 統計データ活用コンペティション公式ページからダウンロードしてください。

⚠️ 補足の落とし穴

🔗 関連用語(補足リンク)

相関係数 最小二乗法 残差 決定係数 共分散 p 値 標準誤差 多重共線性

🖼️ 図解で掴む多重共線性

ここでは、 数式や表だけでは伝わりにくい多重共線性のイメージを 3 枚の図で確認します。 左の図は説明変数同士がどれくらい揃って動いているかを散布で示し、 中央の図は VIF・相関ヒートマップで「どこに共線性の塊があるか」を一目で把握できる構図、 右の図は対処策(リッジ・ラッソ)が共線性下で係数をどのように安定させるかを比較したものです。

図 1: 多重共線性の直感図 — 「同じ方向に動く」を見える化

多重共線性の直感図

2 つの説明変数 X1・X2 がほぼ同じ方向に動くと、 回帰の解は「X1 の係数を増やして X2 を減らす」あるいは「逆」のどちらでも当てはまりが同じになり、 一意に決まらなくなります。 図のように散布が直線上に乗っているほど、 係数の標準誤差が膨張し、 p 値が大きくなり、 結果として「重要な変数なのに有意でない」という誤った結論が出やすくなります。

図 2: 相関ヒートマップ — どの変数同士が危険か

相関ヒートマップによる多重共線性チェック

SSDSE-B-2026 から「総人口・出生数・転入・婚姻」のような関連指標を取り出して相関行列を可視化すると、 ほとんどの組で |r| > 0.95 が並びます。 セルが深い赤になっている箇所が共線性のホットスポットで、 そのまま回帰に投入すると VIF が 10 を大幅に超えます。 まずヒートマップで全体像を眺め、 次に VIF・条件数で定量化、 という順序が実務で扱いやすい流れです。

図 3: リッジ・ラッソによる安定化 — 共線性下の係数の挙動比較

リッジ回帰・ラッソ回帰による係数の安定化

OLS(左)は共線性の影響で係数が大きく振れる一方、 リッジ回帰(中央)は係数を 0 近くに縮め、 ラッソ回帰(右)は寄与の小さい変数を完全に 0 にして変数選択まで行います。 「予測だけが目的」ならリッジ、 「解釈と変数選択を両立したい」ならラッソ、 という使い分けが基本です。 ただし係数が縮むぶん解釈の意味も変わるため、 学術論文の主分析で使う際は補足分析として OLS も併記するのが安全です。

🔬 多重共線性を実データで多角的に確認する(R283 補強)

多重共線性は「症状(係数の符号反転、 巨大な SE)」と「診断指標(VIF、 条件数)」を併用しないと見抜けない。 ここでは SSDSE-B-2026 を使い、 4 段階で確認する。

① 相関ヒートマップで多重共線性ペアを発見

このコードでやること: 「総人口」「出生数」「転入」「婚姻」など実在する人口規模系列の相関行列を計算し、 |r|>0.9 のペアをリストする。

📥 入力: SSDSE-B-2026.csv(47都道府県)。 数値カラムを 4-6 個選択。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import pandas as pd

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]
cols = ['A1101', 'A4101', 'A5101', 'A9101']  # 総人口/出生数/転入/婚姻
df_sub = df[cols + ['I5102']].rename(columns={
    'A1101': '総人口', 'A4101': '出生数', 'A5101': '転入',
    'A9101': '婚姻', 'I5102': '一般診療所'
}).astype(float)
features = ['総人口', '出生数', '転入', '婚姻']
corr = df_sub[features].corr()
print(corr.round(3))
print()
print('|r|>0.9 のペア:')
for i in range(len(corr)):
    for j in range(i+1, len(corr)):
        if abs(corr.iloc[i,j]) > 0.9:
            print(f'  {corr.columns[i]} - {corr.columns[j]}: r={corr.iloc[i,j]:.3f}')

📤 実行例:

総人口 出生数 転入 婚姻 総人口 1.000 0.995 0.959 0.989 出生数 0.995 1.000 0.958 0.991 転入 0.959 0.958 1.000 0.979 婚姻 0.989 0.991 0.979 1.000 |r|>0.9 のペア: 総人口 - 出生数: r=0.995 総人口 - 転入: r=0.959 総人口 - 婚姻: r=0.989 出生数 - 婚姻: r=0.991 ...

💬 結果の読み方: 6 ペアすべてで |r|>0.95 近辺。 これらを重回帰に同時投入すると、 ほぼ確実に多重共線性が深刻になる。 同じ人口規模を反映する変数は互いの代理指標になりやすいため、 代表変数を選ぶ必要がある。

② VIF を計算 — どの変数が多重共線性の原因か特定

このコードでやること: statsmodels の variance_inflation_factor で各変数の VIF を計算する。 VIF > 10 なら除外候補。

📥 入力: 上記 df_sub の 4 列をすべて使う。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import pandas as pd
from statsmodels.stats.outliers_influence import variance_inflation_factor

features = ['総人口', '出生数', '転入', '婚姻']
X = df_sub[features]
Z = (X - X.mean()) / X.std()
vif_rows = []
for i, name in enumerate(Z.columns):
    vif_rows.append({'変数': name, 'VIF': variance_inflation_factor(Z.values, i)})
print(pd.DataFrame(vif_rows).round(2).to_string(index=False))

📤 実行例:

変数 VIF 出生数 163.72 婚姻 143.44 総人口 113.20 転入 30.03

💬 結果の読み方: 全変数が VIF > 10、 特に「総人口」「出生数」「婚姻」は 100 を超える。 ドメイン知識で代表変数を 1 つ残し、 再計算して VIF が十分下がるかを確認する。

③ 係数の不安定性 — 1 変数追加で符号が反転

このコードでやること: 一般診療所を目的変数として、 「総人口だけ」と「総人口 + 出生数」の 2 モデルで係数を比較する。 多重共線性下では係数の符号や大きさが大きく変わる。

📥 入力: 同じ df_sub。

1
2
3
4
5
6
7
8
from sklearn.linear_model import LinearRegression

for cols in [['総人口'], ['総人口','出生数'], ['総人口','出生数','転入'], ['総人口','出生数','転入','婚姻']]:
    X = df_sub[cols].values
    y = df_sub['一般診療所'].values
    m = LinearRegression().fit(X, y)
    coef_str = ', '.join(f'{c}={v:.6f}' for c, v in zip(cols, m.coef_))
    print(f'{cols}: {coef_str}')

📤 実行例:

['総人口']: 総人口=0.000909 ['総人口','出生数']: 総人口=-0.000083, 出生数=0.162506 ['総人口','出生数','転入']: 総人口=-0.000244, 出生数=0.138278, 転入=0.012835 ['総人口','出生数','転入','婚姻']: 総人口=-0.000328, 出生数=-0.001368, 転入=-0.006959, 婚姻=0.306117

💬 結果の読み方: 「総人口」の符号が、 出生数を加えた瞬間に正から負へ反転する。 これは多重共線性の典型的な症状で、 経済的直感に反する係数が出る。 個別係数を解釈するのは危険。

④ Ridge 回帰で安定化 — 多重共線性下の処方箋

このコードでやること: 同じデータに Ridge 回帰を適用し、 alpha を変えたときの係数の挙動と R² を観察する。

📥 入力: 同じ df_sub の 4 変数(総人口、 出生数、 転入、 婚姻)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from sklearn.linear_model import Ridge
from sklearn.preprocessing import StandardScaler

features = ['総人口', '出生数', '転入', '婚姻']
X = StandardScaler().fit_transform(df_sub[features])
y = df_sub['一般診療所'].values

for alpha in [0.0, 1.0, 10.0, 100.0]:
    m = Ridge(alpha=alpha).fit(X, y)
    r2 = m.score(X, y)
    print(f'alpha={alpha:6.1f}: 係数={m.coef_.round(2)}  R²={r2:.4f}')

📤 実行例:

alpha= 0.0: 係数=[-907.87 -23.22 -484.08 3955.45] R²=0.9802 alpha= 1.0: 係数=[ 187.63 592.39 408.52 1359. ] R²=0.9720 alpha= 10.0: 係数=[548.88 604.45 578.77 702.55] R²=0.9646 alpha= 100.0: 係数=[410.97 416.93 409.99 428.29] R²=0.8475

💬 結果の読み方: alpha=0(OLS)では婚姻だけが極端に大きく、 他の係数が負になるが、 alpha を上げると 4 変数の係数が穏当な正の値に近づく。 R² の低下は比較的小さい(0.9802 → 0.9646)。 解釈と予測のバランスを取るなら alpha=10 が良い妥協点。

多重共線性 4 つの実験のまとめ

🧮 数式に値を入れて手で計算する: 多重共線性の VIF

合成 3 変数で他変数による R² から VIF を計算する。

Step 1: 他変数説明 R²

変数VIF
x10.101.11
x20.502.00
x30.9520.0

Step 2: 公式と判定

VIF = 1/(1-R²) x1: 1.11 (OK) x2: 2.00 (OK) x3: 20.0 ≥ 10 → 多重共線性深刻、 除外検討

🐍 Python で再現

1
2
3
4
5
import numpy as np
r2 = np.array([0.10, 0.50, 0.95])
vif = 1/(1-r2)
print(f"VIF: {vif}")
print(f"問題変数 index: {np.where(vif >= 10)[0]}")

📤 実行結果

VIF: [ 1.11111111 2. 20. ] 問題変数 index: [2]

💬 手計算 (Step 2) x3 (VIF=20) と Python 出力が完全一致。

🔗 隣接手法への橋渡し

「多重共線性」は単独で完結する手法ではなく、 隣接領域と連携することで真価を発揮する。

多重共線性は回帰係数の符号反転・標準誤差膨張という形で現れる。 SSDSE-B-2026 で「総人口」と「出生数」を両方説明変数に入れると、 2023年データでは VIF が 100 を超えるため、 一方を除く、 もしくはリッジで縮小するのが定石。

🔖 キーワード索引

multicollinearity」は統計データ分析の文脈で扱う重要概念のひとつ。 本ページでは「multicollinearity」を取り巻く中核キーワードを以下にチップで一覧化する。 各キーワードは関連する概念・手法・道具立てを含み、 文献検索や学習計画の起点になる。

multicollinearity統計分析SSDSE-B-2026前提条件適用範囲落とし穴関連手法Python 実装検証方法

これらのキーワードは「multicollinearity の理解 → 適用 → 検証」のプロセスを構成する。 各章で詳しく解説する。

💡 30 秒で分かる結論

🍰 まずはやさしく

似すぎたデータが混ざる現象です。

正しい分析結果を出すために使います。

テストの点数と勉強時間を両方使う例です。

この現象の正体と解決策を読みます。

📍 あなたが今見ているもの

🍰 まずはやさしく

分析の準備をするためのチェック項目です。

計算ミスのような間違いを防ぐために使います。

部活のデータ分析で役立つ知識です。

診断の方法から対策までを順番に読みます。

このページは 重回帰分析の「前提条件チェック」における中核トピック「多重共線性 (multicollinearity)」の解説。 全 SSDSE-B-2026 ベース教材の中で、 重回帰 → 残差診断 → 多重共線性診断 → 正則化回帰 という学習パスの 3 番目に位置する。 前提として 重回帰分析相関係数 の理解が必要。 本ページ後は リッジ回帰主成分分析VIF への接続が自然。

🎨 直感で掴む

🍰 まずはやさしく

役割が重なるメンバーが多すぎる状態です。

どのデータが本当に重要かを知るために使います。

スマホの利用時間とSNSの時間が似ている例です。

数値で問題を見つける流れを読みます。

多重共線性は「重回帰の説明変数同士がほぼ線形従属になり、 X'X 行列が反転に不安定になる」現象。 SSDSE-B-2026 で「総人口」と「出生数」を同時に説明変数にすると、 両者の相関は 0.9954 となり、 係数の標準誤差が爆発して係数の符号さえ実行ごとに反転しうる。 これが「個別では強い効果に見えるのに、 統合すると効果が消える」典型的な共線性パターン。

本ページでは (1) 入力: 「総人口」「出生数」「転入」「婚姻」を含む説明変数行列 → (2) 処理: VIF (Variance Inflation Factor) と条件数の算出 → (3) 出力: VIF > 10 の変数特定 → (4) 解釈: 「per capita 化 / Ridge / Lasso のどれを選ぶか」の 4 段階で診断と対処を追う。

次節以降では、 47 都道府県のサブセット 5 件で X'X の固有値を手計算し、 条件数の悪化を確認した上で、 statsmodels と sklearn の VIF / Ridge で同じ結論が出ることを示す。

📐 数式または定義

🍰 まずはやさしく

データの重なり具合を数式で表したものです。

客観的に問題を判断するために使います。

買い物で似た商品を比べる感覚に近いです。

定義と計算のルールについて読みます。

multicollinearity の定義や代表的な数式を以下に示す。 数式の各記号の意味は次節で言葉に翻訳する。

multicollinearity は文脈に応じて複数の定式化があるが、 教育目的では最も基本的な形を抑えることが重要。 具体的な値での計算例は後続セクションを参照。

$$\text{multicollinearity}: f(\mathbf{X}, \boldsymbol{\theta}) \to y$$

記号の対応はこうです。 $\text{VIF}_j$ は説明変数 $j$ の分散拡大係数。 $R_j^2$ は「変数 $j$ を、残りの説明変数すべてで回帰したときの決定係数」で、 $j$ が他の変数でどれだけ説明できてしまうかを表します。 $R_j^2 = 0$(他と無関係)なら $\text{VIF} = 1$、 $R_j^2 = 0.9$ なら $\text{VIF} = 10$、 $R_j^2 = 0.99$ なら $100$。 VIF の値は「係数の標準誤差が何倍に膨らむか」の2 乗を意味するので、 $\text{VIF} = 10$ なら標準誤差は $\sqrt{10} \approx 3.2$ 倍です。 目安の「VIF > 10 で要注意」は、 $R_j^2 > 0.9$ に相当します。

🔬 数式を言葉で読み解く

前節の数式に含まれる記号を、 日本語の意味に翻訳する。

multicollinearity の数式は、 これらの記号を組み合わせて「データから未知量を推定する」あるいは「データの構造を要約する」プロセスを記述している。

🧮 実値で計算してみる

multicollinearity を SSDSE-B-2026 の実データで具体的に計算する手順を示す。 数式 → 値代入 → 手計算 → Python 実装 の流れで、 結果が一致することを確認する。

使用データ: SSDSE-B-2026 の 47 都道府県 × 主要列。 まず 5-10 都道府県の小さな部分集合で手計算し、 全件は Python で実行する。

Step操作実際の値
1説明変数を 3 つ選ぶ総人口・65 歳以上人口・出生数(2023 年度・47 県)
2相関行列を見る総人口×出生数 = 0.9954、 総人口×65 歳以上 = 0.9910 — すべて 0.98 超
3総人口を他 2 列で回帰$R^2 = 0.9968$
4VIF を計算$\mathrm{VIF} = 1/(1-0.9968) = 309.07$
5他の列も同様に65 歳以上人口 72.33 / 出生数 142.30 — いずれも目安の 10 を大きく超える

📥 入力:data/raw/SSDSE-B-2026.csv の 2023 年度 47 都道府県。 このコードでやること:Step 3〜5 の VIF を定義どおり「他の列で回帰した $R^2$」から計算し、 手計算と一致するか確かめる。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import pandas as pd
import numpy as np

d = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', header=1)
d = d[d['地域コード'].astype(str).str.match(r'^R\d{5}$', na=False)]
d = d[pd.to_numeric(d['年度'], errors='coerce') == 2023].reset_index(drop=True)

num = lambda c: pd.to_numeric(d[c], errors='coerce')
X = pd.DataFrame({
    '総人口':      num('総人口'),
    '65歳以上人口': num('65歳以上人口'),
    '出生数':      num('出生数'),
})

# VIF_j = 1 / (1 - R^2_j)。R^2_j は「列 j を他の列で回帰した決定係数」
def vif(X, j):
    y = X.iloc[:, j].values
    Z = X.drop(X.columns[j], axis=1).values
    Z = np.column_stack([np.ones(len(Z)), Z])          # 切片を足す
    beta, *_ = np.linalg.lstsq(Z, y, rcond=None)
    resid = y - Z @ beta
    r2 = 1 - (resid ** 2).sum() / ((y - y.mean()) ** 2).sum()
    return r2, 1 / (1 - r2)

for j, col in enumerate(X.columns):
    r2, v = vif(X, j)
    print(f'{col:12s} R^2 = {r2:.4f}  VIF = {v:8.2f}')

print()
print('相関行列:')
print(X.corr().round(4).to_string())

📤 実行すると次の出力が得られる:

総人口 R^2 = 0.9968 VIF = 309.07 65歳以上人口 R^2 = 0.9862 VIF = 72.33 出生数 R^2 = 0.9930 VIF = 142.30 相関行列: 総人口 65歳以上人口 出生数 総人口 1.0000 0.9910 0.9954 65歳以上人口 0.9910 1.0000 0.9803 出生数 0.9954 0.9803 1.0000

💬 VIF が 309 ということは、 総人口の係数の分散が、 他の列と無相関だった場合の 309 倍に膨らんでいるという意味。 標準誤差はその平方根で約 17.6 倍。 これでは個別の係数を解釈できない。 3 列とも「県の規模」を測っているので、 1 つに絞るか、 人口当たりの比率に直して規模の影響を抜く。

🐍 Python 実装

multicollinearity を Python で実装する代表的なコードを示す。 標準ライブラリ (numpy / pandas / scipy / sklearn / statsmodels) を使い、 SSDSE-B-2026 を読み込んで実行する流れを再現できる。

🎯 このコードでやること: multicollinearity を計算するための最小限のコード。 入力データ・処理・出力・結果の読み方を明示する。

📥 入力データ: SSDSE-B-2026 (47 都道府県 × 100 超列) の CSV。

1
2
3
4
5
import pandas as pd

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]
print(df[['Prefecture', 'A1101', 'A4101', 'A5101', 'A9101']].head())

📤 実行結果: 出力された数値を読み、 他手法との比較や有意性検証を行う。

💬 結果の読み方: multicollinearity の出力は単なる数値ではなく、 データの構造や規則性を要約したもの。 適切な解釈と他指標との併用が重要。

⚠ 落とし穴

multicollinearity を実務で使う際に頻発する誤用・落とし穴を列挙する。 多くは「前提の確認不足」「結果の過信」「他手法との比較不足」が原因で、 事前にチェックリスト化することで回避できる。

🗺 概念マップ

multicollinearity を中心に、 関連する概念・上位カテゴリ・応用領域を放射状に配置した。

multicollinearity 重回帰の前提 VIF / 条件数 Ridge / Lasso 係数解釈 相関係数 主成分回帰

🔗 隣接手法への橋渡し

「multicollinearity」を中心に、 隣接する手法・概念との関係を以下に整理する。 単独の手法理解にとどまらず、 分析パイプライン全体での位置付けを把握することで、 適切な前段・後段・代替手法を選べる。

隣接手法関係接続のポイント
重回帰分析上位 / 一般化多重共線性は重回帰の係数推定が不安定化する現象
VIF / 条件数下位 / 特殊化共線性を定量化する 2 大診断指標 (VIF>10、 条件数>30 で深刻)
Ridge / Lasso 回帰並列 / 対比正則化で X'X 行列を安定化させる代替案
標準化 / per capita 化前段 (前処理)スケール統一と本質的共線性の解消
主成分回帰 (PCR)後段 (後処理)直交化された主成分を説明変数として再構成
係数の符号・標準誤差評価 / 比較共線性の影響を係数の不安定性で目視判定

🌳 手法選択フロー

「multicollinearity」を含む手法選択は、 データの性質・分析目的・運用制約の 3 軸で決まる。 以下に典型シナリオと対応する手法の組合せを示す。

典型シナリオ別の手法選択

シナリオ重視する観点候補手法
VIF > 10 の変数が複数個別係数の解釈が重要一方の変数を削除 (ドメイン知識で選択)
VIF > 10 だが全変数が重要予測精度重視Ridge 回帰 (係数を安定化)
変数選択も自動化したい解釈性 + 疎性Lasso 回帰 (不要変数をゼロに)
予測のみが目的係数解釈不要そのまま重回帰 (共線性は予測には響かない)
時系列・パネルデータ個別効果の分離固定効果モデル / 階差変数の利用
47 都道府県のような小標本解釈性 + 過学習回避per capita 化 + Ridge

選んだ後の検証ステップ

  1. 前処理確認: 標準化 / 欠損処理 / カテゴリ変数のエンコード が適切か
  2. ハイパラ調整: 交差検証で安定する値を選ぶ
  3. 性能評価: タスクに応じた指標 (RMSE / Accuracy / F1 / AUC / シルエット等) を複数併用
  4. 頑健性チェック: 別手法 / 別シードで結果が大きく違わないか確認
  5. 解釈: 結果を分野知識と照らし合わせ、 意味のある発見になっているか検討

🧮 補強:多重共線性の 4 大診断指標 — VIF 以外も使い分ける

多重共線性の診断は VIF だけではありません。 用途に応じて 4 つの指標を組み合わせると、 「どの変数群が」「どれくらい」「どんな方向で」共線になっているかが立体的に分かります。 SSDSE-B-2026 を素材に、 4 指標の使い分けを整理します。

指標 計算式・基準 分かること 限界
相関係数|r| > 0.72 変数間の共線性3 変数以上の同時共線性を見逃す
VIF1/(1-R²ⱼ) > 10個別変数の共線寄与「どの方向で」までは特定できない
条件数√(λmax/λmin) > 30設計行列全体の悪さ標準化前の値に依存
固有値分解λmin → 0 で危険共線変数群の方向計算量・解釈の難しさ

🐍 SSDSE-B-2026 で 4 指標を同時計算

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import pandas as pd, numpy as np
from statsmodels.stats.outliers_influence import variance_inflation_factor

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]
cols = ['A1101', 'A4101', 'A5101', 'A9101']
labels = {'A1101': '総人口', 'A4101': '出生数', 'A5101': '転入', 'A9101': '婚姻'}
X = df[cols].rename(columns=labels).astype(float)
Z = (X - X.mean()) / X.std()

# 1. 相関係数
print('相関行列:')
print(X.corr().round(3))

# 2. VIF
print()
print('VIF:')
for i, c in enumerate(Z.columns):
    print(f'  {c}: {variance_inflation_factor(Z.values, i):.2f}')

# 3. 条件数
eig = np.linalg.eigvalsh(Z.T @ Z / len(Z))
print()
print(f'条件数: {np.sqrt(eig.max()/eig.min()):.1f}')

# 4. 固有値(小さいもの = 共線方向)
print(f'最小固有値: {eig.min():.6f}')

📊 多重共線性への 5 つの対処戦略

戦略使う場面注意点
変数削減解釈最優先ドメイン知識で選別、 機械的削除はバイアス源
主成分回帰 (PCR)予測重視 + 解釈断念主成分の解釈が難しい
Ridge 回帰予測最優先係数解釈は OLS とは別物
Lasso 回帰変数選択も同時にグループ化された変数の選択が不安定
標本サイズを増やす構造ではなく標本に起因する場合追加調査のコスト

💡 判断フロー:(1) まず VIF と相関行列でスクリーニング → (2) 共線性が見つかれば条件数で全体の悪さを確認 → (3) 解釈優先なら変数削減、 予測優先なら Ridge/Lasso → (4) 最終モデルで再診断、 を繰り返す。

📚 補強2:多重共線性の歴史的経緯と理論的位置づけ

多重共線性(multicollinearity)という用語は、 1934 年に経済学者 Ragnar Frisch が著書 Statistical Confluence Analysis by Means of Complete Regression Systems で初めて体系化したと言われています。 経済データは観測実験ができないため、 説明変数同士が強く絡み合い、 「真の構造方程式が一意に決まらない」問題に直面し続けてきました。 これが多重共線性研究の出発点です。

🕰 歴史的マイルストーン

出来事 意義
1934Frisch が多重共線性を体系化「経済学は実験できない」問題の理論化
1962Farrar & Glauber のクラシック論文VIF と関連指標の標準化
1970Hoerl & Kennard が Ridge 回帰を提案予測重視の正則化路線
1980Belsley らが条件数診断を整備設計行列の数値線形代数的診断
1996Tibshirani が Lasso を提案同時変数選択と縮約
2005Zou & Hastie の Elastic Net共線変数群を「一緒に」扱う方法

🔬 「予測には響かない / 解釈は壊れる」の両面性

多重共線性は OLS の BLUE 性(最良線形不偏推定量)を損ないません。 つまり「予測の平均的精度」は損なわれない。 しかし個別係数 βⱼ の 標準誤差 は分散拡大係数 VIF 倍に膨らみ、 「どの変数がどれだけ寄与しているか」の解釈が不安定になります。 この区別を理解しているかどうかが、 多重共線性を扱う初心者と熟練者の境界です。

📐 数学的等価条件

説明変数行列 X が完全多重共線(rank(X) < p+1)の場合、 OLS の正規方程式 XᵀXβ = Xᵀy は解を一意に持たず、 (XᵀX)⁻¹ が存在しないため OLS 推定量は定義できません。 これは「設計行列が full column rank ではない」と等価で、 「ある説明変数が他の説明変数の線形結合で完全に再現できる」とも等価です。 SSDSE-B-2026 で「年少人口 + 高齢人口を総人口と同時に扱う」をすべて投入するような状況がこれに該当します。

🐍 Python 実装:完全共線を意図的に作って観察

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import pandas as pd, numpy as np
import statsmodels.api as sm

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023].dropna(subset=['A4101', 'I5102'])

# 完全共線な変数を作る(出生数 × 2)
df['出生数x2'] = df['A4101'].astype(float) * 2

X = sm.add_constant(pd.DataFrame({
    '出生数': df['A4101'].astype(float),
    '出生数x2': df['出生数x2']
}))
try:
    model = sm.OLS(df['I5102'].astype(float), X).fit()
    print(model.summary())
except Exception as e:
    print('完全共線で推定不可:', e)
print('rank:', np.linalg.matrix_rank(X.values), 'cols:', X.shape[1])

💡 実務 5 か条

  1. 分析開始前に相関行列と VIF を確認する習慣をつける
  2. 「予測 vs 解釈」の目的を明確にしてから対処法を選ぶ
  3. 変数削減はドメイン知識ベース、 機械的でない
  4. Ridge/Lasso を使うなら CV で λ を選ぶ
  5. 論文や報告書では VIF も併記する(査読者が見る)

🌐 補強3:実データで多重共線性に遭遇する 6 つの典型シナリオ

多重共線性は「珍しい問題」ではなく、 実データを扱えば ほぼ必ず 出会う問題です。 SSDSE-B-2026 や類似データセットでよく遭遇する 6 つの典型シナリオを整理し、 それぞれの対処を示します。

📋 シナリオ一覧

# シナリオ SSDSE-B での例 推奨対処
1 和が一定(恒等式) 年少人口 + 高齢人口を総人口と同時に扱う どれか 1 つを削除(恒等式の基底変換)
2 スケール変換のみ 人口(人) と 人口(千人) 片方削除
3 高相関(同一概念の代理) 総人口 と 出生数(r = 0.9954) PCA、 ドメイン優先で 1 つ選択
4 多項式項の共線 x と x²、 x と x³ 中心化、 直交多項式
5 交互作用項 x、 z、 x×z 中心化、 標準化
6 ダミー変数の罠 東京/その他のダミー 2 個 基準カテゴリを 1 つ抜く

🐍 シナリオ 3 の実演:総人口と出生数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import pandas as pd
from statsmodels.stats.outliers_influence import variance_inflation_factor

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]
X = df[['A1101', 'A4101', 'A9101']].rename(columns={
    'A1101': '総人口', 'A4101': '出生数', 'A9101': '婚姻'
}).astype(float)

# シナリオ 3:同一概念の代理変数を 3 つ同時投入
print('相関行列:')
print(X.corr().round(4))
Z = (X - X.mean()) / X.std()

print()
print('VIF:')
for i, c in enumerate(Z.columns):
    print(f'  {c}: VIF = {variance_inflation_factor(Z.values, i):.1f}')

🐍 シナリオ 6 の実演:ダミー変数の罠

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
import pandas as pd
import statsmodels.api as sm

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]).copy()
df = df[df['SSDSE-B-2026'] == 2023].dropna(subset=['A1101'])

# 2 区分ダミーを基準カテゴリなしで全部入れる(罠)
df['地域区分'] = df['Prefecture'].map(lambda s: '東京' if s == '東京都' else 'その他')
dummies = pd.get_dummies(df['地域区分'])
# 全部投入:完全共線(dummies.sum(axis=1) == 1)
X = sm.add_constant(dummies.astype(float))
try:
    model = sm.OLS(df['A1101'].astype(float), X).fit()
    print(model.summary())
except Exception as e:
    print('完全共線:', e)
# 解決:drop_first=True で基準カテゴリを抜く
dummies_ok = pd.get_dummies(df['地域区分'], drop_first=True)
print('修正後:', dummies_ok.columns.tolist())

🧮 シナリオ 5 の実演:交互作用項を中心化

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import pandas as pd
from statsmodels.stats.outliers_influence import variance_inflation_factor

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023].dropna(subset=['A1101', 'A1303'])

x = df['A1101'].astype(float)  # 総人口
z = df['A1303'].astype(float)  # 高齢人口

# 中心化なし
X1 = pd.DataFrame({'x': x, 'z': z, 'xz': x * z})
print('中心化なし:')
for i, c in enumerate(X1.columns):
    print(f'  {c}: VIF = {variance_inflation_factor(X1.values, i):.1f}')

# 中心化あり
xc, zc = x - x.mean(), z - z.mean()
X2 = pd.DataFrame({'x': xc, 'z': zc, 'xz': xc * zc})
print('中心化あり:')
for i, c in enumerate(X2.columns):
    print(f'  {c}: VIF = {variance_inflation_factor(X2.values, i):.1f}')

📐 シナリオ別チェックリスト

💡 実務メモ:多重共線性は「設計の問題」であって「データの問題」ではないことが多い。 変数選択や前処理の段階で予防するのが、 後から VIF を見て泣くより早道です。

🌐 補強4:正則化による多重共線性対処 — Ridge / Lasso / Elastic Net 完全比較

多重共線性が深刻なときに、 変数削減ではなく 正則化 で対処する流派があります。 主要 3 手法を SSDSE-B-2026 で並べて、 それぞれの強み・弱みを実体験しましょう。

📐 3 手法の数式比較

手法 目的関数 変数選択 共線変数の扱い
OLS ‖y − Xβ‖² なし 推定が不安定
Ridge (L²) ‖y − Xβ‖² + λ‖β‖² なし(縮約のみ) 均等に縮約
Lasso (L¹) ‖y − Xβ‖² + λ‖β‖₁ あり(係数 → 0) どれか 1 つを残す
Elastic Net ‖y − Xβ‖² + λ₁‖β‖₁ + λ₂‖β‖² あり グループでまとめて残す

🐍 SSDSE-B-2026 で 3 手法を並列比較

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
import pandas as pd, numpy as np
from sklearn.linear_model import LinearRegression, Ridge, Lasso, ElasticNet
from sklearn.preprocessing import StandardScaler

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]
cols = ['A1101', 'A4101', 'A5101', 'A9101']
labels = {'A1101': '総人口', 'A4101': '出生数', 'A5101': '転入', 'A9101': '婚姻'}
df = df.dropna(subset=cols + ['I5102'])

scaler = StandardScaler()
X = scaler.fit_transform(df[cols].astype(float))
y = df['I5102'].astype(float).values
names = [labels[c] for c in cols]

models = {
    'OLS':         LinearRegression(),
    'Ridge λ=1':   Ridge(alpha=1.0),
    'Ridge λ=10':  Ridge(alpha=10.0),
    'Lasso λ=0.5': Lasso(alpha=0.5, max_iter=20000),
    'EN α=0.5':    ElasticNet(alpha=0.5, l1_ratio=0.5, max_iter=20000),
}

print(f"{'method':<14} " + ' '.join(f'{c[:6]:>8}' for c in names))
for name, m in models.items():
    m.fit(X, y)
    coefs = m.coef_
    print(f'{name:<14} ' + ' '.join(f'{c:>8.2f}' for c in coefs))
# Lasso では一部の係数が 0 に近づく。 Ridge では均等縮約。

🧪 λ を変えたときの係数経路(Ridge Trace / Lasso Path)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import numpy as np
from sklearn.linear_model import Ridge

lambdas = np.logspace(-2, 4, 30)
coefs_path = []
for lam in lambdas:
    m = Ridge(alpha=lam).fit(X, y)
    coefs_path.append(m.coef_)
coefs_path = np.array(coefs_path)

# 各係数が λ 増加に対してどう変化するかを表で表示
print(f'\n{"λ":>10}  ' + ' '.join(f'{c[:6]:>8}' for c in cols))
for i, lam in enumerate(lambdas[::5]):
    cf = coefs_path[i*5]
    print(f'{lam:>10.3f}  ' + ' '.join(f'{c:>8.2f}' for c in cf))
# λ → 0 で OLS、 λ → ∞ で全係数 0。 Ridge trace plot の素材。

📊 手法選択ガイドライン

状況 推奨 理由
変数すべてが意味ありRidge縮約のみ、 すべて残る
スパースな解が欲しいLasso変数選択と縮約が同時
グループ共線ありElastic Netグループごと残す
p >> nLasso or EN高次元での疎解探索

💡 実務メモ:λ は CV で選ぶ(RidgeCV, LassoCV)。 「縮約された係数の解釈」と「OLS の係数解釈」は別物 — 縮約モデルでは「効果の方向」程度しか言えないことを忘れずに。

📚 補強5:多重共線性 FAQ — よくある 10 の疑問

多重共線性について実務でよく聞かれる 10 の質問と回答をまとめます。

Q1. VIF が 10 を少し超えただけです。 大丈夫?

絶対基準ではありません。 「予測」目的なら問題なし、 「個別係数の解釈」が目的なら標準誤差の膨らみを確認しましょう。 サンプルサイズも考慮。

Q2. 多重共線性が予測精度に影響しないと聞きました。 本当?

OLS の予測 MSE は VIF に影響されません。 ただし「外挿」では危険。 訓練データの範囲を出ると共線性のせいで予測が大きく外れます。

Q3. PCA で前処理すれば解決?

はい、 共線性は消えます。 ただし「主成分の解釈」が困難になります。 解釈優先か予測優先かで選択。

Q4. Ridge 回帰なら多重共線性を完全に無視できる?

予測目的では OK。 ただし係数の解釈は OLS と異なり、 「縮約された値」なので「効果の方向と相対的大きさ」程度しか言えません。

Q5. 中心化はいつ必要?

多項式項(x, x²)、 交互作用項(x×z)を作るときは必ず。 中心化なしでは VIF が 100 を超えることも。

Q6. カテゴリ変数のダミー化で完全共線になる?

k 個のカテゴリすべてをダミーにすると完全共線(合計 = 1)。 必ず drop_first=True で k-1 個にします。

Q7. 多重共線性が深刻でも、 全変数を残したいときは?

Ridge か Elastic Net。 OLS では係数推定が崩壊しますが、 正則化なら全変数を残しつつ安定推定できます。

Q8. サンプルサイズを 2 倍にすれば解決?

標本に起因する共線(標本相関)なら解決します。 ただし構造的な共線(恒等式・概念的重複)は標本数で解消できません。

Q9. 多重共線性は仮説検定に影響する?

はい。 標準誤差が VIF 倍に膨らみ、 t 値が小さくなって「有意でない」結論になりやすい(第二種の過誤)。

Q10. 全変数の VIF が 1 に近い。 完璧?

共線性は皆無ですが、 「変数選択が独立すぎる」場合、 各変数が説明する情報が分離しすぎている可能性も。 ドメイン知識で確認を。

💡 FAQ の心得:「多重共線性は悪」と短絡しないこと。 目的(予測 vs 推論)とデータ規模を踏まえて判断するのが、 実務家の腕の見せどころです。

📋 補強6:多重共線性 実務チェックリスト

分析を始める前・回帰モデルを構築する際・結果を報告する際の 3 段階で押さえるべき項目を整理します。

🟦 分析開始前

🟦 モデル構築中

🟦 結果報告時

💡 まとめ:多重共線性は「気づかなければスルー、 気づけば対処可能」な問題。 チェックリストを習慣化すれば、 査読でも実務でも怖くなくなります。