ロジスティック回帰(logistic regression)を確実に使いこなすための関連キーワードを難易度別に整理しました。
🍰 まずはやさしく
はいかいいえを分ける道具です。
どちらになるかの確率を出すために使います。
テストに合格するかどうかを予測するような例です。
この章では仕組みと計算方法について読みます。
ロジスティック回帰(logistic regression)は、 目的変数が二値(0/1, Yes/No, 合格/不合格)のときに使う回帰モデル。 「東京の中で、 ある地域が住宅地として人気か(はい/いいえ)」を予測するときなどに使います。
なぜ普通の線形回帰ではダメか:
解決:シグモイド関数で確率に変換
線形結合 $z = \beta_0 + \beta_1 x_1 + \cdots$ をシグモイド $\sigma(z) = 1/(1+e^{-z})$ に通します。 これで必ず 0〜1 の確率になる。
モデル式:$P(y=1|x) = 1/(1 + e^{-(\beta_0 + \beta_1 x_1 + \cdots)})$
係数の解釈:オッズ比
線形回帰のような直接的解釈ができないので、 代わりに「オッズ比」を使います。 $\exp(\beta_j)$ がオッズ比。 「$x_j$ を1単位増やすと、 オッズが何倍になるか」。
例:$\beta_\text{所得} = 0.5$ → $\exp(0.5) = 1.65$ → 「所得が1単位増えると、 イベント発生のオッズが1.65倍」。
用途:(i) 二値分類問題(合否予測、 病気診断)、 (ii) 確率予測、 (iii) リスクファクター分析(医学・公衆衛生)、 (iv) 信用スコアリング。
類似手法:プロビット回帰。 シグモイドの代わりに標準正規 CDF を使う。 結果はほぼ同じ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import pandas as pd import numpy as np from sklearn.linear_model import LogisticRegression # SSDSE-B-2026 を読み込み(1 行目は列コード行なので skip) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] # 2023 年の 47 都道府県 # 2値目的変数:高齢化率(A1303/A1101)が中央値超なら 1 aging = df['A1303'] / df['A1101'] y = (aging > aging.median()).astype(int) X = np.log(df['L3221']).values.reshape(-1, 1) # 消費支出(対数) clf = LogisticRegression().fit(X, y) print('係数 β1 :', clf.coef_[0, 0]) print('オッズ比 :', np.exp(clf.coef_[0, 0])) |
このページの上にある3つの概念マップ(関係マップ、 包含マップ、 ツリーマップ)でこの概念の位置づけが視覚的に分かります。 関連手法を辿って学習を進めましょう。
統計データ活用コンペティションのSSDSE-B-2026データは、 47都道府県の社会経済データ。 この概念を使って以下のような分析ができます:
| 機能 | scikit-learn | statsmodels |
|---|---|---|
| モデル定義・推定 | LogisticRegression().fit(X, y) | sm.Logit(y, X).fit() |
| 係数(対数オッズ) | clf.coef_ / clf.intercept_ | res.params |
| オッズ比 | np.exp(clf.coef_) | np.exp(res.params) |
| 確率予測 | clf.predict_proba(X)[:,1] | res.predict(X) |
| p値・信頼区間 | — | res.summary() / res.conf_int() |
| AUC 評価 | roc_auc_score(y, proba) | — |
| 不均衡対応 | class_weight='balanced' | freq_weights=... |
この概念は、 他の多くの統計概念と密接に関連しています。 ジャストインタイム型学習では、 必要に応じて関連用語へジャンプしながら全体像を構築します。
| グループ | 主要概念 |
|---|---|
| 記述統計 | 平均、 中央値、 最頻値、 分散、 標準偏差、 共分散、 相関係数 |
| 可視化 | ヒストグラム、 散布図、 箱ひげ図、 ヒートマップ |
| 推測統計 | 標本平均、 標準誤差、 信頼区間、 p値、 有意水準 |
| 確率分布 | 正規分布、 t分布、 χ²分布、 F分布、 二項分布 |
| 仮説検定 | t検定、 F検定、 χ²検定、 ノンパラ検定 |
| 回帰 | 単回帰、 重回帰、 OLS、 Ridge、 LASSO |
| 分類 | ロジスティック回帰、 決定木、 SVM、 k-NN |
| 教師なし学習 | クラスタリング、 PCA、 因子分析 |
| 時系列 | ARIMA、 VAR、 指数平滑法、 自己相関 |
| 因果推論 | DiD、 IV、 傾向スコア、 交絡変数 |
| 前処理 | 標準化、 正規化、 欠損値処理、 多重共線性対策 |
| 評価 | R²、 残差、 CV、 RMSE、 効果量 |
🍰 まずはやさしく
2つのグループに分ける分析手法です。
あることが起きる確率を予測するために使います。
持ち家があるかないかを分けるような例です。
ここではこの用語の詳しい意味について読みます。
論文中に 「ロジスティック回帰」として登場する用語。
ロジスティック回帰 とは:目的変数が0/1(二値)のとき使う回帰。確率の対数オッズを線形モデルで予測する。
本ページではロジスティック回帰 (logistic regression) を扱う。 二値分類の最も基本的な統計モデルで、 説明変数の線形和を logit リンク関数で 0〜1 の確率に変換する。 SSDSE-B-2026 で「持ち家比率が中央値超え」「人口減少県か」などの二値変数を予測する例で解説する。
ロジスティック回帰は GLM の「二項分布 + logit リンク」の特例。 係数 β はオッズ比 (exp(β)) として解釈でき、 「説明変数が 1 単位増えるとオッズが何倍になるか」を直接読める。 完全分離 (perfect separation) で係数が発散する病的ケース、 多重共線性、 確率予測のキャリブレーションが主な実務論点。
🍰 まずはやさしく
直感的に確率を捉える方法です。
データから正解のしやすさを知るために使います。
スマホの利用時間で成績を予想するような例です。
ここでは図を使ってイメージを掴むことを読みます。
ロジスティック回帰は「2 値(0/1)の確率を線形予測子の logit で表す」回帰。 係数は対数オッズの増分で、 exp(係数) = オッズ比。 SSDSE-B-2026 で y=(A1101>1,000,000)を log(L3221) で説明すると、 「消費支出 1% 増で人口 100 万超オッズ約 5% 増」のような解釈が得られる。
ロジスティック回帰 は「回帰」カテゴリの中核概念。 初めて触れる読者は、 まずこの「🎨 直感」セクションだけ通読し、 必要になった時点で「📐 数式」「🐍 Python」「⚠️ 落とし穴」へ戻る読み方が定着しやすいです。
ロジスティック回帰の仕組みと使い分けを、 3 点のインライン SVG で 視覚的に整理する。
線形和 β₀+β₁x を 0〜1 の確率に押し込む S 字曲線。 中心の 0.5 が判定境界。
青の点線は線形回帰の予測 → 確率が 1 を超え不自然。 ロジスティック回帰なら必ず 0〜1 に収まる。
OR=1 は影響なし、 OR>1 は発生確率を上げる、 OR<1 は下げる(保護要因)。 係数 β を exp(β) に変換して読む。
読むだけでは掴みにくい「なぜシグモイドが確率か」「決定境界はなぜ直線か」を、 実際に点を置いて体感します。 キャンバスをクリック(スマホはタップ)すると、 選んだクラスの点が配置されます。 1次元モードでは x 軸上に 0/1 の点を置くとシグモイド曲線(確率)が引かれ、 係数スライダー(傾き β₁・切片 β₀)で曲線の急峻さと位置を手で調整できます。 「⚙ 勾配法で自動フィット」を押すと、 対数尤度を最大化する係数へ自動収束します。 2次元モードでは、 点を置くたびに勾配法で再フィットし、 線形の決定境界と確率の等高線(ヒートマップ)が描画されます。 閾値スライダーを動かすと、 分類結果(誤分類の数)が変わる様子も観察できます。
💡 キャンバスをクリック/タップで点を配置。 スライダーで係数と閾値を動かし、 対数尤度・誤分類がどう変わるか観察しましょう。
① シグモイドはなぜ「確率」か: 線形和 $z=\beta_0+\beta_1 x$ は $-\infty$〜$+\infty$ の実数ですが、 確率は $[0,1]$ に収まらねばなりません。 シグモイド関数 $\sigma(z)=1/(1+e^{-z})$ は任意の実数を $0$〜$1$ へ単調に押し込む変換で、 $z=0$ で必ず $0.5$、 $z\to\pm\infty$ で $1/0$ に漸近します。 逆に確率 $p$ を実数に戻す変換が ロジット(対数オッズ) $\operatorname{logit}(p)=\log\frac{p}{1-p}$ で、 モデルは「対数オッズが $x$ の線形関数」$\log\frac{p}{1-p}=\beta_0+\beta_1 x$ と等価です。 スライダーで β₁ を大きくすると曲線が急になり(=オッズの変化率が大きい)、 β₀ を動かすと曲線が左右に平行移動します。 係数 $\beta_j$ をそのまま $\exp(\beta_j)$ にすると オッズ比 になります。
② 決定境界はなぜ「線形」か: 閾値 $t$ で分類するとき、 境界は $p=t$、 すなわち $\sigma(z)=t \Leftrightarrow z=\operatorname{logit}(t)$ を満たす点の集合です。 $z=\beta_0+\beta_1x_1+\beta_2x_2$ は $x$ について一次式なので、 境界 $\beta_0+\beta_1x_1+\beta_2x_2=\operatorname{logit}(t)$ は必ず直線(一般には超平面)になります。 2次元モードのヒートマップで、 等確率線(等高線)が平行な直線群になっているのがこの理由です。 曲がった境界が欲しいときは多項式特徴量や SVM・木モデルを使います。
③ 最尤推定と交差エントロピー損失: 「自動フィット」ボタンは、 各点の予測確率をなるべく正解ラベルに近づけるよう係数を動かしています。 数式では観測データの尤度 $\prod_i p_i^{y_i}(1-p_i)^{1-y_i}$ を最大化する最尤推定(MLE)で、 対数を取って符号を反転すると 交差エントロピー損失(対数損失 / log loss) $$ \mathcal{L}(\beta)=-\sum_i\bigl[y_i\log p_i+(1-y_i)\log(1-p_i)\bigr] $$ になります。 「尤度最大化」と「交差エントロピー最小化」は同じことです。 勾配は $\partial\mathcal{L}/\partial\beta_j=\sum_i (p_i-y_i)x_{ij}$ と綺麗な形になり、 これが勾配降下法(勾配降下法)で解ける理由です。 読み出し欄の「対数尤度 LL」が大きい(=損失が小さい)ほど良い当てはめです。
④ 線形回帰との違い: 線形回帰 は $y$ を直接 $\beta_0+\beta_1x$ で予測し、 損失は二乗誤差(正規分布の最尤)でした。 0/1 データに線形回帰を当てると予測が $0$ 未満や $1$ 超になり確率として破綻します。 ロジスティック回帰は「シグモイドで $[0,1]$ に収める」「二乗誤差ではなく交差エントロピーを使う」の 2 点が本質的な違いです。 なお両者とも「線形予測子 $\beta_0+\beta_1x$ を使う」点は共通で、 一般化線形モデル(GLM)としてリンク関数(恒等 vs ロジット)の違いに統一的に整理できます。
⑤ 正則化: サンプルが少ない・完全分離が起きると MLE の係数は発散します。 損失に係数のペナルティを足す 正則化(L2 / Ridge:$+\lambda\sum\beta_j^2$、 L1 / Lasso:$+\lambda\sum|\beta_j|$)で係数を縮小・一部を $0$ にして安定させます。 上のおもちゃも自動フィットに弱い L2 を入れて発散を防いでいます。 scikit-learn の LogisticRegression は既定で L2 が有効です。
⑥ 多クラスへの拡張(softmax): 3 クラス以上では、 シグモイドを多変数に一般化した ソフトマックス関数 $\;p_k=\dfrac{e^{z_k}}{\sum_{j}e^{z_j}}\;$ を使う多項ロジスティック回帰になります。 各クラスに線形予測子 $z_k=\beta_{k0}+\boldsymbol{\beta}_k^\top x$ を持たせ、 損失は多クラス版の交差エントロピーです。 2 クラスの softmax はシグモイドと一致します。
🍰 まずはやさしく
計算するための正確なルールです。
予測を数式で正しく表すために使います。
買い物などのデータを数式に入れるような例です。
ここでは記号の意味と計算式について読みます。
やさしい説明で掴んだ感覚を、ここで ロジスティック回帰 の定義式に対応づけます。下の式は左辺 $\Pr(Y$ が何で決まるかを右辺で書き下したもので、分数(割り算)、exp(指数)、β(回帰係数) が現れます。それぞれの記号が何の量を指すのかは、次の「🔬 数式を言葉で読み解く」で 1 つずつ確かめてください。
上の数式を眺めるだけでは身につかないので、 各記号がどんな役割を担っているかを言葉で押さえます。 「数式を音読する習慣」がつくと、 論文や教科書を読むスピードが体感で 2 倍ほど上がります。
合成データではなく、 SSDSE-B-2026 から「人口減少県」(過去 10 年で人口減少した県)を 1、 増加または横ばいの県を 0 として分類する例で、 ロジスティック回帰の手順を具体的に示します。
# 目的変数 Y:1 = 人口減少県(おおよそ 38 県)、 0 = 増加県(東京・沖縄・神奈川・千葉・埼玉・愛知・福岡・滋賀・大阪 の 9 県)
# 説明変数 X:
# x₁ = 高齢化率(%、 27〜38 程度)
# x₂ = 1 人当たり県民所得(万円、 200〜500 程度)
# x₃ = 大学進学率(%、 35〜70 程度)
1 2 3 4 5 6 7 8 9 10 | logit(P(Y=1)) = β₀ + β₁·高齢化率 + β₂·県民所得 + β₃·大学進学率 # 最尤推定の結果(仮想的だが現実的な値) β₀ ≈ -8.20 (切片) β₁ ≈ +0.52 (高齢化率 1% 増で logit +0.52、 OR ≈ exp(0.52) ≈ 1.68) β₂ ≈ -0.012 (所得 1 万円増で OR ≈ exp(-0.012) ≈ 0.988) β₃ ≈ -0.038 (進学率 1% 増で OR ≈ exp(-0.038) ≈ 0.963) → 高齢化率が高いほど人口減少県になる確率が大きく上昇 → 県民所得・大学進学率が高いほど減少しにくい |
1 2 3 4 5 6 7 8 | # 例:秋田県(高齢化率 38%、 県民所得 245 万円、 大学進学率 47%) logit = -8.20 + 0.52·38 + (-0.012)·245 + (-0.038)·47 = -8.20 + 19.76 - 2.94 - 1.79 ≈ +6.83 P = 1 / (1 + exp(-6.83)) ≈ 0.9989 → 秋田は人口減少県である確率 99.89%(実際に減少県) |
1 2 3 4 5 6 7 8 | # 例:東京都(高齢化率 23%、 県民所得 540 万円、 大学進学率 73%) logit = -8.20 + 0.52·23 + (-0.012)·540 + (-0.038)·73 = -8.20 + 11.96 - 6.48 - 2.77 ≈ -5.49 P = 1 / (1 + exp(5.49)) ≈ 0.0041 → 東京は人口減少県である確率 0.41%(実際に増加県) |
1 2 3 4 5 6 7 8 9 10 | # 47 県を 50% 閾値で予測した結果(仮想) 予測 0 予測 1 実測 0(9 県) 8 1 ← 1 県を誤って減少県と予測 実測 1(38 県) 2 36 ← 2 県を誤って増加県と予測 正解率 (Accuracy) = (8+36)/47 ≈ 0.936 適合率 (Precision) = 36/(36+1) ≈ 0.973 再現率 (Recall) = 36/(36+2) ≈ 0.947 F1 スコア ≈ 0.960 AUC ≈ 0.985 |
1 2 3 4 5 6 | # 高齢化率の係数 β₁ = 0.52、 SE = 0.18 # 95% 信頼区間(β₁): 0.52 ± 1.96·0.18 = [0.167, 0.873] # OR の 95% CI: [exp(0.167), exp(0.873)] = [1.18, 2.39] → 「高齢化率が 1% 増えると、 人口減少県になるオッズが 1.18〜2.39 倍になる(95% 信頼)」 |
数式だけでは「実感」が湧きにくいので、 実データ data/raw/SSDSE-B-2026.csv(47 都道府県 × 16 年)で 1 度手計算してみると理解が定着します。
SSDSE-B-2026 (2023) で y=(A1101>1,000,000)、 X=log(L3221) のロジスティック回帰を行うと、 切片≈-58、 傾き≈4.7、 exp(4.7) ≈ 110。 つまり log(L3221) が 1 単位上がるとオッズが 110 倍。 L3221 が 28 万→32 万(log 差 0.13)でオッズ約 1.83 倍。
| 都道府県 | 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 実装で得る値と一致することを確認すると、 「数式とコードの対応関係」がクリアに見えるようになります。
合成 z = 0.5x + 1 から p を計算する。
| x | z | p=σ(z) |
|---|---|---|
| 0 | 1.0 | 0.731 |
| -2 | 0.0 | 0.500 |
| 4 | 3.0 | 0.953 |
| -4 | -1.0 | 0.269 |
1 2 3 4 5 6 | import numpy as np x = np.array([0, -2, 4, -4]) z = 0.5*x + 1 p = 1/(1+np.exp(-z)) print(f"p: {p.round(3)}") print(f"クラス: {(p>0.5).astype(int)}") |
💬 手計算 (Step 2) と Python 出力が完全一致。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import pandas as pd import numpy as np from sklearn.linear_model import LogisticRegression from sklearn.preprocessing import StandardScaler 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] # 目的変数:高齢化率(A1303/A1101)が中央値超なら 1 aging = df['A1303'] / df['A1101'] y = (aging > aging.median()).astype(int) X = df[['A1101', 'L3221']] # 総人口・消費支出 Xs = StandardScaler().fit_transform(X) # 標準化 X_train, X_test, y_train, y_test = train_test_split(Xs, y, test_size=0.3, random_state=0) model = LogisticRegression(C=1.0, penalty='l2', max_iter=1000) model.fit(X_train, y_train) print('係数:', {c: round(float(w), 4) for c, w in zip(X.columns, model.coef_[0])}) print('切片:', round(float(model.intercept_[0]), 4)) print('精度:', round(model.score(X_test, y_test), 4), f'(テスト {len(y_test)} 県)') |
1 2 3 4 5 6 7 8 9 10 11 12 13 | import statsmodels.api as sm X_const = sm.add_constant(X) model = sm.Logit(y, X_const).fit() print(model.summary()) # オッズ比とその 95% 信頼区間 params = model.params conf = model.conf_int() conf['OR'] = np.exp(params) conf.columns = ['CI 2.5%', 'CI 97.5%', 'OR'] conf[['CI 2.5%', 'CI 97.5%']] = np.exp(conf[['CI 2.5%', 'CI 97.5%']]) print(conf) |
1 2 3 4 5 6 | model_l1 = LogisticRegression(C=0.5, penalty='l1', solver='liblinear', max_iter=1000) model_l1.fit(Xs, y) print('L1 で残った係数:') for name, coef in zip(X.columns, model_l1.coef_[0]): print(f' {name}: {coef:.4f}') |
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 | import pandas as pd import numpy as np from sklearn.linear_model import LogisticRegression from sklearn.preprocessing import StandardScaler from sklearn.model_selection import train_test_split from sklearn.metrics import roc_curve, roc_auc_score import matplotlib.pyplot as plt # 直前のブロックで model は statsmodels の Logit に置き換わっているので、 # predict_proba を持つ scikit-learn のモデルをここで作り直す df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] aging = df['A1303'] / df['A1101'] y = (aging > aging.median()).astype(int) X = df[['A1101', 'L3221']] Xs = StandardScaler().fit_transform(X) X_train, X_test, y_train, y_test = train_test_split(Xs, y, test_size=0.3, random_state=0) sk_model = LogisticRegression(C=1.0, penalty='l2', max_iter=1000).fit(X_train, y_train) y_proba = sk_model.predict_proba(X_test)[:, 1] fpr, tpr, thresholds = roc_curve(y_test, y_proba) auc = roc_auc_score(y_test, y_proba) print(f'AUC = {auc:.3f}') plt.plot(fpr, tpr, label=f'AUC = {auc:.3f}') plt.plot([0,1], [0,1], 'k--') plt.xlabel('偽陽性率 (FPR)') plt.ylabel('真陽性率 (TPR)') plt.legend() plt.savefig('roc_curve.png', dpi=150) |
1 2 3 4 5 6 | model_balanced = LogisticRegression( C=1.0, penalty='l2', class_weight='balanced', # 自動で逆頻度の重み付け max_iter=1000 ) model_balanced.fit(X_train, y_train) |
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 | import pandas as pd import numpy as np from sklearn.linear_model import LogisticRegression from sklearn.preprocessing import StandardScaler from sklearn.model_selection import train_test_split # 3 クラスの目的変数を作る(人口規模 小/中/大) df = pd.read_csv('data/raw/SSDSE-B-2026.csv', encoding='cp932', skiprows=[1]) df = df[df['SSDSE-B-2026'] == 2023] y_multi = pd.cut(df['A1101'], bins=[0, 1_500_000, 3_000_000, 1e9], labels=['小', '中', '大']) Xs = StandardScaler().fit_transform(df[['A4101', 'L3221']]) X_train, X_test, y_train_multi, y_test_multi = train_test_split( Xs, y_multi, test_size=0.3, random_state=0) # sklearn 1.5 以降、multi_class 引数は廃止(クラスが 3 つ以上なら自動で多項ロジット) model_multi = LogisticRegression( solver='lbfgs', max_iter=1000 ) model_multi.fit(X_train, y_train_multi) # softmax 出力で全クラスの確率を取得 probs = model_multi.predict_proba(X_test) print(pd.DataFrame(probs, columns=model_multi.classes_).round(3).head()) |
1 2 3 4 5 6 7 8 9 10 11 12 13 | from sklearn.calibration import CalibratedClassifierCV cal = CalibratedClassifierCV(LogisticRegression(max_iter=1000), method='sigmoid', cv=5) cal.fit(X_train, y_train) # 確率の信頼性確認 from sklearn.calibration import calibration_curve prob_true, prob_pred = calibration_curve(y_test, cal.predict_proba(X_test)[:, 1], n_bins=10) plt.plot(prob_pred, prob_true, 's-', label='Calibrated') plt.plot([0,1], [0,1], 'k--') plt.xlabel('予測確率') plt.ylabel('実測陽性率') plt.legend() |
公的統計(SSDSE-B-2026)を題材に、 最小限の Python コードで ロジスティック回帰 を動作させます。 まずはこのまま実行してみてください。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # ロジスティック回帰 を 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 sklearn.linear_model import LogisticRegression import numpy as np y = (df['A1101'] > 1_000_000).astype(int).values X = np.log(df['L3221'].values).reshape(-1, 1) clf = LogisticRegression().fit(X, y) print('切片:', clf.intercept_) print('係数:', clf.coef_) print('オッズ比:', np.exp(clf.coef_)) |
▶ 実行 を押せばこのページの中でそのまま動きます(ライブラリもデータも同梱済みで、 準備は要りません)。 手元の Python に移して動かすときは pip install matplotlib numpy pandas scikit-learn scipy seaborn statsmodels が必要です。 読んでいるデータは data/raw/SSDSE-B-2026.csv。 日本語を含むので encoding='cp932' の指定を落とさないでください。
ロジスティック回帰では通常の決定係数 R² が定義できません(目的変数が 0/1 のため)。 McFadden's R²、 Cox–Snell R²、 Nagelkerke R² といった擬似 R² や、 ROC-AUC、 log loss、 F1 スコアなどの分類性能指標で評価する必要があります。 「R² が低い = モデルが悪い」と決めつけず、 適切な評価指標を選びましょう。
ロジスティック回帰が出すのはオッズ比 (OR) であって、 相対リスク (RR) ではありません。 稀少イベント(陽性率 < 10%)なら OR ≈ RR ですが、 陽性率が高い場合は OR が RR を過大評価します。 たとえば OR = 3 でも、 ベースライン確率が 0.5 なら実際の RR は 1.5 倍程度です。 ニュース記事などで「リスクが 3 倍」と単純に書くのは誤解を招きます。
説明変数が完全に陽性・陰性を分けてしまうと、 最尤推定の係数が無限大に発散し、 数値解が収束しません。 サンプル数が少ない、 稀少イベント、 ダミー変数が多すぎる場合に起こりがち。 対策は (i) Firth 補正、 (ii) L2 正則化(Ridge)、 (iii) ベイズ推定(弱情報事前分布)。 sklearn の LogisticRegression はデフォルトで L2 が入っているため安定です。
陽性が 1%、 陰性が 99% のデータでは、 「全部 0 と予測」するだけで Accuracy 99% になります。 ロジスティック回帰も多数派クラスに偏ったモデルを学習します。 対策は (i) `class_weight='balanced'` で重み付け、 (ii) アンダーサンプリング、 (iii) SMOTE などのオーバーサンプリング、 (iv) 評価指標を AUC・F1・recall などに切り替え、 (v) 閾値を 0.5 ではなく Youden's J 統計量で最適化。
説明変数同士が強く相関していると(VIF > 5〜10)、 係数の標準誤差が膨張し、 個別の係数解釈が不可能になります。 例えば「総人口」と「労働人口」を両方入れると、 一方の係数が大きくプラス、 他方がマイナスになる「打ち消し」が起こりがち。 事前に相関行列・VIF を確認し、 必要なら片方を除外、 PCA、 Lasso などで対処してください。
「説明変数 1 つにつき最低 10〜20 件の陽性イベント(EPV: events per variable)」が経験則です。 47 都道府県データで陽性 9 件・陰性 38 件の場合、 EPV ベースで使える説明変数は 陽性 9 件 ÷ 10 ≈ 1 個 しかありません。 安易に多変量に進まず、 L2 正則化、 PCA、 ドメイン知識による変数選択を組み合わせてください。
分類精度(accuracy、 AUC)が高くても、 予測確率そのものは現実の頻度を反映していないことがあります。 「P = 0.7 と予測した中で実際に陽性は 50%」など。 これは不均衡データや L1 正則化で特に顕著。 対策は Platt スケーリング、 isotonic regression、 calibration plot(reliability diagram)で確認。 sklearn の `CalibratedClassifierCV` が便利です。
ロジスティック回帰 を使うときに初学者が踏みやすい失敗パターン。 1 度経験してしまえば次から避けられますが、 先に知っておくに越したことはありません。
ロジスティック回帰では Odds Ratio と 擬似 R² が効果量・適合度の主指標。 解釈基準:
| 指標 | 意味 | 弱い | 中 | 強い |
|---|---|---|---|---|
| Odds Ratio | 説明変数 +1 で odds が何倍になるか | 1.0 ~ 1.5 | 1.5 ~ 2.5 | > 2.5 |
| McFadden 擬似 R² | 対数尤度の改善率 | < 0.1 | 0.1 ~ 0.3 | > 0.3 (Excellent 域) |
| AUC | 識別能力 (確率予測の順序性) | 0.5 ~ 0.7 | 0.7 ~ 0.85 | > 0.85 |
| Hosmer-Lemeshow | 適合度検定 (p 値) | p < 0.05 (適合不良) | p ~ 0.1 | p > 0.2 (良好) |
ロジスティック回帰 がデータサイエンスの体系の中でどこに位置するかを、 3つの異なる視点で可視化します。 同じ情報でも見方を変えると気付きが変わります。
🌐 統計・データサイエンス › 関連・回帰 › 回帰 › ロジスティック回帰(一般化線形モデル(二項+ロジット))
中心に ロジスティック回帰 を置き、 そこから 重回帰・プロビット・OLS・分類・単回帰・Ridge回帰 計 6 個の用語へ、 前提・兄弟・発展形といった関係を矢印で結んでいます。 線がどちら向きかを見れば、 先に読むべき用語とあとから読む用語が分かります。 ノードはドラッグで動かせ、 ホイールでズーム、 クリックでその用語のページへ遷移します。
大きな円が小さな円を包含する Circle Packing 図。 「ロジスティック回帰」は緑色でハイライト。
長方形を入れ子に分割した Treemap 図。 各分野の規模感を面積で比較。 「ロジスティック回帰」は緑色でハイライト。
| マップ | 分かること | こんな時に見る |
|---|---|---|
| 🔗 関係マップ | 手法間の横の関係(前提→発展→応用) | 「次に何を学べばよい?」 学習順序の判断 |
| ⭕ 包含マップ | 分類体系の入れ子構造(上位⊃下位) | 「この手法はどんなジャンルに属する?」 |
| 🌳 ツリーマップ | 分野の規模比較(面積=ボリューム) | 「データサイエンス全体の俯瞰像」 |
💡 3 つの図は同じ位置関係を別の角度から描いています。 関係マップは ロジスティック回帰 の隣に何が並ぶかを、 包含マップとツリーマップは 統計・データサイエンス → 回帰 → ロジスティック回帰 という入れ子の位置を示します。 「回帰には他に何があったか」を思い出したいときは包含マップを、 「次に何を読むか」を決めたいときは関係マップを開いてください。
ロジスティック回帰は二値分類の代表モデルであり、 前段の説明変数設計と後段のオッズ比解釈・ROC 評価を組み合わせて医療・ビジネスで定番化している。
上流の特徴量選択と多重共線性検査 (VIF) で安定した推定を確保し、 並列の決定木/SVM/Random Forest と比較して解釈性 vs 精度のトレードオフを判断し、 下流の ROC/AUC とオッズ比解釈でビジネス示唆 (どの要因がどれだけ確率を上げるか) を抽出する流れで二値分類の標準パイプラインが完成する。
「logistic regression」を含む手法選択は、 データの性質・分析目的・運用制約の 3 軸で決まる。 以下に典型シナリオと対応する手法の組合せを示す。
| シナリオ | 重視する観点 | 候補手法 |
|---|---|---|
| 大規模・高次元 (n > 1e6, d > 1e4) | 計算効率 / スパース対応 | SGDClassifier (log loss), LogisticRegression(solver='saga') + L1, Vowpal Wabbit |
| クラス不均衡 (陽性率 < 5%) | 少数クラスの誤分類を重視 | class_weight='balanced', SMOTE で oversampling, Focal Loss |
| 係数の解釈・統計的検定が必要 | オッズ比 / Wald 検定 | statsmodels Logit (summary で z / p 値 / 95%CI), GLM(family=Binomial()) |
| 特徴量が非線形・交互作用 | 表現力 / 自動的特徴抽出 | LightGBM / XGBoost, GAM (一般化加法モデル), 多項式特徴 + ロジスティック回帰 |
| データが少ない (n < 100) / 完全分離 | 推定の発散回避 | Firth's penalized logistic, ベイズロジスティック (PyMC), 強い L2 正則化 |
| 確率を本当に確率として使う | キャリブレーション | CalibratedClassifierCV (Platt / Isotonic), Brier score / Reliability diagram で検証 |
上の「🎨 直感」を土台に、 ロジスティック回帰を貫く 4 つの視点を一段深く言語化する。 いずれも同じモデルを別角度から見たものであり、 相互に翻訳できることが本質。
二値の結果 $y\in\{0,1\}$ の「1 になる確率」$p$ を直接線形式で書くと $[0,1]$ をはみ出す。 そこで線形結合 $z=\beta_0+\beta_1x_1+\dots$ を シグモイド関数 $\sigma(z)=1/(1+e^{-z})$ に通し、 必ず $0\sim1$ に収める。 $z$ が大きいほど $p\to1$、 小さいほど $p\to0$、 $z=0$ でちょうど $p=0.5$。 S 字の傾きが最も急なのは $p=0.5$ 付近で、 ここでは説明変数のわずかな変化が確率を大きく動かす。 逆に $p$ が 0 や 1 に近い端では、 同じだけ $z$ を動かしても確率はほとんど動かない(飽和)。
シグモイドの逆関数を取ると $z=\log\dfrac{p}{1-p}$。 つまり線形結合 $z$ の正体は オッズ $p/(1-p)$ の対数(ロジット)である。 ロジスティック回帰は「確率そのもの」ではなく「対数オッズ」を線形にモデル化している、 と読むと係数の意味が一気に通る。 確率スケールでは非線形(S 字)だが、 ロジットスケールに移せば完全に線形——これが線形回帰の直感をそのまま持ち込める理由。
$x_j$ を 1 単位増やすと $z$ は $\beta_j$ だけ増える。 ロジットが $\beta_j$ 増えることは、 オッズが $e^{\beta_j}$ 倍になることと同値。 よって$\exp(\beta_j)$ がオッズ比 (odds ratio, OR)。 $\beta_j>0\Rightarrow OR>1$(発生確率を上げる)、 $\beta_j<0\Rightarrow OR<1$(保護的)、 $\beta_j=0\Rightarrow OR=1$(影響なし)。 SSDSE-B-2026 の 2023 年 47 都道府県で「高齢化率(A1303/A1101)が中央値超かどうか」を目的変数(陽性 23 県・陰性 24 県のほぼ均衡)にし、 説明変数を標準化した総人口 log(A1101) と消費支出 log(L3221) で当てはめると、 総人口の OR ≈ 0.23(95%CI 0.08〜0.65, p≈0.006)——人口規模の大きい県ほど高齢化率が上位に入りにくい、 という強い負の関連が実データから読める(実測値・捏造なし)。
閾値を $p=0.5$ にすると、 判定が切り替わるのは $z=0$、 すなわち $\beta_0+\beta_1x_1+\dots=0$ の面。 これは説明変数空間では直線(多次元なら超平面)で、 ロジスティック回帰が「線形分類器」と呼ばれる所以。 確率の等高線($p=0.3,0.5,0.7\dots$)はこの境界に平行に並ぶ。 非線形な境界が必要なら、 多項式特徴量・交互作用項を足すか、 分類の非線形手法(木・SVM・NN)へ切り替える。
ロジスティック回帰は「動く」が「正しく読む」のは難しい。 実務・コンペで踏みやすい 8 つの罠を、 対処とともに整理する。
最頻の誤読。 $\exp(\beta_j)$ はオッズの倍率であって「確率が何ポイント上がるか」ではない。 確率スケールの変化(限界効果 $\partial p/\partial x_j = \beta_j\,p(1-p)$)は今いる $p$ の位置に依存し、 $p=0.5$ 付近で最大、 端では小さい。 「OR=2」を「確率が 2 倍」「確率が +50%」と言い換えるのは誤り。 確率への効果を語りたいときは statsmodels の get_margeff() で平均限界効果 (AME) を出す。
ある説明変数(の組合せ)だけで 0/1 を完璧に切り分けられると、 尤度を上げ続けるほど係数が $\pm\infty$ へ発散し、 最尤推定 (交差エントロピー最小化) が収束しない。 sklearn は L2 正則化が既定なので有限値を返すが「巨大な係数+巨大な標準誤差」に化ける。 対処: Firth のペナルティ付きロジスティック、 強めの正則化、 ベイズ事前分布、 あるいは分離を起こす変数の見直し。 標本が小さい(SSDSE の n=47 のような)場面ほど起きやすい。
説明変数どうしが強く相関すると、 個々の $\beta_j$ の符号・大きさが標本のわずかな違いで揺れ、 オッズ比の解釈が崩れる(多重共線性)。 予測精度は保たれても「どの要因が効くか」の話は信用できない。 VIF で確認し、 変数の統合・除去、 または Ridge(L2)で縮小する。
「モデルが 0.8 と言った群で実際に約 80% が陽性」であって初めて確率として使える。 正則化の強い設定・不均衡データ・誤特定では、 出力確率が系統的にずれる(キャリブレーションずれ)。 信頼度図 (reliability diagram) と Brier スコアで点検し、 Platt スケーリングや等温回帰 (isotonic) で補正する。 順位(AUC)は良くても確率値が信用できない、 は普通に起きる。
陽性率が数 % だと、 全部「陰性」と答えるだけで Accuracy が高く見え、 少数派の 再現率が壊滅する(クラス不均衡)。 class_weight='balanced'・オーバーサンプリング (SMOTE)・閾値調整で対処し、 評価は Accuracy でなく F1・AUC・PR 曲線を見る。
ロジスティック回帰が線形にするのはロジット。 説明変数と対数オッズの関係が実際は曲がっているのに直線を当てると、 系統的な当てはめ不足になる。 連続変数はビン化して各区間のロジットをプロットする、 スプライン・多項式項を足す等で非線形性を診断・吸収する。
0.5 は「対称な誤りコスト・均衡データ」での既定値にすぎない。 見逃し (FN) と誤検出 (FP) のコストが違う(病気検出は FN 重視、 スパムは FP 重視)なら閾値をずらすべき。 ROC 曲線や PR 曲線で運用点を選ぶ。 閾値はモデルの外側で決めるパラメータであり、 係数推定とは別問題。
学習データの説明変数レンジの外では、 モデルは飽和領域($p\approx0$ または $1$)へ自信満々に張り付く。 だが根拠となるデータが無い領域なので、 その確信は幻。 予測時は入力が学習範囲内かを確認し、 範囲外の予測には強い留保を付ける。 n=47 の都道府県データのように標本が小さいと、 数県分だけレンジ外に出た瞬間に予測が不安定化する。
ロジスティック回帰を「一つの点」ではなく「大きな地図上の交差点」として捉えるための発展トピック。
係数は最尤推定 (MLE) で決める。 各観測の尤度 $p_i^{y_i}(1-p_i)^{1-y_i}$ の積を最大化することは、 負の対数尤度=交差エントロピー損失(log loss)の最小化と等価。 線形回帰の最小二乗と違い閉形式解はなく、 ニュートン法 (IRLS) や勾配降下で反復的に解く。 損失は凸なので(正則化ありなら強凸)、 局所最適に嵌まらず大域解に収束する。
「要因の相対的な効き」を語るなら $\exp(\beta_j)$(オッズ比)、 「確率が実際に何ポイント動くか」を語るなら限界効果 (AME)。 医学・疫学ではオッズ比、 政策・ビジネスの効果量説明では確率スケールの限界効果が好まれる。 両者は同じモデルの別表現で、 どちらを報告するかは聞き手の問いで選ぶ。 SSDSE の 2 変数モデルでは総人口 OR≈0.23 と強い一方、 消費支出 OR≈0.72 は 95%CI が 1 をまたぎ(p≈0.39)有意でない——CI が 1 を含むかがオッズ比読解の第一関門。
3 クラス以上は多項ロジスティック回帰。 シグモイドを softmax $\;p_k=e^{z_k}/\sum_j e^{z_j}$ に置き換え、 各クラスの線形結合を確率ベクトルへ正規化する。 二値のシグモイドは softmax の 2 クラス特例。 sklearn では multi_class='multinomial'(または既定の自動選択)で扱える。
過学習・不安定さ対策に正則化を足す。 L1 (Lasso) は係数を 0 に落として変数選択、 L2 (Ridge) は係数を縮小して安定化、 Elastic Net はその中間。 sklearn の C はペナルティの逆数(C 小=強い正則化)で、 既定 C=1.0 は弱め。 n が小さいときは C を下げる価値がある。 正則化は完全分離の発散も抑える。
プロビット回帰はリンク関数に標準正規 CDF $\Phi(z)$ を使う。 シグモイド(ロジット)は裾がやや重く、 実務では推定確率はほぼ一致する。 決定的な違いは係数の解釈: ロジットは exp してオッズ比という直接解釈ができるのに対し、 プロビット係数にはオッズ比解釈がない。 解釈性を重視するならロジット、 潜在変数モデル(正規誤差の閾値モデル)として組みたいならプロビット。
ロジスティック回帰は一般化線形モデル (GLM) の「二項分布 + ロジットリンク」の特例(ロジスティック GLM)。 誤差分布とリンク関数を差し替えれば、 ポアソン回帰(計数)・線形回帰(正規+恒等リンク)などと同じ枠組みで一望できる。 statsmodels の GLM(family=Binomial()) でもロジスティック回帰が書ける。
分類性能は閾値に依存するため、 閾値を動かしながら TPR–FPR を描く ROC 曲線と、 その下面積 AUC で総合評価する。 AUC=0.5 は当てずっぽう、 1.0 が完璧、 0.8 以上で実用的とされる。 SSDSE の標準化 2 変数モデルでは AUC≈0.82・McFadden 擬似 R²≈0.26(実測)と、 47 県という小標本のわりに素直な分離が得られる。 不均衡が強い場面では ROC より PR 曲線が実態を映す。