#创作挑战赛#

先来认识下真正的神经元。

神经网络的强大之处(神秘又有趣的神经网络)(1)

图1:典型神经元的结构(来自维基百科“树突”词条)

神经元大致可以分为树突、突触、细胞体和轴突。树突为神经元的输入通道,其功能是将其他神经元的动作电位传递至细胞体。其他神经元的动作电位借由位于树突分支上的多个突触传递至树突上。神经细胞可以视为有两种状态的机器,激活时为“是”,不激活时为“否”。神经细胞的状态取决于从其他神经细胞接收到的信号量,以及突触的性质(抑制或加强)。当信号量超过某个阈值时,细胞体就会被激活,产生电脉冲。电脉冲沿着轴突并通过突触传递到其它神经元。(内容来自维基百科“感知机”词条,稍作整理)

我们的视觉系统非常复杂。大致来讲,当光线投射到视网膜后,视觉膜上的光感受细胞的突触直接与双极细胞相连,双极细胞突触则与最外层的节细胞相连,节细胞将动作电位传递到大脑。我们的视网膜有大约1亿3千万个光感受细胞接收光信号,然后通过大约120万个节细胞轴突将信息从视网膜传递到大脑。(内容来自维基百科“视觉系统”词条)

视觉系统使我们有了视知觉能力,将外部世界的二维投射重构为三维世界。

人类的视觉系统可以毫不费力的识别出下面图片中的数字(当然还有文字)。但如果让计算机来识别,就会明显感觉到视觉识别的困难。

神经网络的强大之处(神秘又有趣的神经网络)(2)

图2:街道地址(来源于维基百科“Handwriting recognition”词条)

我们不能简单地把“数字2像一只水面上的天鹅,数字7像一把锄头”这样的规则教给计算机。因此,我们需要把手写识别的问题表述成计算机可以理解的方式。

神经网络的强大之处(神秘又有趣的神经网络)(3)

图3:水面上的天鹅像极了数字2

假设我们有5x5像素的图片来显示每个数字,例如数字2表示如下:

@@@@@

. . . . @

@@@@@

@. . . .

@@@@@

由于我们的神经网络是以数字组成向量作为输入的,所以我们将每个图片转换成长度为25的向量,其元素的值是1(“这个像素位于该图像中”)或0(“这个像素不在该图像中”)

例如,数字2可以表示为:

two_digit=[1,1,1,1,1

0,0,0,0,1

1,1,1,1,1

1,0,0,0,0

1,1,1,1,1]

我们希望神经网络最终的输出是一个具体的数字,因此我们需要10个不同的输出结果。例如,对于数字2,正确的输出结果将是:

[0,0,1,0,0,0,0,0,0,0]

神经网络的强大之处(神秘又有趣的神经网络)(4)

图4:使用python列表解析式建立一个代表0-9不同数字的列表

其中targets[2]就是输出结果数字2。

那么,神经网络是如何把信息的输入转换成我们想要的输出的呢?

感知器(Perceptron)

感知器是一种二元分类器,它是神经网络的基石。感知器是对神经细胞的模拟,如权量(突触)、偏置(阈值)及激活函数(细胞体)。

神经网络的强大之处(神秘又有趣的神经网络)(5)

输入以向量的形式表示x=(x_0, x_1, x_2),你可以把它们理解为不同的特征维度,其中的x_0是偏置单元(bias unit),相当于线性回归中的常数项。在经过“神经元”(激活函数)的计算后,感知器会输出一个大于0或小于0的数。箭头上的数字代表每个特征的权量(weights),相当于线性回归模型的参数,是收集信息的神经突触。

例如,上图列出了每个特征的权量,于是我们有这样的模型:

hθ(x)=-3 2*x_1 2*x_2

当x_1和x_2同时为1时,输出为1,而不同时都将得到负数。这实际上就是逻辑与或称为与门。

我们的感知器将根据输出大于或小于0来对输入进行分类:

神经网络的强大之处(神秘又有趣的神经网络)(6)

这是一个单层的感知器。通过修改权量,我们也可以建立或门(weights=[2,2], bias=-1)、非门(weights=[-2],bias=1,只有一个输入端)。但是,无论如何,你都无法通过一个单层的感知器来建立“异或门”(XOR),即两个输入相同时输出1,否则输出0。这种情况下,我们就需要更复杂的神经网络了,即多层神经网络,也被称为前馈神经网络(feedforward neural network)。

前馈神经网络

前馈神经网络是多个感知器的组合,这些感知器以不同的方式产生连接,并由不同的激活函数控制激活。

神经网络的强大之处(神秘又有趣的神经网络)(7)

图6:前馈神经网络示意图 我们来认识下前馈神经网络:

超越线性

在“感知器”中我们谈到,单层感知器虽然可以建立与门、或门、非门等,但无法建立更为复杂的异或门(XOR),即两个输入相同时输出1,否则输出0。

为了更为直观地理解这个问题,我们可以看下图:

神经网络的强大之处(神秘又有趣的神经网络)(8)

图7:双输入感知器的决策空间

模型有两个输入(input1和input2),我们可以线性地区分或门的两类情况:即同时为0时在左下角,其它情况在右上角;与门的情况也可以线性地区分,即输出同时为1时在右上角,其它情况在左下角。但异或门呢?这种情况是无法作出线性区分的,也就是说,单层感知器无法实现异或门。

多层感知器吗?

先来分析输入和输出的情况。最左边两列列出了输入的4种情况。异或门的输出是最右边一列的情况,即两个输入相同时输出1,否则为0。我们在输入层和输出层之间加入两个单元的隐藏层,那么,它给输出层的输入应该是什么呢?答案如下图。你可以发现,对于隐藏层的a_1单元(上标2代表这是第2层)来说,它实际上是且门(都为1时才输出1);对a_2单元来说,它的逻辑是(not x_1) and (not x_2),即同时为0时才输出1。而从隐藏层到输出层,是逻辑或。前馈神经网络可以实现异或门!

神经网络的强大之处(神秘又有趣的神经网络)(9)

图8:异或门输入输出下推导隐藏层

于是我们建立如下的神经网络,但是其输出并非我们想要。为什么?

神经网络的强大之处(神秘又有趣的神经网络)(10)

图9:线性激活函数下的前馈神经网络

这是因为上面感知器的激活函数是线性函数。这种情况下,神经网络的输出也只是输入的某种线性函数,只不过是通过网络的形式来进行加权。线性函数的线性组合仍然是线性函数。也就是说,即便是多层的感知器,激活函数为线性时也无法实现输入00和输入11时的输出比输入01和10时大,即非线性。

如果激活函数是线性函数,前馈神经网络将不会比单层感知器强大多少,不管它有多少层。

我们需要logistic函数的帮助。大部分神经网络会使用非线性激活函数,比如logistic函数(也被称为Sigmoid函数,这是就其形状而言的)。此外,由于训练神经网络要使用微积分,而要使用微积分,就得使用光滑函数(在反向传播时我们会详细讲解)。logistic函数也满足这一要求。

在logistic函数的作用下,线性函数的输出值将被转化到0到1之间。从下图右上角的logistc曲线可以看到,输入值越大,输出越接近1,输入为4时输出为0.99;输入值越小,输出越接近0,输入值为-4时,输出为0.01。

下图是单层感知器的激活函数为logitic函数时与门的示例。

神经网络的强大之处(神秘又有趣的神经网络)(11)

图10:激活函数为logitic函数时的与门单层感知器

综上,我们可以通过前馈神经网络和logistic函数解决异或门的问题:

神经网络的强大之处(神秘又有趣的神经网络)(12)

图11:非线性神经网络实现异或门

反向传播(backpropagation):训练神经网络

反向传播是使用数据来训练神经网络的算法,它是神经网络的梯度下降算法。

假设我们有一个训练集,其中含有输入向量和相应的目标输出向量。同时,假定我们的网络已经拥有一组权量(相当于我们知道每个神经元的激活函数),那么接下来,我们就需要使用以下算法来调整这些权量。

1、利用初始权量,在输入向量上运行前向传播,从而得到所有网络所有神经元的输出。

2、这样,每个输出层神经元都会得到一个误差,即输出值与实际值之差。

3、计算作为神经元权量的函数的误差的梯度,然后根据误差降低最快的方向调整权量。

4、将这些输出误差反向传播给隐藏层以便计算相应误差。

5、计算这些误差的梯度,并利用同样的方式调整隐藏层的权量。

不断迭代,直到网络收敛。

要理解上述过程,梯度下降算法是关键。

神经网络的强大之处(神秘又有趣的神经网络)(13)

图12:单个参数的损失函数示例

在梯度下降算法中,我们需要损失函数(即上面提到的作为神经元权量的函数的误差)。损失函数衡量了模型的误差,即神经网络的输出值与实际值之间的差异,它的参数是模型的参数,即连接的权量。当损失函数达到全局最低时,得到最优的权权量。在训练阶段,权量不断被更新,慢慢接近全局最低值。例如,权量是0.6时,它就需要向0.4变化,这样才能接近全局最低值。

上图描述的是只有一个参数的情况,即模型的误差取决于一个参数。然而,神经网络的误差取决于每一个权量,它的损失函数也会复杂得多。 J(θ)=−1m[∑i=1m∑k=1Kyk(i)log⁡hθ(x(i))k (1−yk(i))log⁡(1−hθ(x(i))k)] λ2m∑l=1L−1∑i=1sl∑j=1sl 1(θj(l))2J\left( \theta \right)=-\frac{1}{m}\left[ \sum_{i=1}^{m}{\sum_{k=1}^{K}{y_{k}^{\left( i \right)}\log h_{\theta }\left( x^{\left( i \right)} \right)_{k} \left( 1-y_{k}^{\left( i \right)} \right)\log \left( 1-h_{\theta }\left( x^{\left( i \right)} \right)_{k} \right)}} \right] \frac{\lambda }{2m}\sum_{l=1}^{L-1}{\sum_{i=1}^{s_{l}}{\sum_{j=1}^{s_{l 1}}{\left( \theta _{j}^{\left( l \right)} \right)^{2}}}}

其中,i代表第几层,k代表第i层的第几个单元。可见,损失函数把整个神经网络的误差都加和了。后面的第二部分是正则化项,暂时不用理睬,不影响后面的理解。

有人可能会问,为什么神经网络的损失函数是上面的形式?这个问题等价于为什么logistic函数采用上面的形式?

在回归模型中,损失函数是平方误差函数(最小二乘法):

J(θ)=1m∑i=1m12(hθ(x(i))−y(i))2J\left( \theta \right)=\frac{1}{m}\sum_{i=1}^{m}{\frac{1}{2}\left( h_{\theta }\left( x^{\left( i \right)} \right)-y^{\left( i \right)} \right)^{2}}

损失函数衡量了模型的输出与实际值之间的误差:

Cost(hθ(x),y)=12(hθ(x)−y)2\mbox{C}ost\left( h_{\theta }\left( x \right),\; y \right)=\frac{1}{2}\left( h_{\theta }\left( x \right)-y \right)^{2}

但对logistic函数而言,平方误差函数是一个非凸函数,利用梯度下降算法,它将无法保证找到损失函数的全局最优解。

神经网络的强大之处(神秘又有趣的神经网络)(14)

图13:非凸函数

对logistic函数,我们需要其他的损失函数:

神经网络的强大之处(神秘又有趣的神经网络)(15)

图14:

神经网络的强大之处(神秘又有趣的神经网络)(16)

图15:

神经网络的强大之处(神秘又有趣的神经网络)(17)

如果y=1,而h(x)=1的话,则cost=0,即图14曲线上(1,0)的位置;如果h(x)=0,则cost函数输出值趋向于无穷大,这意味着当我们认为某种情况不会发生,例如用户不会成为付费用户,而事实上是可能的时,这种损失是不可估量的。同理,如果y=0,而h(x)=0的话,则cost=0,即图15曲线上(0,0)的位置;如果h(x)=1,则cost趋向于无穷大。

可以把两种情况写在一个表达式中:

Cost(hθ(x),y)=−ylog⁡(hθ(x))−(1−y)log⁡(1−hθ(x))\mbox{C}ost\left( h_{\theta }\left( x \right),\; y \right)=-y\log \left( h_{\theta }\left( x \right) \right)-\left( 1-y \right)\log \left( 1-h_{\theta }\left( x \right) \right)

也即:

J(θ)=−1m[∑i=1my(i)log⁡hθ(x(i)) (1−y(i))log⁡(1−hθ(x(i)))]J\left( \theta \right)=-\frac{1}{m}\left[ \sum_{i=1}^{m}{y^{\left( i \right)}\log h_{\theta }\left( x^{\left( i \right)} \right) \left( 1-y^{\left( i \right)} \right)\log \left( 1-h_{\theta }\left( x^{\left( i \right)} \right) \right)} \right]

神经网络衡量整个网络的误差,所以在形式上看起来会复杂些,但实质是一样的。

那么,接下来我们要如何更新权量才能使得损失函数接近全局最低值呢?

在神经网络中,我们使用反向传播算法来更新神经元之间连接的权量。反向传播的意思是指,我们从输出层开始计算,计算输出层与实际值的误差,然后返回到前面的隐藏层计算其误差,以此类推,不断迭代,直到网络收敛。

在完成第一步的前向传播后,我们会得到神经网络的输出值,利用损失函数可以计算出输出值与实际值之间的误差。损失函数的偏导数可以告诉我们参数往哪个方向更新可以得到更小的损失函数值。导数的几何意义为曲线的斜率,例如,对于图12简单的损失函数而言,参数在0.5时斜率为正,参数值需要减少才能得到更小的损失函数值;而如果参数值为0.1,斜率为负,参数值需要增加才能得到更小的损失函数值。导数可以告诉我们全局最低的方向!

为了得到最小的J(θ),我们需要不断更新参数θ,即神经网络连接的权量。每次更新的变化值由下面的公式决定:

Δθ=−α∂∂θijlJ(θ)\Delta \theta =-\alpha \frac{\partial }{\partial \theta _{ij}^{l}}J\left( \theta \right)

其中, ∂∂θijlJ(θ)\frac{\partial }{\partial \theta _{ij}^{l}}J\left( \theta \right)为损失函数的偏导数,前面为负是因为斜率为正时,我们需要减少参数的值才能“下山”,而斜率为负时,我们需要增加参数的值才能“下山”, 代表学习速率,代表下山的步子有多大,如果步子太小,要走很远才能走到山底,如果步子太大,容易越过谷底,导致无法收敛;J(θ)为神经元输出的误差。

从隐藏层到输出层的两个神经元之间的权量一旦更新,就可以更新隐藏层神经元的输出,从而得到隐藏层神经元新的误差值(更新后的输出值和之前前向传播时得到的输出值),进而根据上述公式更新隐藏层和上一层两个神经元之间的权量。依此类推,直到更新完整个神经网络的权量。

利用损失函数继续更新整个网络的权量,直到神经网络输出值的误差达到最小。

所有神经元之间的权量确定后,神经网络就完成训练了。

综上,让机器人看到2绝非易事。

#今日头条小助手##神经网络#

,