目录
一、引言
上一节课我们通过顶点坐标公式求解出抛物线的最低点的W坐标,得到了让误差代价最小的W,但是我们也通过算一笔账,说明了这种一步到位的求解方式固然是好,但是在输入特征过多,样本数量过大的时候,却非常消耗计算资源。
二、“挪”
现在我们就来看看另外一种更加常用的方法,其实在上节课的讲解中也暗示了这一点,我们用了一个“挪”字来描述这个过程。抛物线最低点坐标的寻找过程其实不必一步到位,大可采用一点点挪动的方式。比如一开始W的值是2,误差是这么多,如果在这里画一个球,那要到达最低点需要向左滑落而不是向右攀升,如果W等于0.6,要到达最低点,需要向右滑落,而不是向左攀升。这规律就很明显了,在最低点的左边需要不断的把W调大,而在右边的时候,不断的把W调小。而具体实施起来也很方便,我们使用斜率,一个开口向上,抛物线的最低点的斜率是零,而左边的斜率是负数,右边的斜率是正数。所以现在我们的目的很明确,想办法得到代价函数曲线在当前W取值这个点上的斜率,这样我们就可以判断当前W取值是在最低点的左边还是在右边,然后不断去调整W,直到到达最低点,也就是说得到一个让误差代价最小的W。我们之前已经证明了误差e和W形成的代价函数是一个标准的一元二次函数。
求斜率有两样求法,定义法和求导法则。
定义法:
求导法则:
三、梯度下降
小蓝的神经元终于可以根据代价函数的斜率是否大于零来决定W的调整行为了。那么问题又来了,每次调整多少合适呢?按照目前的经验和直觉来看,每次只能调一点点,不能调多,不如我们就先试试每次调整0.01吧。这样好像可以,但是我们发现下降的过程有点慢,在最低处还反复的震荡,因为不论当前是几,调整的幅度都是呆板的0.01。(详见可视化工具的固定步调整方法)
那有没有更聪明一点的方式呢?有。当W距离最低点比较远的时候,我们其实希望它能够快一点,而逐渐接近最低点的时候,我们希望它慢下来,这样就既能加快下降的速度,又能在最低点处,稳如老狗。同时我们发现距离最低点越远的地方,这个斜率的绝对值越大,而越近的地方越小,当接近最低点的时候,这个值几乎为0,而最低点的斜率它就是0,是分界点,而斜率在左右的符号又正好不同,这可太好了,刚好可以利用斜率的值来做这件事情,让W每次直接减这个点的斜率的值。
但是当我们打开代价函数调整的可视化工具,运行一下这个调整过程的时候,你会发现调整的过程太震荡,无法收敛。但是没有关系,方法还是一样的。考虑给斜率也乘上一个比较小的学习率阿尔法调和一下,比如阿尔法等于0.1,你看这次的调整过程变得又快,在最低点处又稳。(详见可视化工具的批量梯度下降)
这种根据曲线不同处斜率去调整W的方式,也就是所谓的梯度下降,为什么叫梯度下降而不是斜率下降呢?梯度是一个比斜率更加广泛的概念。在这里我们的代价函数是二维的,似乎说斜率也就够了,但后面说到更高维度的时候,斜率这个词就不太合适了。这里我们暂时就把梯度先理解为斜率吧,这样也可以。而当我们经过多次梯度下降的过程后,W收敛到最低点附近,停止梯度下降的过程,把此时W作为预测模型中的W值,此时便能够相当准确的完成预测了。
到此,我们终于可以回过头来去看看rosenblatt感知器的参数调整方式了。它为什么好使?你会发现那正好是一个方差代价函数的斜率,和我们这里的梯度下降如出一辙。
所以梯度下降和前面说的一步求解的正规方程相比,优势何在呢?我们一开始就讨论过单个样本的情况,它的代价函数是一个开口向上的抛物线,每个样本都是。之后我们又讨论了把所有样本合在一起的代价函数,仍然是一个开口向上的抛物线,这个合成代价函数的最低点是整个样本全局最优点我们直接用全部样本进行梯度下降,你看这个下降的过程是一个明确且顺滑的轨迹,这也就是标准的梯度下降,也称之为批量梯度下降。
那如果我们每次只使用一个样本,这个样本的最低点不一定是全局最优。如果我们不断的依次在这些单样本代价函数上进行梯度下降,虽然会有震荡和波动,但是多次以后,他们的整体趋势仍然会向全局最优点挪动,最后也可成功,而不像正规方程中那样一次性带入全部的样本进行计算。如果我们有海量的数据,你的机器必然GG。这种每次取一个样本进行的梯度下降,因为其收敛的过程是一个随机震荡的轨迹,所以也称之为随机梯度下降,实际上最后在最低点附近,这个震荡的轨迹是一个经典的布朗运动。(详见可视化工具的随机梯度下降)
批量有批量的好处,可以并行计算,且更容易向全局最优点收敛,但是其缺点也是明显的,还是那个极端的例子,100万个数据要一次性计算出来,那么和正规方也就没啥区别了。随机也有随机的好处,海量数据可以慢慢的来,每次都更新参数,参数的更新过程变得更快了。但是其缺点也是明显的,无法并行计算,且不容易向全局最优点收敛。所以综合二者的优缺点,我们又是向来喜欢折中的,人们往往采用一种调和的方法,mini-batch迷你批量梯度下降,每次选择全体样本中的一小批,比如100个、200个进行梯度下降。不得不说折中调和真是经久不衰的智慧。那到此为止,你也就了解了机器学习精髓之一的梯度下降。
四、编程
以小蓝吃豆豆为引子,求豆豆大小与毒性关系,介绍随机梯度下降、批量梯度下降、固定步长调整求w的编程。
同样豆豆的毒性数据生成dataset.py
import numpy as np
def get_beans(counts): #构造吃豆豆的函数
xs = np.random.rand(counts) #
xs = np.sort(xs) #进行行排序
ys = [1.2*x+np.random.rand()/10 for x in xs]
return xs,ys
随机梯度下降:
plt.clf()#清理窗口
plt.xlim()函数限制x轴范围
plt.ylim()函数限制y轴范围
plt.pause(0.01) #暂停0.01s
import dataset #调用dataset库
from matplotlib import pyplot as plt #调用matplotlib库的pyplot
#import matplotlib.pyplot as plt
import numpy as np
xs,ys=dataset.get_beans(100) #获取100个豆子数据
#配置图像,坐标信息
plt.title("Size-Toxicity Function",fontsize=12)#设置图像名称
plt.xlabel("Bean Size")#设置横坐标的名字
plt.ylabel("Toxicity")#设置纵坐标的名字
plt.scatter(xs,ys) #画散点图
#预测函数
#y=0.1*x
w=0.1 #初始权值
y_pre=w * xs
plt.plot(xs,y_pre)
plt.show() #显示图像
for m in range(100):#调整50次全部,0-99的整数,用range 函数进行for循环
for i in range(100):#调整1次全部,可能会导致线不拟合
x=xs[i];
y=ys[i];
#a=x^2
#b=-2*x*y
#c=y^2
#斜率k=2aw+b
k=2*(x**2)*w+(-2*x*y)
alpha=0.1 #学习率,学习率不可过大也不可过小
w=w-alpha*k
plt.clf( )#清理窗口
plt.scatter(xs,ys)
y_pre = w*xs
plt.xlim(0,1) #plt.xlim()函数限制x轴范围
plt.ylim(0,1.5) #plt.ylim()函数限制y轴范围
plt.plot(xs,y_pre)
plt.pause(0.01) #暂停0.01s
批量梯度下降:
import dataset #调用dataset库
from matplotlib import pyplot as plt #调用matplotlib库的pyplot
#import matplotlib.pyplot as plt
import numpy as np
xs,ys=dataset.get_beans(100) #获取100个豆子数据
#配置图像,坐标信息
plt.title("Size-Toxicity Function",fontsize=12)#设置图像名称
plt.xlabel("Bean Size")#设置横坐标的名字
plt.ylabel("Toxicity")#设置纵坐标的名字
plt.scatter(xs,ys) #画散点图
#预测函数
#y=0.1*x
w=0.1 #初始权值
y_pre=w * xs
plt.plot(xs,y_pre)
plt.show() #显示图像
alpha=0.1 #学习率,学习率不可过大也不可过小
for i in range(100):#调整50次全部,0-99的整数,用range 函数进行for循环
#代价函数:e=(y-w*x)^2=x^2*w^2+(-2X*y)*w+y^2
#a=x^2
#b=-2*x*y
#c=y^2
#斜率k=2aw+b
k=2*np.sum(xs**2)*w+np.sum(-2*xs*ys)
k=k/100
w=w-alpha*k
y_pre = w*xs
#预测函数
plt.clf()#清理窗口
plt.scatter(xs,ys)
plt.xlim(0,1)#plt.xlim()函数限制x轴范围
plt.ylim(0,1.5) #plt.ylim()函数限制y轴范围
plt.plot(xs,y_pre)
plt.pause(0.01) #暂停0.01s
固定步长调整:
import dataset #调用dataset库
from matplotlib import pyplot as plt #调用matplotlib库的pyplot
#import matplotlib.pyplot as plt
import numpy as np
xs,ys=dataset.get_beans(100) #获取100个豆子数据
#配置图像,坐标信息
plt.title("Size-Toxicity Function",fontsize=12)#设置图像名称
plt.xlabel("Bean Size")#设置横坐标的名字
plt.ylabel("Toxicity")#设置纵坐标的名字
plt.scatter(xs,ys) #画散点图
#预测函数
#y=0.1*x
w=0.1 #初始权值
y_pre=w * xs
plt.plot(xs,y_pre)
plt.show() #显示图像
alpha=0.1 #学习率,学习率不可过大也不可过小
step=0.01
for i in range(100):#调整50次全部,0-99的整数,用range 函数进行for循环
#代价函数:e=(y-w*x)^2=x^2*w^2+(-2X*y)*w+y^2
#a=x^2
#b=-2*x*y
#c=y^2
#斜率k=2aw+b
k=2*np.sum(xs**2)*w+np.sum(-2*xs*ys)
k=k/100
if k>0:
w=w-step
else
w=w+step
y_pre = w*xs
#预测函数
plt.clf()#清理窗口
plt.scatter(xs,ys)
plt.xlim(0,1)#plt.xlim()函数限制x轴范围
plt.ylim(0,1.5) #plt.ylim()函数限制y轴范围
plt.plot(xs,y_pre)
plt.pause(0.01) #暂停0.01s
五、总结
在本节课中,我们详细讲了现代神经网络精髓之一的梯度下降算法,包括固定步长调整方法,批量梯度下降,随机梯度下降,mini-batch迷你批量梯度下降。在下一节课中,我们就继续前行,去了解反向传播的概念。
六、往期内容
3.梯度下降:能改
4.反向传播:能改
5.激活函数:给机器注入灵魂
6.隐藏层:神经网络为什么working
7.高维空间:机器如何面对越来越复杂的问题
8.初识Keras:轻松完成神经网络模型搭建
9.深度学习:神奇的DeepLearning
10.卷积神经网络:打破图像识别的瓶颈
11. 卷积神经网络:图像识别实战
12.循环:序列依赖问题
13.LSTM网络:自然语言处理实践
14.机器学习:最后一节课也是第一节课
可视化工具链接:https://blog.csdn.net/wanlin_yang/article/details/129131751视频链接:
http://pan.baidu.com/s/1RKvYoi3FKAeDkYrhMIh4YA?pwd=z39j%C2%A0