BP算法 反向传播算法 python实现
先提出一个问题:怎样拟合一条线性函数??一条线性函数重要的两个参数w,b,当我们给定这2 个参数时如何通BP算法实现无限逼近,多个W,B又能实现什么功能?
1. 什么是BP(反向传播算法)?
反向传播算法:本质上是用链式求导法则通过梯度下降对各个参数更新的一种算法。
2. 过程
回到开头的问题,假设现在给定需要被拟合的直线的参数w=2,b=1即y1=2x+1。并给定拟合的直线参数(随意给)w=0,b=0即 y2=0x+0.现在我们引入描述拟合直线与被拟合直线之间差异的一个函数称为损失函数
那么如何通过损失函数更新参数w与b呢?这里就不得不提到梯度下降。
3. 梯度下降
把下面的图理解为有多个参数纵坐标为损失的三维函数。只要我们沿着最高点从梯度(也就是导数)最大的点一直向下走便能走到最低点。(当然也会走到其他点的情况,后面再讨论)最低点所对应的w,b便是我们要找到拟合直线的w和b
上面简要的的说明了梯度下降是如何操作的,如果我说的还不是太清楚的话可以继续看下面一个更具体的例子
下山:
我们通过一个下山的例子来讲解.当我们需要快速下山时首先找到梯度最大时的路线也就是B路线,走一步后梯度发生变化,更新梯度,再次寻找梯度最大的点沿着走。那么最后就能快速下山。从这里我们引出了梯度下降的主要步骤
梯度下降:
1.梯度下降就是沿着梯度最陡的地方下降。
2.如果我们从x点开始下降每次Δh,位置更新为x-Δh,继续沿着最陡的地方,直到我们下降到最低点。
运用梯度下降时可能存在的问题:
从上面的例子来看我们可以很容易的想到:
1.当我们“步子”迈的过大我们很可能会一个坑里来回的跨越,这也就是我们常说的学习率太大,也可能造成梯度爆炸。那么学习率的选取就显得比较重要。对于大多数学习模型一般设置为0.001,生成模型GAN为1e-4.
2.当我们走到一个坑的最低点时梯度为0了,梯度不走了,但是这个坑不是全局最小的坑就出现了问题。解决方案则是我们可以给梯度一个“动量”,让他能够冲出这个坑。或者从另外一个起点下降。
4.BP过程(代码)
回到刚才的问题,我们通过对w,b求偏导找到w,b最低的损失那么我们所求的直线与被拟合的直线可以无限的逼近。下面是python拟合的代码
import random
import matplotlib.pyplot as plt
_x = [i/100 for i in range(100)] #生成一个 1-100再/100的列表
_y = [3*j+2*random.random() for j in _x] #生成一条关于x的k为3 b=随机数的散点图
w = random.random() #初始化w
b = random.random() #初始化b
plt.ion() #打开实时画图
if __name__ == '__main__': #这里是主程序执行
for i in range(100): #学习次数为100
for x,y in zip(_x,_y): #遍历列表 _x _y
z = w*x+b #前向
loss = 1/2*(z-y)**2 #损失函数
dw = -(z-y)*x #x的梯度
db = -(z-y)*1 #b的梯度
w = w+0.5*dw #后向
b = b+0.5*db #后向
print("w={},b={},loss={}".format(w,b,loss))#显示w b loss
plt.clf() #清除坐标轴
plt.plot(_x,_y,".","r") #画出原始散点图
v = [w*i+b for i in _x]
plt.plot(_x,v,"b") #画出拟合的直线
plt.pause(0.1) #0.1秒间隔
plt.ioff() #关闭
plt.show() #显示最后画面