本文在介绍神经网络算法模型基础知识的同时,详细阐述了正向传播神经网络的计算过程。
斯坦福大学教授Andrew Ng(吴恩达)在Coursera网课平台上开设的Machine Learning课程,非常适合机器学习新手入门,看过之后有种豁然开朗的感觉。但这门课程是英文讲解的,况且对于快速理解神经网络算法来讲,观看视频课程全面学习Machine Learning的知识体系,效率自然不如阅读专题文章。这是我花费精力写这篇文章的主要原因。本文结构与算法描述方式也主要借鉴于Andrew Ng的课程。只是在细节的地方做了些调整和补充。在这里提前做出说明,避免误被控诉为抄袭。
写本文之前,我查阅了大量网络上相关的文章。发现这些文章大多存在两个极端:一部分太注重于解释神经网络的感性理解,忽略了数学基础,太过简单;另一部分则又过于学术化,大量的复杂公式推导,让很多感兴趣的读者望而却步。我以为,尽管神经网络听上去很深奥,但其实要理解并掌握它的算法原理,并非那么困难。因此,本文想要从感性理解和理性认知两者中间找到合适的平衡,暂且跳过复杂的参数求解过程,从简单的理论出发,一步步阐述神经网络的基本计算方式,让读者可以快速对神经网络算法有个比较直观的认识。
建议英文基础较好,并且有精力的读者学习Andrew的这门课程,我将链接附在这里:https://www.coursera.org/learn/machine-learning
1.神经网络算法的创造缘由
在基础机器学习中,Linear Regression和Logistic Regression都能够拟合输入和输出之间的定量关系,并根据新的输入预测输出值或者进行分类。那为什么还需要神经网络这样的复杂算法呢?主要有两方面的原因:一是现实生活中的很多问题并非线性的。二是在Linear Regression和Logistic Regression模型中,当输入特征的数量比较大时,模型参数的解算效率会非常低。并且随着输入特征数量的增长,参数解算效率以指数形式降低,非常不利于模型学习和应用。
1.1 非线性问题
非线性问题比线性问题要复杂的多,但却是现实世界中的最常见的问题形式。对于非线性问题,Linear Regression和Logistic Regression不能达到很好的效果。简单举个例子。假设有两个输入要素,分别是 x 1 , x 2 ∈ R x_1, x_2 ∈ R x1,x2∈R,下图表示了 x 1 x_1 x1和 x 2 x_2 x2构成的两个不同类别的点分布情况。可以看到,这两个类别是没有办法用一条直线进行分割的。现为了区分开这两个类别,在Logistic Regression模型中,就需要引入高阶变量,例如 x 1 x 2 , x 1 2 x 2 , x 1 x 2 2 x_1x_2, x_1^2x_2, x_1x_2^2 x1x2,x12x2,x1x22等等作为新的输入要素加入模型,这首先会带来输入要素的数量增加,且高阶变量自然会让模型变得更加复杂,同时容易引起Overfitting的问题。
1.2 大量特征带来的问题
除了上面讲到的非线性问题导致的特征数量增多的情况,现实生活中的很多问题,其特征本来就是非常多的。计算机视觉问题就是典型的例子。图像通过像素矩阵来表示现实世界的物体,像素矩阵中的点往往非常多,将这些像素点的值作为特征输入模型,庞大的特征数量是显而易见的。而当特征数量上升时,线性回归和逻辑回归模型会让求解变得非常慢。事实上,这个关系根据使用的输入特征阶数的不同,线性回归和逻辑回归模型的参数求解会有 O ( n 2 ) 、 O ( n 3 ) O(n^2)、O(n^3) O(n2)、O(n3)等时间复杂度。传统的输入特征为1~1000时尚可接受,而一个普通 50 ∗ 50 50*50 50∗50的灰度图像像素矩阵,输入特征都是2500个,更别说更大、更复杂的图像了,
2.神经网络模型表示
2.1 神经网络的结构和数学定义
(1)模型结构
神经网络模型包含三个部分:input layer(输入层)、hidden layer(中间层或隐藏层)、output layer(输出层)。其中,hidden layer的层数不固定,在某些简单问题中,hidden layer的层数可能为0,仅有input layer和output layer;在复杂问题中,hidden layer的层数也可能成百上千。
模型中每一层的节点称为“神经元”。位于input layer的神经元对应着训练数据的特征。hidden layer和output layer中的神经元由activation function(激活函数)表达,我们用字母 g g g表示。Activation function有很多种类型,最常用是sigmoid函数,它的表达式如下:
s i g m o i d ( x ) = 1 1 + e − x sigmoid(x)=\frac{1}{1+e^{-x}} sigmoid(x)=1+e−x1
sigmoid函数图像如下图所示。当 x > > 0 x>>0 x>>0时, f ( x ) f(x) f(x)无限逼近于1;当 x < < 0 x<<0 x<<0时, f ( x ) f(x) f(x)无限逼近于0;当 x = 0 x=0 x=0时, f ( x ) = 0.5 f(x)=0.5 f(x)=0.5。
(2)训练样本数据
为了深入阐述神经网络模型算法过程,我们来定义一些需要用到的数学变量和符号。
我们用 x x x表示输入的特征向量, x i x_i xi表示单独的特征变量。 y y y表示真实类别标签向量, y i y_i yi对应单独的真实类别,为了简单起见,我们先从二元分类讲起,也就是说 y ∈ { 0 , 1 } y∈\{0,1\} y∈{
0,1}。假如,我们想训练一个神经网络模型,根据房子的某些特征自动判断该房子是否为别墅,那么特征向量 x x x就可以表示为:
x = [ x 1 = 卧 室 数 目 x 2 = 客 厅 面 积 x 3 = 总 体 面 积 . . . ] x=\begin{bmatrix}x_1=卧室数目\\x_2=客厅面积\\x_3=总体面积\\...\end{bmatrix} x=⎣⎢⎢⎡x1=卧室数目x2=客厅面积x3=总体面积...⎦⎥⎥⎤
其中,卧室数目、客厅面积、总体面积等等数据都是特征变量,它们共同衡量了房子的属性。并且,我们定义当 y = 1 y=1 y=1时,表示该房子为别墅;当 y = 0 y=0 y=0时,表示房子为其他类型。这样,我们就可以收集整理一些如下表所示的训练样本数据:
卧室数目( x 1 x_1 x1) | 客厅面积( x 2 x_2 x2 ) | 总体面积( x 3 x_3 x3) | … | 别墅? |
---|---|---|---|---|
8 | 60 | 300 | … | 1 |
2 | 20 | 90 | … | 0 |
… | … | … | … | … |
10 | 80 | 400 | … | 1 |
(3)模型数学表示
为了方便使用数学表示,我们不单独为input layer、hidden layer和output layer定义数学表示,而是使用 a = { a ( 1 ) , a ( 2 ) , a ( 3 ) , . . . , a ( n ) } a=\{a^{(1)}, a^{(2)}, a^{(3)},...,a^{(n)}\} a={
a(1),a(2),a(3),...,a(n)}来表示从左到右的各个层。例如在简单的三层神经网络模型中, a ( 1 ) a^{(1)} a(1)表示输入层, a ( 2 ) a^{(2)} a(2)表示中间层, a ( 3 ) a^{(3)} a(3)表示输出层。用 θ j ( i ) \theta_j^{(i)} θj(i)来表示各层对应的权重参数, i i i表示层号, j j j表示该层中的神经元。由此,一个简单的三层神经网络模型中,各个结构的数学可以表示如下图:
2.2 Forward Propagation
我们以Forward Propagation(正向传递)计算过程为例,详细介绍神经网络模型当中的数学计算。为了简单起见,我们以下图中展示的神经网络模型为例。这里我们先暂时不介绍模型参数求解相关方法,而是假设已经计算得到了所有的模型参数值。
在这个模型中,第一层有2个神经元,分别用 x 1 , x 2 x_1, x_2 x1,x