🍰 まずはやさしく
線形回帰(直線の式)を広げたものです。
いろいろな種類のデータを分析するために使います。
部活の出席か欠席かを分析する時に便利です。
このモデルで扱う用語や仕組みを読みます。
本ページでは、 ロジスティック回帰と一般化線形モデル (GLM)を統合的に解説します。 ロジット・オッズ比・ポアソン回帰・順序ロジット・リンク関数を一気通貫で扱います。
GLM は線形回帰の一般化で、 応答変数が二値・カウント・順序など、 正規分布以外でも線形モデルを使えるようにしたものです。 SSDSE-B でも「高齢化率が中央値以上か」など二値化した検証で頻出します。
論文記事から各用語のリンクをクリックすると、 該当箇所が開きます:
🍰 まずはやさしく
データの種類に合わせて使い分ける道具です。
正しく予測や分析をするために使います。
買い物の「買うか買わないか」を予測します。
モデルの作り方と使い方のまとめを読みます。
| 章 | 内容 |
|---|---|
| 1. なぜGLM | 線形回帰の拡張 |
| 2. GLMの枠組み | 3つの構成要素 |
| 3. ロジスティック回帰 | 二値分類 |
| 4. オッズと係数解釈 | オッズ比 |
| 5. 最尤推定 | IRLS 法 |
| 6. ポアソン回帰 | カウント応答 |
| 7. 順序・多項ロジット | 順序・多クラス |
| 8. 診断・モデル比較 | 残差・AIC・ROC |
線形回帰 $y = \boldsymbol{\beta}^\top \mathbf{x} + \varepsilon$ は次のような仮定を置く:
しかし現実には二値(買う/買わない)・カウント(事故件数)・順序(5段階評価)といったデータも多い。 これらに OLS を使うと、 確率が 0 未満や 1 超に予測されるなどの問題が起きる。
GLM はリンク関数で線形予測子と平均を結び、 応答分布も指数型族から選べる枠組み。
GLM は次の 3 要素:
この表の設定:SSDSE-B-2026 の最新年度・47 都道府県。目的変数は「高齢化率(65歳以上人口 ÷ 総人口)が中央値以上か」の 2 値、説明変数は「消費支出(L3221)の対数を標準化した値」1 本。リンク関数だけを差し替えて係数を比べています。
係数の大きさはリンクごとに違いますが、予測確率どうしはほぼ完全に一致します(相関 0.996 以上)。つまり「どのリンクを選ぶか」で結論はほとんど変わりません。
| 応答変数 | 分布 | リンク | 逆リンク | モデル名 |
|---|---|---|---|---|
| 連続 | 正規 | 恒等 $\mu$ | $\eta$ | 線形回帰 |
| 二値 | 二項 | ロジット $\log(p/(1-p))$ | シグモイド | ロジスティック |
| 二値 | 二項 | プロビット $\Phi^{-1}$ | $\Phi$ | プロビット |
| カウント | ポアソン | log | $e^\eta$ | ポアソン回帰 |
| 正連続 | ガンマ | 逆数 $1/\mu$ | $1/\eta$ | ガンマ回帰 |
$$f(y; \theta, \phi) = \exp\left(\frac{y\theta - b(\theta)}{\phi} + c(y, \phi)\right)$$
正規・二項・ポアソン・ガンマ・指数分布などはすべて指数型族に属し、 一般的な推定理論で扱える。
二値応答 $y \in \{0, 1\}$ に対し、 確率 $p = P(y=1|\mathbf{x})$ をモデル化:
$$\mathrm{logit}(p) = \log\frac{p}{1-p} = \beta_0 + \beta_1 x_1 + \cdots + \beta_k x_k$$
逆リンク(シグモイド)で確率に戻す:
$$p = \sigma(\boldsymbol{\beta}^\top \mathbf{x}) = \frac{1}{1+\exp(-\boldsymbol{\beta}^\top \mathbf{x})}$$
$\beta_0=-2$、 $\beta_1=0.5$、 $x=5$ のとき:
data/raw/SSDSE-B-2026.csv(cp932・skiprows=[1]・2023 年度)。 実在列 A1101(総人口)・A1303(65 歳以上人口)・A4103(合計特殊出生率)・L3221(消費支出)・B4101(年平均気温)などを使用。1 2 3 4 5 6 7 8 9 10 11 12 13 | import pandas as pd import numpy as np # 数式内の np.log で使う import statsmodels.api as sm import statsmodels.formula.api as smf df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] # 2023 年度に絞る df['高齢化率'] = df['A1303'] / df['A1101'] # 65歳以上 / 総人口 df['高齢化率高'] = (df['高齢化率'] >= df['高齢化率'].median()).astype(int) # statsmodels で詳細な結果(係数のp値・CIなど) model = smf.glm('高齢化率高 ~ A4103 + np.log(L3221) + B4101', data=df, family=sm.families.Binomial()).fit() print(model.summary()) |
data/raw/SSDSE-B-2026.csv(cp932・skiprows=[1]・2023 年度)。 実在列 A1101(総人口)・A1303(65 歳以上人口)・A4103(合計特殊出生率)・L3221(消費支出)・B4101(年平均気温)などを使用。1 2 3 4 5 6 7 8 9 10 | from sklearn.linear_model import LogisticRegression from sklearn.preprocessing import StandardScaler from sklearn.pipeline import Pipeline X = df[['A4103', 'L3221', 'B4101']] y = df['高齢化率高'] pipe = Pipeline([('scale', StandardScaler()), ('lr', LogisticRegression(C=1.0, max_iter=1000))]) pipe.fit(X, y) print('係数:', dict(zip(X.columns, pipe.named_steps['lr'].coef_[0]))) |
$\beta_j$ は「$x_j$ が 1 単位増加すると、 オッズが $e^{\beta_j}$ 倍になる」と読む。
data/raw/SSDSE-B-2026.csv(cp932・skiprows=[1]・2023 年度)。 実在列 A1101(総人口)・A1303(65 歳以上人口)・A4103(合計特殊出生率)・L3221(消費支出)・B4101(年平均気温)などを使用。1 2 3 4 5 6 7 | import numpy as np or_table = np.exp(model.params) or_ci = np.exp(model.conf_int()) print('オッズ比:') print(or_table.round(3)) print('95% CI:') print(or_ci.round(3)) |
対数尤度:
$$\ell(\boldsymbol{\beta}) = \sum_{i=1}^{n} \big[y_i \log p_i + (1-y_i)\log(1-p_i)\big]$$
これを最大化する $\boldsymbol{\beta}$ が最尤推定量。 解析解はなく、 IRLS(反復重み付き最小二乗)や Newton–Raphson で数値解を求める。
$D = -2(\ell_{\text{model}} - \ell_{\text{saturated}})$。 線形回帰の RSS に対応。 小さいほどよく当てはまる。
$AIC = -2\ell + 2k$、 $BIC = -2\ell + k\log n$。 モデル比較に使う。
カウントデータ $y \in \{0, 1, 2, \dots\}$ に対し:
$$\log \mu = \boldsymbol{\beta}^\top \mathbf{x}, \quad y \sim \mathrm{Poisson}(\mu)$$
$\beta_j$ の解釈:$x_j$ が 1 単位増えると、 期待カウントが $e^{\beta_j}$ 倍。
「人口当たりの事故件数」のように露出量を考慮するときは、 オフセット項 $\log(\text{人口})$ を線形予測子に固定で入れる。
data/raw/SSDSE-B-2026.csv(cp932・skiprows=[1]・2023 年度)。 実在列 A1101(総人口)・A1303(65 歳以上人口)・A4103(合計特殊出生率)・L3221(消費支出)・B4101(年平均気温)などを使用。1 2 3 4 5 6 7 8 9 10 11 12 13 | import statsmodels.api as sm import statsmodels.formula.api as smf import numpy as np df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] df['高齢化率'] = df['A1303'] / df['A1101'] df['log_pop'] = np.log(df['A1101']) # 露出量 = 総人口 # 出生数(A4101)を人口あたりのカウントとして回帰 model_pois = smf.glm('A4101 ~ 高齢化率 + np.log(L3221)', data=df, family=sm.families.Poisson(), offset=df['log_pop']).fit() print(model_pois.summary()) |
ポアソンは「分散=平均」を仮定。 実データでは分散 > 平均(過分散)が多い。 そのときは負の二項回帰:
data/raw/SSDSE-B-2026.csv(cp932・skiprows=[1]・2023 年度)。 実在列 A1101(総人口)・A1303(65 歳以上人口)・A4103(合計特殊出生率)・L3221(消費支出)・B4101(年平均気温)などを使用。1 2 3 4 | model_nb = smf.glm('A4101 ~ 高齢化率 + np.log(L3221)', data=df, family=sm.families.NegativeBinomial(), offset=df['log_pop']).fit() print(model_nb.summary()) |
応答が順序尺度(不満〜満足の 5 段階等)のときに使う。 K カテゴリで K-1 個のしきい値 $\alpha_k$ を推定。
$$\log\frac{P(Y \leq k)}{P(Y > k)} = \alpha_k - \boldsymbol{\beta}^\top \mathbf{x}$$
data/raw/SSDSE-B-2026.csv(cp932・skiprows=[1]・2023 年度)。 実在列 A1101(総人口)・A1303(65 歳以上人口)・A4103(合計特殊出生率)・L3221(消費支出)・B4101(年平均気温)などを使用。1 2 3 4 5 6 | from statsmodels.miscmodels.ordinal_model import OrderedModel df['高齢化3群'] = pd.qcut(df['高齢化率'], q=3, labels=[0, 1, 2]) model_ord = OrderedModel(df['高齢化3群'].astype(int), df[['A4103', 'B4101']], distr='logit').fit(method='bfgs') print(model_ord.summary()) |
順序のないカテゴリ K 個の応答(職業・選好等)。 1 カテゴリを基準にし、 他 K-1 個の対基準対数オッズを線形モデル化。
data/raw/SSDSE-B-2026.csv(cp932・skiprows=[1]・2023 年度)。 実在列 A1101(総人口)・A1303(65 歳以上人口)・A4103(合計特殊出生率)・L3221(消費支出)・B4101(年平均気温)などを使用。1 2 3 4 5 6 7 | from sklearn.linear_model import LogisticRegression df['人口規模'] = pd.qcut(df['A1101'], q=3, labels=['小', '中', '大']) # multi_class 引数は sklearn 1.7 で廃止。lbfgs では多項ロジスティックが既定 lr_multi = LogisticRegression(solver='lbfgs', max_iter=1000) lr_multi.fit(df[['A4103', 'B4101']], df['人口規模']) print(lr_multi.classes_) print(lr_multi.coef_.round(3)) |
data/raw/SSDSE-B-2026.csv(cp932・skiprows=[1]・2023 年度)。 実在列 A1101(総人口)・A1303(65 歳以上人口)・A4103(合計特殊出生率)・L3221(消費支出)・B4101(年平均気温)などを使用。1 2 3 4 5 6 7 8 | from statsmodels.stats.outliers_influence import variance_inflation_factor import pandas as pd X_ = df[['A4103', 'L3221', 'B4101']] vif = pd.DataFrame({ 'feature': X_.columns, 'VIF': [variance_inflation_factor(X_.values, i) for i in range(X_.shape[1])] }) print(vif) |
data/raw/SSDSE-B-2026.csv(cp932・skiprows=[1]・2023 年度)。 実在列 A1101(総人口)・A1303(65 歳以上人口)・A4103(合計特殊出生率)・L3221(消費支出)・B4101(年平均気温)などを使用。1 2 3 | from sklearn.metrics import roc_auc_score, roc_curve proba = pipe.predict_proba(X)[:, 1] print('AUC =', roc_auc_score(y, proba)) |
ロジスティック回帰の適合度を確認する標準検定。 期待頻度と観測頻度を 10 グループで χ² 検定。
| 落とし穴 | 対処 |
|---|---|
| 係数を直接「効果量」と読む | 必ず $e^\beta$ をとってオッズ比 / 率比で報告。 |
| 不均衡データに普通に学習 | class_weight='balanced' や閾値調整。 |
| 完全分離(Quasi-Complete Separation) | $\hat{\beta}$ が発散。 正則化(Firth ロジスティックや L2)で対応。 |
| ポアソンで過分散を無視 | 分散/平均を確認、 過分散なら負の二項に切り替え。 |
| オフセット項を忘れる | 「率」をモデル化したいなら必ず log(露出量) をオフセットに。 |
| 順序ロジットの比例オッズ仮定 | Brant検定で確認。 違反なら一般化順序ロジット。 |
| 多項ロジットの IIA 仮定 | 独立な選択肢の仮定。 違反するなら入れ子ロジット等。 |
data/raw/SSDSE-B-2026.csv(cp932・skiprows=[1]・2023 年度)。 実在列 A1101(総人口)・A1303(65 歳以上人口)・A4103(合計特殊出生率)・L3221(消費支出)・B4101(年平均気温)などを使用。1 2 3 4 5 6 7 8 9 10 11 12 13 | import pandas as pd, numpy as np import statsmodels.api as sm import statsmodels.formula.api as smf df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] df['高齢化率'] = df['A1303'] / df['A1101'] df['高齢化率高'] = (df['高齢化率'] >= df['高齢化率'].median()).astype(int) m = smf.glm('高齢化率高 ~ A4103 + np.log(L3221) + B4101', data=df, family=sm.families.Binomial()).fit() print(pd.DataFrame({'OR': np.exp(m.params), 'CI_low': np.exp(m.conf_int()[0]), 'CI_high': np.exp(m.conf_int()[1]), 'p': m.pvalues}).round(3)) |
応答の分散/平均比を確認、 1 を大きく超えれば過分散の疑い。
data/raw/SSDSE-B-2026.csv(cp932・skiprows=[1]・2023 年度)。 実在列 A1101(総人口)・A1303(65 歳以上人口)・A4103(合計特殊出生率)・L3221(消費支出)・B4101(年平均気温)などを使用。1 2 3 4 5 6 7 8 9 10 11 | from sklearn.linear_model import LogisticRegression from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import cross_val_score from sklearn.pipeline import Pipeline from sklearn.preprocessing import StandardScaler X = df[['A4103', 'L3221', 'B4101']] y = df['高齢化率高'] for name, m in [('LR', Pipeline([('s',StandardScaler()),('m',LogisticRegression(max_iter=1000))])), ('RF', RandomForestClassifier(n_estimators=200, random_state=42))]: sc = cross_val_score(m, X, y, cv=5, scoring='roc_auc') print(f'{name}: AUC = {sc.mean():.3f} ± {sc.std():.3f}') |
「ロジスティック回帰の結果、 所得が有意でした (p < 0.05)。」
※ 以下の数値(オッズ比・CI・p 値・AUC)は、 本ページ §3 の実データ推定コード(高齢化率高 ~ A4103 + np.log(L3221) + B4101、 SSDSE-B-2026・cp932・skiprows=[1]・2023 年度 47 県)を実際に実行して得た実測値です。
「高齢化率が中央値以上か(1/0)を二値応答とするロジスティック回帰を実施。 合計特殊出生率 0.1 上昇に対する高齢化率高グループ所属オッズ比は 3.03 (95% CI [1.21, 7.54], p = .018)、 すなわち本データでは出生率が高い県ほど高齢化率高グループに属しやすいことを示した。 年平均気温 1℃ 上昇のオッズ比は 0.36 (95% CI [0.18, 0.69], p = .002) で、 温暖な県ほど高齢化率高グループに属しにくかった。 log(消費支出) は有意でなかった(オッズ比の 95% CI が 1 をまたぐ, p = .090)。 モデル全体の AUC = 0.83 (5-fold CV)、 Hosmer–Lemeshow 検定(10 分位)p = .22 で適合度に大きな問題は認められなかった。」
| モデル | statsmodels | scikit-learn |
|---|---|---|
| ロジスティック | sm.GLM(..., family=Binomial()) | LogisticRegression |
| プロビット | sm.Probit | なし |
| ポアソン | sm.GLM(..., family=Poisson()) | PoissonRegressor |
| 負の二項 | sm.GLM(..., family=NegativeBinomial()) | なし |
| ガンマ | sm.GLM(..., family=Gamma()) | GammaRegressor |
| 順序ロジット | OrderedModel | OrdinalEncoder + LR |
| 多項ロジット | sm.MNLogit | LogisticRegression(multi_class='multinomial') |
| 混合GLM | BinomialBayesMixedGLM | なし |
論文・記事に登場する用語のリンクで該当箇所へジャンプ:
SSDSE-B 2018→2023の人口変化率が負の県(人口減少県)を 1、 そうでない県を 0 として、 家計支出の3項目(食料費・住居費・教育費)でロジスティック回帰します。
data/raw/SSDSE-B-2026.csv(cp932・skiprows=[1]・2023 年度)。 実在列 A1101(総人口)・A1303(65 歳以上人口)・A4103(合計特殊出生率)・L3221(消費支出)・B4101(年平均気温)などを使用。1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import pandas as pd import statsmodels.api as sm df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) p18 = df[df['SSDSE-B-2026']==2018].set_index('Prefecture')['A1101'] p23 = df[df['SSDSE-B-2026']==2023].set_index('Prefecture')['A1101'] y = (p23 < p18).astype(int) # 1=減少、 0=非減少 d23 = df[df['SSDSE-B-2026']==2023].set_index('Prefecture') X = d23[['L322101', 'L322102', 'L322108']] / 10000 X = sm.add_constant(X) # Logistic(=GLM with Binomial) res = sm.GLM(y, X, family=sm.families.Binomial()).fit() print(res.summary()) print("OR:", round(float(res.params['L322101']), 3)) |
たとえば 食料費係数 β = -0.18(OR = exp(-0.18) ≈ 0.84)とすると、 「年間 1 万円食料費が増えると、 人口減少県である確率のオッズは約 16% 減少」と読めます。 解釈時は 確率とオッズとオッズ比を混同しない。
| 指標 | 仮想値 | 解釈 |
|---|---|---|
| 逸脱度 Deviance | 52.3 | 残差平方和の GLM 版(小さいほど良い) |
| AIC | 60.3 | 変数選択に使う |
| 疑似 R²(McFadden) | 0.18 | 0.2-0.4 が「良いフィット」(OLS の R² より基準が低い) |
| AUC-ROC | 0.79 | 分類性能の指標、 0.5=ランダム、 1=完璧 |
OLS の係数は「x が 1 単位増えると y が β 増える」と読めるが、 ロジスティックでは β はリンク関数(logit)越し。 直接の確率変化ではなく 対数オッズの変化を表します。 確率での影響を見るには 限界効果(marginal effect)を計算する必要があり、 これは x の値に依存します。 statsmodels の get_margeff() で平均限界効果が出せる。
「ある変数の値だけで y を完全に分類できてしまう」状態を complete separation という。 このとき MLE が発散して係数が無限大になり、 標準誤差も巨大化。 statsmodels なら warning が出る、 sklearn なら正則化のおかげで気づきにくい。 対策:(1) 該当変数を除く / 合算する、 (2) Firth ロジスティック(バイアス補正)、 (3) ベイズ的事前分布、 (4) ペナルティ付き L2 ロジスティック。 サンプル少 + 二値説明変数で頻発します。
ポアソン分布は「平均 = 分散」を仮定します。 現実のカウントデータは平均 < 分散になりがち(過分散)。 過分散を無視すると標準誤差が過小評価され、 偽陽性が増える。 必ず Pearson カイ二乗 / 自由度 を計算し、 1.5 以上なら負の二項回帰かquasi-Poissonに切り替える。 計数 0 が多いならゼロ過剰モデル(ZIP / ZINB)も検討。
陽性率が 1% 未満のような稀な事象では、 通常のロジスティックは係数を過大評価する(特に切片)。 King & Zeng (2001) の稀事象ロジスティック(rare event logistic)や、 Firth ペナルティ、 weight-adjusted logistic を使う。 機械学習では SMOTE などのオーバーサンプリングと組合せる手もありますが、 推定された確率の校正(calibration)が崩れる点に注意。
logit(p) = β₀ + β₁ x の関係は、 「x の対数オッズへの効果が線形」という強い仮定。 実際は U 字や J 字の場合が多い(例:年齢と疾患リスク)。 対策:(1) x を多項式化 (x², x³)、 (2) スプライン、 (3) GAM(一般化加法モデル)、 (4) ビン化してダミー変数化。 Box-Tidwell 検定で線形性をチェックできます。
説明変数同士が強く相関していると、 個々の係数の解釈が「他の変数を一定として」になり、 単独相関と符号が逆になることがある(Simpson's paradox の係数版)。 VIF(分散拡大係数)を計算して 5-10 を超える変数は要警戒。 対策:(1) 相関の強い変数を1つに絞る、 (2) 主成分回帰、 (3) Ridge / LASSO で正則化、 (4) 因子分析。 因果解釈をする際は特にこの問題が致命的になります。
data/raw/SSDSE-B-2026.csv(cp932・skiprows=[1]・2023 年度)。 実在列 A1101(総人口)・A1303(65 歳以上人口)・A4103(合計特殊出生率)・L3221(消費支出)・B4101(年平均気温)などを使用。1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # ── この抜粋で使うデータを用意します ── import numpy as np import pandas as pd 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 都道府県 X_raw = df[['A1101', 'B4101']].astype(float) _aging = df['A1303'] / df['A1101'] * 100 y = (_aging >= _aging.median()).astype(int).values # 高齢化率が中央値以上か X = sm.add_constant(X_raw) res = sm.GLM(y, X, family=sm.families.Binomial()).fit() print(res.summary(), res.conf_int().apply(np.exp)) |
注意:LogisticRegression はデフォルトで L2 正則化が入っているので、 純粋な MLE 推定をしたい場合は penalty=None を指定。
data/raw/SSDSE-B-2026.csv(cp932・skiprows=[1]・2023 年度)。 実在列 A1101(総人口)・A1303(65 歳以上人口)・A4103(合計特殊出生率)・L3221(消費支出)・B4101(年平均気温)などを使用。1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | # ── この抜粋で使うデータを用意します ── import numpy as np import pandas as pd from sklearn.model_selection import train_test_split df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] # 2023 年の 47 都道府県 X = df[['A1101', 'B4101', 'L3221']].astype(float).values _aging = df['A1303'] / df['A1101'] * 100 y = y_binary = (_aging >= _aging.median()).astype(int).values # 高齢化率が中央値以上か X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.3, random_state=42, stratify=y) from sklearn.linear_model import LogisticRegression from sklearn.metrics import roc_auc_score, classification_report model = LogisticRegression(penalty='l2', C=1.0, max_iter=1000).fit(X, y) p = model.predict_proba(X_test)[:, 1] print(roc_auc_score(y_test, p), classification_report(y_test, model.predict(X_test))) |
data/raw/SSDSE-B-2026.csv(cp932・skiprows=[1]・2023 年度)。 実在列 A1101(総人口)・A1303(65 歳以上人口)・A4103(合計特殊出生率)・L3221(消費支出)・B4101(年平均気温)などを使用。1 2 3 4 5 | # 3クラス以上の多項ロジスティック # multi_class 引数は sklearn 1.7 で廃止(lbfgs では多項が既定) model = LogisticRegression(solver='lbfgs', max_iter=1000).fit(X, y) # 順序ロジスティック from statsmodels.miscmodels.ordinal_model import OrderedModel |
scipy では「ロジスティック分布」のCDFが logit の逆関数(sigmoid)として使えます。 確率の理論計算で便利。
data/raw/SSDSE-B-2026.csv(cp932・skiprows=[1]・2023 年度)。 実在列 A1101(総人口)・A1303(65 歳以上人口)・A4103(合計特殊出生率)・L3221(消費支出)・B4101(年平均気温)などを使用。1 2 3 | from scipy.special import expit, logit print(expit([-2, 0, 2])) # sigmoid = [0.119, 0.5, 0.881] print(logit([0.1, 0.5, 0.9])) # logit 関数 |
🍰 まずはやさしく
確率を計算する魔法のメガネのようなものです。
あることが起きる確率を知るために使います。
テストに合格するかどうかを予想します。
まずはイメージで全体の流れを読みます。
ロジスティック GLM は「0/1 の確率を線形予測子のロジスティック関数で表す一般化線形モデル」。 リンク関数は logit、 分布は Bernoulli。 SSDSE-B-2026 では「人口 100 万人超え=1」のような 2 値を、 A1303(高齢人口)や L3221(消費)で予測するのが演習に適する。
ロジスティック GLM は「回帰」カテゴリの中核概念。 初めて触れる読者は、 まずこの「🎨 直感」セクションだけ通読し、 必要になった時点で「📐 数式」「🐍 Python」「⚠️ 落とし穴」へ戻る読み方が定着しやすいです。
🍰 まずはやさしく
計算ルールを決めた数式のセットです。
正確に分析の結果を出すために使います。
スマホの利用時間と成績の関係を式にします。
記号の意味と計算の手順について読みます。
直感の次は、 厳密な定義を確認します。 数式は言語の一種で、 一度書き慣れれば「言葉より速く伝えられる」便利な道具。 慣れていない方は、 各記号が何を表すかを下の「🔬 数式を言葉で読み解く」で 1 つずつ確認してください。
上の数式を眺めるだけでは身につかないので、 各記号がどんな役割を担っているかを言葉で押さえます。 「数式を音読する習慣」がつくと、 論文や教科書を読むスピードが体感で 2 倍ほど上がります。
数式だけでは「実感」が湧きにくいので、 実データ data/raw/SSDSE-B-2026.csv(47 都道府県 × 12 年)で 1 度手計算してみると理解が定着します。
SSDSE-B-2026 (2023) で y = (A1101 > 1,000,000) の 0/1(37 県が 1)、 説明変数を log(L3221) として GLM(Binomial, logit) を当てると、 切片≈-91、 傾き≈7.3 程度になる(実行で確認)。 L3221 が 28 万→32 万に上がると、 県人口 100 万超え確率が約 0.74 → 0.88 へ上昇する。
| 都道府県 | A1101 総人口 | A1303 65 歳以上 | L3221 消費支出 |
|---|---|---|---|
| 東京都 | 14,086,000 | 3,205,000 | 341,320 |
| 神奈川県 | 9,229,000 | 2,390,000 | 306,565 |
| 大阪府 | 8,763,000 | 2,424,000 | 271,246 |
| 愛知県 | 7,477,000 | 1,923,000 | 300,221 |
| 埼玉県 | 7,331,000 | 2,012,000 | 344,092 |
| 千葉県 | 6,257,000 | 1,756,000 | 306,943 |
上記は SSDSE-B-2026 (2023) からの抜粋。 手計算で確認した値が、 後述の Python 実装で得る値と一致することを確認すると、 「数式とコードの対応関係」がクリアに見えるようになります。
公的統計(SSDSE-B-2026)を題材に、 最小限の Python コードで ロジスティック GLM を動作させます。 まずはこのまま実行してみてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # ロジスティック GLM を 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()) import statsmodels.api as sm import numpy as np y = (df['A1101'] > 1_000_000).astype(int) X = np.log(df['L3221']) X = sm.add_constant(X) model = sm.GLM(y, X, family=sm.families.Binomial()).fit() print(model.summary()) print('オッズ比:', np.exp(model.params[1])) |
▶ 実行 を押せばこのページの中でそのまま動きます(ライブラリもデータも同梱済みで、 準備は要りません)。 手元の Python に移して動かすときは pip install numpy pandas scikit-learn scipy statsmodels が必要です。 読んでいるデータは data/raw/SSDSE-B-2026.csv。 日本語を含むので encoding='cp932' の指定を落とさないでください。
ロジスティック GLM を使うときに初学者が踏みやすい失敗パターン。 1 度経験してしまえば次から避けられますが、 先に知っておくに越したことはありません。
ロジスティック回帰・一般化線形モデル (GLM) の核心は、 ① 線形予測子 η = β₀ + β₁x₁ + … を「リンク関数の逆関数 (例: シグモイド)」で確率に変換する点、 ② 推定は最尤法 (反復重み付け最小二乗 IRLS) で行う点、 ③ 残差・分布族・リンク関数の組合せで二値・多値・カウントなど多様な応答に拡張できる点、 にある。 ここでは SSDSE-B-2026 を題材に「ロジスティック関数の形」「ROC 曲線」「正則化と汎化のトレードオフ」の 3 図を再掲し、 直感的に押さえ直す。



scikit-learn 実装でも penalty パラメータで L1/L2/ElasticNet を切り替えられる。💬 3 枚を通して見ると、 「線形予測子 → リンク関数 → 確率 → 閾値で 0/1 分類 → 評価は ROC/AUC → 過学習対策は L1/L2 正則化」という GLM の全体パイプラインが俯瞰できる。 古典的な OLS との大きな違いは、 ① 残差正規性を仮定しない、 ② 最尤推定で係数を求める、 ③ 応答変数の分布に合わせて分布族 (binomial / poisson / gamma 等) を選べる点であり、 これがロジスティック回帰を「分類」だけでなく「広範な確率モデリングのフレームワーク」に押し上げている。
| 応答変数の型 | 分布族 (family) | 標準リンク | 使い所 |
|---|---|---|---|
| 二値 (0/1) | Binomial | logit | 合否、 購入有無、 病気の有無 |
| 多項 (k クラス) | Multinomial | multinomial logit | 3 種以上のカテゴリ分類 |
| カウント (≥0) | Poisson | log | 人口あたり事故件数、 アクセス数 |
| 過分散カウント | Negative Binomial | log | 分散 > 平均 のカウント |
| 連続 (正の値) | Gamma | inverse / log | 保険金支払額、 故障までの時間 |
| 連続 (実数) | Gaussian | identity | 通常の線形回帰 (OLS) と等価 |
この表のポイントは、 「応答変数の型を見れば、 どの分布族とリンク関数を選ぶべきかが自動的に決まる」 という GLM の設計思想である。 OLS は Gaussian + identity link を選んだ特殊例にすぎず、 GLM はその発想を分布族レベルで一般化したものと捉えると整理が早い。
ロジスティック回帰の係数は OLS と異なり「対数オッズ」 のスケールで出力されるため、 解釈に慣れが必要である。 ここでは実務でよく出る 5 つのパターンに分けて、 数値例とともに整理する。 SSDSE-B-2026 を題材に「都道府県の高齢化率が 1 ポイント上がると、 ある政策の採用オッズが何倍になるか」 のような問いを想定して読むとよい。
どのパターンでも共通する注意点は、 「係数自体は対数オッズ」 「exp(係数) で初めてオッズ比」 「確率に変換するにはベースラインが必要」 という三段階の翻訳が必要なこと。 ここを混同するとプレゼン資料で「効果が 1.65 倍」 と書いてしまい (オッズ倍率なのに確率倍率と誤解させる)、 後で炎上することがよくある。 GLM の解釈は、 数式の理解と同じくらい「言葉での正確さ」 が重要である。
ロジスティックGLMでは、 係数をそのまま確率差として読まず、 オッズ比や予測確率へ変換して説明します。 分類閾値、校正、クラス不均衡、説明変数のスケールも合わせて確認します。
合成データで p=0.7 を logit に変換、 逆変換も計算する。
1 2 3 4 5 | import numpy as np ps = np.array([0.5, 0.7, 0.9]) logits = np.log(ps/(1-ps)) print(f"logit: {logits.round(3)}") print(f"逆: {(1/(1+np.exp(-logits))).round(3)}") |
💬 手計算 (Step 1,2) と Python 出力が完全一致。
ロジスティック GLM を実際の課題に当てはめるとき、 用語固有の判断軸に沿って次の 3 段階で適切な選択を行う。
このフローは GLM (一般化線形モデル) における分布族選択軸。 リンク関数 (logit/log/identity) と分布族 (Binomial/Poisson/Gaussian/Gamma) のペアで目的変数の性質に合わせた回帰モデルが構成される。
ロジスティック GLM は二項分布 + logit リンクの代表 GLM であり、 前段の説明変数前処理と後段のオッズ比解釈・ROC 評価を統合して効果が現れる。
上流のリンク関数選択 (logit vs probit) と分布族 (Binomial) の指定で GLM の枠組みが決まり、 並列の Poisson 回帰/Gamma 回帰と比較して目的変数の分布に応じた切替えを判断し、 下流の擬似 R²/Deviance で当てはまりを評価する流れで一般化線形モデルの体系的活用が完結する。
ロジスティック GLM を中心に、 GLM 全般 (上位枠組み)、 ポアソン・ガンマ・プロビット (並列分布族)、 オッズ比解釈・キャリブレーション (後段) を並べた一般化線形モデルマップ。
ロジスティック GLM を中心に、 (a) 上位枠組み = 一般化線形モデル GLM (指数型分布族 + リンク関数)、 (b) 並列手法 = ポアソン回帰・ガンマ回帰・多項ロジット・プロビット、 (c) 派生・拡張 = 正則化版 (L1/L2)・GLMM (混合効果)・ベイジアン・Firth 補正、 (d) 前段 = 標準化・ダミー変数化・多重共線性確認、 (e) 後段 = オッズ比解釈・Hosmer-Lemeshow 適合度・ROC/AUC・キャリブレーション、 (f) 応用 = 疾患リスク予測・与信判定・離反予測 を放射状に配置できる。
これらの周辺概念は「logit リンク関数」を共通の軸として繋がっており、 logistic GLM を起点に他の GLM 派生に視野を広げると、 二値以外の目的変数 (カウント・連続正値・順序) も同じ設計思想で扱える。
「ロジスティック GLM」は2 値応答 + logit リンク + 二項分布で構成される GLM の代表格。 本ページの中核キーワードを以下に整理する。
これらのキーワードは「logistic glm の理解 → 適用 → 検証」のプロセスを構成する。 各章で詳しく解説する。
ロジスティック GLM を 30 秒で把握する重要ポイント:
本ページでは「ロジスティック回帰と一般化線形モデル (logistic GLM)」を扱う。 ロジスティック回帰は GLM ファミリーの「二項分布 + logit リンク」の特例であり、 GLM 全体の枠組み (指数型分布族 + リンク関数) を理解することで、 ポアソン回帰やガンマ回帰など他の派生にも応用が効く。
SSDSE-B-2026 (47 都道府県 × 複数年) を用いて「高齢化率の中央値超え」「人口 100 万人以上」など二値目的変数を作り、 経済指標を説明変数としてロジスティック GLM を当てる流れを示す。 statsmodels.GLM と sklearn.LogisticRegression の使い分けも併せて解説する。
ロジスティック GLM は「説明変数 X の線形和を logit 関数で確率 p に変換するモデル」だ。 直感的には「合格しそう / 不合格 を 0-1 の確率で表現したいが、 線形回帰だと負数や 1 超を吐く」問題を、 logit (p) = log(p/(1-p)) の変換で解決している。 オッズ (合格 / 不合格の比) の対数が線形和で表せる、 と解釈すると応用しやすい。
本ページでは入力 (X = 説明変数行列) → 線形予測子 (Xβ) → logit リンク関数 → 確率 p → 二項尤度の最大化 → 係数 β、 という 6 段階で処理を追う。 各段で線形回帰との違い (リンク関数の有無、 尤度の形) が見える。
具体例として SSDSE-B-2026 の都道府県データから「高齢化率が中央値以上か」のような二値変数を作り、 説明変数 (合計特殊出生率・消費支出など) から確率を予測するパイプラインを次節以降で示す。
ロジスティック GLM の定義を「線形予測子 → リンク関数 → 確率」の 3 段で示す。 数式の各記号の意味は次節で言葉に翻訳する。
$$ \eta_i = \beta_0 + \beta_1 x_{i1} + \cdots + \beta_p x_{ip} $$
$$ \mathrm{logit}(p_i) = \log\frac{p_i}{1 - p_i} = \eta_i \quad\Leftrightarrow\quad p_i = \frac{1}{1 + e^{-\eta_i}} $$
$$ y_i \sim \mathrm{Bernoulli}(p_i),\quad L(\boldsymbol{\beta}) = \prod_i p_i^{y_i} (1 - p_i)^{1 - y_i} $$
ここで $\eta_i$ は線形予測子、 $p_i$ は予測確率、 $\beta$ は最尤推定される係数、 $y_i \in \{0, 1\}$ は二値目的変数。 推定は対数尤度 $\log L(\beta)$ を最大化する $\beta$ を IRLS (反復重み付き最小二乗) で求める。
ロジスティック GLM の中心式 $\mathrm{logit}(p_i) = \log\dfrac{p_i}{1-p_i} = \beta_0 + \beta_1 x_{i1} + \cdots + \beta_p x_{ip}$ の記号を翻訳する。
「線形予測子 $\eta$ を logit 逆関数 ($\sigma$ シグモイド) で確率に圧縮 → 二項尤度で最尤推定」が GLM 全体の流れ。 係数解釈はリンク関数の逆 (オッズ比) で報告する点が線形回帰との大きな違い。
logistic glm を SSDSE-B-2026 の実データで具体的に計算する手順を示す。 数式 → 値代入 → 手計算 → Python 実装 の流れで、 結果が一致することを確認する。
使用データ: SSDSE-B-2026 の 47 都道府県 × 主要列。 まず 5-10 都道府県の小さな部分集合で手計算し、 全件は Python で実行する。
| Step | 操作 | 実際の値 |
|---|---|---|
| 1 | 目的変数を 0/1 にする | 高齢化率 33% 以上=1(19 県)/未満=0(28 県) |
| 2 | 説明変数を用意する | 総人口の常用対数 $\log_{10}(\text{総人口})$ |
| 3 | 係数を推定する | $b_0 = 27.0426$、 $b_1 = -4.4256$ |
| 4 | 線形予測子 $z$ を計算 | 人口 100 万人 → $\log_{10} = 6.0000$、 $z = 27.0426 - 4.4256 \times 6 = 0.4891$ |
| 5 | ロジスティック関数で確率に | $p = 1/(1+e^{-0.4891}) = 0.6199$ |
| 6 | オッズ比を読む | $e^{-4.4256} = 0.01197$ — 人口が 10 倍になるとオッズは約 1/84 倍 |
📥 入力:data/raw/SSDSE-B-2026.csv の 2023 年度 47 都道府県。 このコードでやること:ニュートン法で係数を解き、 Step 4〜6 の手計算と同じ値が出るか確かめる。
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 32 33 | 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) pop = pd.to_numeric(d['総人口'], errors='coerce') old = pd.to_numeric(d['65歳以上人口'], errors='coerce') rate = old / pop * 100 y = (rate >= 33).astype(int) # 高齢化率 33% 以上なら 1 x = np.log10(pop) # 説明変数:総人口の常用対数 # ニュートン法でロジスティック回帰を解く(切片 + 傾き) Xm = np.column_stack([np.ones(len(x)), x.values]) beta = np.zeros(2) for _ in range(50): p = 1 / (1 + np.exp(-Xm @ beta)) W = p * (1 - p) grad = Xm.T @ (y.values - p) H = -(Xm * W[:, None]).T @ Xm beta -= np.linalg.solve(H, grad) print(f'切片 b0 = {beta[0]:.4f}, 傾き b1 = {beta[1]:.4f}') print(f'オッズ比 (log10(人口) が 1 増える = 人口 10 倍) = {np.exp(beta[1]):.5f}') # 人口 100 万人の県での予測確率を手計算と同じ手順で x0 = np.log10(1_000_000) z = beta[0] + beta[1] * x0 print(f'\n人口 100 万人 → log10 = {x0:.4f}') print(f' z = {beta[0]:.4f} + {beta[1]:.4f} x {x0:.4f} = {z:.4f}') print(f' p = 1/(1+exp(-z)) = {1/(1+np.exp(-z)):.4f}') |
📤 実行すると次の出力が得られる:
💬 人口 100 万人の県が「高齢化率 33% 以上」である確率は 0.62。 傾きが負なので、 人口が大きい県ほど高齢化率が低いという関係を捉えている。 オッズ比 0.012 は「人口 10 倍でオッズが 1/84」という強い効果に見えるが、 47 件のうち片方のクラスが 19 件しかないので、 係数の信頼区間は広い点に注意。
logistic glm を Python で実装する代表的なコードを示す。 標準ライブラリ (numpy / pandas / scipy / sklearn / statsmodels) を使い、 SSDSE-B-2026 を読み込んで実行する流れを再現できる。
🎯 このコードでやること: logistic glm を計算するための最小限のコード。 入力データ・処理・出力・結果の読み方を明示する。
📥 入力データ: SSDSE-B-2026 (47 都道府県 × 100 超列) の CSV。
1 2 3 4 | import pandas as pd df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) # logistic glm を計算 print(df.head()) |
📤 実行結果: 出力された数値を読み、 他手法との比較や有意性検証を行う。
💬 結果の読み方: logistic glm の出力は単なる数値ではなく、 データの構造や規則性を要約したもの。 適切な解釈と他指標との併用が重要。
ロジスティック GLM を実務で使う際に頻発する誤用・落とし穴を列挙する。 多くは「前提の確認不足」「結果の過信」「他手法との比較不足」が原因で、 事前にチェックリスト化することで回避できる。
ロジスティック GLM を中心に、 上位の GLM 枠組み・並列の GLM 派生 (ポアソン / プロビット / 多項ロジット)・前後段の分析パイプラインを放射状に配置した。
「logistic glm」を中心に、 隣接する手法・概念との関係を以下に整理する。 単独の手法理解にとどまらず、 分析パイプライン全体での位置付けを把握することで、 適切な前段・後段・代替手法を選べる。
| 隣接手法 | 関係 | 接続のポイント |
|---|---|---|
| 一般化線形モデル (GLM) | 上位 / 一般化 | 分布族 (Binomial) と リンク (logit) を指定すれば GLM の特殊例として導出可能。 Poisson / Gamma 等への切替えも同枠組み |
| 多項ロジスティック / 順序ロジット | 下位 / 特殊化 | 3 値以上のカテゴリ目的変数に拡張。 softmax リンクで多項分布、 cumulative logit で順序応答 |
| 線形判別分析 (LDA) / probit GLM | 並列 / 対比 | LDA は等共分散正規仮定で同じ線形決定境界を導く。 probit はリンクを正規 CDF に変えただけ |
| 特徴量設計 / 標準化 / カテゴリ符号化 | 前段 (前処理) | 交互作用項・多項式項の導入、 ダミー変数化で β の解釈可能性とフィットを両立 |
| キャリブレーション / 閾値選択 | 後段 (後処理) | Platt scaling や Isotonic Regression で確率の校正、 ROC で運用閾値を決定 |
| AUC / Log Loss / Brier / pseudo-R² / Deviance | 評価 / 比較 | 判別能力 (AUC)、 確率予測の精度 (Log Loss / Brier)、 当てはまり (擬似 R² / Deviance) を併用 |
「logistic glm」を含む手法選択は、 データの性質・分析目的・運用制約の 3 軸で決まる。 以下に典型シナリオと対応する手法の組合せを示す。
| シナリオ | 重視する観点 | 候補手法 |
|---|---|---|
| 大規模 (n が多い、 高次元) | 計算効率 / スパース対応 | sklearn LogisticRegression (saga/liblinear), L1 で変数選択 |
| 外れ値が多い / 分離問題 | 完全分離での発散回避 | Firth's penalized logistic, 弱情報事前分布のベイズ GLM |
| 解釈性 (β の検定・オッズ比) 重視 | 古典統計の推論 | statsmodels.GLM(family=Binomial()), Wald/LR 検定で係数の有意性 |
| 予測精度最優先 | 非線形性 / 交互作用 | GBDT (LightGBM/XGBoost), ロジスティック GLM を比較ベースラインに据える |
| データが少ない (n < 数百) | 過学習防止 | L2 正則化 (Ridge logistic), ベイズ GLM, 単純な ロジスティック GLM + 少数特徴量 |
| 過分散・クラスタリング | 分散補正 | 準二項 GLM (quasi-binomial), 一般化線形混合モデル (GLMM) |
この ロジスティック回帰・GLM ページで出てくる主要キーワードを一覧します。チップをクリックすると該当箇所へジャンプできます。
あなたは、回帰モデル の入口で「ロジスティック回帰・GLM(Logistic Regression & GLM)」という用語に出会ったところです。 この用語は 2 値(0/1)の結果や、カウント・比率を、線形予測子 + リンク関数で扱う一般化線形モデル。
本ページでは、まず数式や形式的定義よりも、実データ(SSDSE-B-2026, 47 都道府県)で具体的な値を見ます。 そのあと、数式 → 計算 → Python 実装 → 落とし穴 → 関連用語、という順で「使える知識」に組み立てていきます。
ロジスティック回帰・GLM の本質は、ひとことで言うと「2 値(0/1)の結果や、カウント・比率を、線形予測子 + リンク関数で扱う一般化線形モデル。」です。 数式に踏み込む前に、まずイメージで掴みましょう。
ヒント:直感が掴めたら、次の「数式または定義」セクションで形式化を確認してください。 形式化と直感がつながれば、ロジスティック回帰・GLM はもう武器です。
ロジスティック回帰・GLM を一般化して書くと、観測ペア $(x_1, y_1), \dots, (x_n, y_n)$(ここでは $n = 47$ 都道府県)に対して、次の関係を仮定します。
$$ \boxed{\quad y = f(x_1, x_2, \dots, x_p; \theta) + \varepsilon \quad} $$ここで $\theta$ は推定したいパラメータ、$\varepsilon$ はモデルでは説明しきれない誤差項。 ロジスティック回帰・GLM の流派ごとに、$f$ の形(線形・ロジスティック・木)、$\varepsilon$ の分布(正規・二項・ポアソン)が変わります。
| 記号 | 意味 | SSDSE-B での例 |
|---|---|---|
| $x$ | 説明変数 | A1101(人口 × 家計支出) |
| $y$ | 目的変数 | 死亡率・出生率など |
| $n$ | 標本数 | 47(都道府県数) |
| $\theta$ | パラメータ | 傾き・切片など |
| $\varepsilon$ | 誤差項 | モデルで説明しきれない残り |
上の式 $y = f(x; \theta) + \varepsilon$ を「数学者の声」ではなく、「現場の声」で読み直してみます。
合言葉:「定義は短い、解釈は長い」。ロジスティック回帰・GLM はたった 1 行の式ですが、それを 47 都道府県データに当てると、5 種類のチェックリスト(線形性・独立性・等分散・正規性・外れ値)が芋づる式に出てきます。
数式が読めたら、すぐに 実データ(SSDSE-B-2026, 47 都道府県, 2023 年度)で計算しましょう。 抽象を 47 行の表に落とすと、急に理解できることがあります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import pandas as pd # df2023 はこのあとのブロックで作っているので、ここでも用意しておく df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df2023 = df[df['SSDSE-B-2026'] == 2023].reset_index(drop=True) # ロジスティック回帰・GLM の代表値を SSDSE-B-2026 で確認 col = 'A1101' s = df2023[col].astype(float) print('n :', len(s)) # 47 print('mean :', round(s.mean(), 2)) print('median :', round(s.median(), 2)) print('std :', round(s.std(), 2)) print('min / max :', s.min(), '/', s.max()) print('Top 3 prefs :') print(df2023.nlargest(3, col)[['Prefecture', col]]) |
結果を見ると、47 都道府県のうち上位 3 県が突出しているか、なだらかに分布しているか、すぐ分かります。 この「分布の形」が見えると、ロジスティック回帰・GLM を語る土台ができたことになります。
Python の実装は「読む → 集計 → 描く → 報告」を一直線に書きます。長いコードよりも、各ステップが分離していることが大事です。
1 2 3 4 5 6 7 8 9 10 11 | import pandas as pd import numpy as np import matplotlib.pyplot as plt # SSDSE-B-2026 を読み込み(人口 × 家計支出) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) # 2023 年度(最新)だけ抽出 df2023 = df[df['SSDSE-B-2026'] == 2023].copy() print(df2023.shape) # (47, ...) print(df2023[['Prefecture', 'A1101']].head()) |
# ロジスティック回帰・GLM を 47 都道府県でビジュアル化
fig, ax = plt.subplots(figsize=(9, 6))
df2023.sort_values(col, ascending=False).plot.bar(
x='Prefecture', y=col, ax=ax, color='#00897B', legend=False)
ax.set_title('人口 × 家計支出(SSDSE-B-2026, 2023)')
ax.set_ylabel(col)
ax.set_xlabel('都道府県')
plt.xticks(rotation=90)
plt.tight_layout()
plt.savefig('figures/logistic-glm.html_r18_bar.png', dpi=120)
plt.show()
レポート文例:「SSDSE-B-2026(2023 年度, n=47)に基づいて ロジスティック回帰・GLM を確認したところ、平均は X、標準偏差は Y、上位 3 県は東京・神奈川・大阪であった。 SSDSE-B-2026 の 47 都道府県を「人口減少県(1)/そうでない(0)」に二分化し、家計支出(食料・教育など)からロジスティック回帰で予測すると、各係数が「オッズ比」として読めます。」
合言葉:レポート提出前に「ゼロ起点で 1 枚描き直す」「外れ値を 1 県外して再計算」「逆方向の因果を 1 行で否定する」を必ずやる。
本ページに登場した Python コードはすべて以下のテンプレートで読み解けます:
覚え方:「Read → Roll up → Render → Read it back」。 最後の「Read it back」は、出力された数字や図を口に出して 1 度言うこと。 これで ロジスティック回帰・GLM の現場運用は十分に回ります。
使います。前処理(特徴量 → 入力ベクトル)、評価(指標の可視化)、解釈(係数の可視化)など、機械学習のあらゆる工程で ロジスティック回帰・GLM は登場します。
記述統計や 1 変量・2 変量の可視化には十分。ただし複数の説明変数を同時に検討するときは、自由度が枯れます。bootstrap や情報量規準(AIC/BIC)で補強しましょう。
独立行政法人統計センター(NSTAC)「SSDSE」サイトから無料でダウンロードできます。本ページの実装はすべて data/raw/SSDSE-B-2026.csv を前提にしています。
SSDSE は教育目的での利用が許諾されています(出典明示、改変記録)。論文公開時は出典欄に「総務省統計局, SSDSE-B-2026」を必ず書きましょう。
① ヒストグラム 1 枚を描く → ② 平均・中央値・標準偏差を読み上げる → ③ 上位 3 県・下位 3 県を暗記する → ④ 2 変量の相関を 1 つ確認する → ⑤ レポート 1 行にまとめる。これを 47 都道府県データで 3 回回せば、用語の地形が掴めます。
本リポジトリの 論文一覧 から「回帰モデル」カテゴリの論文を見ると、ロジスティック回帰・GLM を実際に使った再現コードが付いています。
「目的 → データ → ロジスティック回帰・GLM の選択理由 → 結果(図 + 数値)→ 解釈 → 限界(n=47, 単年)→ 次の一手」の順が王道です。
用語は単独では覚えづらいので、前提・並列・発展の 3 方向で 16 件並べます。
勧め方:1 日 1 リンク。クリックして読んだら、ロジスティック回帰・GLM のページに戻り、「ロジスティック回帰・GLM とこの用語はどう違う?」を 1 行書く。
合言葉:5 STEP のうちどれか 1 段でも飛ばすと、結論が「数字だけ」になり、読者の腑に落ちなくなります。 ロジスティック回帰・GLM は「数字 + 物語」のセットで完成です。
np.random.seed で作って「再現実験しました」と書く(教育用途では SSDSE-B-2026 を使うのが必須)iloc[:, 5] のように位置で参照し、SSDSE のバージョン違いで壊れるコードを書くx1, x2, x3 のように匿名化し、読者が意味を追えないコードにするロジスティック回帰・GLM は、19 世紀末〜 20 世紀初頭の統計学黎明期から発達してきました。回帰モデル の中核として、Galton、Pearson、Fisher、Yule などが基礎を築き、現代では SSDSE のような公的データを使った教育素材で広く扱われています。
ロジスティック回帰・GLM は、観測ペア $(x_i, y_i)_{i=1}^{n}$ から条件付き期待値 $E[y \mid x]$ または分布 $P(y \mid x)$ を推定する道具です。 線形・非線形・パラメトリック・ノンパラメトリックという 4 つの軸の中で、ロジスティック回帰・GLM は「回帰モデル」という棚に並んでいます。
df.dropna() の前に必ず欠損率を df.isna().mean() で測る。ロジスティック回帰・GLM は 記述統計・データサイエンス・機械学習 の交差点に位置します。 どの分野から入っても、いずれは ロジスティック回帰・GLM を通ります。
同じテーマで使い回せる narration を 5 つ並べておきます。コピペして「コード解説」欄に貼ってください。
ロジスティック回帰・GLM を学ぶときに使う SSDSE-B-2026 は、47 都道府県 × 約 110 列 × 複数年度のパネルデータです。 本ページでは「2023 年度の 47 行」を主に使います。 以下に、よく登場する代表的なカラムを示します。
| SSDSE コード | 日本語名 | 単位 | ロジスティック回帰・GLM での主な使い方 |
|---|---|---|---|
| Code | 地域コード | — | JOIN キー |
| Prefecture | 都道府県名 | — | カテゴリ軸・ラベル |
| A1101 | 総人口 | 人 | 説明変数(規模) |
| A1303 | 65 歳以上人口 | 人 | 高齢化率の分子 |
| A4101 | 出生数 | 人 | 人口動態の説明変数 |
| A4200 | 死亡率 | ‰ | 目的変数の代表 |
| B4101 | 年平均気温 | ℃ | 気候系の説明変数 |
| L3221 | 消費支出 | 円 | 家計の目的変数 |
使い方のコツ:列名はすべて A1101 のような英数記号です。SSDSE のコードブックで日本語ラベルを確認しながら使ってください。
本ページの例では A1101, L3221(人口 × 家計支出)を中心に使っています。
解説は最小限。コードは 10 行以内。これで ロジスティック回帰・GLM の最短ルートが手に入ります。
import pandas as pddf = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1])df = df[df['SSDSE-B-2026'] == 2023]col = 'A1101'print(df[['Prefecture', col]].sort_values(col, ascending=False).head())import matplotlib.pyplot as pltdf.plot.hist(y=col, bins=20)plt.title('人口 × 家計支出(SSDSE-B-2026, 2023)')plt.savefig('figures/logistic-glm.html_r18_hist.png', dpi=120)plt.show()注意:10 行で動かせる、というだけで、これがゴールではありません。 ロジスティック回帰・GLM の本当の難しさは「描いた図をどう解釈するか」「報告にどう落とすか」にあります。
ロジスティック回帰・GLM の結果を、ゼミ・卒論・社内会議で報告するときの定型文を 3 つ用意しました。 最初は丸ごとコピー、慣れたら差し替えて使ってください。
「本研究では、SSDSE-B-2026(n=47, 2023 年度)を用いて ロジスティック回帰・GLM を確認した。 主たる説明変数は A1101, L3221(人口 × 家計支出)であり、47 都道府県を対象とした分布の確認、相関の評価、ロジスティック回帰・GLM を用いた分析を実施した。 分析の結果、上位 3 県・下位 3 県の特徴と、SSDSE-B-2026 の 47 都道府県を「人口減少県(1)/そうでない(0)」に二分化し、家計支出(食料・教育など)からロジスティック回帰で予測すると、各係数が「オッズ比」として読めます。」
「人口 × 家計支出 を 47 都道府県で比較したところ、東京・神奈川・大阪など大都市圏が突出していることが分かった。 ロジスティック回帰・GLM を用いた分析から、地域差は単に人口規模の違いだけでは説明できず、複数要因の組み合わせで生じていると示唆された。 今後の打ち手は、上位県のベストプラクティスを参考にしつつ、下位県への支援策を検討することである。」
「皆さん、ロジスティック回帰・GLM はひとことで言うと『2 値(0/1)の結果や、カウント・比率を、線形予測子 + リンク関数で扱う一般化線形モデル。』です。 今回は SSDSE-B-2026(総務省統計局, 47 都道府県, 2023 年度)を使って、実際の数字でこの考え方を確かめました。 皆さん自身でも、別の指標(人口、出生率、家計支出など)に置き換えて同じ手順を試してみてください。」
同じ用語でも、見る立場によって意味が変わります。3 つの視点を切り替えて、用語の輪郭を立体的に掴みましょう。
統計学者にとって ロジスティック回帰・GLM は「データから母集団を推定する道具」です。 確率モデル・尤度・不偏性・効率性・一致性などの数学的性質に注目し、漸近理論で性能保証を行います。 47 都道府県データは「小標本(n=47)」と分類され、bootstrap や情報量規準による補強が必要になります。
データサイエンティストにとって ロジスティック回帰・GLM は「ビジネス課題を数字で答えるパイプラインの 1 部品」です。 モデルの理論的性質より、運用性・解釈性・更新コストを重視します。 SSDSE のような公的データを用いるときは「データの出典・更新頻度・ライセンス」を最優先で確認します。
教育の現場では ロジスティック回帰・GLM は「初学者が躓きやすいポイント」を含む単元です。 抽象的な数式よりも、具体的な 47 都道府県データで手を動かし、図を描き、結果を口頭で説明できるようになることが目標になります。 本ページの並び(直感 → 数式 → 計算 → Python → 落とし穴)は、まさにこの教育的アプローチに沿っています。
視点切り替えの効果:1 つの用語を 3 通りに眺めると、自分が今どの立場で議論しているか自覚できます。 論文を読むときは ①、現場で使うときは ②、人に教えるときは ③ ── と意識的に切り替えてください。
ロジスティック回帰・GLM と似た用語を、使い分けの観点から並べます。違いを言語化できれば、迷いが減ります。
| 用語 | 目的 | 入力 | 出力 | 強み | 弱み |
|---|---|---|---|---|---|
| ロジスティック回帰・GLM | 2 値(0/1)の結果や、カウント・比率を、線形予測子 + リンク関数で扱う一般化線形モデル。 | 47 都道府県 × 約 110 変数 | 図 + 表 + 200 字レポート | 直感的、再現容易 | 小標本(n=47)の制約 |
| 相関係数 | 2 変量の同調を 1 数で要約 | x, y の 47 ペア | r ∈ [−1, +1] | シンプル | 非線形は捉えられない |
| 線形回帰 | 条件付き期待値の線形近似 | 説明変数群 | 回帰係数・予測値 | 解釈容易 | 非線形には弱い |
| ロジスティック回帰 | 2 値分類 | 説明変数群 | 確率 + 係数 | 分類問題の標準 | 線形決定境界 |
| ランダムフォレスト | 非線形分類・回帰 | 大量変数 | 予測 + 重要度 | 非線形対応 | 解釈やや難 |
ロジスティック回帰・GLM は 回帰モデル の中で「2 値(0/1)の結果や、カウント・比率を、線形予測子 + リンク関数で扱う一般化線形モデル。」を担う基本道具です。回帰モデル の他のトピックは、この基本の応用または並列の道具にあたります。
使えます。SSDSE-A(市区町村)、SSDSE-C(年次推移)、SSDSE-D・E(個票)など、ロジスティック回帰・GLM の手順はそのまま適用できます。粒度(県・市・個人)に応じて n が変わるので、結果の信頼性も変わります。
SSDSE は年に 1 度更新されます。ロジスティック回帰・GLM のコード自体は変更不要ですが、結果(数値・図)は最新年度のものに置き換えてレポートしましょう。出典欄に「SSDSE-B-2027(仮)」と書き換えるのを忘れずに。
できます。ピボット → グラフ → 関数 で代表値や相関は出ます。ただし、再現性・履歴管理・自動化の面で Python に劣ります。学習用には Python を強く勧めます。
進めます。ロジスティック回帰・GLM は機械学習の「特徴量設計」と「結果解釈」の両端で必須です。AI と聞くと深層学習を連想しがちですが、SSDSE のような表形式データでは線形モデル + ロジスティック回帰・GLM の組み合わせで十分実用になります。
3 つ確認します:①ファイルパス(data/raw/SSDSE-B-2026.csv)が合っているか、②エンコーディングが cp932 か、③ヘッダ 2 行目の日本語ラベルを skiprows で飛ばしたか。これで 9 割解決します。
figures/ ディレクトリが存在しない可能性があります。import os; os.makedirs('figures', exist_ok=True) を先頭に追加してください。
本ページの 12 セクションを順に読み進めるのが最短です。特に「直感 → 数式 → 計算 → Python」の 4 段が腑に落ちれば、用語の 80 % は理解できたとみなせます。
このカードを印刷し、SSDSE-B-2026 で 1 回手を動かせば、用語の「使える形」が定着します。 ロジスティック回帰・GLM はあくまで「2 値(0/1)の結果や、カウント・比率を、線形予測子 + リンク関数で扱う一般化線形モデル。」というシンプルな考え方の道具ですので、迷ったらこの 1 行に戻ってください。
ロジスティック回帰・一般化線形モデル (GLM) は 2 値・カウント・比率データを「線形予測子 + リンク関数」で扱う基本枠組み。 ここでは 3 つの概念図で、 ロジスティック曲線・分類境界・モデル評価を視覚的に整理する。
説明変数 x と 2 値アウトカム y(0 か 1) のデータ点を並べ、
切片 β₀ と傾き β₁ をスライダー(またはグラフを指で/マウスでドラッグ)で動かすと、
ロジスティック曲線 p = 1 / (1 + exp(−(β₀ + β₁x))) がリアルタイムに変化します。
β₁ を大きくすると境界が急峻に、β₀ を動かすと境界の位置が左右にシフトします。
比較用に「直線回帰(OLS)」を破線で重ね、確率が 0〜1 をはみ出す様子も確認できます。
(データは仕組みを体感するための説明用の架空サンプルです。SSDSE-B の実測計算は上の「🧮 SSDSE-B 実値計算例」を参照してください。)
※ グラフを直接ドラッグ/スワイプしても操作できます(横 = β₀、縦 = β₁)。
下の図は同じ β₀・β₁ による対数オッズ(ロジット)
log( p / (1−p) ) = β₀ + β₁x。ロジスティック曲線は S 字ですが、
ロジット尺度ではまっすぐな直線になります。これが「一般化線形モデル(GLM)」の核心
―― リンク関数(ここではロジット)を通せば線形―― です。
直線回帰は ŷ = β₀ + β₁x を素直に予測しますが、これは ±∞ まで伸びるため
「確率」としては 0 未満・1 超という意味を持たない値を平気で出します(上の破線で体感できます)。
そこで確率 p を一度オッズ p/(1−p)(0〜∞)に、さらに対数オッズ log(p/(1−p))(−∞〜+∞)に写すと、
値域が実数全体に広がり、線形予測子 β₀+β₁x と同じ土俵に乗ります。
この対応を逆に辿るのがシグモイド σ(η)=1/(1+e^(−η)) で、どんな実数 η も必ず 0〜1 に収まります。
「確率を直接は線形にできないが、対数オッズなら線形にできる」―― これがロジスティック回帰の一行要約です。
exp(β₁) = オッズ比に直します。
上の readout に exp(β₁) を表示しています。ロジスティック回帰は一般化線形モデル(GLM)の一員にすぎません。GLM は ①分布族(誤差の分布)、②線形予測子 η=β₀+β₁x+…、③リンク関数 g(μ)=η の 3 部品で定義されます。リンクを取り替えるだけで多彩なモデルになります:
※ このブロックは既存の本文・実測値・📝補足に対する追記(非破壊)です。数値は data/raw/SSDSE-B-2026.csv(encoding='cp932', skiprows=[1]、2023 年・47 都道府県)を実際に statsmodels で当てはめた実測値のみを転記しています。
ロジスティック GLM の係数 β は log-odds(ロジット)の上では一定ですが、 確率の上では一定ではありません。 シグモイドの傾きは p=0.5 で最大になり、 そこでの「x が 1 単位増えたときの確率の変化量」の上限がちょうど β/4 になります(Gelman & Hill の "divide-by-4 rule")。 端(p が 0 や 1 に近い所)では同じ β でも確率はほとんど動きません。
実測で確かめます。 高齢化率(A1303/A1101)が全国中央値 31.78% より高い「超高齢県」ダミー(該当 23 / 47 県)を、 年平均気温 B4101(平均 16.80℃・標準偏差 2.05℃、 標準化して投入)で予測すると、 logit の傾きは β₁ = -0.849(オッズ比 exp(-0.849) = 0.428)でした。 ここで β₁/4 = -0.212。 つまり気温が 1 標準偏差(約 2.05℃)上がると、 超高齢県になる確率は最大でおよそ 21 ポイント下がる(ただし p=0.5 付近が最大で、 端では小さい)と読めます。 「オッズは一定倍、 確率は場所によって変わる」——これが β を素の確率差として読んではいけない理由です。
(1) リンク関数を変えると係数の「尺度」が変わる。 上とまったく同じデータ・同じ説明変数で、 リンクだけ差し替えて当てはめた実測値は次の通りです。
| リンク | 切片 β₀ | 傾き β₁ | logit との予測確率の相関 |
|---|---|---|---|
| logit(ロジスティック) | +0.0615 | -0.6721 | — |
| probit(プロビット) | +0.0340 | -0.4146 | 0.99990 |
| cloglog(補対数対数) | -0.3528 | -0.4300 | 0.99598 |
logit の傾きは probit の -0.849 / -0.532 = 1.60 倍で、 理論値(logit ≒ 1.6〜1.8 × probit)と一致します。 一方で予測確率どうしはほぼ同一(logit と probit の相関 0.99991、 最大差わずか 0.018)。 つまりリンクの選択は予測をほとんど変えないのに、 係数の絶対値は大きく変える。 別々のリンクで推定した生の β を横並びで比較したり、 他論文の probit 係数と自分の logit 係数をそのまま比べるのは誤りです。 比較したいならオッズ比(logit 固有)か、 「4 で割る」等で確率スケールの限界効果に統一してから比べます。
(2) 完全分離(perfect separation)で係数が発散する。 n=47 の小標本+少数クラスでは、 ある説明変数が結果をほぼ完全に切り分けてしまうと最尤推定値が有限に定まらず、 係数と標準誤差がともに爆発します。 意図的な実演(実データ・作為あり)として、 上の中央値スプリットで作った「超高齢県」ダミーを、 それを定義した高齢化率そのもの(完全に分離する変数)で予測すると β₁ = 265.97, 標準誤差 = 160420.55 という無意味な値になり、 反復が収束しません。 現実にはここまで極端でなくても、 高齢化率上位だけ(6 / 47 の稀クラス)を年少人口率で予測すると β₁ = -3.66, 標準誤差 = 1.49 と、 少数クラスで推定が目に見えて不安定になります。 危険サイン:収束しない旨の警告、 桁外れに大きい |β|、 天文学的に広い信頼区間。 これらが出たら係数を鵜呑みにせず分離を疑ってください。
1 2 3 4 5 6 7 8 9 10 11 12 13 | import pandas as pd, numpy as np, statsmodels.api as sm df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) d = df[df['SSDSE-B-2026'] == 2023].copy() d['aging'] = d['A1303'] / d['A1101'] * 100 # 高齢化率(%) d['y'] = (d['aging'] > d['aging'].median()).astype(int) # 超高齢県ダミー(23/47) xs = (d['B4101'] - d['B4101'].mean()) / d['B4101'].std() # 年平均気温(標準化) X = sm.add_constant(xs) for link in [sm.families.links.Logit(), sm.families.links.Probit(), sm.families.links.CLogLog()]: r = sm.GLM(d['y'], X, family=sm.families.Binomial(link)).fit() print(type(link).__name__, r.params.round(4).tolist()) # 係数はリンクで別物 # 完全分離の実演: y を定義した aging 自身で予測すると β・SE が発散する xa = (d['aging'] - d['aging'].mean()) / d['aging'].std() print(sm.GLM(d['y'], sm.add_constant(xa), family=sm.families.Binomial()).fit().bse) |
なぜリンクで係数尺度が違うのかは、 潜在変数(latent variable)解釈で腑に落ちます。 観測される 0/1 は、 見えない連続量が閾値を超えたかどうかだと考えると、 logit=潜在誤差がロジスティック分布、 probit=正規分布、 cloglog=極値(Gumbel)分布で非対称という違いに対応します。 分散のスケールが分布ごとに違うので、 係数の絶対値も一定倍でずれるわけです。 「不可逆な事象・稀にしか起きない事象」には非対称な cloglog が自然なことがあります。
完全分離・稀事象の実務的な処方箋:(1) Firth のペナルティ付き最尤(バイアス低減。 分離していても有限の推定値と妥当な標準誤差を返す。 少数クラスの標準対処)、 (2) 弱情報事前分布を置いたベイズ・ロジット、 (3) sklearn の LogisticRegression の L2 正則化(発散は止まるが係数は 0 方向に縮むので解釈に注意)。 まず疑い、 次に罰則、 が定石です。
そもそも n=47 横断は情報が薄い。 SSDSE-B-2026 は 2012–2023 の時系列(564 行=47 県 × 12 年)を持つので、 県を変量効果にした ロジスティック GLMM(一般化線形混合モデル)でパネル構造を活かせば、 47 県の小標本を年次方向の反復で補え、 完全分離も起きにくくなります。 横断の単発ロジットは「入口」、 混合モデルは「本番」と位置づけると良いでしょう。
係数解釈の基礎は ロジスティック回帰、 exp(β) の読み方は オッズ比。 係数が暴れる原因は 多重共線性 と VIF を、 分類性能の評価は ROC 曲線 と AUC を参照。 多クラスへの一般化は ソフトマックス、 2012–2023 の反復構造を活かす発展は パネルデータ が入口です。 (関連が深いものの本教材に単独ページが未整備の概念:probit / cloglog リンク回帰、 Firth のペナルティ付きロジスティック、 完全分離(perfect separation)、 ロジスティック GLMM / 混合効果モデル、 限界効果(marginal effect)。 リンク先は現時点で未作成のためテキストのみ。)