神经网络与多层感知机MLP

807 阅读14分钟

神经网络与多层感知机MLP

神经元的逻辑计算

人工神经元:一个或多个二元(开或关)输入,一个二元输出。当达到一定的输入量时,神经元就会产生输出。

img

这些网络的逻辑计算如下:

  • 左边第一个网络是确认函数:如果神经元A被激活,那么神经元C也被激活(因为它接收来自神经元A的两个输入信号),但是如果神经元A关闭,那么神经元C也关闭。
  • 第二个网络执行逻辑 AND:神经元C只有在激活神经元AB(单个输入信号不足以激活神经元C)时才被激活。
  • 第三个网络执行逻辑 OR:如果神经元A或神经元B被激活(或两者),神经元C被激活。
  • 最后,如果我们假设输入连接可以抑制神经元的活动(生物神经元是这样的情况),那么第四个网络计算一个稍微复杂的逻辑命题:如果神经元B关闭,只有当神经元A是激活的,神经元C才被激活。如果神经元A始终是激活的,那么你得到一个逻辑 NOT:神经元C在神经元B关闭时是激活的,反之亦然。

感知机

感知器

感知器是最简单的人工神经网络结构之一,由 Frank Rosenblatt 发明于 1957 年。它基于一种稍微不同的人工神经元,阈值逻辑单元(TLU),或称为线性阈值单元(LTU):输入和输出是数字(而不是二元开/关值),并且每个输入连接一个权重。TLU 计算其输入的加权和(z = W[1]x[1] + W[2]x[2]+ ... + W[n]x[n] = x^T · W),然后将阶跃函数应用于该和,并输出结果:h[W](x) = step(z),其中z = x^T · W

img

阈值逻辑单元TLU:人工神经元做权重求和,然后对和做阶跃函数

感知机最常用的阶跃函数是单位阶跃函数(Heaviside step function)。有时候也使用符号函数sgn

img

单一 TLU 可用于简单的线性二元分类。它计算输入的线性组合,如果结果超过阈值,它输出正类或者输出负类(就像逻辑回归分类或线性 SVM 分类)。例如,你可以使用单一 TLU,基于花瓣长度和宽度分类鸢尾花(也可添加额外的偏置特征x[0] = 1)。训练 TLU 意味着去寻找合适的W[0], W[1]W[2]值。

感知器只由一层 TLU 组成,每个 TLU 连接到所有输入。**当一层的神经元连接着前一层的每个神经元时,该层被称为全连接层,或紧密层。**感知机的输入来自输入神经元,输入神经元只输出从输入层接收的任何输入。所有的输入神经元位于输入层。此外,通常再添加一个偏置特征(X[0] = 1):这种偏置特性通常用一种称为偏置神经元的特殊类型的神经元来表示,它总是输出 1。下图展示了一个具有两个输入和三个输出的感知机,它可以将实例同时分成为三个不同的二元类,这使它成为一个多输出分类器。

img

一个具有两个输入神经元、一个偏置神经元和三个输出神经元的感知机架构

借助线性代数,利用公式可以方便地同时算出几个实例的一层神经网络的输出:

img

在这个公式中,

  • X表示输入特征矩阵,每行是一个实例,每列是一个特征;
  • 权重矩阵W包含所有的连接权重,除了偏置神经元。每有一个输入神经元权重矩阵就有一行,神经层每有一个神经元权重矩阵就有一列;
  • 偏置向量b含有所有偏置神经元和人工神经元的连接权重。每有一个人工神经元就对应一个偏置项;
  • 函数φ被称为激活函数,当人工神经网络是 TLU 时,激活函数是阶跃函数。

感知器训练

Frank Rosenblatt 提出的感知器训练算法在很大程度上受到 Hebb 规则的启发。在 1949 出版的《行为组织》一书中,Donald Hebb 提出,当一个生物神经元经常触发另一个神经元时,这两个神经元之间的联系就会变得更强。这个想法后来被 Siegrid Löwel 总结为一经典短语:“一起燃烧的细胞,汇合在一起。”这个规则后来被称为 Hebb 规则(或 Hebbian learning)。使用这个规则的变体来训练感知器,该规则考虑了网络所犯的误差。更具体地,感知器一次被馈送一个训练实例,对于每个实例,它进行预测。对于每一个产生错误预测的输出神经元,修正输入的连接权重,以获得正确的预测。

img

在这个公式中:

  • 其中w[i, j]是第i个输入神经元与第j个输出神经元之间的连接权重;
  • x[i]是当前训练实例的第i个输入值;
  • y_hat[j]是当前训练实例的第j个输出神经元的输出;
  • y[j]是当前训练实例的第j个输出神经元的目标输出;
  • η是学习率。

每个输出神经元的决策边界是线性的,因此感知器不能学习复杂的模式(比如 Logistic 回归分类器)。然而,如果训练实例是线性可分的,Rosenblatt 证明该算法将收敛到一个解。这被称为感知器收敛定理。

Scikit-Learn 提供了一个Perceptron类,它实现了一个 单 TLU 网络。它可以实现大部分功能,例如用于鸢尾花数据集:

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]])

感知器学习算法和随机梯度下降很像。事实上,sklearn 的Perceptron类相当于使用具有以下超参数的 SGDClassifierloss="perceptron"learning_rate="constant"eta0=1(学习率),penalty=None(无正则化)。

与逻辑回归分类器相反,感知机不输出类概率,而是基于硬阈值进行预测。这是逻辑回归优于感知机的一点。

感知器与多层感知机(MLP)

在 1969 年题为“感知机”的专著中,Marvin Minsky 和 Seymour Papert 强调了感知器的许多严重缺陷,特别是它们不能解决一些琐碎的问题(例如,异或(XOR)分类问题)。当然,其他的线性分类模型(如 Logistic 回归分类器)也都实现不了,但研究人员期望从感知器中得到更多,他们的失望是很大的,导致许多人彻底放弃了神经网络,而是转向高层次的问题,如逻辑、问题解决和搜索。

然而,事实证明,感知机的一些局限性可以通过堆叠多个感知机消除。**由此产生的人工神经网络被称为多层感知机(MLP)。**特别地,MLP 可以解决 XOR 问题,你可以通过计算图右侧所示的 MLP 的输出来验证输入的每一个组合:输入(0, 0)(1, 1)网络输出 0,输入(0, 1)(1, 0)它输出 1。除了四个连接的权重不是 1,其它连接都是 1。

img

多层感知机与反向传播(BP)

MLP 由一个输入层、一个或多个称为隐藏层的 TLU 组成,一个 TLU 层称为输出层。靠近输入层的层,通常被称为浅层,靠近输出层的层通常被称为上层。除了输出层,每一层都有一个偏置神经元,并且全连接到下一层。

img

注意:信号是从输入到输出单向流动的,因此这种架构被称为前馈神经网络(FNN)。

**当人工神经网络有多个隐含层时,称为深度神经网络(DNN)。**深度学习研究的是 DNN 和深层计算模型。但是大多数人用深度学习泛化代替神经网络,即便网络很浅时。

多年来,研究人员努力寻找一种训练 MLP 的方法,但没有成功。但在 1986,David Rumelhart、Geoffrey Hinton、Ronald Williams 发表了一篇突破性的论文(Learning internal representations by error propagation),提出了至今仍在使用的反向传播训练算法(BP算法)。总而言之,**反向传播算法是使用了高效梯度计算的梯度下降算法:只需要两次网络传播(一次向前,一次向后),就可以算出网络误差的、和每个独立模型参数相关的梯度。**换句话说,反向传播算法为了减小误差,可以算出每个连接权重和每个偏置项的调整量。当得到梯度之后,就做一次常规的梯度下降,不断重复这个过程,直到网络得到收敛解。

自动计算梯度被称为自动微分。有多种自动微分的方法,各有优缺点。反向传播使用的是反向模式自微分。这种方法快而准,当函数有多个变量(连接权重)和多个输出(损失函数)要微分时也能应对。

对 BP 做详细分解:

  • 每次处理一个微批次(假如每个批次包含 32 个实例),用训练集多次训练 BP,每次被称为一个周期(epoch)
  • 每个微批次先进入输入层,输入层再将其发到第一个隐藏层。计算得到该层所有神经元的(微批次的每个实例的)输出。输出接着传到下一层,直到得到输出层的输出。这个过程就是前向传播:就像做预测一样,只是保存了每个中间结果,中间结果要用于反向传播;
  • 然后计算输出误差(使用损失函数比较目标值和实际输出值,然后返回误差);
  • 接着,计算每个输出连接对误差的贡献量。这是通过链式法则(就是对多个变量做微分的方法)实现的;
  • 然后还是使用链式法则,计算最后一个隐藏层的每个连接对误差的贡献,这个过程不断向后传播,直到到达输入层。
  • 最后,BP 算法做一次梯度下降步骤,用刚刚计算的误差梯度调整所有连接权重

BP 算法十分重要,再归纳一下:对每个训练实例,BP 算法先做一次预测(前向传播),然后计算误差,然后反向通过每一层以测量误差贡献量(反向传播),最后调整所有连接权重以降低误差(梯度下降)。(每次训练都先是要设置周期数,每个周期其实做的就是三件事,向前传一次,向后传一次,然后调整参数,接着再进行下一周期。

注意:随机初始化隐藏层的连接权重是很重要的。假如所有的权重和偏置都初始化为 0,则在给定一层的所有神经元都是一样的,BP 算法对这些神经元的调整也会是一样的。换句话,就算每层有几百个神经元,模型的整体表现就像每层只有一个神经元一样,模型会显得笨笨的。如果权重是随机初始化的,就可以打破对称性,训练出不同的神经元。

**为了使 BP 算法正常工作,作者对 MLP 的架构做了一个关键调整:用 Logistic 函数(sigmoid)代替阶跃函数,σ(z) = 1 / (1 + exp(–z))。这是必要的,因为阶跃函数只包含平坦的段,因此没有梯度(梯度下降不能在平面上移动),而 Logistic 函数处处都有一个定义良好的非零导数,允许梯度下降在每步上取得一些进展。**反向传播算法也可以与其他激活函数一起使用,下面就是两个流行的激活函数:

  • 双曲正切函数: tanh (z) = 2σ(2z) – 1

类似 Logistic 函数,它是 S 形、连续可微的,但是它的输出值范围从-1 到 1(不是 Logistic 函数的 0 到 1),这往往使每层的输出在训练开始时或多或少都变得以 0 为中心,这常常有助于加快收敛速度。

  • ReLU 函数:ReLU(z) = max(0, z)

ReLU 函数是连续的,但是在z=0时不可微(斜率突然改变,导致梯度下降在 0 点左右跳跃),ReLU 的变体是当z<0时,z=0。但在实践中,ReLU 效果很好,并且具有计算快速的优点,于是成为了默认激活函数。最重要的是,它没有最大输出值,这有助于减少梯度下降期间的一些问题。

为什么需要激活函数?

如果将几个线性变化链式组合起来,得到的还是线性变换。比如,对于 f(x) = 2x + 3g(x) = 5x – 1 ,两者组合起来仍是线性变换:f(g(x)) = 2(5x – 1) + 3 = 10x + 1。如果层之间不具有非线性,则深层网络和单层网络其实是等同的,这样就不能解决复杂问题。相反的,足够深且有非线性激活函数的 DNN,在理论上可以近似于任意连续数。

img

激活函数及其变体

MLP分类

回归MLP

MLP 可以用来回归任务。如果想要预测一个单值(例如根据许多特征预测房价),就只需要一个输出神经元,它的输出值就是预测值。对于多变量回归(即一次预测多个值),则每一维度都要有一个神经元。例如,想要定位一张图片的中心,就要预测 2D 坐标,因此需要两个输出神经元。如果再给对象加个边框,还需要两个值:对象的宽度和高度。

通常,当用 MLP 做回归时,输出神经元不需要任何激活函数。如果要让输出是正值,则可在输出值使用 ReLU 激活函数。另外,还可以使用 softplus 激活函数,这是 ReLu 的一个平滑化变体:softplus(z) = log(1 + exp(z))z是负值时,softplus 接近 0,z是正值时,softplus 接近z。最后,如果想让输出落入一定范围内,则可以使用调整过的 Logistic 或双曲正切函数:Logistic 函数用于 0 到 1,双曲正切函数用于 -1 到 1。

训练中的损失函数一般是均方误差,但如果训练集有许多异常值,则可以使用平均绝对误差。另外,也可以使用 Huber 损失函数,它是前两者的组合。

当误差小于阈值δ时(一般为 1),Huber 损失函数是二次的;误差大于阈值时,Huber 损失函数是线性的。相比均方误差,线性部分可以让 Huber 对异常值不那么敏感,二次部分可以让收敛更快,也比均绝对误差更精确。

img

分类MLP

MLP 也可用于分类,对于二元分类问题,只需要一个使用 Logistic 激活的输出神经元:输出是一个 0 和 1 之间的值,作为正类的估计概率。

MLP 也可以处理多标签二元分类。例如,邮件分类系统可以预测一封邮件是垃圾邮件,还是正常邮件,同时预测是紧急,还是非紧急邮件。这时,就需要两个输出神经元,两个都是用 Logistic 函数:第一个输出垃圾邮件的概率,第二个输出紧急的概率。更为一般的讲,需要为每个正类配一个输出神经元。多个输出概率的和不一定非要等于 1。这样模型就可以输出各种标签的组合:非紧急非垃圾邮件、紧急非垃圾邮件、非紧急垃圾邮件、紧急垃圾邮件。

如果每个实例只能属于一个类,但可能是三个或多个类中的一个(比如对于数字图片分类,可以是类 0 到类 9),则每一类都要有一个输出神经元,整个输出层要使用 softmax 激活函数。softmax 函数可以保证,每个估计概率位于 0 和 1 之间,并且各个值相加等于 1。这被称为多类分类。

img

根据损失函数,因为要预测概率分布,交叉商损失函数是不错的选择。

img

内容来源

  1. Sklearn 与 TensorFlow 机器学习实用指南第二版