【ラビットチャレンジ】要点のまとめ - 機械学習 その３

# 1. はじめに
本記事はJDLA E資格の認定プログラム「ラビットチャレンジ」における機械学習のレポート記事である。
本記事では機械学習における「ロジスティック回帰モデル」について要点をまとめている。

[【ラビットチャレンジ】要点のまとめ - 機械学習 その１](https://qiita.com/PoppeDwarf/items/92ba5a6ebd35a9f53ae0)
[【ラビットチャレンジ】要点のまとめ - 機械学習 その２](https://qiita.com/PoppeDwarf/items/80724b0b92d01c9a9421)
【ラビットチャレンジ】要点のまとめ - 機械学習 その３
[【ラビットチャレンジ】要点のまとめ - 機械学習 その４](https://qiita.com/PoppeDwarf/items/01cc119c707fe3e26f1d)
[【ラビットチャレンジ】要点のまとめ - 機械学習 その５](https://qiita.com/PoppeDwarf/items/6cb3929a4668ecf1c2ab)
[【ラビットチャレンジ】要点のまとめ - 機械学習 その６](https://qiita.com/PoppeDwarf/items/83f7e350e6720e801038)

# 2. ロジスティック回帰モデル
## 2.1. 分類問題
ある入力（数値）からクラスに分類する問題

## 2.2. 分類で扱うデータ
説明変数：$ \boldsymbol{x} = (x_{1}, x_{2}, ... , x_{m})^{T} \in \mathbb{R}^{m} $
$ \qquad \boldsymbol{x} $：説明変数。$m$次元のベクトル
$ \qquad x_{1}, x_{2}, ... , x_{m} $：説明変数$ \boldsymbol{x} $のエレメント

目的変数：$ \boldsymbol{y} \in \\{0, 1\\} $
$ \qquad \boldsymbol{y} $：目的変数。0か1

## 2.3. ロジスティック線形回帰モデル
分類問題を解くための機械学習モデルの一。教師あり学習。
$m$次元の入力およびパラメータの線形結合をシグモイド関数に入力し、$ y=1 $になる確率を出力する。

教師データ：$ \smash{\bigl\\{ ( \boldsymbol{x_{i}}, \boldsymbol{y_{i}} ); i = 1, ... , n\bigr\\}} $
$ \qquad $説明変数と目的変数をひとつのペアとしたデータ
$ \qquad \boldsymbol{x} $：説明変数。$m$次元のベクトル
$ \qquad \boldsymbol{y} $：目的変数。0か1
$ \qquad n $：教師データ数
$ \qquad i $：教師データの参照インデックス。$1～n$の間をとる

パラメータ：$ \boldsymbol{w} = (w_{1}, w_{2}, ... , w_{m})^{T} \in \mathbb{R}^{m}  $
$ \qquad \boldsymbol{w} $：パラメータ。$m$次元のベクトル

線形結合：$ \hat{y} = \boldsymbol{w}^{T}\boldsymbol{x} + w_{0} = \sum_{j=1}^{m}w_{j}x_{j} + w_{0} $
$ \qquad \hat{y} $：予測値。正解データと区別するためハット「$\hat{}$」をつける。
$ \qquad \boldsymbol{x} $：説明変数
$ \qquad \boldsymbol{w} $：モデルのパラメータ
$ \qquad w_{0} $：切片
$ \qquad m $：パラメータおよび説明変数の次元数
$ \qquad j $：次元のインデックス。$1～m$の間をとる

## 2.4. シグモイド関数
### 2.4.1. シグモイド関数
入力は実数、出力は必ず$0～1$の値をとる単調増加関数。
クラス１に分類される確率を表現する。

シグモイド関数：$ \smash{ \qquad \sigma(x) = \dfrac{1}{1 + exp(-ax)} }$

### 2.4.2. シグモイド関数の性質
シグモイド関数の微分はシグモイド関数自身で表現可能。

$ \smash{ \dfrac{ \partial \sigma(x) }{ \partial x } = \dfrac{ \partial }{ \partial x } \Bigl( \dfrac{1}{1 + exp(-ax)} \Bigr) } $

このとき$ t = 1 + exp(-ax) $とおくと$ \smash{ \dfrac{ \partial \sigma(x) }{ \partial x } = \dfrac{ \partial }{ \partial x } \Bigl( \dfrac{1}{t} \Bigr) = \dfrac{ \partial }{ \partial x } \Bigl( t^{-1} \Bigr) } $

連鎖律より$ \smash{ \dfrac{ \partial \sigma(x) }{ \partial x } = \dfrac{ \partial \sigma(x) }{ \partial t }\dfrac{ \partial t }{ \partial x } = \dfrac{ \partial }{ \partial t }\Bigl( t^{-1} \Bigr)\dfrac{ \partial }{ \partial x }\Bigl( 
1 + exp(-ax) \Bigr) } $

これを解くと$ \smash{ \dfrac{ \partial \sigma(x) }{ \partial x } = (-1) \cdot \Bigl\\{ 1 + exp(-ax) \Bigr\\}^{-2} } \cdot exp(-ax) \cdot (-a) = \dfrac{a \; exp(-ax)}{\\{ 1 + exp(-ax) \\}^{2} } $

さらに整理して$ \smash{ \dfrac{a \; exp(-ax)}{\\{ 1 + exp(-ax) \\}^{2}} = a \cdot \dfrac{1}{1 + exp(-ax)} \cdot \Bigl( \dfrac{1 + exp(-ax)}{1 + exp(-ax)} - \dfrac{1}{1 + exp(-ax)} \Bigr) } $
　
　
よって $ \smash{ \sigma(x) = \dfrac{1}{1 + exp(-ax)} }$ より $ \smash{ \dfrac{ \partial \sigma(x) }{ \partial x } = \sigma(x)(1 - \sigma(x))} $ となり、

シグモイド関数の微分はシグモイド関数自身で表現できるとわかる。

機械学習はモデルを決めてその中のパラメータを推定する、つまりMSEや尤度などの基準を最小 or 最大にすることで推定するため、必ず微分が必要になってくる。
そこで微分を自身で表現できるシグモイド関数を使うと計算量を抑えることができるため、シグモイド関数が使われやすいという背景がある。

## 2.5. 最尤推定
### 2.5.1. 最尤推定
データから、そのデータを生成したであろう尤もらしい分布（パラメータ）を推定する方法。データを固定し、尤度関数が最大となるようにパラメータを選ぶ。

### 2.5.2. 尤度関数・対数尤度関数
尤度関数：$ \smash{ L(\boldsymbol{w}) = \prod_{i=1}^{n}\sigma(\boldsymbol{w}^{T}\boldsymbol{x}\_{i})^{\boldsymbol{y}\_{i}}(1 - \sigma(\boldsymbol{w}^{T}\boldsymbol{x}\_{i}))^{1-\boldsymbol{y}\_{i}} } $
$ \qquad L(\boldsymbol{w}) $：尤度関数
$ \qquad \prod_{i=1}^{n} $：総乗。$1～n$までをすべて掛け合わせるこをと表す記号
$ \qquad \boldsymbol{w} $：回帰係数
$ \qquad \boldsymbol{x}_{i} $：説明変数。$m$次元のベクトル
$ \qquad \boldsymbol{y}\_{i} $：目的変数。0か1

尤度関数「$ L(\boldsymbol{w}) $」の微分は掛け算の微分となり、計算が煩雑となってしまう。
そこで尤度関数の対数をとる対数尤度関数「$ log \; L(\boldsymbol{w}) $」がよく使用される。

### 2.5.3. 勾配降下法
反復学習によりパラメータを逐次的に更新するアプローチの一。
学習率（$\eta$：イータ）というハイパーパラメータでモデルのパラメータの収束しやすさを調整する必要がある。

線形回帰モデル（最小二乗法）では平均二乗誤差の微分が0になる点を解析的に求めることが可能だったが、ロジスティック回帰モデルにおいて、同様に対数尤度関数をパラメータで微分⇒0になる点を解析的に求めることが不可能である。
そのため、勾配降下法という手法を用いてパラメータを逐次的に更新し、パラメータの最適化を図る必要がある。

### 2.5.4. 確率的勾配降下法（SGD）
データをひとつずつランダムに選んでパラメータを逐次的に更新していくアプローチ。
勾配降下法でパラメータを1回（一巡）更新するのと同じ計算量でパラメータをデータの数ぶん更新できるため、効率よく最適な解を探索可能である。

## 2.6. ロジスティック回帰モデルの評価
### 2.6.1. 混同行列
![MixedMatrix.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110108/b613acd3-ed21-45d3-b2a2-174f22d4b3db.png)

- 真陽性（True Positive）：正しくPositiveと予測された場合
- 偽陽性（False Negative）：本来PositiveなのにNegativeと予測された場合  
  - 日本語と英語で捉え方が逆であることに注意  
    　→日本語：陽性であることを偽った場合  
    　→英　語：誤って陰性と判断した場合
- 偽陰性（False Positive）：本来NegativeなのにPositiveと予測された場合  
  - 日本語と英語で捉え方が逆であることに注意  
    　→日本語：陰性であることを偽った場合  
    　→英　語：誤って陽性と判断した場合
- 真陰性（True Negative）：正しくNegativeと予測された場合

### 2.6.2. 正解率

正解率：$ \smash{ \dfrac{正しく判別できたデータ数}{予測対象の全データ数} = \dfrac{ [True Positive] + [True Negative] }{ [True Positive] + [False Negative] + [False Positive] + [True Negative] } } $
　

- 問題点：データの分類が不均衡だった場合、予測精度が悪くても正解率が高くなってしまう可能性がある。

### 2.6.3. 再現率（Recall）

再現率（Recall）：$ \smash{ \dfrac{正しくPositiveと判別できたデータ数}{実際にPositiveなデータ数} = \dfrac{ [True Positive] }{ [True Positive] + [False Negative] } } $
　

- 使用が適切な場合：  
　偽陰性（False Positive）が多少多くても抜け漏れが少ないことが重要な場合に用いる。  
　例：病気の診断のように異常なしと誤診断するほうが問題な場合など

### 2.6.4. 適合率（Precision）

適合率（Precision）：$ \smash{ \dfrac{実際にPositiveだったデータ数}{Positiveと判別したデータ数　　　　　　　} = \dfrac{ [True Positive] }{ [True Positive] + [False Positive] } } $
　

- 使用が適切な場合：  
　偽陽性（False Negative）が多少多くてもより正確な判別が重要な場合に用いる。  
　例：スパムメールの判別のように重要なメールを誤ってスパムと判別するほうが問題な場合など

### 2.6.5. F値
再現率と適合率の調和平均。再現率と適合率はトレードオフの関係にあり、F値が高ければ高いほど再現率と適合率がともにバランスよく高くなっている。

F値：$ \smash{ \dfrac{2 \cdot Recall \cdot Precision}{Recall + Precision} } $
　

- 参考：  
[F値 - 機械学習の「朱鷺の杜Wiki」](http://ibisforest.org/index.php?F%E5%80%A4)

# 3. ハンズオン
## 3.1. 課題
タイタニックの乗客データからロジスティック回帰モデルを作成し、特徴量を抽出する。
その上で30歳男性の乗客が生き残れるかを判別する。

## 3.2. 演習結果
### 3.2.1. ロジスティック回帰
#### 3.2.1.1. Google Driveのマウント
![03_skl_logistic_regression_01_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110108/c7a6e253-178e-5e9f-4d46-f14900ffc7dd.jpeg)

#### 3.2.1.2. 必要なモジュールのインポート
![03_skl_logistic_regression_02_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110108/a8377d94-c50d-9e61-a039-0e42f57cdce3.jpeg)

#### 3.2.1.3. データの読み込み・不要なデータの削除・欠損値の補完
データをcsvファイルから読み込む。
![03_skl_logistic_regression_02_02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110108/72e68eb3-c8d9-c5c6-1005-ffc02e4fb59a.jpeg)

不要なデータ（カラム）の削除はdropメソッドを用いる。
`titanic_df[titanic_df.isnull().any(1)])`
　→タイタニック乗客データのうち、いずれかのカラムに一つでもnull(NaN)が含まれている行をすべて取得する。

- 参考：[pandasで欠損値NaNが含まれているか判定、個数をカウント](https://note.nkmk.me/python-pandas-nan-judge-count/)

![03_skl_logistic_regression_03_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110108/4f019885-13c2-8a53-1c63-45d6ee2fe50d.jpeg)

欠損を含んでいる行を確認。
![03_skl_logistic_regression_03_02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110108/d25e335d-7325-dfad-f00a-1e15fe0af9d9.jpeg)

年齢カラムで欠損しているデータを平均値で補完する。
`DataFrame.fillna()`
　→欠損データを引数で与えた設定や数値で補完するメソッド。
　　今回は年齢の平均値（`titanic_df['Age'].mean()`）で補完しているが、これ以外にも中央値（`titanic_df['Age'].median()`）、最頻値（`titanic_df['Age'].mode()`）などでの補完、前後のデータを利用した補完（`method='ffill'、method='bfill'`）などもある。

- 参考：[Pandasでnan値を削除、穴埋めするfillna、dropnaの使い方 - DeepAge](https://deepage.net/features/pandas-manipulate-na.html)

![03_skl_logistic_regression_04.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110108/e3f7c43f-4f84-4fb0-2fff-3c38a1236ef8.jpeg)

#### 3.2.1.4. 1変数（チケット価格）でのロジスティック回帰
![03_skl_logistic_regression_05_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110108/9c65da02-c18c-da3f-f727-c8fb3a081023.jpeg)

- 考察：
　チケットが61ドルの乗客は死亡と判定されている。
　しかし62ドルの乗客のほうは辛うじてではあるが生存のほうの確率が高い。
　つまり61ドルと62ドルの間に分岐点があることがわかる。

- model.intercept
　：切片 = -0.9413
- model.coef
　：回帰係数 = 0.0151

![03_skl_logistic_regression_06_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110108/45eb8261-67be-4c64-e77d-d9e85d4de6fb.jpeg)

#### 3.2.1.5. 2変数でのロジスティック回帰
性別（Sex）を文字列から数値（女性：0, 男性：1）に変換しGenderに格納。
![03_skl_logistic_regression_09_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110108/ebbca0e0-926a-09df-2db1-1cf2a4c534f4.jpeg)

#### 3.2.1.6. 年齢と性別でのロジスティック回帰（課題に該当）
説明変数に「年齢」「性別」を、目的変数に「生死」を設定→学習。
「30歳男性」の
　生死判定を`model_assignment.predict([30, 1])`
　生存確率を`model_assignment.predict_proba([30, 1])`
で予測する。
![03_skl_logistic_regression_10_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110108/04ede989-ef28-58e2-3275-cd7aaba3e848.jpeg)
「生存判定：死亡　生存確率：0.1933」という、ほぼほぼ死亡する予測が出た。
タイタニック乗客データを「年齢」「性別」「生死」でプロットしてみる。
![03_skl_logistic_regression_11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110108/ad90e746-1820-ae25-5bdc-1e039c747772.jpeg)
上記より、女性は年齢問わず生存者数が高いことがわかる。
気になるのは「30歳男性」のあたりが生存者数（青い点）が多いように見えることだが、おそらく「人数的に多いこと（生存者も多い）」および「プロット時生存者（青い点）のほうを後にプロットしている」ことに起因しているだけだと推察する。

#### 3.2.1.7. 年齢と社会階級+性別でのロジスティック回帰
まず「社会階級」データおよび「性別」データを結合する。
　このとき、「『社会階級高 かつ 女性』 = 1」 ⇔ 「『社会階級低 かつ 男性』 = 4」 となる。
次に不要なカラム（社会階級、性別（Stringおよび数値）、年齢（欠損あり））を「drop()メソッド」で削除する
![03_skl_logistic_regression_12_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110108/2c8ee1fc-09c2-48dc-a7b9-5631730bda5c.jpeg)
「社会階級 + 性別」「年齢」および「生死」でプロットする。
![03_skl_logistic_regression_13.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110108/07978e58-e0f3-b285-ad93-cd5ec3f7d06a.jpeg)
以下のような傾向がわかる。

- 社会階級の高い女性のほうが生存者数が多く、社会階級の低い男性のほうが生存者数が少ない
- 若い人のほうが生存率が高い

説明変数に「年齢」「社会階級 + 性別」を、目的変数に「生死」を設定→学習。
「10歳の社会階級が高い女の子」
　生死判定を`model2.predict([10, 1])`
　生存確率を`model2.predict_proba([10, 1])`
で予測する。
![03_skl_logistic_regression_14.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110108/f156b703-d79e-a30f-7f10-77dcaa297098.jpeg)
「生存判定：生存　生存確率：0.9624」という、生存する確率が非常に高い予測が出た。

このとき、算出された回帰係数、切片を用いて生死の境界をプロットする。
![03_skl_logistic_regression_15.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110108/327affd0-fa91-b749-1413-8819f3492998.jpeg)
結果として、図の点線の箇所が境界であると推察する。

### 3.2.2. モデル評価
#### 3.2.2.1. データの分割
![03_skl_logistic_regression_16_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110108/dff6b808-213a-c368-1feb-147c91902561.jpeg)

#### 3.2.2.2. ロジスティック回帰モデルの作成
eval_model1：説明変数がひとつの場合のロジスティック回帰モデル
eval_model2：説明変数がふたつの場合のロジスティック回帰モデル
![03_skl_logistic_regression_17.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110108/349279a8-3eaa-a060-b8d5-b3d92aa4e39e.jpeg)

- 上記決定係数の比較
  - 1変数で作成したモデルと2変数で作成したモデルでは2変数で作成したモデルのほうが精度がよいことがわかる。

#### 3.2.2.3. 分類の評価
- 評価指標
metrics.classification_report()：
　0, 1：ラベル
　precision：適合率
　recall：再現率
　f1-score：F値
　support：データ数

- 混合行列
confusion_matrix：
　混合行列。並びは以下のとおり。
　array([[TP, FN],
　　　　[FP, TN]])

- 参考：
　[sklearn.metrics.precision_recall_fscore_support -- scikit-learn 0.23.1 documentation](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.precision_recall_fscore_support.html)
　[scikit-learn でクラス分類結果を評価する - pythonでデータサイエンス](https://pythondatascience.plavox.info/scikit-learn/%E5%88%86%E9%A1%9E%E7%B5%90%E6%9E%9C%E3%81%AE%E3%83%A2%E3%83%87%E3%83%AB%E8%A9%95%E4%BE%A1)

次に各評価指標の値および混合行列を出力する。
![03_skl_logistic_regression_18.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110108/2f124cb5-bfea-5838-0c0d-2e729bf1d9cc.jpeg)

モデル1の混合行列をヒートマップで表示する。
![03_skl_logistic_regression_19.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110108/c8cf2440-ec16-0ada-1701-71492e85f647.jpeg)

- confusion_matrix1（モデル1の混合行列）：
  - FPが多いためRecallが低くなっているが、Precisionは高い。

モデル2の混合行列をヒートマップで表示する。
![03_skl_logistic_regression_20.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110108/43d97f9b-40ed-e2c1-2bbb-f16494a538a0.jpeg)

- confusion_matrix2（モデル2の混合行列）：
  - 1変数の場合に比べRecallは高くなっているが、Precisionはやや低い。
  - F値は1変数の場合より高くなっている。

#### 3.2.2.4. 各項目での比較
seabornでタイタニックデータセットを取得し、

  - チケットクラス
  - 性別
  - 男性/女性/子供
  - 一人か否か

でそれぞれ生存率を比較する。
![03_skl_logistic_regression_21.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110108/8a9d20a9-b783-7e91-3107-5f8c5b48b508.jpeg)

- 上記グラフより以下のようなことがわかる。
  - チケットクラスが高いほうが生存しやすい
  - 女性のほうが生存しやすい
  - 女性、子供、男性の順に生存しやすい
  - 一人ではないほうが生存しやすい

seabornでタイタニックデータセットを取得し男女別に年齢に関して生存率を確認する。
![03_skl_logistic_regression_22.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110108/357d88fb-b227-6763-4931-d03c97607f60.jpeg)

- 上記グラフより以下のようなことがわかる。
  - 全体的に女性のほうが生存率は高い
  - 女性は高齢なほど生存率が高いのに比べ、男性は高齢なほど生存率が低い