什么是神经网络
简介
人工神经网络(ANN)或连接系统是由构成动物大脑的生物神经网络模糊地启发的计算系统。神经网络本身不是算法,而是许多不同机器学习算法的框架,它们协同工作并处理复杂的数据输入。此类系统通过考虑示例“学习”执行任务,通常不用任何特定于任务的规则编程。例如,在图像识别中,他们可能通过分析手动的示例图像来学习识别包含猫的图像标记为“猫”或“没有猫”,并使用结果来识别其他图像中的猫。他们在没有任何关于猫的先验知识的情况下这样做,例如,他们有毛皮,尾巴,胡须和猫般的面孔。相反,它们会自动从他们处理的学习资料中生成识别特征。
ANN基于称为人工神经元的连接单元或节点的集合,其松散地模拟生物大脑中的神经元。每个连接,如生物大脑中的突触,可以将信号从一个人工神经元传递到另一个人工神经元。接收信号的人工神经元可以处理它,然后发信号通知与之相连的其他人工神经元。
在常见的ANN实现中,人工神经元之间的连接处的信号是实数,并且每个人工神经元的输出通过其输入之和的一些非线性函数来计算。人工神经元之间的联系称为“边缘”。人工神经元和边缘通常具有重量随着学习的进行而调整。重量增加或减少连接处信号的强度。人工神经元可以具有阈值,使得仅在聚合信号超过该阈值时才发送信号。通常,人工神经元聚集成层。不同的层可以对其输入执行不同类型的转换。信号可能在多次遍历各层之后从第一层(输入层)传播到最后一层(输出层)。
人工神经网络方法的最初目标是以与人类大脑相同的方式解决问题。然而,随着时间的推移,注意力转移到执行特定任务,导致偏离生物学。人工神经网络已经用于各种任务,包括计算机视觉,语音识别,机器翻译,社交网络过滤,游戏板和视频游戏以及医学诊断。
人工网络神经的结构
让我们来看一个经典的神经网络。这是一个包含三个层次的神经网络。红色的是输入层,绿色的是输出层,紫色的是中间层(也叫隐藏层)。输入层有3个输入单元,隐藏层有4个单元,输出层有2个单元。后文中,我们统一使用这种颜色来表达神经网络的结构。
在开始介绍前,有一些知识可以先记在心里:
设计一个神经网络时,输入层与输出层的节点数往往是固定的,中间层则可以自由指定;
神经网络结构图中的拓扑与箭头代表着预测过程时数据的流向,跟训练时的数据流有一定的区别;
结构图里的关键不是圆圈(代表“神经元”),而是连接线(代表“神经元”之间的连接)。每个连接线对应一个不同的权重(其值称为权值),这是需要训练得到的。
除了从左到右的形式表达的结构图,还有一种常见的表达形式是从下到上来表示一个神经网络。这时候,输入层在图的最下方。输出层则在图的最上方,如下图:
从左到右的表达形式以Andrew Ng和LeCun的文献使用较多,Caffe里使用的则是从下到上的表达。在本文中使用Andrew Ng代表的从左到右的表达形式。
下面从简单的神经元开始说起,一步一步介绍神经网络复杂结构的形成。
从生物学到神经元
生物神经元
在讨论人工神经元之前,让我们快速看一下生物神经元。它是一种看起来不寻常的细胞,主要存在于动物的大脑中。它由包含核和大多数细胞复杂成分的细胞体组成,其中许多分支延伸称为树突,再加上一个很长的延伸称为轴突。轴突的长度可能比细胞体长几倍,或者长几万倍。轴突在其末端附近分裂成许多分支,称为端粒,在这些分支的顶端是称为突触末端(或简称为突触)的微小结构,与其他神经元的树突或细胞体相连。
生物神经元产生短的电脉冲称为动作电位(AP,或只是信号),它们沿着轴突传播,使突触释放称为神经递质的化学信号。当神经元在几毫秒内接收到足够数量的这些神经递质时,它会激发自己的电脉冲(实际上,它取决于神经递质,因为其中一些会抑制神经元的发射 )。
因此,单个生物神经元的行为似乎很简单,但是它们组成了数十亿个庞大的网络,每个神经元都与数千个其他神经元相连。高度复杂的计算可以通过相当简单的神经元网络来执行,就像复杂的蚁丘可以通过简单蚂蚁的共同努力而出现一样。生物神经网络(BNNs)的架构仍是活跃的研究主题,但大脑的某些部分已被绘制成图,似乎神经元通常组织成连续的层,尤其是在大脑皮层中 ( 大脑的外层 ),如下图所示。
神经元的逻辑计算
McCulloch和Pitts提出了一个非常简单的生物神经元模型,该模型后来被称为神经元:它具有一个或多个二进制 ( 开/关 ) 输入和一个二进制输出。当超过一定数量的输入处于激活状态时,人工神经元将激活其输出。在他们的论文中,表明即使使用这样的简化模型,也可以构建一个人工神经元网络来计算所需的任何逻辑命题。
为了了解这种网络的工作原理,让我们构建一些执行各种逻辑计算的ANN ,假设神经元的至少两个输入处于激活状态时,神经元就会被激活。
让我们看看这些网络的作用:
- 左边的第一个网络是恒等函数:如果神经元A被激活,那么神经元C也被激活 ( 因为它从神经元A接收到两个输入信号 );但是如果神经元A关闭,那么神经元C也关闭。
- 第二个网络执行逻辑AND:仅当神经元A和B都被激活 ( 单个输入信号不足以激活神经元C ) 时,神经元C才被激活。
- 第三个网络执行逻辑OR:如果神经元A或神经元B被激活 ( 或两者都激活 ),则神经元C被激活。
- 最后,如果我们假设输入连接可以抑制神经元的活动 ( 生物神经元就是这种情况 ),则第四网络计算出一个稍微复杂的逻辑命题:只有在神经元A处于活动状态和神经元B关闭时,神经元C才被激活。如果神经元A一直处于活动状态,那么你会得到逻辑非:神经元B关闭时神经元C处于活动状态,反之亦然。
你可以想象如何将这些网络组合起来以计算复杂的逻辑表达式。
感知器
感知器是最简单的ANN架构之一,由Frank Rosenblatt于1957年发明。它基于稍微不同的人工神经元 ,称为阈值逻辑单元 ( TLU ),有时也称为线性阈值单元 ( LTU )。输入和输出是数字 ( 而不是二进制开/关值 ),并且每个输入连接都与权重相关联。TLU计算其输入的加权总和 ( z = w1x1 + w2x2 + … + wnxn = xTw ),然后将阶跃函数应用于该和并输出结果:hw(x) = step(z),其中z = xTw。
感知器中最常用的阶跃函数是Heaviside阶跃函数 ( 见公式1 )。有时使用符号函数代替。
公式1. 感知器中使用的常见阶跃函数 ( 假设阈值=0 )
单个TLU可用于简单的线性二进制分类。它计算输入的线性组合,如果结果超过阈值,则输出正类。否则,它将输出负类 ( 就像逻辑回归或线性SVM分类器一样 )。例如,你可以使用单个TLU根据花瓣的长度和宽度对鸢尾花进行分类 ( 就像我们在前面的章节中所做的那样,还添加了额外的偏移特征x0=1 )。在这种情况下,训练TLU意味着找到w0,w1和w2的正确值 ( 稍后将讨论训练算法 )。
感知器仅由单层TLU 组成,每个TLU连接到所有的输入。当一层中的所有神经元都连接到上一层中的每个神经元 ( 即其输入神经元 ) 时,该层称为全连接层或密集层。感知器的输入被送到称为输入神经元的特殊直通神经元:它们输出被送入的任何输入。所有输入神经元形成输入层。此外,通常会添加一个额外的偏置特征 ( x0 = 1 ):通常使用一种称为"偏置神经元"的特殊类型的神经元来表示该特征,该神经元始终输出1。具有两个输入和三个输出的感知器如图5所示。该感知器可以将实例同时分为三个不同的二进制类,这使其成为多输出分类器。
借助线性代数的魔力,公式2使得可以同时为多个实例高效地计算出一层人工神经元的输出。
公式2 计算全连接层的输出
在此等式中:
- 与往常一样,X代表输入特征的矩阵。每个实例一行,每个特征一列。
- 权重矩阵W包含除偏置神经元外的所有连接权重。在该层中,每个输入神经元一行,每个人工神经元一列。
- 偏置向量b包含偏置神经元和人工神经元之间的所有连接权重。每个人工神经元有一个偏置项。
- 函数φ称为激活函数:当人工神经元是TLU时,它是阶跃函数 ( 但我们在后面会讨论其他激活函数 )。
那么,感知器如何训练?Rosenblatt提出的感知器训练算法在很大程度上受Hebb规则启发。唐纳德·赫布 ( Donald Hebb ) 在其1949年的《行为组织》 ( Wiley ) 中提出,当一个生物神经元经常触发另一个神经元时,这两个神经元之间的联系就会增强。后来,Siegrid Lowel用有名的措辞概括了赫布的思想,即"触发的细胞,连接在一起"。也就是说,两个神经元同时触发时,它们之间的连接权重会增加。该规则后来被称为Hebb规则 ( 或Hebb学习 )。使用此规则的变体训练感知器,该变体考虑了网络进行预测时所犯的错误;感知器学习规则加强了有助于减少错误的连接。更具体地说,感知器一次被送入一个训练实例,并且针对每个实例进行预测。对于产生错误预测的每个输出神经元,它会增强来自输入的连接权重,这些权重将有助于正确的预测。该规则如公式3所示。
公式3. 感知器学习规则 ( 权重更新 )
在此等式中:
- Wi,j是第i个输入神经元和第j个输出神经元之间的连接权重。
- xi是当前训练实例的第i个输入值。
- y^j是当前训练实例的第j个输出神经元的输出。
- yj是当前训练实例的第j个输出神经元的目标输出。
- η是学习率。
每个输出神经元的决策边界都是线性的,因此感知器无法学习复杂的模式 ( 就像逻辑回归分类器一样 )。但是,如果训练实例是线性可分的,Rosenblatt证明了该算法将收敛到一个解。这被称为感知器收敛定理。
Scikit-Learn提供了一个Perceptron类,该类实现了单个TLU网络。它可以像你期望的那样使用,例如,在iris数据集上:
import numpy as np
from sklearn.datasets import load_iris
from sklearn.linear_model import Perceptron
iris = load_iris()
X = iris.data[:, (2, 3)] # petal length, petal width
y = (iris.target == 0).astype(np.int) # Iris setosa?
per_clf = Perceptron()
per_clf.fit(X, y)
y_pred = per_clf.predict([[2, 0.5]])
你可能已经注意到,感知器学习算法非常类似于随机梯度下降。实际上,Scikit-Learn的Perceptron类等效于使用具有以下超参数的SGDClassifier:loss =" perceptron",learning_rate ="constant",eta0 = 1 ( 学习率 ) 和penalty = None ( 无正则化 )。
请注意,与逻辑回归分类器相反,感知器不输出分类概率;相反,他们基于硬阈值进行预测。这是逻辑回归胜过感知器的原因。
Marvin Minsky和Seymour Papert在1969年的专着Perceptron中,特别指出了感知器的一些严重缺陷,即它们无法解决一些琐碎的问题 ( 例如,异或 ( XOR ) 分类问题;参见图6的左侧 )。任何其他线性分类模型 ( 例如逻辑回归分类器 ) 都是如此,但是研究人员对感知器的期望更高,有些人感到失望,他们完全放弃了神经网络,转而支持更高层次的问题,例如逻辑,解决问题和搜索。
事实证明,可以通过堆叠多个感知器来消除感知器的某些局限性。所得的ANN称为多层感知器 ( MLP )。MLP可以解决XOR问题,你可以通过计算图6右侧所示的MLP的输出来验证:输入 ( 0,0 ) 或 ( 1,1 ) ,网络输出0 ,输入 ( 0,1 ) 或 ( 1,0 ) 输出1。所有连接的权重等于1,但显示权重的四个连接除外。尝试验证该网络确实解决了XOR问题!
多层感知器和反向传播
MLP由一层 ( 直通 ) 输入层,一层或多层TLU ( 称为隐藏层 ) 和一个TLU的最后一层 ( 称为输出层 ) 组成 。靠近输入层的层通常称为较低层,靠近输出层的层通常称为较高层。除输出层外的每一层都包含一个偏置神经元,并完全连接到下一层。
信号仅沿一个方向 ( 从输入到输出 ) 流动,因此该结构是前馈神经网络 ( FNN ) 的例子。
当一个ANN包含一个深层的隐藏层时,它称为深层神经网络 ( DNN )。深度学习领域研究DNN,更广泛地讲包含深度计算堆栈的模型。即便如此,只要涉及神经网络 ( 甚至是浅层的神经网络 ),许多人就会谈论深度学习。
多年来,研究人员一直在努力寻找一种训练MLP的方法,但没有成功。但在1986年,大卫·鲁梅尔哈特 ( David Rumelhart ),杰弗里·欣顿 ( Geoffrey Hinton ) 和罗纳德·威廉姆斯 ( Ronald Williams ) 出版了开创性的论文介绍了反向传播训练算法,该算法至今仍在使用。简而言之,它是使用有效的技术自动计算梯度下降:在仅两次通过网络的过程中 ( 一次前向,一次反向 ),反向传播算法能够针对每个模型参数计算网络误差的梯度。换句话说,它可以找出应如何调整每个连接权重和每个偏置项以减少误差。一旦获得了这些梯度,它便会执行常规的梯度下降步骤,然后重复整个过程,直到网络收敛到有解。
自动计算梯度称为自动微分,或者audodiff 。有各种autodiff技术,各有优缺点。反向传播使用的一种称为反向模式。它快速而精确,并且非常适用于微分函数具有多个变量
( 例如,连接权重 ) 和少量输出 ( 例如,一个损失 ) 的情况。
让我们更详细地介绍一下该算法:
- 它一次处理一个小批量 ( 例如,每次包含32个实例 ),并且多次遍历整个训练集。每次遍历都称为一个轮次。
- 每个小批量都传递到网络的输入层,然后将其送到第一个隐藏层。然后该算法将计算该层中所有神经元的输出 ( 对于小批量中的每个实例 )。结果传递到下一层,计算其输出并传递到下一层,以此类推,直到获得最后一层的输出,即输出层。这就是前向通路:就像进行预测一样,只是保留了所有中间结果,因为反向遍历需要它们。
- 接下来,该算法测量网络的输出误差 ( 该算法使用一种损失函数,该函数将网络的期望输出与实际输出进行比较,并返回一些误差测量值 )。
- 然后,它计算每个输出连接对错误的贡献程度。通过应用链式法则 ( 可能是微积分中最基本的规则 ) 来进行分析,从而使此步骤变得快速而精确。
- 然后,算法再次使用链式法则来测量这些错误贡献中有多少是来自下面层中每个连接的错误贡献,算法一直进行,到达输入层为止。如前所述,这种反向传递通过在网络中向后传播误差梯度,从而有效地测量了网络中所有连接权重上的误差梯度 ( 因此称为算法 )。
- 最终,该算法执行梯度下降步骤,使用刚刚计算出的误差梯度来调整网络中的所有连接权重。
该算法非常重要,值得再次总结:对于每个训练实例,反向传播算法首先进行预测 ( 正向传递 ) 并测量误差,然后反向经过每个层以测量来自每个连接的误差贡献 ( 反向传递 ),最后调整连接权重以减少错误 ( 梯度下降步骤 )。
随机初始化所有隐藏层的连接权重很重要,否则训练将失败。例如,如果将所有权重和偏置初始化为零,则给定层中的所有神经元将完全相同,因此反向传播将以完全相同的方式影响它们,因此它们将保持相同。换句话说,尽管每层有数百个神经元,但是你的模型会像每层只有一个神经元一样工作:不会太聪明。相反,如果你随机初始化权重,则会破坏对称性,并允许反向传播来训练各种各样的神经元。
为了使该算法正常工作,作者对MLP的体系结构进行了重要更改:他们将阶跃函数替换为逻辑函数 ( sigmoid ),σ(z) = 1 / (1 + exp(–z))。这一点很重要,因为阶跃函数仅包含平坦段,因此没有梯度可使用 ( 梯度下降不能在平面上移动 ),而逻辑函数在各处均具有定义明确的非零导数,从而使梯度下降在每一步都可以有所进展。实际上,反向传播算法可以与许多其他激活函数 ( 不仅是逻辑函数 ) 一起很好地工作。这是另外两个受欢迎的选择:
双曲正切函数:tanh(z) = 2σ(2z) – 1
与逻辑函数一样,该激活函数为S形,连续且可微,但其输出值范围为-1至1 ( 而不是逻辑函数的从0到1 )。在训练开始时,该范围倾向于使每一层的输出或多或少地以0为中心,这通常有助于加快收敛速度。
线性整流单位函数:ReLU(z) = max(0, z)
ReLU函数是连续的,但不幸的是,在z = 0时,该函数不可微分 ( 斜率会突然变化,这可能使梯度下降反弹 ),并且其导数为0 如果z<0。但是,实际上它运行良好并且具有计算快速的优点,因此它已成为默认值< span="">。最重要的是,它没有最大输出值这一事实有助于减少"梯度下降"期间的某些问题。
这些流行的激活函数及其派生函数如图8所示。可是等等!为什么我们首先需要激活函数?好吧,如果你连接多个线性变换,那么你得到的只是一个线性变换。例如,如果f(x) = 2x + 3且g(x) = 5x – 1,则连接这两个线性函数可以得到另一个线性函数:f(g(x))= 2 ( 5x – 1 ) + 3 = 10x +1。因此,如果层之间没有非线性,那么即使是很深的层堆叠也等同于单个层,因此你无法解决非常复杂的问题。相反,具有非线性激活的足够大的DNN理论上可以近似任何连续函数。
单层神经网络(感知器)
引子
1958年,计算科学家Rosenblatt提出了由两层神经元组成的神经网络。他给它起了一个名字--“感知器”(Perceptron)(有的文献翻译成“感知机”,下文统一用“感知器”来指代)。
感知器是当时首个可以学习的人工神经网络。Rosenblatt现场演示了其学习识别简单图像的过程,在当时的社会引起了轰动。
人们认为已经发现了智能的奥秘,许多学者和科研机构纷纷投入到神经网络的研究中。美国军方大力资助了神经网络的研究,并认为神经网络比“原子弹工程”更重要。这段时间直到1969年才结束,这个时期可以看作神经网络的第一次高潮。
结构
下面来说明感知器模型。
在原来MP模型的“输入”位置添加神经元节点,标志其为“输入单元”。其余不变,于是我们就有了下图:从本图开始,我们将权值w1, w2, w3写到“连接线”的中间。
在“感知器”中,有两个层次。分别是输入层和输出层。输入层里的“输入单元”只负责传输数据,不做计算。输出层里的“输出单元”则需要对前面一层的输入进行计算。
我们把需要计算的层次称之为“计算层”,并把拥有一个计算层的网络称之为“单层神经网络”。有一些文献会按照网络拥有的层数来命名,例如把“感知器”称为两层神经网络。但在本文里,我们根据计算层的数量来命名。
假如我们要预测的目标不再是一个值,而是一个向量,例如[2,3]。那么可以在输出层再增加一个“输出单元”。
下图显示了带有两个输出单元的单层神经网络,其中输出单元z1的计算公式如下图。
可以看到,z1的计算跟原先的z并没有区别。
我们已知一个神经元的输出可以向多个神经元传递,因此z2的计算公式如下图。
可以看到,z2的计算中除了三个新的权值:w4,w5,w6以外,其他与z1是一样的。
整个网络的输出如下图。
目前的表达公式有一点不让人满意的就是:w4,w5,w6是后来加的,很难表现出跟原先的w1,w2,w3的关系。
因此我们改用二维的下标,用wx,y来表达一个权值。下标中的x代表后一层神经元的序号,而y代表前一层神经元的序号(序号的顺序从上到下)。
例如,w1,2代表后一层的第1个神经元与前一层的第2个神经元的连接的权值(这种标记方式参照了Andrew Ng的课件)。根据以上方法标记,我们有了下图。
如果我们仔细看输出的计算公式,会发现这两个公式就是线性代数方程组。因此可以用矩阵乘法来表达这两个公式。
例如,输入的变量是[a1,a2,a3]T(代表由a1,a2,a3组成的列向量),用向量a来表示。方程的左边是[z1,z2]T,用向量z来表示。
系数则是矩阵W(2行3列的矩阵,排列形式与公式中的一样)。
于是,输出公式可以改写成:
g(W * a) = z;
这个公式就是神经网络中从前一层计算后一层的矩阵运算。
效果
与神经元模型不同,感知器中的权值是通过训练得到的。因此,根据以前的知识我们知道,感知器类似一个逻辑回归模型,可以做线性分类任务。
我们可以用决策分界来形象的表达分类的效果。决策分界就是在二维的数据平面中划出一条直线,当数据的维度是3维的时候,就是划出一个平面,当数据的维度是n维时,就是划出一个n-1维的超平面。
下图显示了在二维平面中划出决策分界的效果,也就是感知器的分类效果。
影响
感知器只能做简单的线性分类任务。但是当时的人们热情太过于高涨,并没有人清醒的认识到这点。于是,当人工智能领域的巨擘Minsky指出这点时,事态就发生了变化。
Minsky在1969年出版了一本叫《Perceptron》的书,里面用详细的数学证明了感知器的弱点,尤其是感知器对XOR(异或)这样的简单分类任务都无法解决。
Minsky认为,如果将计算层增加到两层,计算量则过大,而且没有有效的学习算法。所以,他认为研究更深层的网络是没有价值的。(本文成文后一个月,即2016年1月,Minsky在美国去世。谨在本文中纪念这位著名的计算机研究专家与大拿。)
由于Minsky的巨大影响力以及书中呈现的悲观态度,让很多学者和实验室纷纷放弃了神经网络的研究。神经网络的研究陷入了冰河期。这个时期又被称为“AI winter”。
接近10年以后,对于两层神经网络的研究才带来神经网络的复苏。
两层神经网络(多层感知器)
引子
两层神经网络是本文的重点,因为正是在这时候,神经网络开始了大范围的推广与使用。
Minsky说过单层神经网络无法解决异或问题。但是当增加一个计算层以后,两层神经网络不仅可以解决异或问题,而且具有非常好的非线性分类效果。不过两层神经网络的计算是一个问题,没有一个较好的解法。
1986年,Rumelhar和Hinton等人提出了反向传播(Backpropagation,BP)算法,解决了两层神经网络所需要的复杂计算量问题,从而带动了业界使用两层神经网络研究的热潮。目前,大量的教授神经网络的教材,都是重点介绍两层(带一个隐藏层)神经网络的内容。
这时候的Hinton还很年轻,30年以后,正是他重新定义了神经网络,带来了神经网络复苏的又一春。
结构
两层神经网络除了包含一个输入层,一个输出层以外,还增加了一个中间层。此时,中间层和输出层都是计算层。我们扩展上节的单层神经网络,在右边新加一个层次(只含有一个节点)。
现在,我们的权值矩阵增加到了两个,我们用上标来区分不同层次之间的变量。
例如ax(y)代表第y层的第x个节点。z1,z2变成了a1(2),a2(2)。下图给出了a1(2),a2(2)的计算公式。
计算最终输出z的方式是利用了中间层的a1(2),a2(2)和第二个权值矩阵计算得到的,如下图。
假设我们的预测目标是一个向量,那么与前面类似,只需要在“输出层”再增加节点即可。
我们使用向量和矩阵来表示层次中的变量。a(1),a(2),z是网络中传输的向量数据。W(1)和W(2)是网络的矩阵参数。如下图。
使用矩阵运算来表达整个计算公式的话如下:
g(W(1) * a(1)) = a(2);
g(W(2) * a(2)) = z;
由此可见,使用矩阵运算来表达是很简洁的,而且也不会受到节点数增多的影响(无论有多少节点参与运算,乘法两端都只有一个变量)。因此神经网络的教程中大量使用矩阵运算来描述。
需要说明的是,至今为止,我们对神经网络的结构图的讨论中都没有提到偏置节点(bias unit)。事实上,这些节点是默认存在的。它本质上是一个只含有存储功能,且存储值永远为1的单元。在神经网络的每个层次中,除了输出层以外,都会含有这样一个偏置单元。正如线性回归模型与逻辑回归模型中的一样。
偏置单元与后一层的所有节点都有连接,我们设这些参数值为向量b,称之为偏置。如下图。
可以看出,偏置节点很好认,因为其没有输入(前一层中没有箭头指向它)。有些神经网络的结构图中会把偏置节点明显画出来,有些不会。一般情况下,我们都不会明确画出偏置节点。
在考虑了偏置以后的一个神经网络的矩阵运算如下:
g(W(1) * a(1) + b(1)) = a(2);
g(W(2) * a(2) + b(2)) = z;
需要说明的是,在两层神经网络中,我们不再使用sgn函数作为函数g,而是使用平滑函数sigmoid作为函数g。我们把函数g也称作激活函数(active function)。
事实上,神经网络的本质就是通过参数与激活函数来拟合特征与目标之间的真实函数关系。初学者可能认为画神经网络的结构图是为了在程序中实现这些圆圈与线,但在一个神经网络的程序中,既没有“线”这个对象,也没有“单元”这个对象。实现一个神经网络最需要的是线性代数库。
效果
与单层神经网络不同。理论证明,两层神经网络可以无限逼近任意连续函数。
这是什么意思呢?也就是说,面对复杂的非线性分类任务,两层(带一个隐藏层)神经网络可以分类的很好。
下面就是一个例子(此两图来自colah的博客),红色的线与蓝色的线代表数据。而红色区域和蓝色区域代表由神经网络划开的区域,两者的分界线就是决策分界。
可以看到,这个两层神经网络的决策分界是非常平滑的曲线,而且分类的很好。有趣的是,前面已经学到过,单层网络只能做线性分类任务。而两层神经网络中的后一层也是线性分类层,应该只能做线性分类任务。为什么两个线性分类任务结合就可以做非线性分类任务?
我们可以把输出层的决策分界单独拿出来看一下。就是下图。
可以看到,输出层的决策分界仍然是直线。关键就是,从输入层到隐藏层时,数据发生了空间变换。也就是说,两层神经网络中,隐藏层对原始的数据进行了一个空间变换,使其可以被线性分类,然后输出层的决策分界划出了一个线性分类分界线,对其进行分类。
这样就导出了两层神经网络可以做非线性分类的关键--隐藏层。联想到我们一开始推导出的矩阵公式,我们知道,矩阵和向量相乘,本质上就是对向量的坐标空间进行一个变换。因此,隐藏层的参数矩阵的作用就是使得数据的原始坐标空间从线性不可分,转换成了线性可分。
两层神经网络通过两层的线性模型模拟了数据内真实的非线性函数。因此,多层的神经网络的本质就是复杂函数拟合。
下面来讨论一下隐藏层的节点数设计。在设计一个神经网络时,输入层的节点数需要与特征的维度匹配,输出层的节点数要与目标的维度匹配。而中间层的节点数,却是由设计者指定的。因此,“自由”把握在设计者的手中。但是,节点数设置的多少,却会影响到整个模型的效果。如何决定这个自由层的节点数呢?目前业界没有完善的理论来指导这个决策。一般是根据经验来设置。较好的方法就是预先设定几个可选值,通过切换这几个值来看整个模型的预测效果,选择效果最好的值作为最终选择。这种方法又叫做Grid Search(网格搜索)。
了解了两层神经网络的结构以后,我们就可以看懂其它类似的结构图。例如EasyPR字符识别网络架构(下图)。
EasyPR使用了字符的图像去进行字符文字的识别。输入是120维的向量。输出是要预测的文字类别,共有65类。根据实验,我们测试了一些隐藏层数目,发现当值为40时,整个网络在测试集上的效果较好,因此选择网络的最终结构就是120,40,65。
训练
下面简单介绍一下两层神经网络的训练。
在Rosenblat提出的感知器模型中,模型中的参数可以被训练,但是使用的方法较为简单,并没有使用目前机器学习中通用的方法,这导致其扩展性与适用性非常有限。从两层神经网络开始,神经网络的研究人员开始使用机器学习相关的技术进行神经网络的训练。例如用大量的数据(1000-10000左右),使用算法进行优化等等,从而使得模型训练可以获得性能与数据利用上的双重优势。
机器学习模型训练的目的,就是使得参数尽可能的与真实的模型逼近。具体做法是这样的。首先给所有参数赋上随机值。我们使用这些随机生成的参数值,来预测训练数据中的样本。样本的预测目标为Yp,真实目标为y。那么,定义一个值loss,计算公式如下。
loss = (Yp - y)2
这个值称之为损失(loss),我们的目标就是使对所有训练数据的损失和尽可能的小。
如果将先前的神经网络预测的矩阵公式带入到Yp中(因为有z=Yp),那么我们可以把损失写为关于参数(parameter)的函数,这个函数称之为损失函数(loss function)。下面的问题就是求:如何优化参数,能够让损失函数的值最小。
此时这个问题就被转化为一个优化问题。一个常用方法就是高等数学中的求导,但是这里的问题由于参数不止一个,求导后计算导数等于0的运算量很大,所以一般来说解决这个优化问题使用的是梯度下降算法。梯度下降算法每次计算参数在当前的梯度,然后让参数向着梯度的反方向前进一段距离,不断重复,直到梯度接近零时截止。一般这个时候,所有的参数恰好达到使损失函数达到一个最低值的状态。
在神经网络模型中,由于结构复杂,每次计算梯度的代价很大。因此还需要使用反向传播算法。反向传播算法是利用了神经网络的结构进行的计算。不一次计算所有参数的梯度,而是从后往前。首先计算输出层的梯度,然后是第二个参数矩阵的梯度,接着是中间层的梯度,再然后是第一个参数矩阵的梯度,最后是输入层的梯度。计算结束以后,所要的两个参数矩阵的梯度就都有了。
反向传播算法可以直观的理解为下图。梯度的计算从后往前,一层层反向传播。前缀E代表着相对导数的意思。
反向传播算法的启示是数学中的链式法则。在此需要说明的是,尽管早期神经网络的研究人员努力从生物学中得到启发,但从BP算法开始,研究者们更多地从数学上寻求问题的最优解。不再盲目模拟人脑网络是神经网络研究走向成熟的标志。正如科学家们可以从鸟类的飞行中得到启发,但没有必要一定要完全模拟鸟类的飞行方式,也能制造可以飞天的飞机。
优化问题只是训练中的一个部分。机器学习问题之所以称为学习问题,而不是优化问题,就是因为它不仅要求数据在训练集上求得一个较小的误差,在测试集上也要表现好。因为模型最终是要部署到没有见过训练数据的真实场景。提升模型在测试集上的预测效果的主题叫做泛化(generalization),相关方法被称作正则化(regularization)。神经网络中常用的泛化技术有权重衰减等。
影响
两层神经网络在多个地方的应用说明了其效用与价值。10年前困扰神经网络界的异或问题被轻松解决。神经网络在这个时候,已经可以发力于语音识别,图像识别,自动驾驶等多个领域。
历史总是惊人的相似,神经网络的学者们再次登上了《纽约时报》的专访。人们认为神经网络可以解决许多问题。就连娱乐界都开始受到了影响,当年的《终结者》电影中的阿诺都赶时髦地说一句:我的CPU是一个神经网络处理器,一个会学习的计算机。
但是神经网络仍然存在若干的问题:尽管使用了BP算法,一次神经网络的训练仍然耗时太久,而且困扰训练优化的一个问题就是局部最优解问题,这使得神经网络的优化较为困难。同时,隐藏层的节点数需要调参,这使得使用不太方便,工程和研究人员对此多有抱怨。
90年代中期,由Vapnik等人发明的SVM(Support Vector Machines,支持向量机)算法诞生,很快就在若干个方面体现出了对比神经网络的优势:无需调参;高效;全局最优解。基于以上种种理由,SVM迅速打败了神经网络算法成为主流。
神经网络的研究再次陷入了冰河期。当时,只要你的论文中包含神经网络相关的字眼,非常容易被会议和期刊拒收,研究界那时对神经网络的不待见可想而知。
多层神经网络(深度学习)
引子
在被人摒弃的10年中,有几个学者仍然在坚持研究。这其中的棋手就是加拿大多伦多大学的Geoffery Hinton教授。
2006年,Hinton在《Science》和相关期刊上发表了论文,首次提出了“深度信念网络”的概念。与传统的训练方式不同,“深度信念网络”有一个“预训练”(pre-training)的过程,这可以方便的让神经网络中的权值找到一个接近最优解的值,之后再使用“微调”(fine-tuning)技术来对整个网络进行优化训练。这两个技术的运用大幅度减少了训练多层神经网络的时间。他给多层神经网络相关的学习方法赋予了一个新名词--“深度学习”。
很快,深度学习在语音识别领域暂露头角。接着,2012年,深度学习技术又在图像识别领域大展拳脚。Hinton与他的学生在ImageNet竞赛中,用多层的卷积神经网络成功地对包含一千类别的一百万张图片进行了训练,取得了分类错误率15%的好成绩,这个成绩比第二名高了近11个百分点,充分证明了多层神经网络识别效果的优越性。
在这之后,关于深度神经网络的研究与应用不断涌现。
由于篇幅原因,本文不介绍CNN(Conventional Neural Network,卷积神经网络)可参看《AI算法01-卷积神经网络CNN》与RNN(Recurrent Neural Network,递归神经网络)可参看《AI算法02-循环神经网络Recurrent Neural Network | RNN》的架构,下面我们只讨论普通的多层神经网络。
结构
我们延续两层神经网络的方式来设计一个多层神经网络。
在两层神经网络的输出层后面,继续添加层次。原来的输出层变成中间层,新加的层次成为新的输出层。所以可以得到下图。
依照这样的方式不断添加,我们可以得到更多层的多层神经网络。公式推导的话其实跟两层神经网络类似,使用矩阵运算的话就仅仅是加一个公式而已。
在已知输入a(1),参数W(1),W(2),W(3)的情况下,输出z的推导公式如下:
g(W(1) * a(1)) = a(2);
g(W(2) * a(2)) = a(3);
g(W(3) * a(3)) = z;
多层神经网络中,输出也是按照一层一层的方式来计算。从最外面的层开始,算出所有单元的值以后,再继续计算更深一层。只有当前层所有单元的值都计算完毕以后,才会算下一层。有点像计算向前不断推进的感觉。所以这个过程叫做“正向传播”。
下面讨论一下多层神经网络中的参数。
首先我们看第一张图,可以看出W(1)中有6个参数,W(2)中有4个参数,W(3)中有6个参数,所以整个神经网络中的参数有16个(这里我们不考虑偏置节点,下同)。
假设我们将中间层的节点数做一下调整。第一个中间层改为3个单元,第二个中间层改为4个单元。
经过调整以后,整个网络的参数变成了33个。
虽然层数保持不变,但是第二个神经网络的参数数量却是第一个神经网络的接近两倍之多,从而带来了更好的表示(represention)能力。表示能力是多层神经网络的一个重要性质,下面会做介绍。
在参数一致的情况下,我们也可以获得一个“更深”的网络。
上图的网络中,虽然参数数量仍然是33,但却有4个中间层,是原来层数的接近两倍。这意味着一样的参数数量,可以用更深的层次去表达。
效果
与两层层神经网络不同。多层神经网络中的层数增加了很多。
增加更多的层次有什么好处?更深入的表示特征,以及更强的函数模拟能力。
更深入的表示特征可以这样理解,随着网络的层数增加,每一层对于前一层次的抽象表示更深入。在神经网络中,每一层神经元学习到的是前一层神经元值的更抽象的表示。例如第一个隐藏层学习到的是“边缘”的特征,第二个隐藏层学习到的是由“边缘”组成的“形状”的特征,第三个隐藏层学习到的是由“形状”组成的“图案”的特征,最后的隐藏层学习到的是由“图案”组成的“目标”的特征。通过抽取更抽象的特征来对事物进行区分,从而获得更好的区分与分类能力。
关于逐层特征学习的例子,可以参考下图。
更强的函数模拟能力是由于随着层数的增加,整个网络的参数就越多。而神经网络其实本质就是模拟特征与目标之间的真实关系函数的方法,更多的参数意味着其模拟的函数可以更加的复杂,可以有更多的容量(capcity)去拟合真正的关系。
通过研究发现,在参数数量一样的情况下,更深的网络往往具有比浅层的网络更好的识别效率。这点也在ImageNet的多次大赛中得到了证实。从2012年起,每年获得ImageNet冠军的深度神经网络的层数逐年增加,2015年最好的方法GoogleNet是一个多达22层的神经网络。
在最新一届的ImageNet大赛上,目前拿到最好成绩的MSRA团队的方法使用的更是一个深达152层的网络!关于这个方法更多的信息有兴趣的可以查阅ImageNet网站。
4.训练
在单层神经网络时,我们使用的激活函数是sgn函数。到了两层神经网络时,我们使用的最多的是sigmoid函数。而到了多层神经网络时,通过一系列的研究发现,ReLU函数在训练多层神经网络时,更容易收敛,并且预测性能更好。因此,目前在深度学习中,最流行的非线性函数是ReLU函数。ReLU函数不是传统的非线性函数,而是分段线性函数。其表达式非常简单,就是y=max(x,0)。简而言之,在x大于0,输出就是输入,而在x小于0时,输出就保持为0。这种函数的设计启发来自于生物神经元对于激励的线性响应,以及当低于某个阈值后就不再响应的模拟。
在多层神经网络中,训练的主题仍然是优化和泛化。当使用足够强的计算芯片(例如GPU图形加速卡)时,梯度下降算法以及反向传播算法在多层神经网络中的训练中仍然工作的很好。目前学术界主要的研究既在于开发新的算法,也在于对这两个算法进行不断的优化,例如,增加了一种带动量因子(momentum)的梯度下降算法。
在深度学习中,泛化技术变的比以往更加的重要。这主要是因为神经网络的层数增加了,参数也增加了,表示能力大幅度增强,很容易出现过拟合现象。因此正则化技术就显得十分重要。目前,Dropout技术,以及数据扩容(Data-Augmentation)技术是目前使用的最多的正则化技术。
5.影响
目前,深度神经网络在人工智能界占据统治地位。但凡有关人工智能的产业报道,必然离不开深度学习。神经网络界当下的四位引领者除了前文所说的Ng,Hinton以外,还有CNN的发明人Yann Lecun,以及《Deep Learning》的作者Bengio。
前段时间一直对人工智能持谨慎态度的马斯克,搞了一个OpenAI项目,邀请Bengio作为高级顾问。马斯克认为,人工智能技术不应该掌握在大公司如Google,Facebook的手里,更应该作为一种开放技术,让所有人都可以参与研究。马斯克的这种精神值得让人敬佩。
多层神经网络的研究仍在进行中。现在最为火热的研究技术包括RNN,LSTM等,研究方向则是图像理解方面。图像理解技术是给计算机一幅图片,让它用语言来表达这幅图片的意思。ImageNet竞赛也在不断召开,有更多的方法涌现出来,刷新以往的正确率。
人工神经网络展望
量子计算
回到我们对神经网络历史的讨论,根据历史趋势图来看,神经网络以及深度学习会不会像以往一样再次陷入谷底?作者认为,这个过程可能取决于量子计算机的发展。
根据一些最近的研究发现,人脑内部进行的计算可能是类似于量子计算形态的东西。而且目前已知的最大神经网络跟人脑的神经元数量相比,仍然显得非常小,仅不及1%左右。所以未来真正想实现人脑神经网络的模拟,可能需要借助量子计算的强大计算能力。
各大研究组也已经认识到了量子计算的重要性。谷歌就在开展量子计算机D-wave的研究,希望用量子计算来进行机器学习,并且在前段时间有了突破性的进展。国内方面,阿里和中科院合作成立了量子计算实验室,意图进行量子计算的研究。
如果量子计算发展不力,仍然需要数十年才能使我们的计算能力得以突飞猛进的发展,那么缺少了强大计算能力的神经网络可能会无法一帆风顺的发展下去。这种情况可以类比为80-90年时期神经网络因为计算能力的限制而被低估与忽视。假设量子计算机真的能够与神经网络结合,并且助力真正的人工智能技术的诞生,而且量子计算机发展需要10年的话,那么神经网络可能还有10年的发展期。直到那时期以后,神经网络才能真正接近实现AI这一目标。
人工智能
最后,作者想简单地谈谈对目前人工智能的看法。虽然现在人工智能非常火热,但是距离真正的人工智能还有很大的距离。就拿计算机视觉方向来说,面对稍微复杂一些的场景,以及易于混淆的图像,计算机就可能难以识别。因此,这个方向还有很多的工作要做。
就普通人看来,这么辛苦的做各种实验,以及投入大量的人力就是为了实现一些不及孩童能力的视觉能力,未免有些不值。但是这只是第一步。虽然计算机需要很大的运算量才能完成一个普通人简单能完成的识图工作,但计算机最大的优势在于并行化与批量推广能力。使用计算机以后,我们可以很轻易地将以前需要人眼去判断的工作交给计算机做,而且几乎没有任何的推广成本。这就具有很大的价值。正如火车刚诞生的时候,有人嘲笑它又笨又重,速度还没有马快。但是很快规模化推广的火车就替代了马车的使用。人工智能也是如此。这也是为什么目前世界上各著名公司以及政府都对此热衷的原因。
目前看来,神经网络要想实现人工智能还有很多的路要走,但方向至少是正确的,下面就要看后来者的不断努力了。