サムネがコーヒーの記事は書きかけです。

二次元の勾配降下法【機械学習】

二次元での勾配降下法を実装してみます。

今回は以下のような関数について考えます。

$$f(x,y) = -(x^2\sin{y}*y^2\sin{x})$$

関数の描画

matplotlibを使用して、二次元座標上にカラーマップを使って関数を描画します。


import numpy as np
import matplotlib.pyplot as plt
import sympy as sym 


def f(x,y):
  x,y = np.meshgrid(x,y)
  return-(x**2*np.sin(y)*y**2*np.sin(x))

x = np.linspace(-1.5,3,201)
y = np.linspace(-1.5,3,201)
Z = f(x,y)
fig = plt.figure()

plt.imshow(Z,extent=[x[0],x[-1],y[0],y[-1]],vmin=-5,vmax=5,origin='lower')
fig.savefig("a.png",dpi =500)

勾配の最小化

勾配が小さくなる方向にlcminを進めます。

import numpy as np
import matplotlib.pyplot as plt
import sympy as sp


def f(x,y):
  x,y = np.meshgrid(x,y)
  return-(x**2*np.sin(y)*y**2*np.sin(x))

x = np.linspace(-1.5,3,201)
y = np.linspace(-1.5,3,201)
Z = f(x,y)

fig = plt.figure()
sx,sy = sp.symbols('sx,sy')
sZ = -(sx**2*sp.sin(sy)*sy**2*sp.sin(sx))


df_x = sp.lambdify( (sx,sy),sp.diff(sZ,sx),'sympy' )
df_y = sp.lambdify( (sx,sy),sp.diff(sZ,sy),'sympy' )

#パーシャルxについて、x,y = (1,1)の勾配
print(df_x(1,1).evalf())
#パーシャルyについて、x,y = (1,1)の勾配
print(df_y(1,2).evalf())

#init local min
#ランダムな値を2つ生成
lc_min = np.random.rand(2)*4.5-1.5


init_pt = lc_min[:]
learning_rate = .01
epochs = 1000

#追跡軌道
traj = np.zeros((epochs,2))
for i in range(epochs):
    grad_i = np.array([ df_x(lc_min[0],lc_min[1]).evalf(),
                       df_y(lc_min[0],lc_min[1]).evalf()])
    #勾配が0になる方向に進んでいく
    lc_min = lc_min - learning_rate*grad_i
    traj[i,:] = lc_min


plt.imshow(Z,extent=[x[0],x[-1],y[0],y[-1]],vmin=-5,vmax=5,origin='lower')
plt.plot(init_pt[0],init_pt[1],'bs')
plt.plot(lc_min[0],lc_min[1],'ro')
plt.plot(traj[:,0],traj[:,1],'r')
plt.legend(['init_pt','lc_min'])
plt.colorbar()
fig.savefig("a.png",dpi =500)

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です