单层感知机示例图
如图所示,单层感知机的输入为(x),其中上标代表了第几层数,下标代表了在该层的第几个节点。而后的w(权重)也一样上标为第一层感知,下标为第几个节点到第几个节点。通过这些权重的累加(阈值)通过激活函数得到O也为第一层(因为是单层感知机),最后利用上节讲过的公式最终得到损失。
附图1.
附图2. 单层感知机代码
单层多个感知机
如图3所示,我们可以看到损失对于权重的偏导公式如下,通过公式我们可以了解到,这其中的偏导和输入以及输出节点有关(x为输入,O为输出)
附图3.单层多个感知机
附图4. 单层多个感知机代码
链式法则
高等数学中链式法则让我们对于求解复杂的多层感知机的反向传播求梯度损失去进行优化提供了基础
附图5.链式法则图片
多层感知机
上面我们提了单层感知机为多层感知机的基础,在图中,我们将阴影部分遮盖掉,先去求本层的梯度。梯度的公式如图所示,为了简化公式我们将公式的本层输出简化为 δkK\delta_k^KδkK
附图6.多层感知机结构
而后,我们拿开阴影部分,得到的推导公式大全如下图所示:
附图7.推导过程大全
附图8.依次向前面每一层传播,最终得到最优权重
实例
我们通过给定一个函数来在pytorch中进行试验,设置不同的初始化点,来验证正确性
附图9.实例函数
话不多说,直接上代码:
import numpy as np
from mpl_toolkits.mplot3d import Axes3D #绘制3D坐标的函数
from matplotlib import pyplot as plt #绘图用的模块
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)#创建了从-6,6的步长为0.1的arange对象
print('x,y range',x.shape,y.shape)
X,Y=np.meshgrid(x,y) #用这两个arange对象可能的取值一一映射去扩充为所有可能的取样点
print('X,Y maps:',X.shape,Y.shape)
Z=himmelblau([X,Y])#用取样点的横纵坐标去求取样点Z坐标
fig=plt.figure('himmelblau')#创建一个绘图对象
ax=fig.gca(projection='3d')
ax.plot_surface(X,Y,Z) #利用取样点构建曲面
ax.view_init(60,-30)
ax.set_xlabel('x')
ax.set_ylabel('y')#给坐标轴注明
plt.show()
#[1.,0.],[-4,0.],[4,0.]
x=torch.tensor([4.,0.],requires_grad=True)#可更改初始化的点,找到不同的局部最小值
optimizer=torch.optim.Adam([x],lr=1e-3)
for step in range(20000):
pred=himmelblau(x)#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()))
结论
本文主要通过图解的方法,给出了推导的过程以及相对应的代码,供大家参考,由一层感知机到多层感知机的前向传播推导,最终得到相对应的梯度来获得最优化的权重,代码中给出了函数的三维可移动图像以及最终得到的最优点(可理解为最优权重)。多层感知机的分类器我们将在以后进行讲解。