实例说明
基于Pytorch,手动编写SGD(随机梯度下降)方法,求-sin2(x)-sin2(y)的最小值,x∈[-2.5 , 2.5] , y∈[-2.5 , 2.5]。
画一下要拟合的函数图像
代码
import matplotlib.pyplot
from mpl_toolkits.mplot3d import Axes3D
import numpy
import os
os.environ['KMP_DUPLICATE_LIB_OK'] = 'TRUE'
def fix_fun(x,y):
return -numpy.sin(x)**2 - numpy.sin(y)**2
x = numpy.arange(-2.5,2.5,0.1)
y = numpy.arange(-2.5,2.5,0.1)
x, y = numpy.meshgrid(x, y)
z = fix_fun(x,y)
fig = matplotlib.pyplot.figure()
ax = Axes3D(fig)
ax.plot_surface(x,y,z, cmap='rainbow')
matplotlib.pyplot.show()
画出来后,曲面长下面的样子↓
SGD算法构建思路
非常简单:用.backward()方法求出要优化的函数的梯度,按照SGD的定义找出最优解。 即: θ=θ-η·▽J(θ)
运行结果
看看随机生成的几个优化的结果
源码
老规矩,细节的备注仍然写在代码里面。
import torch
from torch.autograd import Variable
import matplotlib.pyplot
from mpl_toolkits.mplot3d import Axes3D
import numpy
import os
os.environ['KMP_DUPLICATE_LIB_OK'] = 'TRUE'
def fix_fun_numpy(x,y):
return -numpy.sin(x)**2 - numpy.sin(y)**2
def fix_fun_tensor(x,y):
return -torch.sin(x)**2 - torch.sin(y)**2
x = numpy.arange(-2.5,2.5,0.1)
y = numpy.arange(-2.5,2.5,0.1)
x, y = numpy.meshgrid(x, y)
z = fix_fun_numpy(x,y)
fig = matplotlib.pyplot.figure()
ax = Axes3D(fig)
X = (torch.rand(2,dtype=float)-0.5)*5
X_dots = []
Y_dots = []
Z_dots = []
for iter in range(50):
X = Variable(X, requires_grad = True)
Z = fix_fun_tensor(X[0],X[1])
Z.backward()
X = X - 0.1*X.grad
X_dots.append(X[0].detach().numpy())
Y_dots.append(X[1].detach().numpy())
Z_dots.append(Z.detach().numpy())
ax.plot_wireframe(x, y, z)
ax.plot(X_dots,Y_dots,Z_dots,color='red')
matplotlib.pyplot.show()
后记
喜欢探索的同学还可以把上面的源码改一改,并试试Adagrad, Adam, Momentum这些方法,也对比下各自的优劣。
|