神经网络简介

BP神经网络结构

我们知道单层感知机(perceptron)的局限性:它无法解决异或(XOR)问题,或者其它线性不可分问题。
考虑下图的数据集的分类问题。这是一个线性不可分的问题,显然单个单层感知机无法将其正确分类。


异或门

异或问题的例子

但是我们可以通过组合三个单层感知机,来解决这个问题:


堆叠多个单层感知器解决异或问题

其中三个单层感知机可分别为:
\begin{align} f_{11}(x,y)&= \begin{cases} 0 &, y\geq x + \frac{3}{2}\\ 1 & ,y< x + \frac{3}{2} \end{cases}\\ f_{12}(x,y)&= \begin{cases} 0 &, y< x + \frac{1}{2}\\ 1 & , y\geq x + \frac{1}{2} \end{cases}\\ f_{21}(x,y)&= \begin{cases} 0 &, x=0\text{ or }y=0 \\ 1 &, x=y=1 \end{cases} \end{align}
需要注意的是,可以正确分类的感知机组合的选择不唯一。

从上述例子,我们可以看到:通过堆叠多个单层感知机,可以解决该线性不可分问题。这启发我们用一种新的更复杂的框架——神经网络(neural network)——来建模。它包括输入层隐含层输出层三部分。在一个神经网络中,输入层和输出层的层数仅为1,但维度可以为任意维,即输入x、输出y分别既可以为标量(scaler)、又可以为向量(vector),甚至是二维矩阵(matrix)或高维数组(array)。在本章,我们仅考虑神经网络的输入、输出为向量,神经元结点的输入、输出为标量的情形。神经网络的隐含层却可以有多层(假设层数至少为1)。在每一个隐含层或输出层,输入该层的元素x首先进行仿射变换\mathbf{w}^{\top}\mathbf{x}+b,再通过激活函数映射后输出f(\mathbf{w}^{\top}\mathbf{x}+b)。这个过程与人的神经细胞在传递神经信号的过程极为相似,故也常将每一层的每个仿射变换、激活函数的组合称为一个神经元。

仿射变换和激活函数映射在图中分别用符号\Sigmaf表示。如果仅从数学函数的角度看待神经网络,则可将其看做一个计算图,不同的变量结点(variable node)通过计算结点(operator node)发生相互作用,这也是Tensorflow的基本框架。

以下我们通过前文的例子来理解上述定义。

解决异或问题的多个单层感知机模型可以看做是一个具有一个隐含层的神经网络,其中激活函数f为阶跃函数,即f(x)= \begin{cases} 1&, x\geq 0\\ 0&, x<0 \end{cases}

利用神经网络的计算图框架解释模型
利用神经网络的神经元框架解释模型

显然单层感知机无法对回归问题建模,因为它的输出只能为0或1。为了改进这个缺陷,我们可以将激活函数替换为其他线性或非线性函数。常用的激活函数有:

激活函数 表达式 图像
sigmoid函数 S(x)={\frac {1}{1+e^{-x}}}={\frac {e^{x}}{e^{x}+1}}
sigmoid.png
tanh函数 tanh(x)={\frac {sinh(x)}{cosh(x)}}={\frac {e^{x}-e^{-x}}{e^{x}+e^{-x}}}
tanh.png
ReLU函数(Rectified Linear Unit) ReLU(x)= \max\{x,0\}
relu.png

因此,现在我们就有了一般的神经网络结构——层级结构——每一层由多个结点组成,相邻层的结点相互全连接。输入层结点可视为将输入的标量通过恒等函数变换输出,隐含层和输出层则将输入的标量做仿射变换、激活函数变换后输出。

神经网络的神经元基本框架

通过这样的神经元结构,我们能较好地理解神经网络模型,但在后续的网络权值更新过程中,计算图框架会更加适用。

损失函数和代价函数

同样的网络结构,搭配不同的仿射变换或激活函数,都能得到不同的模型。因此,我们自然会问:如何评价一个神经网络模型的效果呢?

首先,对一个给定的输入向量\mathbf{x}和真实的输出向量\mathbf{y},我们定义模型的损失函数(loss function)来衡量模型对\mathbf{x}的预测值\hat{\mathbf{y}}=f(\mathbf{x})\mathbf{y}的差异,这里我们假设神经网络模型的映射为f。常用的损失函数如下:

损失函数 表达式 应用场景
平方损失(square loss)函数 L(\hat{\mathbf{y}},\mathbf{y})=(\hat{\mathbf{y}}-\mathbf{y})^{\top}(\hat{\mathbf{y}}-\mathbf{y}) ,\qquad\hat{\mathbf{y}},\mathbf{y}\in \mathbb{R}^n 线性回归模型
合页损失(hinge loss)函数 L(\hat{\mathbf{y}},\mathbf{y})=\max\{0,1-\hat{\mathbf{y}}\mathbf{y}\},\qquad \mathbf{y}\in\{-1,1\},\hat{\mathbf{y}}\in \mathbb{R} 支持向量机模型(SVM)
0-1损失(0-1 loss)函数 L(\hat{\mathbf{y}},\mathbf{y})=\mathds{1}_{\{\hat{\mathbf{y}}\neq\mathbf{y}\}},\qquad \hat{\mathbf{y}},\mathbf{y}\in \mathbb{R} 用于理论分析及准确度的定义
交叉熵损失(cross entropy loss)函数 L(\hat{\mathbf{y}},\mathbf{y})= - \sum\limits_{c\in C} \mathbf{y}_c\log \hat{\mathbf{y}}_c,\qquad\sum\limits_{c\in C}\mathbf{y}_c=\sum\limits_{c\in C}\hat{\mathbf{y}}_c=1, \qquad\mathbf{y}_c\in\{0,1\},\hat{\mathbf{y}}_c\in[0,1] 二分类或多分类问题
指数损失(exponential loss)函数 L(\hat{\mathbf{y}},\mathbf{y})= e^{-\hat{\mathbf{y}}\mathbf{y}},\qquad \mathbf{y}\in\{-1,1\},\hat{\mathbf{y}}\in \mathbb{R} Adaboost模型

其次,对于一个模型,我们更关心的是其在某个数据集上的表现而不仅局限于某个样本,因此,我们也定义了代价函数(cost function),来衡量模型在某个分布上的表现:Cost(\mathscr{X},\mathscr{Y} )= \mathbb{E}_{(\mathscr{X},\mathscr{Y} )}[L(f(\mathbf{x}),\mathbf{y})]
其中\mathbb{E}_{(\mathscr{X},\mathscr{Y} )}是在数据集(\mathscr{X},\mathscr{Y} )的真实分布上求期望。在实际应用中,由于我们可能并不知道数据的真实分布,故常用数据集中每个样本点在特定损失函数下的损失平均值作为代价函数,例如均方误差(mean squared error),此时有
Cost(\mathscr{X},\mathscr{Y} )= \sum\limits_{(\mathbf{x}, \mathbf{y})\in (\mathscr{X},\mathscr{Y} )}L(f(\mathbf{x}),\mathbf{y})

对于神经网络这样的参数模型,通常我们不仅考虑代价函数在数据集上的值,同时也考虑模型参数的复杂程度。因此我们希望模型优化的目标函数(objective function)定义为:
Obj(\mathscr{X},\mathscr{Y})= Cost(\mathscr{X},\mathscr{Y} ) + R(f)
其中R(f)是正则项(regularization),它有助于防止过拟合。目标函数就是我们在实际求解神经网络参数用的准则,好的参数可以在训练集、测试集上都有较低的目标函数值。

需要注意的是,代价函数和目标函数在某些语境下并不区分,此时代价函数本身便包含正则项。

反向传播算法

在前面的章节,我们已经有了神经网络的结构与模型的评价标准,接下来,我们要考虑的是:给定数据集和神经网络结构,我们应该怎样让网络从数据中学习、更新参数?

在数值计算中,我们常用梯度下降法来求取一个函数的局部极小值,在神经网络中,我们可以将其推广,利用链式法则将误差从后往前传播,并利用梯度下降法更新相邻两层间的权重,最小化误差。


正向传播

每一个神经元的结构

误差反向传播

在图中,我们用x_{ij}表示神经网络中第i层第j个神经元的输入值(其中第0层表示输入层),同时也是第i+1层,用W_{jk}^{i+1}表示第i层第j个神经元对第i+1层第k个神经元贡献的权重,用b_{i+1}表示第i层与与第i+1层仿射变换的偏移量,用z_{i+1,k}表示第i+1层第k个神经元的输出值,n_i为第i层神经元的个数。我们也可以用向量和矩阵的形式将每个神经元结点表示为:
\begin{align} \mathbf{z}_{i+1}&= \mathbf{W}_{i+1}\mathbf{x}_i + \mathbf{b}_{i+1} \\ \mathbf{x}_{i+1} &= f(\mathbf{z}_{i+1} ) \end{align}
其中
\begin{align} \mathbf{x}_i = \begin{pmatrix} x_{i1}\cr \vdots \cr x_{in_i} \end{pmatrix} \qquad \mathbf{W}_{i+1}= \begin{pmatrix} W_{11}^{i+1}& \cdots & W_{1n_i}^{i+1} \cr \vdots & \ddots & \vdots \cr W_{n_{i+1}1}^{i+1}& \cdots & W_{n_{i+1}n_i}^{i+1} \cr \end{pmatrix} \qquad \mathbf{b}_i = \begin{pmatrix} b_{i1}\cr \vdots \cr b_{in_i} \end{pmatrix} \qquad \mathbf{z}_i = \begin{pmatrix} z_{i1}\cr \vdots \cr z_{in_i} \end{pmatrix} \end{align}
f(\mathbf{z}_{i+1})是分别作用在向量\mathbf{z}_{i+1}的每一个分量上(element-wise)。

以上图中的三层网络为例,这个网络的输出层只有一个神经元,假设我们已经计算出该结点仿射变换输出的误差\delta_{21},其下标表示第2层第1个神经元。读者也可以选择每个结点输出值的误差进行反向传播更新参数,但是选择仿射变换后的误差更加方便理解与计算,因此我们按照该约定进行反向传播算法的介绍。

  1. 更新隐含层与输出层之间的参数。

注意到误差与损失函数L的关系:
\begin{align} {\boldsymbol\delta}_2 &= \delta_{21} \\ &= \dfrac{\partial L}{\partial \mathbf{z}_2}\\ &=\dfrac{\partial L}{\partial \mathbf{x}_2}\odot \dfrac{\partial f(\mathbf{z}_2)}{\partial \mathbf{z}_2}\\ &=\dfrac{\partial L( \mathbf{x}_{2}, y)}{\partial \mathbf{x}_2} \odot f'(\mathbf{z}_2) \end{align}
其中\odot表示逐元素相乘(element-wise multiplication / Hadamard product)。我们希望更新参数\mathbf{W}_2b_2,首先根据链式法则有
\begin{align} \dfrac{\partial L}{\partial W^{2}_{1j}}&= \dfrac{\partial L}{ \partial z_{21}}\cdot \dfrac{ \partial z_{21}}{\partial W_{1j}^2} \end{align}
因此有
\begin{align} \dfrac{\partial L}{\partial \mathbf{W}_2} &= \delta_{21}\cdot\mathbf{x}_1^{\top} \end{align}
类似地,
\begin{align*} \dfrac{\partial L}{\partial b_2}&={\boldsymbol\delta}_2\\ \end{align*}
因此由梯度下降法,我们可以用以下公式更新该神经网络中输出层之前的参数:
\begin{align*} \mathbf{W}_2' & = \mathbf{W}_2 - \eta \cdot \delta_{21} \cdot \mathbf{x}_1^{\top}\\ b_2'&= b_2- \eta \cdot {\boldsymbol\delta}_2\\ \end{align*}
其中\eta\in (0 ,1]为人工设定的学习率,用于调整权重更新的步长。

需要注意的是,在实际数值计算中,需要先求解相应的偏导函数,再将\mathbf{x}_2\mathbf{z}_2对应的具体数值代入得到对应的偏导数值。

  1. 误差反向传播。

我们希望计算出网络隐含层每个结点的误差,同样地根据链式法则计算偏导
\begin{align} {\boldsymbol \delta_1} &= \dfrac{\partial L}{\partial \mathbf{z}_1}\\ &=\dfrac{\partial L}{\partial \mathbf{x}_1}\odot \dfrac{\partial f(\mathbf{z}_1)}{\partial \mathbf{z}_1} \\ &=\left\{ \left[\dfrac{\partial (\mathbf{W}_{2}\mathbf{x}_1 + b_{2} ) }{\partial \mathbf{x}_1}\right]^{\top} \cdot \dfrac{\partial L(\mathbf{x}_2,y)}{\partial \mathbf{z}_2} \right\}\odot \dfrac{\partial f(\mathbf{z}_1)}{\partial \mathbf{z}_1} \\ &=(\mathbf{W}_2^{\top} \cdot \delta_{21} ) \odot f'(\mathbf{z}_1) \end{align}
其中{\boldsymbol \delta_1}= \begin{pmatrix} \delta_{11}\cr\delta_{12} \end{pmatrix}
在上述计算中涉及向量的求导运算,具体的公式可以查阅Matrix Cookbook

  1. 更新输入层与隐含层之间的参数。

有了隐含层的输出误差后,我们可以重复第一步的工作,利用梯度下降法再次更新误差。首先从每一个分量入手,
\begin{align} \dfrac{\partial L}{\partial W^{1}_{ji}}&= \dfrac{\partial L}{ \partial z_{1j}}\cdot \dfrac{ \partial z_{1j}}{\partial W_{ji}^1}\\ &=\delta_{1j}\cdot x_{0i} \end{align}
因此我们有
\begin{align} \dfrac{\partial L}{\partial \mathbf{W}_1} &={\boldsymbol\delta}_1\cdot \mathbf{x}_0^{\top} \end{align}
类似地,
\begin{align} \dfrac{\partial L}{\partial \mathbf{b}_1} &= {\boldsymbol\delta}_1 \end{align}

我们可以用以下公式更新该神经网络中输出层之前的参数:
\begin{align} \mathbf{W}_1' & = \mathbf{W}_1 - \eta \cdot {\boldsymbol\delta}_1\cdot \mathbf{x}_0^{\top}\\ \mathbf{b}_1'&= \mathbf{b}_1- \eta \cdot {\boldsymbol\delta}_1 \end{align}
对于上述例子,至此我们已经完成了对一个训练样本上权重的一次更新。

对于更加一般的情况,假设我们有第i+1层的输出结点误差向量\delta_{i+1}\in \mathbf{R}^{n_{i+1}},我们可以计算相应的梯度
\begin{align} \dfrac{\partial L}{\partial \mathbf{W}_{i+1}} &= {\boldsymbol\delta}_{i+1}\cdot \mathbf{x}_i^{\top}\\ \dfrac{\partial L}{\partial \mathbf{b}_{i+1}} &= {\boldsymbol\delta}_{i+1} \end{align}
其中相邻层误差的关系满足
\begin{align} {\boldsymbol \delta}_{i}&= (\mathbf{W}_{i+1}^{\top}\cdot {\boldsymbol \delta}_{i+1})\odot f'(\mathbf{z}_{i+1}) \end{align}
在实际训练过程中,逐个训练样本更新权重的效率太低,而且不利于算法的收敛,因此在深度学习中常使用批次方法(mini-batch),权重每次更新只考虑某一小批次的训练样本,这时相应的更新方向即为各个样本更新方向的平均。

完整的反向传播算法在以下算法中给出,该算法给出了训练一个多层简单神经网络的一般流程。


反向传播算法
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容