综述
前文“神经网络小白篇”已经研究了神经网络的基本结构和运算过程。下面我们来考虑两个问题提升训练速度和过拟合。首先我们来看一下第一个问题。
如何提升神经网络的训练速度
要提升训练速度我们得先来看看神经网络的训练速度与什么有关。首先回顾一下上文阐述的几个公式和模型:
上图给出的结构和公式仍然是上一篇的结构。我们观察一下对w和b偏导结构。根据渐进思想,发现用来衡量学习速度的是在z的条件下激活函数的梯度值。
插播一句话:怎么去看待一个神经网络的训练速度。观察一下数学公式梯度的大小与z相关、与w的初始值相关、当然也与损失函数有关。接下来就分这几个方向进行分析一下。
损失函数——cross_entropy
观察上面图片中关于w和b的偏导,激活函数的输出值趋向于1(假设x=1,y=0)的时候。其倒数趋向于水平的,也就是偏导数小。虽然我们一直选择的都是梯度(偏导数最大的方向)但在这种情况下即使大也是相对的也就是说这是偏小的。
很显然我们想要选择一种cross function经过导数后,可以很好的解决这个问题。
提出一个新的函数:
对函数求导:
观察发现,梯度的大小与erro值有关。当error大的时候梯度大,学习的就快。error小的时候梯度小学的就慢。
注意:这个只能提高学习的速度,对最终学习的效果改进不大。
初始化权重
上文初始化权重的时候使用标准正态分布随机生成的,观察正态分布的图像发现大部分数据是分布于(-1,1)之外的,当初始化的w和b远离于这个范围的时候。反应在激活函数的图像中就是右上和左下比较平缓的那两部分,对着两部分求导斜率是小的相应的变化也是平缓的。这个时候学习的速度是偏慢的。
那么我们怎么通过调整初始化数据来提高速度呢?根据数理统计的知识,当高斯分布的标准差越小的时候函数图像呈现出”瘦高”的形态。我们调整高斯分布的标准差后再在其中进行采样,得到的数据大多都集中在(-1,1)中间。
根据数据的性质,整个分布的标准差我们可以通过每一个数据的放缩来体现(标准差变为数据的sqrt值)
所以我们有了下面的代码:
def new_parameter_initializer(self):
self.biases = [np.random.randn(y, 1) for y in self.sizes[1:]]
self.weights = [np.random.randn(y, x) / np.sqrt(x)
for x, y in zip(self.sizes[:-1], self.sizes[1:])]
补充:
趁热打铁,上文我们通过改变损失函数来提高训练速度。下面补充一种新的方法——softmax:
第一步
与之前相同
第二步 输出层方程
通过观察输出层方程发现,通过这种方式把输出的数据映射成概率值。这样在后面决策的时候就更加容易了。
同样新的损失函数定义为:
对w求偏导后,结果为:
发现与cross entropy的学习速度原理是相同的。
关于过拟合的问题
在传统机器学习中通过正则化的方法来缓解过拟合的问题,同样深度学习中也有相关的方法。这一部分来看一下正则化技巧和理解。首先看公式
第一种正则化方法L2范数
公式中出现了一个新的参数lamda,正则化项偏向于让w比较小。lamda存在的意义就是调整C0项和正则化项的重要程度。lamda小倾向于让C0项最小化,lamda大倾向于最小化增大的项。其实还没想清楚这个参数一般该咋调?
求解偏导后得到
那么为什么加入正则化项可以有效的防止过拟合呢?如果放开手单纯的让系统自己去学习调整权重,那么对于一些噪声点可能比较敏感学到了较大的权重。大权重意味着对数据的敏感度大。当我们加入一个参数的时候就好比是加入了一只手来控制它的学习欲望。我们所有的w都比较小,这样对数据的敏感程度就没有那么强烈。这样学习到的结果更偏向于真正的规律。真正有效的数学证明现在还在论证过程中。。。
上文使用L2范数作为正则化项,下面使用L1范数作为正则化项:
注:sgn(x)是符号函数,x<0时y=-1,x>0时y=1。对w求偏导w只可能出来两种情况啊1和-1。就像y = x,y对x的导数不是1吗?
eta:学习率
对比以上两种更新权重的方法的到:
L1减少的是个常量,L2减少的是个固定的比例。如果权重本身很大,L1减少的比L2少。但如果权重本身很小,L1减少的比L2多。
DropOut
文章的最后说一种防止过拟合的方法。
方法步骤为:
删除隐藏层的一些神经单元
在新的神经网络上正向,反向更新
恢复最初始的神经元,重新随机选择一半删除。正反更新
重复上面的过程