现在的位置: 首页 > 综合 > 正文

神经网络简介

2013年10月24日 ⁄ 综合 ⁄ 共 4736字 ⁄ 字号 评论关闭

最近在研究Deep Learning在个性化推荐中的应用,由于DL跟神经网络有很大的关系,索性开篇就介绍下神经网络和自己所了解到的知识。接触ML时间不是很长,难免有描述不当的地方,旨在于交流学习,有啥想法直接后面回复。


在这篇博文中,你将会看到如下知识:


神经网络的基本模型,前向神经网络(Feed-forward neural network),General Feed-forward  NN 的组件,优化目标函数,逆向误差传播算法


“ 根据一个简化的统计,人脑由百亿条神经组成 ― 每条神经平均连结到其它几千条神经。通过这种连结方式,神经可以收发不同数量的能量。神经的一个非常重要的功能是它们对能量的接受并不是立即作出响应,而 是将它们累加起来,当这个累加的总和达到某个临界阈值时,它们将它们自己的那部分能量发送给其它的神经。大脑通过调节这些连结的数目和强度进行学习。尽管
这是个生物行为的简化描述。但同样可以充分有力地被看作是神经网络的模型。 ” 

人的大脑是非常复杂的,特别是大脑神经系统,可以说没有它,大脑就是一些组织,细胞而已。在机器学习领域,对神经网络的研究应该是希望从大脑的工作机制和神经系统结构中获得启发,一方面可以设计高效的学习算法,让机器也能够对问题进行大规模学习,另一方面可以从神经元的并行工作方式中得到启发,设计高效的并行计算算法,让机器拥有更强的实时处理大规模数据的能力。

在这里就不介绍生物上的神经网络了,一来是不懂,二来这里的神经网络一概指 机器学习领域的神经网络模型(人工神经网络),如果你对这个生物的神经网络感兴趣的话,可以参考《A Brief
Introduction to Neural Networks · D. Kriesel》
这篇文章有讲到不同类型的神经网络,大多数跟生物神经系统的基本结构有关系。在机器学习领域的神经网络一般会指 前向传播神经网络 (Feed-forward neural network),这种模型较为通用。


人工神经网络的基本模型


前向神经网络

上图描述的是一个目前研究最为成熟Shallow 结构的神经网络(只含有单层隐藏层神经元的结构)。第一层为输入层 (input layer ),第二层称为隐藏层 ( hidden layer ),最后一层为输出层( output layer )。神经元之间都是由低层出发,终止于高层神经元的一条有向边进行连接,每条边都有自己的权重。每个神经元都是一个计算单元,如在Feed-forward neural network 中,除输入层神经元外,每个神经元为一个计算单元,可以通过一个计算函数
f()  来表示,函数的具体形式可以自己定义,现在用的较多的是 感知器计算神经元,如果你对感知器有所了解的话,理解起来会容易很多。 可以计算此时神经元所具有的能量值,当该值超过一定阀值的时候神经元的状态就会发生改变,神经元只有两种状态,激活或未激活。在实际的人工神经网络中,一般是用一种概率的方式去表示神经元是否处于激活状态,可以用 h(f) 来表示,f 代表神经元的能量值,h(f) 代表该能量值使得神经元的状态发生改变的概率有多大,能量值越大,处于激活状态的概率就越高。到这部分你已经接触到了关于神经网络的几个基本术语,神经元的能量值 通过
f()  计算得到, 神经元的激活状态  h(f),h表示激活函数。

激活函数有好几种形式,这里列举两种,

f(z) = \frac{1}{1+\exp(-z)}.                                 f(z) = \tanh(z) = \frac{e^z - e^{-z}}{e^z + e^{-z}},

General Feed-forward  NN 的组件

假设有 包涵有N个样本的数据集 = { (X1,T1) , (X2,T2) , (X3,T3)......  (Xn,Tn)} ,其中T的取值可以根据你的任务不同而不同,比如你要用神经网络进行回归分析,T ( target value)就是一个连续值,如果你面对的是一个回归问题的话,T 的取值就是离散的,比如二分类问题 T = { 0,1 },输入样本的每个观测值(Observation) Xi 都具有相同的维度数量 m ,与之对应的输入层的神经元个数也为
(m + 1)个,包含有一个偏置神经元( bais unit )。

这里采用了Andrew Ng的 Deep Learning tutorials  上的符号系统。nl表示神经网络具有的总层数, L_{n_l} 表示最后一层神经网络,下标就是表示第几层,L1表示第一层,也就是输入层。低层与高层的神经元之间都是通过带权重的单向边进行连接,(W,b)表示整个神经网络中的参数,W
表示连边的权重,b表示偏置。在上图中(W,b)
(W(1),b(1),W(2),b(2)),上角标表示第
i 层与(i + 1)层之间的权重系数矩阵(如无特殊说明,下文中的上角标都表示层号,当然对于系数矩阵和神经元来说,上角标的意思是不太一样的),W^{(l)}_{ij}表示第L层的第
j 个神经元与第 L + 1 层的第 i 个神经元之间的权重系数。
在上图的例子中 W^{(1)} \in \Re^{3\times 3}W^{(2)} \in \Re^{1\times 3} 。
该部分采用向量化的表述方式,这个为后面的向量化编程会带来非常大的好处,不用一个一个的去记哪个跟哪个权重系数对应,直接一个矩阵,非常简洁。整个神经网络可以用一个函数  hW,b(x)
来表示。

接着来看下跟每个神经元都相关的符号,a^{(l)}_i = f(z^{(l)}_i)表示第L层的第i个神经元的激活状态(activations),该过程是非线性操作,这个概念非常重要,要牢记。当L
= 1的时候,可以认为a^{(1)}_i = x_i 就是等于输入神经元的值, z^{(l)}_i表示该神经元具有的能量值。

到此为止,你已经可以掌握一个神经网络中的基本符号和表示方法,尽快熟悉这些符号,在你的脑子里面神经网络已经不再是抽象的神经元之间的连接方式了,可以通过上述的符号来刻画,这对后面公式的理解会有很大的帮助。


下面来看下神经网络的基本成分(
neural network components)


对线性模型(Linear Model)比较了解的人应该非常熟悉这个公式

线性模型可以表示成有限个基函数(basis function)的线性融合,基函数的形式可以自己定义,举个简单的例子,可以是关于输入
m 次幂的多项式 x^m(顺便吐槽一下,这里敲公式实在麻烦)。实际上神经网络也可以看成是一些线性函数的叠加,不过中间有了一个激活函数,情况就变得跟线性模型不一样了。还是以FNN(Feed-forward Neural Network)为例对除输入层之外的每个神经元进行 \textstyle z_i^{(2)} = \sum_{j=1}^n W^{(1)}_{ij} x_j + b^{(1)}_i 的操作就可以得到神经元的能量值,每个神经元的激活状态就可以表示成 a^{(l)}_i = f(z^{(l)}_i) (
非线性操作 ) ,下面对整个网络进行同样的操作就可以得到

\begin{align}a_1^{(2)} &= f(W_{11}^{(1)}x_1 + W_{12}^{(1)} x_2 + W_{13}^{(1)} x_3 + b_1^{(1)})  \\a_2^{(2)} &= f(W_{21}^{(1)}x_1 + W_{22}^{(1)} x_2 + W_{23}^{(1)} x_3 + b_2^{(1)})  \\a_3^{(2)} &= f(W_{31}^{(1)}x_1 + W_{32}^{(1)} x_2 + W_{33}^{(1)} x_3 + b_3^{(1)})  \\h_{W,b}(x) &= a_1^{(3)} =  f(W_{11}^{(2)}a_1^{(2)} + W_{12}^{(2)} a_2^{(2)} + W_{13}^{(2)} a_3^{(2)} + b_1^{(2)}) \end{align}

上述过程的向量化表示,这里的f和h函数就都变成了向量函数,如 f([z1,z2,z3])
= [
f(z1),f(z2),f(z3)]

\begin{align}z^{(2)} &= W^{(1)} x + b^{(1)} \\a^{(2)} &= f(z^{(2)}) \\z^{(3)} &= W^{(2)} a^{(2)} + b^{(2)} \\h_{W,b}(x) &= a^{(3)} = f(z^{(3)})\end{align}

到该部分,你已经基本掌握了一个神经网络的结构,如何执行得到输出,但是还差如何去训练得到我们的参数 (W,b)。上面都是以单隐藏层的神经网络而且输出只有一个神经元,如果你知道了如何去训练这个简易的神经网络,那下面这个看起来更复杂一些的例子你同样知道该如何去训练。

Network3322.png


优化目标函数

这个是在用机器学习方式为问题建模的第二部,确定你的损失函数(Loss Function),也就是你的优化目标。该过程会涉及到一些基本的优化方法,统计学概念以及一些实际的应用经验。当然如果你跟我一样是刚接触机器学习(Machine Learning)不久的话,了解了一些关于梯度优化方法的话,你就能掌控这里的一切啦。

假设我们有m个样本  \{ (x^{(1)}, y^{(1)}), \ldots, (x^{(m)}, y^{(m)}) \} ,这里采用的是二次平方和最小化 (最小二乘)作为损失函数(关于损失函数的类型可以参考《统计学习方法》-
李航)  ,用该公式表示损失函数
\begin{align}J(W,b; x,y) = \frac{1}{2} \left\| h_{W,b}(x) - y \right\|^2.\end{align},在实际优化目标函数需要表示成如下形式,比上面的公式多了一个
"+"好后面的内容,该项也称作 weight decay,该部分是起正则作用,防止过拟合。

\begin{align}J(W,b)&= \left[ \frac{1}{m} \sum_{i=1}^m J(W,b;x^{(i)},y^{(i)}) \right]                       + \frac{\lambda}{2} \sum_{l=1}^{n_l-1} \; \sum_{i=1}^{s_l} \; \sum_{j=1}^{s_{l+1}} \left( W^{(l)}_{ji} \right)^2 \\&= \left[ \frac{1}{m} \sum_{i=1}^m \left( \frac{1}{2} \left\| h_{W,b}(x^{(i)}) - y^{(i)} \right\|^2 \right) \right]                       + \frac{\lambda}{2} \sum_{l=1}^{n_l-1} \; \sum_{i=1}^{s_l} \; \sum_{j=1}^{s_{l+1}} \left( W^{(l)}_{ji} \right)^2\end{align}

之所以采用二次损失函数,我想应该是为了构建一个具有 convex 性质的目标函数,便于使用梯度优化的方法寻找最优值。下图就是在参数(w,b)下的误差曲面(error surface)。


下面公式表示了权重系数更新的方式,也就是为了找到一个使得目标函数最小值的系数 (w,b) 。在整个优化的过程中,最重要的就是如何求解不同W^{(l)}_{ij}的梯度信息,为了求解这个东西,又要来一个新的概念了,逆误差传播(error
backpropagation)学习算法。机器学习的问题总是会这样,找到优化目标以后,就需要相应的学习算法寻找最优值,此时的系数就是我们所要选择的模型的参数了。

\begin{align}W_{ij}^{(l)} &= W_{ij}^{(l)} - \alpha \frac{\partial}{\partial W_{ij}^{(l)}} J(W,b) \\b_{i}^{(l)} &= b_{i}^{(l)} - \alpha \frac{\partial}{\partial b_{i}^{(l)}} J(W,b)\end{align}

\begin{align}\frac{\partial}{\partial W_{ij}^{(l)}} J(W,b) &=\left[ \frac{1}{m} \sum_{i=1}^m \frac{\partial}{\partial W_{ij}^{(l)}} J(W,b; x^{(i)}, y^{(i)}) \right] + \lambda W_{ij}^{(l)} \\\frac{\partial}{\partial b_{i}^{(l)}} J(W,b) &=\frac{1}{m}\sum_{i=1}^m \frac{\partial}{\partial b_{i}^{(l)}} J(W,b; x^{(i)}, y^{(i)})\end{align}

逆向误差传播算法 (error backpropagation)

如其名,该方法就是让输出层的预测值与 目标值 的误差往回传播。因为我们在求每个参数的梯度的时候是通过对真值与预测值之间的误差项求导得到的,对于输出神经元还可以做到,但是我们无法获取隐藏层的真值,这就造成了隐藏层的神经元梯度不可求的尴尬局面。还好领域大牛们想到了这种方式,让输出层的误差往回传播,计算出底层神经元的激活状态要为该误差付出多大的责任,也可以理解成该神经元的误差值,用\delta^{(l)}_i表示,\delta^{(n_l)}_i表示输出层神经元的误差。


逆误差传播算法执行过程:

1,先执行一次前向传播,计算出每一层的神经元的激活值a^{(l)}_i = f(z^{(l)}_i),直到输出层为止

2,对于每一个输出层神经元,采用如下方式计算误差(实际上在Andrew的资料中省略了很多推到部分,该部分我后面会放上,你们先理解个大概过程)

                     \begin{align}\delta^{(n_l)}_i= \frac{\partial}{\partial z^{(n_l)}_i} \;\;        \frac{1}{2} \left\|y - h_{W,b}(x)\right\|^2 = - (y_i - a^{(n_l)}_i) \cdot f'(z^{(n_l)}_i)\end{align}

3,对于较低层的神经元的误差用如下公式进行表示,l = n_l-1, n_l-2, n_l-3, \ldots, 2

                                      \delta^{(l)}_i = \left( \sum_{j=1}^{s_{l+1}} W^{(l)}_{ji} \delta^{(l+1)}_j \right) f'(z^{(l)}_i)

4,关于不同参数的梯度

                    \begin{align}\frac{\partial}{\partial W_{ij}^{(l)}} J(W,b; x, y) &= a^{(l)}_j \delta_i^{(l+1)} \\\frac{\partial}{\partial b_{i}^{(l)}} J(W,b; x, y) &= \delta_i^{(l+1)}.\end{align}

下面来看下\delta^{(l)}_i项的具体推导过程。

PS:其实要想更好的理解该推导过程可以参考《Pattern Recognition and Machine Learning》中5.3节部分关于估计误差函数梯度的内容,由于里面采用的符号系统跟Andrew的是相反的,我就没有放上来,借用了一个简易的推导过程。



摘自《Deep Learning 教程中文版》--邓侃老师主导,各路英雄好汉共同翻译

下面来看一个利用神经网络拟合不同函数(Linear Regression)的例子,你可以在《Pattern Recognition and Machine Learning》的5.1节中找到。4副图分别对应四个不同的函数,红色的实线表示利用神经网络拟合的函数,圆点表示原函数生成的样本点,虚线表示不同的神经元在对应于不同 x 取值的输出值,几条虚线经过线性添加后得到的就是拟合后的曲线。




总结:

1,简易的神经网络结构并不复杂,但在实际训练一个神经网络的时候是会遇见很多问题的,比如 选择线上梯度下降还是Batch梯度下降 ,隐藏层神经元个数的选择, 是选择多层神经网络还是单层。这些都需要多多实践才行。

2,从理论上来讲,神经网络是可以拟合任何函数,但实际上并非如此。就我个人的实际经验来看,对于某些数据神经网络是失败的。

3,模型不是万能,还需要做很多功课。


#梯度信息在训练 NN 中的使用

#Batch 梯度上升和线上梯度上升的比较


理解了该部分的神经网络知识对后面理解深度神经网络会很大帮助,包括其中的优化方法,能量模型(Energy-based Model),以及RBM(EBM的一个特例)

参考文献:

《Pattern Recognition and Machine Learning》

Andrew Ng's Wiki Page http://deeplearning.stanford.edu/wiki/index.php/Neural_Networks

http://www.cppblog.com/billhsu/archive/2008/08/30/60455.html

Geoff Hinton's Coursera Lectures  https://d396qusza40orc.cloudfront.net/neuralnets/lecture_slides%2Flec1.pdf

【上篇】
【下篇】

抱歉!评论已关闭.