筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (15)

前回
[筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (14)](https://qiita.com/legacyworld/items/d8274455667555248353)
https://github.com/legacyworld/sklearn-basic

# 課題6.6 ロジスティック回帰と対数尤度
Youtubeでの解説は第8回(1) 20分あたり
この課題自体は非常に簡単だったので、ロジスティック回帰の理解のために自分でちょっと追加でプログラムを組んでいる。
訓練サンプル($x_{1i},x_{2i} ,i=(1,2,\cdots,10)$)に対して$E(w)$をそれぞれ求める問題。
$E(w)$は以下のようにあらわされる。

```math
E(w) = -\sum_{n=1}^{N}{t_n\,ln\hat t_n + (1-t_n)\,ln(1-\hat t_n)}
```
今回の例だと
$N = 10$
$t_n = (1,0,0,1,1,1,0,1,0,0)$

$E(w)$を求めた後にロジスティック回帰を使って$w$も求めている。
ソースコードはこちら

```python:Homework_6.6.py
import numpy as np
from sklearn.linear_model import LogisticRegression

# シグモイド関数
def sigmoid(w,x):
    return 1/(1+np.exp(-np.dot(w,x)))

# 交差エントロピー損失
def cross_entropy_loss(w,x,y):
    y_sig = sigmoid(w,x)
    return -np.sum(y*np.log(y_sig)+(1-y)*np.log(1-y_sig),axis=1)

X = np.array([[1.5,-0.5],[-0.5,-1.0],[1.0,-2.5],[1.5,-1.0],[0.5,0.0],[1.5,-2.0],[-0.5,-0.5],[1.0,-1.0],[0.0,-1.0],[0.0,0.5]])
X = np.concatenate([X,np.ones(10).reshape(-1,1)],1)
y = np.array([1,0,0,1,1,1,0,1,0,0])
w = np.array([[6,3,-2],[4.6,1,-2.2],[1,-1,-2]])
print(f"E(w1) = {cross_entropy_loss(w,X.T,y)[0]:.3f} E(w2) = {cross_entropy_loss(w,X.T,y)[1]:.3f} E(w3) = {cross_entropy_loss(w,X.T,y)[2]:.3f}")

for c_value in [10**(a-2) for a in range(5)]:
    clf = LogisticRegression(C=c_value).fit(X,y)
    w = np.array([[clf.coef_[0][0],clf.coef_[0][1],clf.intercept_[0]]])
    print(f"C = {c_value} w = {w} E(w) = {cross_entropy_loss(w,X.T,y)}")
```
実行結果

```
E(w1) = 1.474 E(w2) = 1.832 E(w3) = 6.185
C = 0.01 w = [[ 0.02956523  0.00018875 -0.01756914]] E(w) = [6.84341713]
C = 0.1 w = [[ 0.26242317  0.01451582 -0.1445077 ]] E(w) = [6.19257501]
C = 1 w = [[ 1.38391039  0.32530732 -0.55198479]] E(w) = [3.91381807]
C = 10 w = [[ 3.9100986   1.36910424 -1.28870173]] E(w) = [1.77721899]
C = 100 w = [[ 9.40098848  3.40849535 -3.23672119]] E(w) = [0.57516562]
```
ロジスティック回帰においてL2正則化パラメータを0.01から100まで動かして、それぞれ求められた$w$に対して交差エントロピー損失も表示している。
正則化があまり効いていない（Cが大きい）ところでは当然ながら$w$の絶対値が大きくなっていくのがわかる。

因みに正則化を行わないと以下のようになる

```
Homework_6.6.py:13: RuntimeWarning: divide by zero encountered in log
  return -np.sum(y*np.log(y_sig)+(1-y)*np.log(1-y_sig),axis=1)
Homework_6.6.py:13: RuntimeWarning: invalid value encountered in multiply
  return -np.sum(y*np.log(y_sig)+(1-y)*np.log(1-y_sig),axis=1)
No regularization w = [[57.89037518 20.53048228 -9.91476711]] E(w) = [nan]
```
$w$の絶対値が大きくなりすぎてシグモイド関数の計算で1が返ってしまい、logの計算が出来なくなってエラーとなる。

# 過去の投稿
[筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (1)](https://qiita.com/legacyworld/items/a3763760e65774dc0e33)
[筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (2)](https://qiita.com/legacyworld/items/5a72c83860c1d0b1d352)
[筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (3)](https://qiita.com/legacyworld/items/c9cd7865efb343c42e5e)
[筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (4)](https://qiita.com/legacyworld/items/9231c44206c8f0823ff5)
[筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (5)](https://qiita.com/legacyworld/items/2d2db10024d7dfb5f89b)
[筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (6)](https://qiita.com/legacyworld/items/e54c664fc138b75dd166)
[筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (7) 最急降下法を自作](https://qiita.com/legacyworld/items/bdbb0cbdc5b9b33fd1eb)
[筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (8) 確率的最急降下法を自作](https://qiita.com/legacyworld/items/663fcd8189f0bdf38f64)
[筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (9)](https://qiita.com/legacyworld/items/8da3476d40f9861a38e4)
[筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (10)](https://qiita.com/legacyworld/items/4f2656e994fdbbfa44fc)
[筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (11)](https://qiita.com/legacyworld/items/c3890ab296f3b4f0918d)
[筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (12)](https://qiita.com/legacyworld/items/9f3c14931acd8d22ae39)
[筑波大学の機械学習講座：課題のPythonスクリプト部分を作りながらsklearnを勉強する (13)](https://qiita.com/legacyworld/items/784d362cdf6c513d28b6)
https://github.com/legacyworld/sklearn-basic
https://ocw.tsukuba.ac.jp/course/systeminformation/machine_learning/