0
2

ロジスティック回帰を復習

Last updated at Posted at 2024-04-02

分類アルゴリズム

  • 目的変数0/1の2値として扱う(2値分類の場合)
  • 回帰だと予測値が0~1の範囲を超えてしまうため、そのまま使うことができない
  • 多クラス分類の場合、目的変数を0, 1, 2のように量的変数のように使うことができない
    • なぜなら、量的変数にすると、数値間で距離、順序があると捉えられるから

ロジスティック回帰について

  • 2値分類の基本的なアルゴリズムである. (回帰と書いてあるが、分類のアルゴリズム)
  • いくつかの要因(説明変数)から、目的変数[0/1]が起こる確率を予測するアルゴリズム
    例) 患者の情報(年齢、体重、血圧など)から、ある病気にかかるかどうかを予測する

回帰をそのまま分類に使うと、0~1の範囲を超えてしまう問題がある。どうにかして0~1の範囲に収める必要がある。そこで、シグモイド(ロジスティック)関数を用いる。シグモイド関数は以下のような数式である。 $$ f(x) = \frac{1}{1 + \exp(-x)} $$ このシグモイド関数をグラフに表すと、下のようになる。

このシグモイド関数のxに線形回帰を代入すれば、上記のように0~1の範囲に収めることができる。
出力した値は0~1になるから、確率して解釈することができる。

損失関数

損失関数とは、モデルが出力した予測値と正解値のズレ(差)を計算する関数である。
機械学習や深層学習では、損失関数の値を最小化するように学習を行っていく。

ロジスティック回帰の損失関数は、交差エントロピー(Cross entropy)を用いる。
まず、ロジスティック回帰は以下のように定義しておく。
$$ \hat{y_i} = \frac{1}{1 + \exp (-(\theta_0 + \theta_1 x))} $$
次に、データiにおける損失を$Cost(y, \hat{y_i})$とすると、交差エントロピーは以下のような数式で表される。

$$
Cost(y_i, \hat{y_i}) = -(y_i \log(\hat{y}_i) + (1 - y_i) \log(1 - \hat{y}_i))
$$

これは、$y=0$と$y=1$で別々に考えるとわかりやすい。

  • $y = 0$のとき、つまり、正解データが0であるとき
    上記の式に、$y_i = 0$を代入すると、以下の式になる。
    $$
    Cost(y_i, \hat{y_i}) = -\log(1 - \hat{y}_i)
    $$

例えば、予測した結果$ y_i = 0 $だった場合、正解データと同じだから、損失0であることはグラフや数式からわかる。
一方で、予測した結果が正解データ0より遠ければ遠いほど、的外れな予測をしているため、損失が大きいことがわかる。

  • $y = 1$のとき、つまり、正解データが1であるとき

上記の式に、$y_i = 1$を代入すると、以下の式にある
$$
Cost(y_i, \hat{y_i}) = -\log(\hat{y}_i)
$$

$ y = 0$の時と同様に、予測した結果が$y_i = 1$だった場合、正解データと同じだから、損失が0であることはグラフや数式からわかる。
一方で、予測した結果が正解データ1より遠ければ遠いほど、的外れな予測をしているため、損失が大きいことがわかる。

しかし、先ほどの交差エントロピーの数式はあるデータ$i$の損失を求める式である。そして、データ数N個あるときの損失を求める式は以下のようになる。

$$
L(\theta) = -\frac{1}{N} \sum_{i=1}^{N} \left[ y_i \log(\hat{y}_i) + (1 - y_i) \log(1 - \hat{y}_i) \right]
$$

最急降下法を用いて、最適なパラメータを見つける

損失関数を定義したら、最急降下法を用いて、最適なパラメータを見つけることができる。パラメータが$\theta_0, \theta_1$の2つを最急降下法を用いて、最適化すると、以下のような数式になる。

$$
\theta_0 := \theta_0 - \alpha \frac{\partial}{\partial \theta_0} L(\theta_0, \theta_1)
$$

$$
\theta_1 := \theta_1 - \alpha \frac{\partial}{\partial \theta_1} L(\theta_0, \theta_1)
$$

なお、学習率を$\alpha$とする。
そしてロジスティック回帰の式を$ \hat{y} = \frac{1}{1 + \exp(-(\theta_0 + \theta_1x))} $とすると、最急降下法で最適なパラメータ$\theta$を最適化する式は、以下のようになる。
まず、$\frac{\partial L}{\partial \theta_0} $は以下のようになる。

\frac{\partial L}{\partial \theta_0} =\frac{\partial L}{\partial \hat{y}_i}\frac{\partial \hat{y}_i}{\partial z}\frac{\partial z}{\partial \theta_0}   

次に、それぞれの、$\frac{\partial L}{\partial \hat{y}_i}, \frac{\partial \hat{y}_i}{\partial z}, \frac{\partial z}{\partial \theta_0} $を求める。

\frac{\partial L}{\partial \hat{y}_i}=  -\frac{1}{N} \sum_{i=1}^{N} \left(-\frac{y_i}{\hat{y}_i} + \frac{1 - y_i}{1 - \hat{y}_i} \right
)

\frac{\partial \hat{y}_i}{\partial z} = \sigma(z)(1 - \sigma(z))= \hat{y}_i(1-  \hat{y}_i)

\frac{\partial z}{\partial \theta_0} = 1

そうすると、$\frac{\partial L}{\partial \theta_0}$は 次のようになる。

\begin{align*}
\frac{\partial L}{\partial \theta_0} &= \frac{\partial L}{\partial \hat{y}_i}\frac{\partial \hat{y}_i}{\partial z}\frac{\partial z}{\partial \theta_0} \\
&= -\frac{1}{N} \sum_{i=1}^{N} \left( \frac{y_i}{\hat{y}_i} - \frac{1 - y_i}{1 - \hat{y}_i} \right) \cdot \hat{y}_i(1 - \hat{y}_i) \\
&= -\frac{1}{N} \sum_{i=1}^{N} (y_i - \hat{y}_i)
\end{align*}

この$(y_i - \hat{y}_i)$は正解値と予測値のさになっていることがわかる。
同様に、$\frac{\partial L}{\partial \theta_1}$は以下のようになる。

\frac{\partial L}{\partial \theta_1}= -\frac{1}{N} \sum_{i=1}^{N} (y_i - \hat{y}_i)x_i

したがって、パラメータ$\theta_0, \theta_1$を更新する式は以下のようになる。
$$
\theta_0 := \theta_0 + \alpha\frac{1}{N} \sum_{i=1}^{N} (y_i - \hat{y}_i)
$$

$$
\theta_1 := \theta_1 + \alpha\frac{1}{N} \sum_{i=1}^{N} (y_i - \hat{y}_i)x_i
$$

実際にロジスティック回帰を使って、学習してみる

実際にロジスティック回帰を使って、学習してみる
今回はタイタニックのデータを使って、ロジスティック回帰を行う。単にロジスティック回帰を使うこととして、より精度の高い手法があると思うが、それは一旦置いておく。

# ライブラリ
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
# 評価指標
from sklearn.metrics import log_loss, accuracy_score

# Titanicデータセットの読み込み
df = sns.load_dataset("titanic")

# 今回は欠損値のある行は削除
df.dropna(inplace=True)

#  説明変数と目的変数を設定
X = df.loc[:, (df.columns!='alive') & (df.columns!='survived')]
X = pd.get_dummies(X, drop_first=True)
y = df['survived']

# 学習データとテストデータに分ける
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)

model = LogisticRegression()
model.fit(X_train, y_train)

y_pred = model.predict(X_test)
y_pred_proba = model.predict_proba(X_test)

# 評価
logloss = log_loss(y_test, y_pred_proba)
accuracy = accuracy_score(y_test, y_pred)

print('logloss:', logloss)
print('accuracy:', accuracy)

出力結果

logloss: 0.41115807724466186
accuracy: 0.7636363636363637

まとめ

  • 線形回帰の結果をシグモイド関数を使って0~1の範囲に収める
  • 損失関数は交差エントロピーを用いる

参考

[1] https://datawokagaku.com/logistic_reg/
[2] https://www.udemy.com/course/mlpython-2/

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2