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