面白いデータを探して

適当に書く。間違えていたら教えてください。

ロジスティック回帰を数値微分で実装する

netres-bigdata.hatenablog.com
の続きみたいな感じ。

numpyと数値微分でロジスティック回帰を書いてみる。
ロジスティック回帰とか、微分した式めっちゃ簡単だから本当は数値微分をする必要はないけど。
コードもだいぶやっつけ。

コード

# -*- coding:utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt

# h
h = 1e-7

def logits(x, w):
    _x = np.insert(x, x.shape[1], 1, axis=1)
    return 1 / (1 + np.exp(np.dot(_x, w.T)))

def loss(x, y, w, lam):
    l = np.clip(logits(x, w), h*1e+2, 1-(h*1e+2))
    return -np.sum(y*np.log(l)+(1-y)*np.log(1-l))/y.shape[0]+lam*np.sum(np.square(w))

def update_value(x, y, w, h, lam):
    _w = w + np.identity(w.shape[0])*h
    _w_pos = np.array([loss(x, y, __w, lam) for __w in _w])
    _w = w - np.identity(w.shape[0])*h
    _w_neg = np.array([loss(x, y, __w, lam) for __w in _w])
    return (_w_pos-_w_neg)/(2*h)

def pred(x, w):
    return logits(x, w)

# 学習させるデータ : OR
x = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])
y = np.array([0, 1, 1, 1])
w = np.array([0, 0, 0])

# 学習率と正規化率
eta = 0.5
lam = 1e-5

_loss = [loss(x, y, w, lam)]
for i in range(1000):
    _w = update_value(x, y, w, h, lam)
#    print("update value:", _w)
    w = w - eta*_w
    _loss.append(loss(x, y, w, lam))
plt.plot(list(range(len(_loss))), _loss)
plt.title("loss")
plt.xlabel("epoch")
plt.ylabel("loss")
plt.savefig("figure/loss.png")
print(pred(x, w))

結果

予測結果 : [ 0.04184762  0.98330325  0.98330325  0.99998741]

ちゃんと予測出来てるかな

f:id:netres:20190724201933p:plain
lossもちゃんと落ちてる。