Pythonで基礎から機械学習 「ロジスティック回帰分析」

# はじめに
　この「Pythonで基礎から機械学習」シリーズの目的や、環境構築方法、シリーズの他の記事などは以下まとめページを最初にご覧下さい。

[Pythonで基礎から機械学習まとめ](https://karaage.hatenadiary.jp/machine-learning-study)

　今回は、[Pythonで基礎から機械学習 「単回帰分析」](https://qiita.com/karaage0703/items/701367b6c926552fe505)、[Pythonで基礎から機械学習 「重回帰分析」](https://qiita.com/karaage0703/items/f38d18afc1569fcc0418)を読んだことが前提の内容となっております。

　また、本記事は、初学者が自分の勉強のために個人的なまとめを公開している記事になります。そのため、記事中に誤記・間違いがある可能性が大いにあります。あらかじめご了承下さい。

　より良いものにしていきたいので、もし間違いに気づいた方は、編集リクエストやコメントをいただけましたら幸いです。

　本記事のコードは、Google Colaboratory上での実行を想定しています。本記事で使用したGoogle ColabのNotebookは以下となります。

[03_logistic_regression.ipynb](https://github.com/karaage0703/machine-learning-study/blob/master/03_logistic_regression.ipynb)

# ロジスティック回帰分析とは
　ロジスティック回帰は、主に確率の問題や分類問題を扱いたいときに使われます。確率や分類は 0か1、0%〜100%といった一定の範囲で扱われます。例えば降水確率は0〜100%で表現されます。分類の場合は、コンピューター上ではこの写真が猫であるか否か、この写真が犬であるか否かという0 or 1で表現されます（0.0~1.0の確率で表すこともあります）。
 
　この場合、今まで学んだ単回帰分析、重回帰分析では扱いにくいため、ロジスティック回帰というものが用いられます。今までの予測に加えて、分類にも使いやすいのがポイントですね（回帰という名前が紛らわしいですが）。
 
## シグモイド関数
　最初に、ロジスティック回帰で重要な役割をもつ、シグモイド関数に関して説明します。ロジスティック回帰では、結果を一定の範囲（具体的には0〜1）に制限するために、シグモイド関数（ロジスティック関数とも呼ばれます）を使います。同じ関数なのに違う呼ばれ方をするのは、歴史的経緯（使われている分野が異なるため）のようです。興味がある方は調べてみて下さい。
 
 　シグモイド関数の式は以下です。

```math
f(x) = \frac{1}{1 + e^{-ax}}
```

　グラフで可視化してみます。

```python
import numpy as np
import matplotlib.pylab as plt
import seaborn as sns

def sigmoid(x):
    return 1/(1 + np.exp(-x))

x = np.arange(-5.0, 5.0 , 0.1)
y = sigmoid(x)
plt.plot(x, y)
plt.ylim(-0.1, 1.1)
plt.show()
```

　シグモイド関数は、下図のように、$x$にいかなる値を入力しても、結果が0〜1の間に納まる非常に都合の良い関数です。

![sigmoid.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81919/b0852dbf-efa0-08c7-4555-74289d241760.png)

　特に、ディープラーニングでの計算は0〜1の範囲で結果が得られると都合が良いため、シグモイド関数はディープラーニングでも活性化関数と呼ばれる使われ方をします（最近は計算量の関係でReLUを使うことが多いようですが）。

　ロジスティック回帰では、このシグモイド関数の$ax$に、重回帰の式を入れた以下の式を想定します。

```math
p = \frac{1}{1 + e^{-(w_0 + w_1 x_1 + w_2 x_2 + \cdots + w_n x_n)}}
```

　見づらいので、行列を使うと以下のように表せます。

```math
p = \frac{1}{1 + e^{-{\boldsymbol w}^{\mathrm{T}} \boldsymbol x_n}}
```

　重回帰の式は左辺が$y$でしたが、ロジスティック回帰では0〜1の確率となるため$p$を用いるのが一般的です。

　このモデルを与えられたデータに適用して、式の$\boldsymbol w$すなわち重回帰分析のときに求めた重回帰係数と切片変回帰係数を求めるのが、ロジスティック回帰分析です。

　また、上記式は、以下のように変形できます。

```math
\log (\frac{p}{1-p}) = \boldsymbol w^{\mathrm{T}} \boldsymbol x_n
```

　左辺の$\frac{p}{1-p}$は、オッズと呼ばれる確率用語（ギャンブルでもよく使われますね）なので、確率を線形和で表したものという説明もできます（こちらの方が一般的かもしれません）。

　ちなみに、ここまでの説明は2値分類と呼ばれる、データを2つに分類する場合（例えば、犬か猫）の話ですが、ロジスティック回帰は、犬、猫、人間といったように2つ以上に分類する多値分類の問題を解くことも可能です。

　その場合は、偏回帰係数のベクトルが行列に、シグモイド関数をソフトマックス関数に置き換える必要があります。このあたりは「ディープラーニングの数学という本」に詳しく書かれています。詳しくは以下記事参照下さい。

[GW中に「ディープラーニングの数学」と「身近な数学」と「Google Colaboratory（Python）」でじっくり数学を復習しました](https://karaage.hatenadiary.jp/entry/2019/05/08/073000)

## scikit-learnを使ったロジスティック回帰分析
　ではscikit-learnを使ったロジスティック回帰ですが、確率予測とクラス分類に関してとてもわかりやすくまとまっているページがあったので、リンクいたします。

　説明もコードも丁寧でわかりやすいです。なのでscikit-learnでの分析に関しては本記事では省略します。

[Scikit-learn でロジスティック回帰（確率予測編）](https://qiita.com/0NE_shoT_/items/c42d8093e2fed9bf1b7a#_reference-b7902afa648c0b5c9708)

[Scikit-learn でロジスティック回帰（クラス分類編）](https://qiita.com/0NE_shoT_/items/b702ab482466df6e5569)

## ロジスティック回帰分析の解き方
　ここで、今までのようにscikit-learnを使わず、実際に計算してロジスティック回帰分析の解を求めたいところです。

　ところが、ロジスティック回帰の場合、特に0,1の2値の分類の場合、単回帰や重回帰でやっていたように、最小二乗法をもとに行列計算で解析解を求めるといったことはできないようです。

　なので、解を求めるには勾配降下法等の探索アルゴリズムで、任意の値から逐次計算をしていくことで解空間を探索して近似解を求めることになります。

　こういった探索アルゴリズムを用いた解の探索は、実はディープラーニングでも用いられている手法です。

# 分類問題に用いられるアルゴリズム 
　ロジスティック回帰が分類問題にも用いられるという話をしましたが、ロジスティック回帰は線形分類モデルと呼ばれ、解けない分類問題があります（代表的なものはXOR）。

　分類問題には、ロジスティック回帰以外にも、様々なアルゴリズムがあります。代表的なものは以下です。

- 決定木
- SVM
- ニューラルネットワーク（ディープラーニング）

　特に、SVMは線形分類モデルなのですが、カーネルトリックというテクニックを使って非線形な分類問題も解くことが可能な手法です。ディープラーニングが話題になる前は、分類問題といえばSVMだったようです。SVMは以前少し試したことはあるので、興味ある方は以下記事参照ください。

[SVM（サポート・ベクタ・マシン）とpythonで空の写真から天気を判定させてみる](https://karaage.hatenadiary.jp/entry/2017/09/15/073000)

　また、ディープラーニングを含むニューラルネットワークも、分類問題を解くことができます。実は、ニューラルネットワークの中でも、一番単純なパーセプトロンと呼ばれるモデルは、線形分類モデルなのですが、複数層を重ねることで非線形問題が解けるようになります。この複数層を重ねたニューラルネットワークがディープラーニングのベースとなるものです。

# まとめ
　簡単ですが、今回はこれでおしまいです。やる気がないわけではないです。ちょっと休憩したいだけです。

　ロジスティック回帰までくると、シグモイド関数や勾配降下法など出てくるので、だんだんディープラーニングに近づいてきた気がしますね（気のせい？）。

　分類問題の決定木やSVMもとても興味深い題材なのですが、今後の予定としては勾配降下法などの探索アルゴリズムを取り上げた後に、一気にニューラルネットワーク（ディープラーニング）に行こうかなとにしようかなと考えています。

# コメントなど
　とりあえず貼り付けて、あとから理解して記事をアップデートします。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">対数オッズ（値域が実数全体）を線形回帰で求めようとするとロジスティック回帰になる。対数線形モデルの1種。故に分類ではなく回帰と名付けられている。<br><br>線形回帰での値が1より大きければ、オッズで分子の方が値が大きいので、結果的に分子側の事象に入力を離散的に割り当てる分類に応用できる。 <a href="https://t.co/Mos7hrUixk">https://t.co/Mos7hrUixk</a></p>&mdash; HELLO CYBERNETICS (@ML_deep) <a href="https://twitter.com/ML_deep/status/1173969494928027649?ref_src=twsrc%5Etfw">September 17, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ちなみに分子側の事象がパラメータpのベルヌーイ分布に従うと仮定して、最尤推定を試みると例の交差エントロピーと呼ばれる尤度関数が得られる。<br><br>という意味で、シグモイド関数を右辺に携えたときの出力pは、入力データに依存したベルヌーイ分布のパラメータということになる。</p>&mdash; HELLO CYBERNETICS (@ML_deep) <a href="https://twitter.com/ML_deep/status/1173970421873430528?ref_src=twsrc%5Etfw">September 17, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
# 参考リンク
- https://toukei-lab.com/%E3%83%AD%E3%82%B8%E3%82%B9%E3%83%86%E3%82%A3%E3%83%83%E3%82%AF%E5%9B%9E%E5%B8%B0
- https://qiita.com/mamika311/items/a7bb48ae5fc7c7630a3f