神经网络
1. 感知器
一个感知器接受几个二进制的输入,并产生一个二进制的输出。其中,每个输入都配有相应的权重来表示输入对于输出的重要性。和权重一样,阈值是一个实数。
2. S型神经元
由于在网络中,单个感知机上一个权重或者偏置的微小改动有时候会引起那个感知器的输出完全翻转。那样的翻转可能接下来引起其余网络的行为以极其复杂的方式完全改变。这使得逐步修改权重和偏置来让网络接近期望行为变得困难。所以,引入一种称为S型的神经元来克服这个问题。S型神经元和感知器类似,但是被修改为权重和偏置的微小改动只会引起输出的微小变化。这对于让神经元网络学习起来是很关键的。
正如一个感知器,S型神经元有多个输入,但是这些输入可以取0和1中的任何值,而不仅仅是0和1。同样,S型神经元对每个输入有权重和一个总的偏置。但是,输出不是0或者1。相反,它现在是sigma(w*x+b),这里的sigma被称为S型函数。
S型神经元和感知器模型具有很大的相似性,假设z=w*x+b是一个很大的正数,那么e^-z约等于0而sigma(z)约等于1。即当z=w*x+b很大并且为正,S型神经元的输出近似为1,正好和感知器一样。反之亦同。
3. 神经网络的架构
网络中最左边的部分称为输入层,其中的神经元称为输入神经元。最右边的,即输出层包含输出神经元。中间的那些层,被称为隐藏层。
以上一层的输出作为一下层的输入的网络,我们称为前馈神经网络。这意味着网络中是没有回路的,信息总是向前传播,从不反向反馈。如果确实有回路,那么最终的情况是sigma函数的输入会依赖于输出。这将难于理解,所以我们不允许这样的环路。
然而,也有些人工神经网络的模型,其中反馈环路是可行的。这些模型被称为递归神经网络。递归神经网络比前馈网络影响力小得多,部分原因是递归网络的学习算法不够强大。
此外,我们要从根本原因上理解神经网络究竟在做些什么。以MNIST手写数据库为例,为了识别0-9的数字,我们要考虑有10个输出神经元。我们首先要考虑第一个输出神经元,它告诉我们是不是0。它能那么做是因为它可以权衡从隐藏层来的信息。
比如,隐藏层的第一个神经元是用于检测如下图形是否存在:
为了达到这个目的,它通过对此图形部分的像素赋予较大权重,对其他部分赋予较小的权重。同理,我们可以假设隐藏层的第二,第三,第四个神经元是为检测下列图片是否存在:
就像你能猜到的,这四幅图像组合在一起构成了前面显示的一行数字图像中的0:
如果所有隐藏层的这四个神经元被激活那么我们就可以推断出这个数字是0。
4. 梯度下降
我们希望有个算法,能让我们找到权重和偏置,以至于网络的输出能够拟合所有的训练输入。为了量化我们如何实现这个目标,我们定义一个代价函数:
这里w表示所有的网络中权重的集合,b是所有的偏置,n是训练输入数据的个数,a是表示当输入为x的时候输出的向量。我们把C称为二次代价函数,有时候也被称为均方误差或者MSE。代价函数的值相当小的时候,是当对于所有的训练输入x,y(x)接近于输出a时。因此如果我们的学习算法能找到合适的权重和偏置,使得C(w,b)约等于0,它就能很好地工作。反之亦然。
因此,我们训练算法的目的是最小化权重和偏置的代价函数C(w,b)。换句话说,我们想要找到一系列能让代价尽可能小的权重和偏置。我们将采用称为梯度下降的算法达到这个目的。
为什么要用二次代价函数呢?毕竟我们最初感兴趣的内容不就是能正确分类的图像的数量嘛?为什么不试着最大化这个数量,而是去最小化一个类似于二次代价的间接评量呢?这么做是因为在神经网络中,被正确分类的图像数量所关于权重和偏置的函数并不是一个平滑的函数。大多情况下,对权重和偏置做出的微小变动完全不会影响被正确分类的图像的数量。这会导致我们很难去解决如何改变权重和偏置来取得改进的性能。而用一个类似二次代价的平滑代价函数则能更好的解决如何用权重和偏置中的微小变化来取得更好的效果。
强调一下,我们训练神经网络的目的是能找到一个最小化二次代价函数的权重和偏置。
所以,问题转化为求二次代价函数的最小值。
那么一种解决问题的方法是微积分。我们可以计算导数去寻找C的极值点。运气好的话,C是一个或者几个变量的函数。但是,如果变量过多的话,那就是噩梦。而且我们神经网络中经常需要用到大量的变量--那么最大的神经网络有依赖于数亿权重和偏置的代价函数,极其复杂。所以用微积分来计算最小值是不可能的。
所以另一个方法就是梯度下降。首先,我们将函数想象为一个山谷。我们想象有一个小球从山谷的斜坡滚下来。我们日常的经验告诉我们,这个球最终会滚落到谷底。也许我们可以用这个想法来找到函数的最小值。我们可以为假想的球体随机选择一个起始位置,然后模拟球体滚落到谷底的运动。我们通过计算C的导数来模拟这个过程。
为了更精确地描述这个问题,让我们思考一下,我们在v1和v2方向上分别将球体移动一个很小的量,球体会发生什么变化:
我们要寻找一种选择delta1和delta2使得deltaC为负值。我们选择它们是为了让球体滚落。我们用deltaC来表示梯度向量:
所以上面可以重写为:
这个表达式解释了为什么deltaC被称为梯度向量,因为deltaC把v的变化关联为C的变化。这个方程的兴奋之处是它让我们看到了如何选取deltav才能让C的变化值为负。
总结一下,梯度下降算法工作的方式就是重复计算梯度deltaC,然后沿着相反的方向移动,沿着山谷滚落。
为了使梯度下降能够正确的运行,我们需要选择足够小的学习速率才能使方程更好的近似。如果不这样,我们会以C的变化址为正而结束,这显然不好。但是如果学习速率太小,那么使得v变化太小,梯度下降就会进行的非常缓慢。在真正的实现中,学习速率是不断的变化的。
所以,将上面推到的例子运用到神经网络中来。那么就是利用梯度下降算法去寻找使得二次代价函数最小的权重和偏置。
应用梯度下降规则有很多挑战。代价函数有着这样的形式
即,它是遍历每个训练样本代价Cx的平均值。在实践中,为了计算梯度deltaC,我们需要为每个训练输入x单独地计算梯度值,然后再求平均值。不幸的是,当训练输入的数量过大的时候,会花费很长的时间,这样会使得学习变得很缓慢。
4.1 离线学习(Offline Learning)
上面提到的梯度下降,就是Batch learning或者叫offline learning,强调的是每次训练都需要使用全量的样本,因而可能会面临数据量过大的问题。offline learning包括的批量梯度下降法(BGD)和随机梯度下降法(SGD)。首先明确BGD和SGD都属于batch learing,都需要全量训练数据进行训练,需要遍历所有样本。
(1) 批量梯度下降法
BGD在每次更新模型的时候,都要使用全量样本来计算更新的梯度值。如果有m个样本,迭代n轮,那么需要是m*n的计算复杂度。
(2) 随机梯度下降法
SGD在每次更新模型的时候,只要当前遍历到的样本来计算更新的梯度值就行了。如果迭代n轮,则只需要n的计算复杂度,因为每轮只计算一个样本。其思想就是通过随机选取小量训练输入样本计算deltaCx,进而估计deltaC。通过计算少量样本的平均值,我们可以快速的得到一个对于实际梯度值很好的估算,这有助于加速梯度下降。
随机梯度下降通过随机的选取并训练输入的小批量数据来工作:
其中两个求和符合是在当前小批量数据中的所有训练样本Xj上进行的。然后我们再挑选另一随机选定的小批量数据去训练。直到我们用完了所有的训练输入,这被称为完成了一个训练迭代期(epoch)。然后我们就会开始一个新的训练迭代期。
BGD和SGD的区别,容易看出,BGD的优势在于计算的是全局最优解,效果较SGD会好一些,劣势在于计算开销大;SGD则相反,优势在于计算开销减小很多,劣势在于计算的是局部最优解,可能最终达不到全局最优解。在数据量大的时候,SGD是较好的折衷选择。
4.2 在线学习(Online Learning)
Offline learning一般进行多轮迭代来向最优解靠近。Online learning没有多轮的概念,如果数据量不够或训练数据不够充分,通过copy多份同样的训练数据来模拟batch learning的多轮训练也是有效的方法。
梯度下降算法一个极端的版本是把小批量数据的大小设为1。即假设一个训练输入x,我们按照规则更新我们的权重和偏置。然后我们选取另一个训练输入,再一次更新权重和偏置。如此重复。这个过程被称为在线学习或者递增学习。
online learning强调的是学习是实时的,流式的,每次训练不用使用全部样本,而是以之前训练好的模型为基础,每来一个样本就更新一次模型,这种方法叫做OGD(online gradient descent)。这样做的目的是快速地进行模型的更新,提升模型时效性。
5. 反向传播(backpropagation)
前面我们知道了可以用梯度下降算法来学习他们自身的权重和偏置。但是,如何计算代价函数的梯度?这个是很大的缺失。所以,我们将用反向传播来计算梯度。
反向传播的核心是一个对代价函数C关于任何权重w或者偏置b的偏导数的表达式。这个表达式告诉我们在改变权重和偏置的时候,代价函数变化的快慢。所以反向传播不仅仅是一种学习的快速算法,实际上它让我们细致领悟如何通过改变权重和偏置来改变整个网络的行为。
(1) 反向传播的四大公式及其推导
(2) 反向传播与梯度下降的关系
梯度下降方法是给出了一种学习权重和偏置的方法,但是这个方法不包含计算代价函数的梯度。而反向传播则是一种能够快速计算代价函数梯度的方法。