論文一覧に戻る 📚 用語解説(ジャストインタイム型データサイエンス教育)
VIF(分散拡大係数)
Variance Inflation Factor (VIF)
多重共線性の強さを定量化。VIF > 10 は深刻、5以上で注意。1なら他変数と独立。
回帰モデルVIFVIF分散拡大係数
📍 文脈💡 30秒結論📖 詳しく

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

🍰 まずはやさしく

データの重複をチェックする道具です。

分析に不要なデータを見つけるために使います。

スマホの利用時間とアプリの数の関係などで考えます。

この用語がどう使われるかを確認しましょう。

論文中に 「VIF(分散拡大係数)」として登場する用語。

VIF(分散拡大係数) とは:多重共線性の強さを定量化。VIF > 10 は深刻、5以上で注意。1なら他変数と独立。

💡 30秒で分かる結論

🍰 まずはやさしく

データの重なりを測る物差しです。

計算結果が正しいか確かめるために使います。

テストの点数と勉強時間の関係を調べる時に便利です。

まずは結論から簡単に説明します。

📖 もっと詳しく

VIF(Variance Inflation Factor, 分散拡大係数)は、 多重共線性の強さを変数ごとに定量化する指標。 重回帰の診断で必ず計算します。

定義:$\text{VIF}_j = 1 / (1 - R_j^2)$

ここで $R_j^2$ は、 「説明変数 $x_j$ を残りの説明変数で回帰したときの $R^2$」。 もし $x_j$ が他変数で完全に予測できるなら $R_j^2 = 1$ → VIF が無限大。 完全に独立なら $R_j^2 = 0$ → VIF = 1。

目安

使い方

  1. 各説明変数の VIF を計算
  2. 最大の VIF が10超なら、 その変数を落とすか主成分化
  3. 再計算して最大の VIF を確認
  4. すべて VIF < 5 になるまで繰り返す

Pythonfrom statsmodels.stats.outliers_influence import variance_inflation_factor

VIF の閾値は固い決まりではない:10 という値も慣習で、 厳しめに 3 を採用する研究者もいます。 領域ごとの慣行に従いましょう。

📖 包括的解説 — この概念を完全マスター

📍 学習の3ステップ

  1. 定義を理解する:この概念は何か? 数式や条件を確認
  2. 具体例を見る:実データ(SSDSE 等)で計算してみる
  3. 応用する:自分のデータに適用、 結果を解釈

🔧 Python実装パターン

🎯 解説: SSDSE-B-2026 の説明変数間の多重共線性を VIF(分散拡大係数)で診断。 VIF=1/(1-R²ᵢ)、 ある変数を他の変数で回帰した R² から計算。 VIF>10 で問題、 >5 で注意。
📥 入力例: data/raw/SSDSE-B-2026.csv(2023 年度・47 都道府県) X = df[['A1101','A1301','A1303','A4101']] # 総人口/年少人口/高齢人口/出生数 4 変数 + 切片
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import pandas as pd
import numpy as np
from statsmodels.stats.outliers_influence import variance_inflation_factor
from statsmodels.tools.tools import add_constant

# SSDSE-B-2026 を読み込み、2023 年度だけ残す
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]

# 規模が連動しやすい人口系の説明変数で VIF を診断
cols = ['A1101', 'A1301', 'A1303', 'A4101']  # 総人口/年少人口/高齢人口/出生数
X = add_constant(df[cols].astype(float))      # VIF は切片込みで計算する
vif = pd.DataFrame({
    'feature': X.columns,
    'VIF': [variance_inflation_factor(X.values, i) for i in range(X.shape[1])],
})
print(vif)
📤 実行例: VIF 一覧(add_constant 込み) const : 3.7 A1101(総人口) : 314.7(深刻) A1301(年少人口) : 507.3(深刻) A1303(高齢人口) : 116.4(深刻) A4101(出生数) : 478.5(深刻)
💬 読み方: VIF>10 は深刻な多重共線性。 人口が多い県ほど年少人口・高齢人口・出生数もすべて多く、 4 変数が「県の規模」という共通因子で連動している。 対策: 変数を 1 つに絞る・比率化(例 高齢化率)・主成分分析・リッジ回帰。

📚 統計概念マップでの位置

このページの上にある3つの概念マップ(関係マップ、 包含マップ、 ツリーマップ)でこの概念の位置づけが視覚的に分かります。 関連手法を辿って学習を進めましょう。

🎯 SSDSE-B-2026 で挑戦

統計データ活用コンペティションのSSDSE-B-2026データは、 47都道府県の社会経済データ。 この概念を使って以下のような分析ができます:

💡 よく使うコマンド集

機能 Python (pandas) Python (scipy)
要約統計df.describe()stats.describe()
平均df.mean()np.mean()
標準偏差df.std()np.std()
相関df.corr()stats.pearsonr()
t検定stats.ttest_ind()
回帰stats.linregress()
分布フィッティングstats.norm.fit()

🚧 一般的な落とし穴と対策

📊 結果報告の標準フォーマット

🌐 関連分野での応用

🎓 さらに学ぶための文献

🔗 統計用語ネットワーク

この概念は、 他の多くの統計概念と密接に関連しています。 ジャストインタイム型学習では、 必要に応じて関連用語へジャンプしながら全体像を構築します。

主要な関連概念のグループ

グループ 主要概念
記述統計平均、 中央値、 最頻値、 分散、 標準偏差、 共分散、 相関係数
可視化ヒストグラム、 散布図、 箱ひげ図、 ヒートマップ
推測統計標本平均、 標準誤差、 信頼区間、 p値、 有意水準
確率分布正規分布、 t分布、 χ²分布、 F分布、 二項分布
仮説検定t検定、 F検定、 χ²検定、 ノンパラ検定
回帰単回帰、 重回帰、 OLS、 Ridge、 LASSO
分類ロジスティック回帰、 決定木、 SVM、 k-NN
教師なし学習クラスタリング、 PCA、 因子分析
時系列ARIMA、 VAR、 指数平滑法、 自己相関
因果推論DiD、 IV、 傾向スコア、 交絡変数
前処理標準化、 正規化、 欠損値処理、 多重共線性対策
評価R²、 残差、 CV、 RMSE、 効果量

学習順序の推奨

  1. 記述統計(平均、 分散、 標準偏差)
  2. 可視化(ヒストグラム、 散布図)
  3. 確率分布(正規分布)
  4. 推測統計(標準誤差、 信頼区間、 p値)
  5. 仮説検定(t検定、 χ²検定)
  6. 相関と回帰(単回帰、 重回帰)
  7. 多変量解析(PCA、 クラスタリング)
  8. 機械学習(決定木、 RF、 NN)
  9. 時系列・因果推論(応用)

📝 実践練習 — SSDSE-B-2026 で挑戦

初級課題

  1. 東北6県の家計食料費の基本統計量を計算
  2. 食料費のヒストグラムを描く
  3. 食料費と教育費の散布図を描く
  4. 都道府県を「東日本/西日本」に分け、 平均を比較

中級課題

  1. 家計支出 5項目で相関行列を作成、 ヒートマップ可視化
  2. 食料費 → 教育費の単回帰を実行、 残差分析
  3. 家計5項目で PCA を実施、 バイプロット表示
  4. k-means (k=3) で都道府県をクラスタリング、 解釈

上級課題

  1. 地域別の家計パターンに有意差があるか ANOVA で検定
  2. 重回帰で教育費を予測、 多重共線性を VIF で確認
  3. Ridge/LASSO で正則化、 CV で α を最適化
  4. 階層クラスタリングと Ward 法で都道府県を分類、 デンドログラム作成

📚 統計学習の総合ガイド

🎯 学習目標

このページの概念をマスターすることで、 以下のスキルが身につきます:

📊 SSDSE-B-2026 データの構造

このコンペの主要データセット(SSDSE-B-2026)の構造:

🔍 主要な変数群

カテゴリ 変数例
人口総人口、 年齢別人口、 性別人口
人口動態出生数、 死亡数、 合計特殊出生率、 婚姻数
気候気温、 降水量、 降水日数
教育幼小中高校数、 教員数、 生徒数、 大学進学率
経済求職件数、 求人件数、 旅館数
医療病院数、 診療所数、 歯科診療所
家計消費支出、 食料費、 住居費、 教育費等の項目別

💡 ジャストインタイム型学習

このガイドは「必要なときに必要な知識」を提供する設計:

🛠️ Python データサイエンス環境

🎯 解説: 分析に必要なライブラリを一括インストール・インポートし、 SSDSE-B-2026 を cp932 で読み込む土台を作る。 以降の VIF 計算はこの環境を前提とする。
📥 入力例: data/raw/SSDSE-B-2026.csv encoding='cp932' で読み込み 47 都道府県 × 12 年 × 112 列
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 必須ライブラリのインストール
pip install pandas numpy scipy statsmodels scikit-learn matplotlib seaborn

# 標準的なインポート
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from scipy import stats
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.metrics import r2_score, mean_squared_error

# 日本語表示の設定(matplotlib)
plt.rcParams['font.family'] = 'Hiragino Sans'
plt.rcParams['axes.unicode_minus'] = False

# データ読み込み(SSDSE は cp932、 2 行目の日本語見出しは skiprows=[1] で除外)
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
print(df.shape)
print(df.head())
print(df.describe())
📤 実行例: 環境確認 (564, 112) ← 全年度・全列を読み込めた describe() で各列の平均・分散を一覧
💬 読み方: shape が (564, 112) なら読み込み成功(47 都道府県 × 12 年 = 564 行、 2 行目の日本語見出し行は skiprows=[1] で除外済み)。 VIF 計算は次節で 2023 年度を抽出してから行う。

🌟 効果的なEDAテンプレート

🎯 解説: VIF と相関行列の関係を確認。 2 変数間 r=0.9 なら VIF=1/(1-0.81)=5.3。 r=0.95 なら VIF=10.3。 r が大きいと急速に VIF 悪化。
📥 入力例: data/raw/SSDSE-B-2026.csv 相関行列 corr = df[['A1101','A1301']].corr() r ≒ 0.997(総人口と年少人口)
 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 matplotlib.pyplot as plt
import seaborn as sns

def quick_eda(df, target=None):
    """探索的データ分析の基本テンプレート"""
    print(f"Shape: {df.shape}")
    print(f"\nColumn types:\n{df.dtypes}")
    print(f"\nMissing values:\n{df.isnull().sum()}")
    print(f"\nBasic stats:\n{df.describe()}")

    # 数値列の可視化
    numeric_cols = df.select_dtypes(include=[np.number]).columns
    df[numeric_cols].hist(bins=20, figsize=(15, 10))
    plt.tight_layout()
    plt.show()

    # 相関ヒートマップ
    if len(numeric_cols) > 1:
        plt.figure(figsize=(12, 10))
        sns.heatmap(df[numeric_cols].corr(), annot=True, fmt='.2f',
                    cmap='RdBu_r', center=0)
        plt.show()

    # ターゲットがあれば散布図行列
    if target and target in df.columns:
        sns.pairplot(df[numeric_cols[:5]], hue=target if df[target].dtype == 'O' else None)
        plt.show()
📤 実行例(実測) このブロックは標準出力を出さない(図を描く・変数を定義するだけ)。
💬 読み方: 2 変数の場合は r²=R² と一致。 r=0.99 で VIF=50、 r=0.995 で VIF=100、 r=0.999 で VIF=500。 強相関ペアは片方を必ず除外。

📈 報告書テンプレート

分析結果を報告する際の標準的な構成:

  1. 背景・目的:なぜこの分析が必要か
  2. データ:出所、 サンプルサイズ、 期間
  3. 方法:使用した統計手法、 仮定
  4. 結果:図表、 統計量、 検定結果
  5. 解釈:結果が何を意味するか
  6. 限界:分析の制約
  7. 結論:要点まとめ、 今後の課題

🗺️ 統計手法選択フローチャート

Q1: 何を知りたい?

Q2: データの種類は?

Q3: サンプルサイズは?

Q4: 仮定は?

📏 効果量の参照表

p値だけでなく効果量も併記するのが現代統計の標準。 主要な指標と Cohen の解釈基準:

統計量 効果量
2群平均差Cohen's d0.20.50.8
相関r0.10.30.5
線形回帰0.020.130.26
ANOVAη² (eta²)0.010.060.14
χ²Cramér's V0.10.30.5
ロジスティックOdds Ratio1.52.54.0

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

VIF(分散拡大係数) がデータサイエンスの体系の中でどこに位置するかを、 3つの異なる視点で可視化します。 同じ情報でも見方を変えると気付きが変わります。

📍 体系階層のパス

🌐 統計・データサイエンス › 前処理 › 変換 › VIF(分散拡大係数)(多重共線性の強さを測る指標)

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

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

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

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

大きな円が小さな円を包含する Circle Packing 図。 「VIF(分散拡大係数)」は緑色でハイライト

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

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

長方形を入れ子に分割した Treemap 図。 各分野の規模感を面積で比較。 「VIF(分散拡大係数)」は緑色でハイライト

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

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

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

🔖 キーワード索引(拡張版 — VIF 周辺)

多重共線性診断と対処のトピックを網羅。

SSDSE-B VIF 多重共線性 条件数 許容度 主成分回帰 Ridge 回帰 PLS 回帰 閾値10の盲信 交互作用項 中心化 statsmodels scikit-learn numpy.linalg

🧮 SSDSE-B-2026 実値計算例 — 全数値変数の VIF 一覧

SSDSE-B-2026 の数値列で重回帰を組み、 各変数の VIF を計算します。 典型的に「総人口」「世帯数」「就業者数」など強相関の人口系変数で VIF>10 が観測されます。

変数(典型例) VIF 目安 判定 対処
総人口> 50深刻どれか1つに絞る
世帯数> 50深刻主成分化
就業者数> 30深刻人口で割って比率化
平均所得2〜5許容範囲そのまま使用可
持ち家比率1.5〜3問題なし独立性が高い
🎯 解説: VIF 改善の実演。 SSDSE-B-2026 で VIF>10 の変数を 1 つずつ除外し、 残った変数の VIF が許容範囲(<5)に収まることを確認。
📥 入力例: data/raw/SSDSE-B-2026.csv(2023年) 初期 4 変数(A1101 / A1301 / A1303 / A4101) → A1101 を除外して VIF 再計算
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import pandas as pd
from statsmodels.stats.outliers_influence import variance_inflation_factor
from statsmodels.tools.tools import add_constant

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

def vif(cols):
    X = add_constant(d[cols].astype(float))
    return {c: float(round(variance_inflation_factor(X.values, X.columns.get_loc(c)), 1)) for c in cols}
print('初期4変数 :', vif(['A1101', 'A1301', 'A1303', 'A4101']))
print('A1101除外後:', vif(['A1301', 'A1303', 'A4101']))
📤 実行例(2023年、実測): 初期4変数 : {'A1101': 314.7, 'A1301': 507.3, 'A1303': 116.4, 'A4101': 478.5} A1101除外後: {'A1301': 498.1, 'A1303': 57.7, 'A4101': 305.1}
💬 読み方: VIF が最大の変数を 1 つずつ除外。 全変数 VIF<5 になるまで反復。 残す変数の選択は理論的・実務的優先度で決める。 機械的除外より統計的判断重視。
📝 補足(より正確な分析): この 4 変数(総人口・年少人口・高齢人口・出生数)は相互に極めて高相関のため、 A1101 を 1 つ除外しても A1301=498.1・A4101=305.1 と依然 VIF が非常に大きいままです。 さらに A1301 も除いた 2 変数でも VIF≈25.6 で、 単一変数まで減らすか、 主成分回帰・Ridge 等の縮小推定に切り替えないと VIF<5 には到達しません。 「A1101 除外で 8.2、 A1301 除外で 2.3 に収束」という旧記載は実データでは再現しないため、 上の実測値へ差し替えています。

⚠️ 落とし穴(補強版 — VIF 解釈で踏みやすい7つの罠)

① 閾値「10」を絶対視する
VIF>10 は深刻、 >5 は要注意、 という基準は経験則に過ぎません。 標本サイズや変数間の相関構造によっては VIF=3 でも問題になることがあり、 逆に VIF=15 でも実用上問題ないこともあります。 重要なのは「係数推定の標準誤差がどれだけ膨らんでいるか」であり、 ブートストラップで実際の信頼区間幅を確認するのが現代的アプローチです。 機械的な「VIF<10 でクリア」報告は分析の浅さを示します。
② 交互作用項・多項式項で「自然に」高い VIF を見て削除する
x と x² や x と x·z は数学的に強く相関するので、 VIF が高いのは当然です。 この「構造的共線性」は中心化(x の平均を引く)で大幅に解消できます。 中心化前の高 VIF を見て「交互作用項を諦める」のは不要な譲歩。 まず中心化、 それでも高ければ別の対処、 という順序が正しい流れです。 解釈もしやすくなる利点があります。
③ VIF が低いから「多重共線性なし」と断言する
VIF は1対多の線形関係を測るので、 3 変数が同時に絡む(例:a + b = c のような)共線性は捕捉できないことがあります。 条件数(condition number)や singular value の比、 cor 行列の固有値構造を併用しないと診断は不完全。 statsmodels の summary() の Cond.No. は重要な補完情報なので、 必ず VIF と一緒に報告しましょう。
④ 切片を含めずに VIF を計算する
statsmodels の variance_inflation_factor定数項を含むデザイン行列を期待します。 add_constant を忘れると、 各変数の VIF が異常に大きく見える(中心化なしのため)。 「VIF が全部 100 超だった」とパニックになる前に、 まず const 列があるかを確認してください。 この罠は statsmodels の Stack Overflow 質問の常連です。
⑤ 「VIF を下げる」ために大事な変数を捨てる
多重共線性は解釈の問題であって予測の問題ではありません。 予測精度を最優先するなら Ridge / Lasso / PCR で残したまま縮小すべき。 大事なのは「VIF を下げること」ではなく、 「最終的な分析目的(解釈 or 予測)にどう奉仕するか」。 理論上重要な変数を VIF だけで切るのは本末転倒で、 査読でも指摘されます。
⑥ ダミー変数の VIF を強引に計算する
カテゴリのダミー化で k カテゴリ → k−1 ダミーが基本(参照群を 1 つ落とす)。 k 個全部入れると完全共線性で VIF が無限大になります。 また、 同じカテゴリ群内のダミーは互いに相関するので VIF が高めになりがちですが、 これは「ダミー設計の性質」であり問題ではありません。 ダミー群全体の効果を見たいなら GVIF(一般化 VIF)を使うべきです。
⑦ 標準化しても VIF は変わらないと誤解
線形の標準化(z 変換)だけなら VIF は不変です(線形変換に不変)。 ただし、 非線形変換(対数、 平方根)を施せば VIF は変わります。 また、 中心化(平均を引くだけ)は交互作用項・多項式項の VIF を劇的に下げます。 「標準化したのに VIF が変わらない」のは正常。 「中心化したら VIF が下がった」のも正常。 違いを把握しておきましょう。

🐍 Python 実装バリエーション(statsmodels / scikit-learn / numpy / scipy)

🅰️ statsmodels の素直な実装(標準)

🎯 解説: statsmodels の variance_inflation_factor で 4 変数(総人口・年少人口・高齢人口・出生数)の VIF を計算する標準実装。 add_constant で切片を含むデザイン行列を渡すのが要点。
📥 入力例: data/raw/SSDSE-B-2026.csv 2023 年度の 47 都道府県 cols = ['A1101','A1301','A1303','A4101']
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import pandas as pd
from statsmodels.stats.outliers_influence import variance_inflation_factor
from statsmodels.tools.tools import add_constant

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]  # 2023 年度の 47 都道府県だけ
cols = ['A1101', 'A1301', 'A1303', 'A4101']  # 総人口/年少人口/高齢人口/出生数
num = df[cols].astype(float)
X = add_constant(num)
for i, c in enumerate(X.columns):
    if c == 'const': continue
    print(f'{c}: VIF = {variance_inflation_factor(X.values, i):.2f}')
📤 実行例: A1101: VIF = 314.74 A1301: VIF = 507.28 A1303: VIF = 116.41 A4101: VIF = 478.47
💬 読み方: VIF が係数の不安定さを定量化。 VIF=10 なら p 値が大きくなり、 真の効果でも有意でなくなる可能性。 信頼区間も広がる。

🅱️ scikit-learn で自前計算(R²から逆算)

🎯 解説: scikit-learn の LinearRegression で各変数を残り 3 変数へ回帰し、 その R² から VIF=1/(1−R²) を逆算する自前実装。 statsmodels 版と同じ値になる。
📥 入力例: data/raw/SSDSE-B-2026.csv 前ブロックの num(4 変数)を利用 各変数を残り 3 変数で回帰
1
2
3
4
5
6
7
8
from sklearn.linear_model import LinearRegression
X = num.values
cols = num.columns
for j, c in enumerate(cols):
    others = [k for k in range(X.shape[1]) if k != j]
    r2 = LinearRegression().fit(X[:, others], X[:, j]).score(X[:, others], X[:, j])
    vif = 1 / (1 - r2)
    print(f'{c}: R²={r2:.3f}, VIF={vif:.2f}')
📤 実行例: A1101: R²=0.997, VIF=314.74 A1301: R²=0.998, VIF=507.28 A1303: R²=0.991, VIF=116.41 A4101: R²=0.998, VIF=478.47
💬 読み方: statsmodels 版と完全に一致する(同じ VIF 定義)。 R² が 1 に近い変数ほど VIF が急増し、 4 変数すべてが VIF>100 と深刻。

🅲 numpy / scipy で「相関行列の逆行列」から一気に

🎯 解説: numpy で相関行列の逆行列を取り、 その対角成分から 4 変数の VIF を一括計算する方法。 add_constant 版と同じ値になる。
📥 入力例: data/raw/SSDSE-B-2026.csv R = num.corr() np.diag(np.linalg.inv(R))
1
2
3
4
5
import numpy as np
R = num.corr().values
vifs = np.diag(np.linalg.inv(R))
for c, v in zip(num.columns, vifs):
    print(f'{c}: VIF={v:.2f}')
📤 実行例: A1101: VIF=314.74 A1301: VIF=507.28 A1303: VIF=116.41 A4101: VIF=478.47
💬 読み方: 相関行列の逆行列の対角がそのまま VIF に一致する。 4 変数すべて VIF>100 で、 県の人口規模による強い共線性を示す。

🅳 条件数(VIF の上位互換的診断)

🎯 解説: statsmodels の OLS の summary() 末尾に出る Cond. No.(条件数)で、 VIF を補完する全体診断を行う。 30 超で多重共線性、 100 超で深刻。
📥 入力例: data/raw/SSDSE-B-2026.csv 前ブロックの num(4 変数)を利用 目的変数=A1101(総人口)で OLS.summary()
1
2
3
import statsmodels.api as sm
res = sm.OLS(num['A1101'], add_constant(num.drop(columns=['A1101']))).fit()
print(res.summary())  # 末尾に Cond. No. が出る
📤 実行例: summary() 末尾 Cond. No. = 2.01e+06 → 条件数が巨大=多重共線性が深刻
💬 読み方: 条件数は設計行列全体の悪条件性を 1 つの数字で表す。 VIF が個別変数を、 条件数が全体を診断する。 大きすぎる場合は比率化・主成分回帰・リッジ回帰で対処する。

📦 多重共線性診断早見表

指標 問題視する目安 特徴
VIF> 10(厳しめ > 5)変数ごと、 1対多
許容度 1/VIF< 0.1VIF の逆数
条件数> 30全変数構造、 多対多
最小固有値< 0.05相関行列の縮退
GVIF(カテゴリ)^(1/2df) > 2ダミー群全体

🎨 直感で掴む — VIF (分散拡大係数)

🍰 まずはやさしく

データの「かぶり」を直感的に捉える方法です。

計算のズレがどれくらい大きいかを知るために使います。

部活の練習量と試合結果の関係で例えてみます。

イメージを掴むための解説を読みましょう。

VIF は「説明変数同士が強く相関している(多重共線性)と、 推定の分散がどれだけ膨らむか」を示す指標。 VIF=1 で無相関、 10 を超えると要注意、 5 を超えると黄信号。 SSDSE-B-2026 で A1101(総人口)・A1301(15 歳未満)・A1303(65 歳以上)を全部入れると、 A1101 ≈ A1301 + A1302 + A1303 のため VIF が爆発する。

💡 学習のコツ:直感で全体像を掴んだら、 次の「📐 定義・数式」で正確な意味を押さえ、 最後に「🧮 実値で計算してみる」で SSDSE-B-2026 の都道府県データを使った計算をなぞるのが効率的です。 比喩は厳密ではないので、 必ず数式と並べて確認してください。

VIF (分散拡大係数) は「回帰」カテゴリの中核概念。 初めて触れる読者は、 まずこの「🎨 直感」セクションだけ通読し、 必要になった時点で「📐 数式」「🐍 Python」「⚠️ 落とし穴」へ戻る読み方が定着しやすいです。

📐 定義・数式 — VIF (分散拡大係数)

🍰 まずはやさしく

重なり具合を数字にするためのルールです。

正確な値を計算するために使います。

買い物で使う金額と個数の関係などで考えます。

具体的な数式を使って詳しく説明します。

直感の次は、 厳密な定義を確認します。 数式は言語の一種で、 一度書き慣れれば「言葉より速く伝えられる」便利な道具。 慣れていない方は、 各記号が何を表すかを下の「🔬 数式を言葉で読み解く」で 1 つずつ確認してください。

【VIF (分散拡大係数) の中心定義式】
$$ \text{VIF}_j = \frac{1}{1 - R_j^2} $$
この式が「VIF (分散拡大係数)」の骨格。 派生形・拡張形はここから生まれる。
📌 読み方のコツ:数式を見たら「左辺は何を定義しているか」「右辺の各項は何の合計・積・比か」を声に出して読み下してみる。 これだけで理解が大きく進みます。

🔬 数式を言葉で読み解く — 数式を「言葉」に翻訳

上の数式を眺めるだけでは身につかないので、 各記号がどんな役割を担っているかを言葉で押さえます。 「数式を音読する習慣」がつくと、 論文や教科書を読むスピードが体感で 2 倍ほど上がります。

左辺(結果側)
VIF (分散拡大係数) で定義したい量。 解釈の対象。 単位・スケールを必ず確認する。
右辺(構成要素)
観測できる入力変数(SSDSE-B-2026 でいえば A1101・L3221 など)と推定対象パラメータ(β, σ 等)の組合せ。
添字 i, j, t
i=サンプル(県)、 j=変数、 t=時点。 SSDSE-B-2026 は i ∈ {1..47} 県、 t ∈ {2008..2023}。
和記号 Σ
「足し合わせ」を表す。 添字 i が 1 から n まで動く範囲を明示するのが習慣。
期待値 E[·]、 分散 Var[·]
「ランダム変数の平均」と「ばらつき」。 SSDSE-B-2026 のような集計値でも、 標本誤差・年次変動の文脈で使える。
📚 補足:同じ記号でも分野・教科書によって意味が違うことがあります(例: $\hat{y}$ は予測値だが、 統計の文脈では推定量を意味することも)。 不明確なときは、 必ずその文書の記号定義表を確認しましょう。

🧮 実値で計算してみる — SSDSE-B-2026

数式だけでは「実感」が湧きにくいので、 実データ data/raw/SSDSE-B-2026.csv(47 都道府県 × 16 年)で 1 度手計算してみると理解が定着します。

SSDSE-B-2026 (2023) で y=L3221、 説明変数 X={A1101, A1301, A1303} を当てると、 VIF は A1101≒201・A1301≒151・A1303≒56 と 3 変数すべてが VIF≫10 になる(A1101 = A1301 + 15〜64 歳人口 + A1303 という会計恒等式が原因)。 高齢化率(A1303/A1101)へ置き換えると、 その比率変数自体の VIF は約 3 まで下がるが、 規模そのものを表す変数(A1301・A1303)を並べたままでは共線性は解消しないため、 最終的には変数を 1〜2 個に絞る判断が要る。

都道府県A1101 総人口A1303 65 歳以上L3221 消費支出
東京都14,086,0003,205,000341,320
神奈川県9,229,0002,390,000306,565
大阪府8,763,0002,424,000271,246
愛知県7,477,0001,923,000300,221
埼玉県7,331,0002,012,000344,092
千葉県6,257,0001,756,000306,943

上記は SSDSE-B-2026 (2023) からの抜粋。 手計算で確認した値が、 後述の Python 実装で得る値と一致することを確認すると、 「数式とコードの対応関係」がクリアに見えるようになります。

🐍 Python 実装 — VIF (分散拡大係数)

公的統計(SSDSE-B-2026)を題材に、 最小限の Python コードで VIF (分散拡大係数) を動作させます。 まずはこのまま実行してみてください。

📥 入力例(SSDSE-B-2026 の 2023 年・47 都道府県から 3 行) 都道府県 A1101(総人口) A1301(15歳未満人口) A1303(65歳以上人口) L3221(消費支出(二人以上の世帯)) 北海道 5,092,000 514,000 1,681,000 296,888 東京都 14,086,000 1,513,000 3,205,000 341,320 沖縄県 1,468,000 236,000 350,000 251,222 …(全 47 行)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# VIF (分散拡大係数) を SSDSE-B-2026 で実行する最小コード
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]  # 2023 年のみ抽出
print(df.shape)  # (47, 112)
print(df[['Prefecture','A1101','A1303','L3221']].head())

from statsmodels.stats.outliers_influence import variance_inflation_factor
import pandas as pd
import numpy as np
X = df[['A1101','A1301','A1303']].astype(float)
X = pd.DataFrame(X.values, columns=X.columns)
vifs = [variance_inflation_factor(X.values, i) for i in range(X.shape[1])]
for c, v in zip(X.columns, vifs):
    print(f'{c}: VIF={v:.2f}')
📤 実行例(実測) (47, 112) Prefecture A1101 A1303 L3221 0 北海道 5092000 1681000 296888 12 青森県 1184000 417000 263371 24 岩手県 1163000 407000 298536 36 宮城県 2264000 662000 305541 48 秋田県 914000 357000 272086 A1101: VIF=311.45 A1301: VIF=289.46 A1303: VIF=68.15

▶ 実行 を押せばこのページの中でそのまま動きます(ライブラリもデータも同梱済みで、 準備は要りません)。 手元の Python に移して動かすときは pip install matplotlib numpy pandas scikit-learn scipy seaborn statsmodels が必要です。 読んでいるデータは data/raw/SSDSE-B-2026.csv。 日本語を含むので encoding='cp932' の指定を落とさないでください。

⚠️ よくある落とし穴 — VIF (分散拡大係数)

VIF (分散拡大係数) を使うときに初学者が踏みやすい失敗パターン。 1 度経験してしまえば次から避けられますが、 先に知っておくに越したことはありません。

❌ VIF=10 を絶対基準にする
5 でも症状が出る。 標本数・モデルの目的(予測 vs 解釈)で判断。
❌ ダミー変数の参照水準で見落とし
全水準を入れるとダミー罠で VIF=∞。 1 つ落とすのが標準。
❌ VIF が高い=相関係数高い と誤解
3 変数以上の同時相関も VIF に効く。 ペアワイズ相関だけ見ても見抜けない。
🛡 防御策まとめ:「適用条件を確認する」「結果と前提をセットで記述する」「不確実性を必ず併記する」の 3 点を習慣化すれば、 上記の罠の大半は回避できます。

🎨 概念図で押さえる

VIF(分散拡大係数)は、 説明変数同士の相関が回帰係数の推定分散をどれだけ増幅するかを表す。 多重共線性の有無を視覚化する 3 枚を見ておくとイメージが固まる。

VIF 値の分布ヒストグラム
多変数モデルにおける各説明変数の VIF 値分布。 5 や 10 を超える変数は要注意。
2 説明変数の散布図と相関
VIF が高い 2 変数の散布図イメージ。 強い相関(線形に近い分布)が VIF を引き上げる。
多重共線性のある回帰の不安定さ
多重共線性が強いと係数推定が不安定になる。 直線の傾きが少しのデータ変動で大きく振れる。

✅ 理解度チェック

  1. VIF の定義式 1/(1−R²) を説明できるか。
  2. VIF が 5・10 を超えた場合の一般的な解釈と対処を 1 つ挙げられるか。
  3. 多重共線性が回帰係数の標準誤差に与える影響を説明できるか。
  4. VIF と相関係数の違いを 1 行で述べられるか。

🧮 数式に値を入れて手で計算する: VIF

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

Step 1: R² と VIF

変数VIF
x10.201.25
x20.703.33
x30.9520.00

Step 2: 判定

x3 VIF=20 → 多重共線性深刻

🐍 Python で再現

1
2
3
4
import numpy as np
r2 = np.array([0.20, 0.70, 0.95])
vif = 1 / (1 - r2)
print(f"VIF: {vif}")

📤 実行結果

VIF: [ 1.25 3.33 20. ]

💬 手計算 (Step 1) と Python 出力が完全一致。

🔗 隣接手法への橋渡し (VIF 補助)

VIF は重回帰の係数解釈を保証する診断指標であり、 以下のフローで隣接手法と連結する。

SSDSE-B-2026 では「規模変数同士の高 VIF (=100 超) → 比率化 (1 人あたり指標) で解消」が定石。

🔖 キーワード索引

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

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

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

💡 30秒で分かる結論 (補足)

VIF (分散拡大要因) を 30 秒で把握する重要ポイント:

📍 文脈ボックス (補足)

本ページでは「VIF (Variance Inflation Factor、 分散拡大要因)」を扱う。 統計データ分析コンペティション (2026) の教材で、 SSDSE-B-2026 (47 都道府県 × 複数年 × 100 超列) の人口系変数群 (総人口/年少人口/高齢人口/出生数) を題材に、 多重共線性の数値化と対処を再現する。

VIF は回帰分析カテゴリの中核診断指標で、 「OLS の係数解釈が妥当か」を保証する。 本ページは「直感 → 数式 (1/(1-R²_j)) → 47 都道府県データで手計算 → statsmodels.variance_inflation_factor で再現 → 対処 (比率化/正則化/PCA)」の 6 視点で構成される。

🎨 直感で掴む

VIF (Variance Inflation Factor、 分散拡大要因) は「ある説明変数が他の説明変数とどれだけ重複しているか」を測る指標だ。 例えば SSDSE-B-2026 で「総人口」と「高齢人口」を両方説明変数に入れると、 両者は強く相関しているため、 一方の係数を「高齢人口を一定にしたときの総人口の影響」と読むことが難しくなる。 VIF はこの「重複度」を数値化し、 10 を超えれば多重共線性が深刻と判断する慣習がある。

直感的には「説明変数 X_j を、 他の説明変数で重回帰したときの決定係数 R²_j」を使い、 VIF_j = 1 / (1 - R²_j) で求める。 R²_j が 0.9 なら VIF=10、 0.95 なら VIF=20。 つまり「他の変数で X_j の動きの 9 割が説明できるなら、 X_j を独立に解釈するのは無理」というシグナルになる。

具体例として、 SSDSE-B-2026 の「総人口」「年少人口」「高齢人口」「出生数」の 4 列で VIF を計算する。 次節以降で「数式 → 値代入 → 手計算 → statsmodels.variance_inflation_factor」の流れを再現する。

📐 数式または定義

VIF の定義は明確かつ一意である。 各説明変数ごとに次の式で計算する。

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

ここで $R_j^2$ は「説明変数 $X_j$ を、 残りすべての説明変数 $X_{-j}$ で回帰したときの決定係数」である。 つまり「$X_j$ を他の変数たちで予測したときに、 どれだけ説明できるか」。 $R_j^2$ が大きいほど多重共線性が強い。

$$\text{VIF}_j = 1 \ (R_j^2=0) \quad \Rightarrow \quad \text{完全独立}$$

$$\text{VIF}_j = 10 \ (R_j^2=0.9) \quad \Rightarrow \quad \text{多重共線性が強い、 要対処}$$

$$\text{VIF}_j = \infty \ (R_j^2=1) \quad \Rightarrow \quad \text{完全多重共線、 推定不可能}$$

実用的な閾値は VIF=10 (R²_j=0.9)、 厳しい基準では VIF=5 (R²_j=0.8) を採用する。

🔬 数式を言葉で読み解く

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

VIF は「係数推定の標準誤差が独立な場合と比べて何倍になるか」も同時に表す。 VIF=10 なら標準誤差は √10 ≒ 3.16 倍に膨らみ、 t 値が小さく出て「有意でない」と誤判断する原因になる。

🧮 実値で計算してみる

SSDSE-B-2026 の「総人口 (A1101)」「年少人口 (A1301)」「高齢人口 (A1303)」「出生数 (A4101)」 の 4 変数で VIF を手計算する。 VIF_総人口 を計算するため、 「総人口 = β0 + β1*年少人口 + β2*高齢人口 + β3*出生数」 の補助回帰を行う。

Step操作数値結果
1SSDSE-B-2026 から 4 列抽出(2023 年度)47 都道府県 × 4 列
2補助回帰 1: 総人口 ~ 年少+高齢+出生R²_1 ≒ 0.997
3VIF_総人口 = 1 / (1 - 0.997)≒ 315
4補助回帰 2: 年少人口 ~ 総人口+高齢+出生R²_2 ≒ 0.998
5VIF_年少人口 = 1 / (1 - 0.998)≒ 507
6判定いずれも VIF>10、 多重共線性が極めて強い → 1 変数除去

4 変数とも県の人口規模と連動するため、 VIF が爆発的に大きくなる。 実務では「総人口だけ残す」「比率に変換する (高齢化率=高齢人口/総人口)」などの対処が必要。

🐍 Python 実装

🎯 このコードでやること: SSDSE-B-2026(2023 年度)の 4 つの人口系変数 (総人口・年少人口・高齢人口・出生数) に対し、 statsmodels の variance_inflation_factor で VIF を計算し、 多重共線性を診断する。

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import pandas as pd
import numpy as np
from statsmodels.stats.outliers_influence import variance_inflation_factor
from statsmodels.tools.tools import add_constant

df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]                # 2023 年度のみ

cols = ['A1101', 'A1301', 'A1303', 'A4101']        # 総人口/年少人口/高齢人口/出生数
X = add_constant(df[cols].astype(float))           # 切片を加えたデザイン行列
vif = [variance_inflation_factor(X.values, i) for i in range(X.shape[1])]
for name, v in zip(X.columns, vif):
    print(f'{name}: VIF={v:.1f}')

📤 実行結果:

const: VIF=3.7 A1101: VIF=314.7 A1301: VIF=507.3 A1303: VIF=116.4 A4101: VIF=478.5

💬 結果の読み方: const 以外の全変数で VIF が 100 を超え、 極めて深刻な多重共線性。 4 変数すべてが「県の人口規模」と連動しているため。 対処として、 (1) 総人口だけ残す、 (2) 比率化 (高齢化率=A1303/A1101) する、 (3) 主成分分析で次元圧縮、 のいずれかを選ぶ。 A1101 の VIF=314.7 は手計算 (Step 3 の VIF≒315) と一致する。

⚠ 落とし穴

VIF を実務で使う際の典型的な落とし穴を列挙する。

🗺 概念マップ

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

VIF (分散拡大係数) 前提: 重回帰 並列: 条件数 κ 発展: リッジ/Lasso 応用: 係数解釈 対比: 相関行列 統合: PCA

🔗 隣接手法への橋渡し

VIF は多重共線性診断の中核指標であり、 前後の手法と以下のように接続する。

隣接手法関係接続のポイント
重回帰分析上位 / 適用先VIF は重回帰の係数解釈の妥当性を診断する補助指標
相関行列並列 / 下位2 変数間相関だけでは検出できない多重共線性を VIF で補完
条件数 (κ)並列 / 代替全体的な共線性指標。 κ>30 で問題、 κ>100 で深刻
標準化 / 中心化前段 (前処理)2 次項・交互作用項の VIF 膨張を中心化で抑制
リッジ回帰 / Lasso後段 (対処)VIF が高いとき正則化で係数を安定化、 Lasso なら変数除去も自動化
主成分分析 (PCA)後段 (次元圧縮)VIF が極端に高い (>100) 場合、 PCA で直交化して回帰

典型フロー: 重回帰実行 → VIF 計算 → 10 超の変数あり → 比率化 or リッジ or 変数除去 → 再フィット。

🌳 手法選択フロー

VIF の値に応じた対処法の選択フロー。 まず VIF を全変数で計算し、 最大値に応じて分岐する。

VIF 値別の対処フロー

VIF 最大値判定推奨対処
1 〜 5問題なし通常の OLS をそのまま使用
5 〜 10注意係数解釈に注意、 標準誤差を確認、 信頼区間を広めに見積もる
10 〜 30問題あり変数除去 (高 VIF 変数の一つを削除) または比率化
30 〜 100深刻リッジ回帰、 Lasso、 Elastic Net で正則化
100 超致命的PCA で直交化、 または変数設計を根本見直し (SSDSE-B-2026 の規模変数群がここに該当)
∞ (完全共線)推定不可能線形従属な変数を必ず除去 (ダミー変数のトラップ等を確認)

対処後の検証ステップ

  1. VIF 再計算: 対処後に全 VIF が 10 未満に収まっているか確認
  2. 係数の符号一致: 対処前後で符号や大小関係が大きく変わらないかチェック
  3. 予測性能の維持: 変数除去後も R² や RMSE が許容範囲か CV で評価
  4. 解釈の明確化: 残した変数の係数が分野知識と整合するか確認
  5. 条件数との照合: VIF だけでなく κ (条件数) も併用、 両方で問題なしを確認

🔬 補強:VIF の数式的深掘り — 固有値と条件数

VIF は多重共線性の代表指標ですが、 説明変数行列 X の 固有値条件数 に翻訳すると、 なぜ大きい VIF が「数値的不安定」を生むのかが透けて見えます。 SSDSE-B-2026 を題材に、 設計行列の構造から VIF へ降りる道筋を辿ります。

📐 設計行列と分散共分散

標準化された説明変数行列を Z(n×p)とすると、 OLS 推定量の分散は次の形を取ります。

Var(β̂) = σ² (ZᵀZ)⁻¹

(ZᵀZ) を固有値分解すると ZᵀZ = U Λ Uᵀ(Λ は固有値の対角行列)。 VIF が大きくなる方向 = (ZᵀZ)⁻¹ の固有値が小さい方向 = 共線性の「同じ向き」の固有ベクトル。 つまり VIF=10 以上の変数は、 設計行列のある方向で情報がほぼゼロになっていることを意味します。

🧮 SSDSE-B-2026 で固有値を見る

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import pandas as pd, numpy as np
df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])
df = df[df['SSDSE-B-2026'] == 2023]  # 2023 年度のみ
X = df[['A1101', 'A4101', 'A1301', 'A1303']].astype(float)  # 総人口/出生数/年少/高齢
Z = (X - X.mean()) / X.std()
# 共分散行列の固有値
eig = np.linalg.eigvalsh(Z.T @ Z / len(Z))
cond_number = np.sqrt(eig.max() / eig.min())
print('固有値:', np.round(eig, 4))
print('条件数:', round(cond_number, 1))
# 実測出力(2023): 固有値 [≈0.0009, 0.003, 0.021, 3.89]、 条件数 ≈ 64.3
# → 条件数 > 30 で深刻、 100 超で危機的

📊 VIF と固有値の対応表

条件数最小固有値の挙動推定 VIF レンジ解釈
< 10十分大きい1–3健全
10–30小さくなり始める3–10要注意
30–10010⁻³ オーダー10–50深刻
> 10010⁻⁵ 以下100+推定が崩壊

🐍 主成分回帰で VIF を「畳む」

VIF が大きい変数群を主成分(PC)に縮約すれば、 PC 同士は直交(共線性ゼロ)。 SSDSE-B-2026 の人口変数 4 つを 2 主成分に縮約すれば、 累積寄与率 99% を保ちつつ VIF=1 を実現できます。

1
2
3
4
5
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
Z_pc = pca.fit_transform(Z)
print('寄与率:', pca.explained_variance_ratio_.round(3))
# 主成分回帰モデルで Var(β̂) は安定化

💡 実務メモ:VIF が示すのは「数値的不安定さ」であって「予測性能の悪さ」ではない。 予測だけが目的なら Ridge 回帰のような正則化、 解釈が目的なら主成分や変数削減、 と目的別に対処法を選びましょう。

📚 補強2:VIF の閾値「10」の根拠と多変量診断のベストプラクティス

「VIF > 10 は深刻」「VIF > 5 は注意」という閾値はどこから来たのでしょうか。 実は厳密な統計的根拠というよりは、 経験的な慣習に近いものです。 SSDSE-B-2026 で実際に検証してみると、 閾値だけに頼ることの危険性が見えてきます。

📊 閾値の歴史的経緯

閾値 出典 含意
VIF > 10Marquardt (1970)R²ⱼ > 0.9 に対応
VIF > 5慣習的R²ⱼ > 0.8 に対応
VIF > 4O'Brien (2007)R²ⱼ > 0.75 に対応
VIF > 1完全独立しか許さない実務的に不可能

O'Brien (2007) は A Caution Regarding Rules of Thumb for Variance Inflation Factors で、 VIF=10 という閾値が「絶対的な意味を持たない」と警鐘を鳴らしました。 サンプルサイズ・モデルのフィット・他の説明変数の数を考慮した相対的判断が必要です。

🔬 サンプルサイズで閾値の意味は変わる

同じ VIF=10 でも、 n=30 と n=3000 では信頼区間の幅がまったく違います。 大標本では VIF=20 でも実用的に問題ないケースがあり、 小標本では VIF=5 でも係数推定が破綻するケースがあります。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
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]  # 2023 年度のみ (47 都道府県)
n = len(df)

# 信頼区間の幅は std_err × t_critical に比例
# std_err は √VIF に比例
X = sm.add_constant(df[['A4101', 'A1301', 'A1303']].astype(float))
model = sm.OLS(df['A1101'].astype(float), X).fit()
ci = model.conf_int()
ci_width = ci[1] - ci[0]
print(f'n = {n}')
for var in ['A4101', 'A1301', 'A1303']:
    print(f'  {var}: 95% CI 幅 = {ci_width[var]:.2f}')
# n=47 では幅が広く、 同じ VIF でも n=470 なら 1/√10 ≈ 0.32 倍

🌐 「予測 vs 推論」目的別の VIF 対応表

目的 VIF 許容範囲 理由
予測精度VIF=∞ でも可予測の MSE は VIF に影響されない
変数選択VIF < 10 推奨どの変数が効くかの判定が不安定
仮説検定VIF < 5 推奨標準誤差が膨らみ第二種の過誤増
構造方程式VIF < 2.5構造パラメータの一意性

🐍 中心化(centering)で VIF を下げる

多項式項や交互作用項で VIF が爆発する場合、 元の変数を 平均で引いてから(中心化)二乗・乗算すると、 VIF を劇的に下げられます。 これは数学的に等価な変換ですが、 数値計算上は別物として振る舞います。

 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]  # 2023 年度のみ

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

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

# 中心化あり
x_c = x - x.mean()
X2 = pd.DataFrame({'x_c': x_c, 'x_c2': x_c ** 2})
print('中心化あり:')
for i, c in enumerate(X2.columns):
    print(f'  {c}: VIF = {variance_inflation_factor(X2.values, i):.1f}')
# 実測(2023): 中心化なし VIF≈5.4、 中心化あり VIF≈2.6(総人口は右に歪むため低減は緩やか)
📝 補足(より正確な分析): 中心化が VIF を「劇的に」下げるのは、 元変数の分布が概ね対称なときです。 SSDSE-B-2026 (2023) の総人口 (A1101) は東京都が突出する強い右偏りを持つため、 x と x² を使った実測では中心化なし VIF≈5.4 → 中心化あり VIF≈2.6 と、 低減はするものの緩やかです(≈1 までは落ちません)。 中心化が「x と x² の構造的共線性を機械的に消す」メカニズム自体は正しく、 対称に近い変数ほど効果が大きくなります。

💡 実務 4 か条:(1) VIF 単独で判断せず、 標本サイズと目的を併せて評価、 (2) 多項式項は必ず中心化、 (3) ダミー変数は基準カテゴリを意識した解釈、 (4) 高 VIF でも予測目的なら Ridge で正則化、 が王道です。

🎮 触って理解する

2つの説明変数 X1・X2 の相関 r をスライダー(またはグラフを指でドラッグ)で動かすと、 散布図と VIF がリアルタイムに変わります。 説明変数どうしが似てくるほど VIF がどう跳ね上がるかを体感してください。

2変数モデルでは「X1 を X2 で回帰した $R^2$」は相関の2乗に一致します($R^2 = r^2$)。 したがって $\text{VIF} = 1/(1-R^2) = 1/(1-r^2)$。 計算は正確です。

散布図:X1(横)× X2(縦)
VIF 曲線:r を動かすと●が移動(クリック/ドラッグ可)
相関 r
0.90
R² = r²
0.810
VIF = 1/(1−R²)
5.26
問題なし(VIF < 5)

🧠 直感 — なぜ「分散が拡大」するのか

VIF は文字どおり「係数推定量の分散を何倍に膨らませるか」を表します。 ある説明変数が他の説明変数でほぼ説明できてしまうと($R^2$ が1に近い)、 回帰はその変数固有の効果を「見分けられなく」なり、 係数の推定が不安定になります。 標準誤差は $\sqrt{\text{VIF}}$ に比例して伸びるため、 VIF=10 なら標準誤差は約 $\sqrt{10}\approx3.16$ 倍。 上のスライダーで r を 0.9 → 0.95 に上げると、 VIF が約 5.3 → 約 10.3 へ跳ね上がり、 VIF>10 の警告境界を越える様子が見えます。

⚠️ よくある落とし穴

🚀 発展 — 3変数以上・対処法

説明変数が3つ以上になると $R^2 = r^2$ の単純式は使えず、 各変数を「残りすべて」で回帰した $R^2_j$ が必要です(実データでの計算例はこのページ上部の Python コードを参照)。 高 VIF への対処は、 (1) 片方の変数を落とす、 (2) 比率化(例:高齢化率)、 (3) 主成分に置き換える、 (4) リッジ回帰で正則化、 が定番です。

🔗 関連ページ

🧭 補強3:別角度からの直感・落とし穴・発展 — 許容度(1/VIF)・標準化不変性・GVIF

ここまでの節(固有値・条件数は「VIF の数式的深掘り」節、 閾値の根拠は「閾値『10』の根拠」節、 変数除去の実演は「実値計算例」節)で扱わなかった別の切り口だけを、 SSDSE-B-2026(2023年・47県)の実測値で補います。

🧠 直感(別角度)— VIF は「2変数の相関」ではなく「残り全部で回帰した R²ⱼ」

よくある誤解は「VIF は 2 変数の相関係数を見ている」というもの。 正しくは、 変数 $x_j$ を残りの説明変数すべてで重回帰したときの決定係数 $R_j^2$ を使い、 $\text{VIF}_j = 1/(1-R_j^2)$ で定義します。 だからペアごとの相関がどれも中程度でも、 3 変数以上が線形に絡めば VIF は跳ね上がります(その「同じ向き」を固有値・条件数で見るのが別節の話)。

許容度(tolerance)= 1/VIF は「その変数の分散のうち、 他変数で説明しきれず残った割合」を表す裏返しの指標です。 tolerance が 0 に近いほど、 その変数は他変数のほぼ線形結合=固有情報がないことを意味します。 SSDSE-B-2026 の人口系 4 変数(A1101 総人口 / A1301 年少人口 / A1303 高齢人口 / A4101 出生数)の実測:

変数 VIF(実測) tolerance = 1/VIF 残った固有情報
A1101 総人口314.740.0032約 0.3%
A1301 年少人口507.280.0020約 0.2%
A1303 高齢人口116.410.0086約 0.9%
A4101 出生数478.470.0021約 0.2%

tolerance が軒並み 1% 未満 = どの人口系変数も「他の 3 つでほぼ再現できる」状態です。

⚠️ よくある落とし穴(別角度)

🚀 発展(別角度)— GVIF を SSDSE-B-2026 で実測

47 県を全国 7 地域(北海道東北 / 関東 / 中部 / 近畿 / 中国 / 四国 / 九州)に区分した地域因子(ダミー 6 本, df=6)を、 標準化した A1101・A4101 と同じモデルに入れて GVIF を計算した実測:

指標 実測値 √ に直した比較値
地域因子(df=6)GVIF2.79GVIF1/(2·6) = 1.089
A1101 総人口VIF211.43√VIF = 14.5
A4101 出生数VIF202.06√VIF = 14.2

読み方:地域因子の $\text{GVIF}^{1/(2df)}=1.089$ は $\sqrt{\text{VIF}}\approx1$ 相当でほぼ無害。 一方、 総人口と出生数は互いに強相関のため $\sqrt{\text{VIF}}\approx14$ と深刻です。 因子全体は GVIF、 単一の連続変数は通常 VIF と使い分けるのが要点。 高 VIF への対処は「除去 / 比率化 / 正則化 / 主成分」(各手法は関連ページへ)。

※ 地域区分は都道府県コードから機械的に 7 区分したもの。 GVIF・VIF・tolerance の数値はすべて SSDSE-B-2026(cp932, skiprows=[1], 2023年47県)からの実測です。

🔗 関連ページ(別角度)