学习回顾
学习目标
- 涉及Matplotlib,numpy,torch三个库函数。
- 初步了解Matplotlib画图工具。
- 简单学会使用随机梯度下降搜寻Minima。
学习准备
- 理解随机梯度下降算法概念(SGD)
- 简单理解神经网络反向传播算法的概念
效果展示
step 0: x = [-4.999000072479248, -0.0009999999310821295], f(x) = 340.0
step 2000: x = [-3.7791457176208496, -2.2811760902404785], f(x) = 32.14356994628906
step 4000: x = [-3.7531869411468506, -3.2478036880493164], f(x) = 0.06837394088506699
step 6000: x = [-3.779291868209839, -3.283167600631714], f(x) = 2.5277586246374995e-08
step 8000: x = [-3.7793033123016357, -3.2831790447235107], f(x) = 3.624336386565119e-09
step 10000: x = [-3.7793078422546387, -3.2831835746765137], f(x) = 4.240519047016278e-10
step 12000: x = [-3.7793095111846924, -3.2831852436065674], f(x) = 3.728928277269006e-11
step 14000: x = [-3.7793099880218506, -3.2831859588623047], f(x) = 3.637978807091713e-12
step 16000: x = [-3.7793102264404297, -3.2831859588623047], f(x) = 0.0
step 18000: x = [-3.7793102264404297, -3.2831859588623047], f(x) = 0.0
#在Himmelblau函数当中有四个最小点,其值都为 y =(0,0),此处通过随机梯度下降算法计算出 Minima
可以由下图可见 Himmelblau 函数中有四个最小点
代码分析
目标是是选取任意一个随机点,使其找到Minima。
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import pyplot as plt #
#Matplotli绘制3维坐标图像
import numpy as np
import torch
def Himmelblau(x):
return (x[0]**2 + x[1] - 11) ** 2 + (x[0] + x[1] ** 2 - 7) ** 2
#生成三维数据
x = np.arange(-6, 6, 0.1)
y = np.arange(-6, 6, 0.1)
X, Y = np.meshgrid(x, y)
#生成网格数据,将数组变化成矩阵格式
Z = Himmelblau([X, Y])
#定义坐标轴
fig = plt.figure("Himmelblau")
ax = fig.gca(projection="3d")
#alpha 透明度 cmap 颜色 offset 投影在坐标轴上显示的位置
ax.plot_surface(X, Y, Z,alpha=0.7 ,cmap="rainbow")
ax.contour(X,Y,Z,zdir='z', offset=-100,cmap="rainbow") #生成z方向投影,投到x-y平面
ax.contour(X,Y,Z,zdir='x', offset=-7,cmap="rainbow") #生成x方向投影,投到y-z平面
ax.contour(X,Y,Z,zdir='y', offset=7,cmap="rainbow") #生成y方向投影,投到x-z平面
ax.set_xlabel("x")
ax.set_ylabel("y")
plt.show()
#[1., 0.],[4., 0.],[4., 0.]
x = torch.tensor([-5., 0.], requires_grad=True)
#requires_grad表示该Variable及其相关节点都可导
optimizer = torch.optim.Adam([x], lr=1e-3)
# 创建optimizer对象,其中Adam可以认为是RMSprop 和 Momentum 的结合,
# 是属于SDG的变种算法,考虑到SGD在鞍点处会存在停滞的情况(自己把Adam改成SGD,结果停滞)
for step in range(20000):
pred = Himmelblau(x)
optimizer.zero_grad()
#清空所有被优化过的Variable的梯度.
#至于为什么这里要变成0呢,因为对于每一轮batch而言,所有反向传播中梯度是累加的,然后换一轮batch,两个不同的batch,梯度不能累加,具体的例子也可参考MNIST dataset
pred.backward() #预测值反向传播,求梯度
optimizer.step()#可以用所有Variable的grad成员和lr的数值自动更新Variable的数值
if step % 2000 == 0:
print("step {}: x = {}, f(x) = {}"
.format(step, x.tolist(), pred.item()))
#tolist()将矩阵或数组转换成列表
#item()函数以列表返回可遍历的元组和数组
参考文献
- PyTorch 中文文档
- numpy 官方文档
还在学习当中,有不足的地方,还请提出,相互交流讨论,一定及时修正。