在学习深度学习过程中,优化方法一般直接调用,为加深理解,我找了随机梯度下降算法的优化实例,记录如下:
0.前言
梯度的本意是一个向量(矢量),表示某一函数在该点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向(此梯度的方向)变化最快,变化率最大(为该梯度的模)。(来自百度百科)
如果你爱好高数还要追本溯源:知乎上有篇文章:
https://www.zhihu.com/question/305638940万分详细
以下是具体Himmelblau function按梯度下降求解极小值的例子:
1.给出Himmelblau function:
该函数有四个全局最小解,且值都为0,
f(3.0,2.0) = 0.0
f(-2.805118,3.131312) = 0.0
f(-3.779310,-3.283186) = 0.0
f(3.584428,-1.848126) = 0.0
2.实例代码如下:
分两步:
第一,先把函数图像绘出来:
import numpy as np
from matplotlib import pyplot as plt
import warnings #因为版本问题,我的代码一直报警告,如果你的编译器没问题,这两句不必加
warnings.filterwarnings('ignore')
from mpl_toolkits.mplot3d import Axes3D #python3d画图
import torch
def himmelblau(x): 定义Himmelblau function
return (x[0] ** 2 + x[1] -11) ** 2+(x[0] + x[1] ** 2 - 7)**2
x =np.arange(-6,6,0.1) #x取值范围
y =np.arange(-6,6,0.1)
print('x,y range:', x.shape,y.shape)
X, Y = np.meshgrid(x,y)#生成网格点坐标矩阵
print('X,Y maps:', X.shape, Y.shape)
Z = himmelblau([X,Y]) #生成函数值
fig = plt.figure('himmelblau')
ax = fig.gca(projection='3d') ## get current axes,且坐标轴是3d的
ax.plot_surface(X,Y,Z) #绘制3D曲面,x、y数据决定坐标点,z定 X、Y 坐标点对应的高度
ax.view_init = (60,-30) #view_init()旋转曲面,第一个参数指定从哪个高度看曲面# 第二个参数指定曲面的旋转角度旋转后的图形
ax.set_xlabel('x')
ax.set_ylabel('y')
plt.show()
显示结果:
x,y的范围:各有120个点
X的坐标矩阵:(120,120)Y的坐标矩阵:(120,120)
函数图像:
第二,使用随机梯度下降优化,使用torch.optim模块的Adam()方法:
x = torch.tensor([4., 0.],requires_grad=True) #初始化x,即【X,Y】
optimizer = torch.optim.Adam([x], lr=1e-3) #自动计算梯度:x'=x-0.001*x方向的梯度,y'=y-0.001*y方向的梯度
for step in range(20000):
pred = himmelblau(x)
optimizer.zero_grad()#每次计算,梯度被积累,所以每次将梯度设置为0
pred.backward()#生成X,Y的梯度信息
optimizer.step()#更新为x',y'
if step % 2000 == 0:
print('step {}: x = {},f(x) = {}'.format(step,x.tolist(),pred.item())) #x.tolist()显示【X,Y】列表,pred.item()方法 用于将一个零维张量转换成浮点数,比如计算loss,acc
结果:
很快找到最优解,12000次的时候就输出极小值了
我把初始化改为:x = torch.tensor([6., 2.],requires_grad=True)
这次没有那么快,18000次找到极小值。可见初始化的影响蛮大的。