🟠

ロジスティック回帰分析とは?

2023/09/29に公開

はじめに

今回はロジスティック回帰(logistic regression)について、をわかりやすく解説します。
今回扱うのは、yの値が2値の場合です。

そもそも2値ってなんだよ!って、思われた方もいらっしゃると思います。
2値とは、たとえば、'Yes or No'とか、'赤 or 白'みたいな2つの値のことです。

ロジスティック回帰では2つに分類する問題を考えるんです。

医学の領域で使われることが多い分析方法です。回帰と名前についていますが、分類 なので注意です。
分類は基本的にはどちらかに分けるのですが、このロジスティック回帰は分類される確率を出すのでややこしいかもしれませんがこの記事で理解できるはずです!  
わからないことがあればぜひ質問してください!

わかりやすいように例を元に説明させていただきます。

ある学校の生徒10人(Aさん~Jさん)のテストの結果のデータがある。そこから、その10人以外の子(例えばKさん)が、合格か不合格かを分類したいとする。
テストの結果には、1人につき数学の点数、国語の点数、英語の点数の3つと、合格か不合格かの情報がある。

名前 数学の点数 国語の点数 英語の点数 合格か不合格か
Aさん 85 78 92 合格
Bさん 68 74 80 不合格
Cさん 90 85 88 合格
Dさん 73 79 84 合格
Eさん 60 55 65 不合格
Fさん 82 87 89 合格
Gさん 77 70 75 不合格
Hさん 91 88 93 合格
Iさん 65 67 69 不合格
Jさん 80 83 86 合格

これを一般的に数式に直すと、

観測データ (x_1,y_1),\cdots,(x_N,y_N) \in \mathbb R^p \times \{0,1\}からx\in \mathbb R^p \rightarrow y \in \{0,1\}を導きたい。

Nは人数で今回は10。x\in\mathbb R^pはデータが数値でp個あることを意味していて、今回は3。y \in \{0,1\}は合格(y=1)か不合格(y=0)かを表す。
y=1となる確率をpとする。逆にy=0となる確率は1-pになります。

\displaystyle\frac{p}{1-p}オッズと言い、オッズの対数をとったものが線型結合(足し算で繋がっているやつ)で表されると考える。ちょっと意味わからないと思うので、下記モデルを見てください。

つまり次のようなモデルを考える。

Q. なぜこのような変換をしたか?

A. オッズ\displaystyle\frac{p}{1-p}を対数取ると尺度が合うから。

具体例

  • 確率 p=\frac{1}{10}、オッズは \frac{1}{9}=0.11\displaystyle\log\left(\frac{p}{1-p}\right)=-2.2

  • このとき確率 p=\frac{9}{10}、オッズは \frac{9}{1}=9\displaystyle\log\left(\frac{p}{1-p}\right)=2.2

となりこの2つをみると、
オッズを比較すると0.11と9でオッズには対称性がないが、対数を取ると-2.2と2.2となり対称性があるので比較しやすくなる。

ロジスティック回帰曲線

このモデルからpの式に直す。

\begin{align*} &\frac{p}{1-p}=e^{\beta_0+x^T\beta}\\ &p=(1-p)e^{\beta_0+x^T\beta}\\ &p(1+e^{\beta_0+x^T\beta})=e^{\beta_0+x^T\beta}\\ &p=\frac{e^{\beta_0+x^T\beta}}{1+e^{\beta_0+x^T\beta}} =(1+e^{-(\beta_0+x^T\beta)})^{-1} \end{align*}

となる。

ここで注意なのですが、このpは真のpです。つまりデータから得られたp(今回で言うとp=\frac{6}{10})ではないので、pの推定量である\hat{p}を求めます。

最尤推定で(\hat{\beta_0},\hat{\beta})を求めることで、

が求められる。
この最尤推定は普通には解けないのですが、ニュートンラフソン法を用いることで解析的に解くことができます。(証明は長いので次の記事で書いてます)

最終的に、新しい子のデータxを入れるとその子が合格する確率が求められると言う流れでした。

まとめ

今回は、ロジスティック回帰の設定から回帰曲線の導出までやりました。
なぜオッズの対数を取って比較しやすくするテクニックはなるほどなと思いました。
最尤推定の証明はこちらです。
https://zenn.dev/totopironote/articles/1da4388e00306f

おまけのPythonコード

import pandas as pd
import numpy as np
import statsmodels.api as sm
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

#データの準備
data = {
    "名前": ["Aさん", "Bさん", "Cさん", "Dさん", "Eさん", "Fさん", "Gさん", "Hさん", "Iさん", "Jさん"],
    "数学の点数": [85, 68, 90, 73, 60, 82, 77, 91, 65, 80],
    "国語の点数": [78, 74, 85, 79, 55, 87, 70, 88, 67, 83],
    "英語の点数": [92, 80, 88, 84, 65, 89, 75, 93, 69, 86],
    "合格か不合格か": ["合格", "不合格", "合格", "合格", "不合格", "合格", "不合格", "合格", "不合格", "合格"]
}

df = pd.DataFrame(data)
df['合格か不合格か'] = df['合格か不合格か'].map({"合格": 1, "不合格": 0})

#特徴量とターゲットの設定
X = df[["数学の点数", "国語の点数", "英語の点数"]]
y = df["合格か不合格か"]

#ロジスティック回帰モデルの学習
model = LogisticRegression()
model.fit(X, y)

#係数の取得
coefficients = model.coef_
intercept = model.intercept_

#テストデータ
import pandas as pd

test_data = {
    "名前": ["Kさん", "Lさん", "Mさん", "Nさん", "Oさん"],
    "数学の点数": [ 88, 69, 92, 75, 78],
    "国語の点数": [ 80, 76, 86, 72, 75],
    "英語の点数": [ 85, 78, 90, 73, 77],
    "合格か不合格か": ["合格", "不合格", "合格", "不合格", "合格"]
}

df_test = pd.DataFrame(test_data)
df_test['合格か不合格か'] = df_test['合格か不合格か'].map({"合格": 1, "不合格": 0})

#KさんからOさんの合格確率を表示
pre = model.predict_proba(df_test[["数学の点数", "国語の点数", "英語の点数"]])[:,1]

test_predictions = (pre >= 0.5).astype(int)

test_labels = df_test["合格か不合格か"]

#Calculate accuracy
accuracy = accuracy_score(test_labels, test_predictions)

#各生徒の合格率をパーセンテージで表示
for i in range(len(pre)):
    print(df_test["名前"][i], "の合格率:", f"{pre[i]*100:.2f}%", " 予測結果:", test_predictions[i] , " 実際の結果:" , test_labels[i])

print("分類の正解率:", accuracy*100,'%')

結果

Kさん の合格率: 99.93%  予測結果: 1  実際の結果: 1
Lさん の合格率: 8.99%  予測結果: 0  実際の結果: 0
Mさん の合格率: 100.00%  予測結果: 1  実際の結果: 1
Nさん の合格率: 1.05%  予測結果: 0  実際の結果: 0
Oさん の合格率: 30.87%  予測結果: 0  実際の結果: 1
分類の正解率: 80.0 %

参考文献

  • 鈴木 譲 「統計的機械学習の数理100問 with Python」 p.47

Discussion