一文看懂神经网络

介绍

这份资料是面向那些对人工神经网络(ANN)没有接触过、基本上完全不懂的人做的一个简短入门级的介绍。

首先简要的引入网络模型,然后才开始讲解ANN的相关术语。作为一个应用的案例,文档中解释了反向传播(BP)算法,毕竟这一算法已经得到广泛应用并且许多别的算法也是从它继承而来的。

读者应该已经了解线性代数相关知识,也能解决一些函数和向量问题,如果掌握微积分知识更好但不是必须的。

如果能全部看完这份资料,应该对ANN的概念有个清楚的理解。另外对那些想运用BP算法但又对晦涩难懂的公式细节不想深入理解的读者来讲,这份这份资料就非常合适!

网络

复杂问题的有效解决方法就是“分而治之”。为了理解的目的,可以把复杂系统分解成一些简单的元素。同样,简单的元素也可集成为复杂系统[Bar Yam, 1997]。网络就是一种可以达到这种目的的方法。

网络的类型成千上万,但网络的基本元素是固定的:一系列的结点和连接结点之间的线。

网络中的点可以看做是运算单元。它们接受输入、处理输入、获得输出。有些处理过程可能就像计算输入总和这么简单,也有些可能会复杂一点,比如一个结点可能嵌入了另一个网络。

结点之间的连线决定了结点之间的信息流动。它们可能是单向的,连线的两个结点只能单向流动,也有可能是双向的,连线上的两个结点是相互流动的。

各结点通过连线相互交互产生了全局网络行为,这种行为只通过网络的基本元素是不可能观察到的,称这全局行为是“新显”。也就是说,紧随着网络元素而来的网络能力使网络成为了一个强大有效的工具。

物理学、计算机科学、生物化学、行为学、数学、社会学、经济学、电信和许多别的领域网络已经被应用于建立基于各自领域的模型。这是因为许多系统本身就可以看做是一个网络,比如:蛋白质、计算机、通讯等等。

人工神经网络

有一种类型网络把各个结点看做是“人工神经元”,这种网络就叫做“人工神经网络”(Artificial Neural Networks)。

人工神经元是受自然神经元静息和动作电位的产生机制启发而建立的一个运算模型。

神经元通过位于细胞膜或树突上的突触接受信号。当接受到的信号足够大时(超过某个门限值),神经元被激活然后通过轴突发射信号,发射的信号也许被另一个突触接受,并且可能激活别的神经元。


1.png

人工神经元模型已经把自然神经元的复杂性进行了高度抽象的符号性概括。

神经元模型基本上包括多个输入(类似突触),这些输入分别被不同的权值相乘(收到的信号强度不同),然后被一个数学函数用来计算决定是否激发神经元。还有一个函数(也许是不变,就是复制)计算人工神经元的输出(有时依赖于某个门限)。

人工神经网络把这些人工神经元融合一起用于处理信息。


2.png

权值越大表示输入的信号对神经元影响越大。

权值可以为负值,意味着输入信号收到了抑制。权值不同那么神经元的计算也不同。通过调整权值可以得到固定输入下需要的输出值。

当ANN是由成百上千的神经元组成时,手工计算这些权值会变得异常复杂。这时就需要一些算法技巧。调整权重的过程称为“学习”或者“训练”。

ANN的类型和使用方式也有很多种。从McCulloch和Pitts(1943)建立第一个神经元模型起,已经产生了几百个不同的也被称为ANN的模型。

这些模型之间的不同也许是功能不同、也许是接受值和拓扑结构不同、也许是学习算法不同等等。同时也有一些混合模型,这些模型里的神经元有更多在上文中没有提到的属性。

本文档中我们只讲解使用反向传播算法学习的ANN(Rumelhart and McClelland,1986)来学习合适的权值,这种ANN是所有ANNs里最通用的模型,并且许多模型都是基于它的。

由于ANNs是用来处理信息的,自然它被应用在与信息相关的领域。有许多的ANNs就是对真实神经元网络进行建模,用来研究动物和机器的行为与控制,但是也有许多是用于工程的,比如:模式识别、预测、数据压缩。

反向传播算法

反向传播算法(Rumelhart and McClelland,1986)是应用在分层前馈式ANN上的一种算法。其结构如下图所示:

image_22.png

这种算法的网络结构意味着人工神经元是根据不同层次来组织划分的,并且是通过前向方式发送信号的,然后把错误率通过反馈方式传播给后向上的神经元。

网络通过位于输入层(input layer)的神经元收集输入信号,网络的输出值是通过位于输出层(output)的神经元给出的。

可能存在一层或者多层的中间隐藏层(hidden layers)。

反向传播算法使用监督学习,也就是说我们给这个算法提供了输入值和本来想让计算的输出值,然后计算出误差(真实值和计算值之间的误差)。

反向传播算法的思想就在于学习完训练样本后误差要尽量的小。

训练是以权值为任意值开始的,目的就是不停的调整权值,使误差最小。

实现后向传播算法的ANN里的神经元的激发函数是加权和(输入x_i的与各自的权值w_{ij}相乘后的和):

\large A_j(\vec{x}, \vec{w}) = \sum_i x_i w_{ji} \: \: \: \: \: \: (1)

激活函数只与输入值和权值有关

如果输出函数不变(输出等于激活函数),称神经元是线性的。但是这有严重的局限性。

最通用的输出函数是S型函数.

\large O_j(\vec{x}, \vec{w})=\frac{1}{1+e^{-A_j(\vec{x}, \vec{w})}} \: \: \: \: (2)

S型函数是这样的函数:对于大的正数变量,函数的值渐渐趋近与1,对于大的负数变量,函数的值渐渐趋于0,在零点,函数的值为0.5。

S函数给神经元输出的高低值有一个平稳的过度(接近于1或接近于0)。我们发现输出只和激活函数有关,而激活函数又与输入值和对应的权值有关。

现在,训练的目标就变成了给定输入值得到希望的输出值。既然误差是真实输出值与希望输出值的差值,并且误差依赖于权值,我们需要调整权值来最小化误差。

我们可以为每个神经元的输出定义一个误差函数:

\large E_{j}(\vec{x}, \vec{w}, d) = (O_j (\vec{x}, \vec{w}) - d_j)^2 \: \: \: \: (3)

我们把输出值与希望值的差做了平方,这样可以保证误差值都为正,因为差别越大误差值也越大,差别越小误差值也越小。网络的误差值就是简单的把所有在输出层上神经元的误差求和:

\large E (\vec{x}, \vec{w}, d) = \sum_j (O_j (\vec{x}, \vec{w}) - d_j)^2 \: \: \: \: (4)

后向传播算法现在计算误差是怎么随着输出值、输入值和权重而变化的。我们理解了这些,就可以通过梯度下降法来调整权值了:

\large \Delta w_{ji} = - \eta \frac{\partial E}{\partial w_{ji}} \: \: \: \: \: \: \: \: (5)

上面的公式可以按照下面的思路来理解:每个调整的\Delta w_{ji}值将会根据上次调整后权重与网络误差的依赖程度进行调整,这种依赖程度是E关于w_i的导数。每次调整的步长还依赖于\eta。也就是说对误差影响大的权值相比于影响小的,每次调整的值也比较大。公式(5)循环计算直到找到满意的权值才停止(误差很小了)。

如果你对导数不理解,没关系,你可以把它看着一个函数,并且在下文我将立即用线性代数来代替。如果你理解了,请自己写出来然后和我这儿的做个比较。

所以,我们只须求得E关于w_{ji}的导数。这就是后向传播算法的目标,我们需要得到这个反馈。首先,我们需要计算输出值是怎么影响误差的,它是E关于O_j的导数(来自公式(3))。

\large \frac{\partial E}{\partial O_{j}} = 2 ( O_{j} - d_{j} )\: \: \: \: \: \: \: \: (6)

然后计算激活函数是怎么影响输出的,其次是权值怎么影响激活函数的(来自公式(1)和(2)):

\large \frac{\partial O_{j}}{\partial w_{ji}} = \frac{\partial O_{j}}{\partial A_{j}} \frac{\partial A_{j}}{\partial w_{ji}} = O_{j} (1 - O_{j} ) x_{i}\: \: \: \: \: \: \: \: (7)

继续推导(来自公式(6)和(7)):

\large \frac{\partial E}{\partial w_{ji}} = \frac{\partial E}{\partial O_{j}} \frac{\partial O_{j}}{\partial A_{j}} \frac{\partial A_{j}}{\partial w_{ji}} = 2 ( O_j - d_j ) O_{j}\left (1 - O_{j} \right ) x_{i}\: \: \: \: \: \: \: \: (8)

因此,对于每个权值做如下调整(来自公式(5)和(8)):

\large \Delta w_{ji} = - 2 \eta \left ( O_{j} - d_{j} \right )O_{j}\left (1- O_{j} \right ) x_{i}\: \: \: \: \: \: \: \: (9)

我们可以使用公式(9)来训练含有两层的ANN。

现在我们想训练再多一层的网络还要考虑许多。

如果我们想调整前面一层的权重(我们把它记为v_{ik})。我们首先需要计算误差是怎么依赖于来自上层的输入的,而和权值无关。

这很简单,我们只须把公式(7),(8),(9)里的用w_{ji}代替。

但是也需要知道网路的误差是怎么随v_{ik}而变化的。因此:

\large \Delta v_{ik} = - \eta \frac{\partial E}{\partial v_{ik}} = - \eta \frac{\partial E}{\partial x_{i}} \frac{\partial x_{i}}{\partial v_{ik}}\: \: \: \: \: \: \: \: (10)

这里:

\large \frac{\partial E}{\partial x_{i}} = 2 ( O_{j} - d_{j} ) O_{j} ( 1-O_{j} ) w_{ji}\: \: \: \: \: \: \: \: (11)

另外,假设有输入值为u_k、权重为v_{ik}的信号进入神经元(来自公式(7)):

\large \frac{\partial x_i}{\partial v_{ik}} = x_i ( 1 - x_i ) u_k \: \: \: \: \: \: \: \: (11)

如果我们还想增加一层,用同样的方法计算误差是怎么随第一层的输入和权值而变化的。我们只须对这些牵引稍加注意,毕竟每层的神经元个数是不一样的,不能混淆。

对于实践推理来说,实现后向传播算法的ANNs不能有太多的层,因为花在计算上的时间是随层数指数级别上升的。同时,还有许多具有更快学习速度的改进算法。

多层前馈式网络是深度学习的基础,当前已发展并广泛应用的卷积神经网络,循环神经网络中都能看到多层前馈式网络的影子。

我们的学习将继续。。。。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容