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

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

## ロジスティック回帰について
- 2値分類の基本的なアルゴリズムである. (回帰と書いてあるが、分類のアルゴリズム)
- いくつかの要因(説明変数)から、目的変数[0/1]が起こる確率を予測するアルゴリズム
例) 患者の情報(年齢、体重、血圧など)から、ある病気にかかるかどうかを予測する
<br>
回帰をそのまま分類に使うと、0~1の範囲を超えてしまう問題がある。どうにかして0~1の範囲に収める必要がある。そこで、シグモイド(ロジスティック)関数を用いる。シグモイド関数は以下のような数式である。
$$ f(x) = \frac{1}{1 + \exp(-x)} $$
このシグモイド関数をグラフに表すと、下のようになる。

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750206/9f18407d-3ac9-d4eb-a62f-71b48ae6c231.png' width=50%>

このシグモイド関数の*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$のとき、つまり、正解データが０であるとき
上記の式に、$y_i = 0$を代入すると、以下の式になる。
$$
Cost(y_i, \hat{y_i}) = -\log(1 - \hat{y}_i)
$$

<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750206/599264f5-4476-9a04-1937-5086bae1cdcd.png' width=50%>

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

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

上記の式に、$y_i = 1$を代入すると、以下の式にある
$$
Cost(y_i, \hat{y_i}) = -\log(\hat{y}_i)
$$
<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750206/0b80e1c2-d803-1b28-4e2d-c26a25bbe3b5.png' width=50%>


$ y = 0$の時と同様に、予測した結果が$y_i = 1$だった場合、正解データと同じだから、損失が０であることはグラフや数式からわかる。
一方で、予測した結果が正解データ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$の２つを最急降下法を用いて、最適化すると、以下のような数式になる。


$$
\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} $は以下のようになる。
```math
\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}   $を求める。



```math
\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
)
```
```math

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

```math

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

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


```math
\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}$は以下のようになる。
```math
\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
$$



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





```py
# ライブラリ
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/