Pythonで勾配降下法
勾配降下法の更新
$$
\omega _ { i } = \omega _ { i } – \alpha \frac { \partial E } { \partial \omega _ { i } }
$$
数値微分
ここでは、すごく簡単な中央差分を用いて数値微分します。
$$
\lim _ { h \rightarrow 0 } \frac { f ( x + h ) – f ( x – h ) } { 2 h }
$$
h=1e-4などで、簡単な近似させます。
回帰直線を勾配法でパラメータ推定する
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
np.random.seed(1)
#学習率
alpha = 1e-3
#数値微分のh
h = 1e-3
x = np.arange(10).reshape(-1, 1)
seg = np.ones(10).reshape(-1,1)
y = 5*seg + 3*x
print("モデルのパラメータ:b={}, a={}".format(5, 3))
#パラメータの初期値
a = np.random.normal(0.0, 1.0, size=None)
b = np.random.normal(0.0, 1.0, size=None)
print("パラメータの初期値:b={}, a={}".format(b,a))
#評価関数(二乗和誤差)
def E(x, y, a, b):
return 0.5 * (((a*x + b) - y)**2).sum()
#学習
for i in range(10000):
#数値微分
deda = (E(x, y, a+h, b) - E(x, y, a-h, b)) / (2*h)
dedb = (E(x, y, a, b+h) - E(x, y, a, b-h)) / (2*h)
#パラメータ更新
a = a - alpha*deda
b = b - alpha*dedb
print("勾配法のパラメータ推定:b={:.2f}, a={:.2f}".format(b,a))
''' 出力 ''' モデルのパラメータ:b=5, a=3 パラメータの初期値:b=-0.6117564136500754, a=1.6243453636632417 勾配法のパラメータ推定:b=5.00, a=3.00
学習part2
上のプログラムでは、学習回数を10000として、学習させた。
下のプログラムは、勾配が0.01以下になるまで、学習させるようになっている。
#学習
ds = 100
while abs(ds) > 0.01:
#数値微分
deda = (E(x, y, a+h, b) - E(x, y, a-h, b)) / (2*h)
dedb = (E(x, y, a, b+h) - E(x, y, a, b-h)) / (2*h)
#パラメータ更新
a = a - alpha*deda
b = b - alpha*dedb
ds = deda + dedb