3  第三章

类似LMS这样的算法,对线性系统有很好的效果,包括那段时间发展起来的线性系统理论、控制理论、信号理论等等,这些都对工程领域产生了深远的影响。

但随着数据复杂度的增加,线性模型逐渐暴露出表达能力不足的问题,例如XOR问题:

图 3.1: XOR问题

XOR问题里有四个元素,它们两两相同,相同的元素彼此位于对角线上,那是否存在一条直线能把这两类元素区分出来?

答案是不能,不管怎么画都没有一条直线可以将这两类元素分开。这种非线性问题在世界中比比皆是,因为世界本身就是高度非线性的甚至是混沌的,比如天气系统、地震、市场行为等等。

3.1 单层网络

神经网络相关概念或想法最早可以追溯到1943年,直到1986年Hinton等人发明了反向传播算法,才让神经网络真正走向落地应用。

神经网络本质上是一堆组合在一起的分段线性函数,先考虑单输入单输出的情况,其中输入是 \(x\),输出是\(y\),神经网络满足:\(y = f(x,\Phi)\),其中 \(\Phi\)代表了神经网络的参数组或参数集合。

单层网络的\(f\)的定义为:

\[ y=\phi_0+\phi_1a[\theta_{10}+\theta_{11}x]+\phi_2a[\theta_{20}+\theta_{21}x]+ \cdots \tag{3.1}\]

其中\(\Phi=[\phi_0,\phi_1,\phi_2,\cdots,\theta_{10},\theta_{11},\theta_{20},\theta_{21},\cdots]\)\(a[·]\)为激活函数。从公式上可以看到,\(\theta_{i0}+\theta_{i1}x\)就只是关于\(x\)的一条直线,取三组\((\theta_{i0},\theta_{i1})\),其图像如下:

图 3.2: 线性组合项 \(\theta_{i0} + \theta_{i1}x\)

激活函数是一个非线性函数,它有很多种形式,常见的有Sigmoid函数和ReLU函数:

图 3.3: 激活函数

以ReLU函数为例,在经过激活函数后\(\theta_{i0}+\theta_{i1}x\)变为\(a[\theta_{i0}+\theta_{i1}x]\)

图 3.4: 经过激活函数后的\(a[\theta_{i0} + \theta_{i1}x]\)

假设\(\phi_0 = 0\)\(\phi_1 = \phi_2 = \phi_3 = 1\),定义\(h_1=a[\theta_{10}+\theta_{11}x]\)\(h_2=a[\theta_{20}+\theta_{21}x]\)\(h_3=a[\theta_{30}+\theta_{31}x]\),则输出y的图像为:

图 3.5: \(y = \sum h_i(x)\) 及各转折点

所以激活函数的作用是什么呢?假设没有激活函数,那\(\sum{\theta_{i0}+\theta_{i1}x}\)仍然只是一条直线(直线加直线也是直线),但是加入激活函数后,激活函数能提供转折点,从而让直线弯曲,当这样的转折点足够多时,就可以逼近任意一条曲线了。因此激活函数的作用在于提供非线性变化。

将上述行为用图形界面表示:

图 3.6: 神经网络图形表示

一个典型的神经网络包括输入层、输出层,以及除此之外的中间层或隐藏层。中间层的层数也叫神经网络的层数,图 3.6 为单层神经网络,\(h_1、h_2、h_3\)为隐藏层的隐藏单元。通用逼近定理告诉我们,即使是单层神经网络,只要隐藏单元的数量足够多,也可以逼近任意复杂的曲线。

3.2 多输入

当涉及到两个及以上的输入时,需要拓展隐藏单元的定义,以\(x_1, x_2\)为例,面对两个变量输入时隐藏单元\(h_i=a[\theta_{i0} + \theta_{i1} x_1 + \theta_{i2} x_2]\),同样地激活函数内部的表达式也只是输入变量的线性组合,经过激活函数,函数平面会发生折叠:

图 3.7: 多输入隐藏单元激活前平面与激活后折叠面

将这些隐藏单元组合到一起(\(\phi_0=0,\phi_1=\phi_2=\phi_3=1\)),我们就能看到这些折叠面共同叠加出了更复杂的表面形状:

图 3.8: 输出 \(y = h_1 + h_2 + h_3\)

3.3 多输出

类似于输入,其他的输出也是最后一层隐藏层隐藏单元的线性组合\(y_i = \phi_{i0}+\phi_{i1}h_1+\phi_{i2}h_2+\dots\),因为\(h_1、h_2\)等都是相同的,只有系数不同,因此输出的转折点都是相同的,如图所示:

图 3.9: 多输出下相同转折点

多输入多输出神经网络通常可以这样表示:

图 3.10: 通用神经网络

类似这样的网络被称为全连接网络,因为每个计算单元都是上一层所有单元的线性组合,并套上一个激活函数,除此之外没有更多复杂的结构。

3.4 多层神经网络

如果隐藏层不止有一层?先考虑这种情况:

图 3.11: 一层输出作为另一层输入

\(\theta_{10}^\prime = -1\)\(\theta_{11}^\prime = 1\)\(\theta_{20}^\prime = -5\)\(\theta_{21}^\prime = -3\),则\(y^\prime = a[y-1]+a[-3y-5]\),如图所示:

图 3.12: \(y\)\(y'\) 的映射曲线

图 3.12\(y\)\(y^\prime\)的映射,假设从\(x\)\(y\)的映射如图所示:

图 3.13: \(x\)\(y\) 的映射曲线

那你能发现关键在哪儿吗?关键在于 图 3.13 的值域随着\(x\)变大是折叠的,会在-3~3之间反复,考虑到 图 3.12 转折点的输入范围也是-3~3之间,最终\(x\)\(y^\prime\)的图像会出现更多的弯折:

图 3.14: 两层网络复合映射:从 \(x \to y\)(左上)、\(y \to y'\)(右上)至 \(x \to y'\)(右下)

利用这种办法,在同样数量隐藏单元的条件下,多层网络比单层网络有更强的拟合能力,换句话说就是可以用更少的参数获得相似的效果。

图 3.11 的结构也可以写成以下形式,它们是等价的:

图 3.15: 多层网络一般形式

面对多输入与多输出时多层神经网络通常以矩阵的形式列出其表达式:

图 3.16: 矩阵形式的表达式

可以总结出,从\(N\)个单元映射到下一层\(M\)个单元,参数矩阵\(\Omega \in R^{M \times N}\),偏置向量\(\beta \in R^{M \times 1}\)

3.5 再探多输入与多输出

其实多输入是好理解的,多输入可以代表事物的不同特征,例如二手车估值,输入包括出厂年份、行驶里程、量化后的品牌分类、出险次数、过户次数等等,输出就是单一的估值价格。

这种多输入单输出的问题被称为回归问题,其输出通常是一个具体的数字大小。回归问题的主要作用是定量预测,通过已知的特征预测未知或不可测量的数值,例如风力发电机的剩余寿命、下一季度的销售额等。

除了回归问题外另一类问题是分类问题,例如二分类。某个神经网络通过输入图片判断图片是猫或者是狗,它只需要两个输出\(y_1\)\(y_2\),如果是猫则让\(y_1\)输出接近1,\(y_2\)输出接近0,反之图片则是一条狗。

分类问题能实现的原因在于虽然多输出的神经网络会共享一些参数,但每个输出依然有足够多的自由参数可以学习到事物不同的表征。一般来说,任务有几种不同的类别,网络就会有相对应数量的输出。

为了迭代网络参数,针对不同类型问题,要分别设计损失函数。对于回归问题,其损失函数通常是均方误差函数:

\[ L[\phi] = \frac{1}{n}\sum^n_{i=1}(y_i - f(x_i,\phi))^2 \tag{3.2}\]

其中\(n\)是训练样本总数,\((x_i,y_i)\)为第\(i\)组训练样本,\(\phi\)为神经网络的参数,\(f(x_i,\phi)\)为第\(i\)组训练样本输入后神经网络得到的输出。

训练目的在于找到一组参数集\(\hat{\phi}\),使\(L[\hat{\phi}]\)最小:

\[ \hat{\phi} = \arg\min_{\phi} \frac{1}{n}\sum^n_{i=1}(y_i - f(x_i,\phi))^2 \tag{3.3}\]

而分类任务通常会把输出\(y_i\)看成是判断输入属于第\(i\)类的概率,例如分类任务里图片是一只猫的概率为0.1,是一只狗的概率为0.9,那选择概率最大的那个作为分类最终结果。为了满足概率论要求的所有概率和为1,分类任务通常在输出层之后应用softmax函数将所有的输出结果映射至0到1之间,并且所有输出值的和为1:

\[ \text{softmax}(z_i) = \frac{e^{z_i}}{\sum_{j=1}^K e^{z_j}}, \quad i = 1, 2, \dots, K \tag{3.4}\]

对于分类任务,损失函数通常使用交叉熵损失函数:

\[ L[\phi] = -\frac{1}{n}\sum_{i=1}^n \sum_{k=1}^K y_{ik} \log(\hat{y}_{ik}) \tag{3.5}\]

其中 \(n\) 为训练样本总数,\(K\) 为类别总数,\(y_{ik} \in \{0, 1\}\) 为第 \(i\) 个样本属于第 \(k\) 类的真实标签(通常采用独热编码),\(\hat{y}_{ik} = \text{softmax}(z_{ik})\) 为网络预测该样本属于第 \(k\) 类的概率。

在有了损失函数之后,下一步就是通过算法迭代网络参数,最基本的方法就是梯度下降,在章节开头提到过神经网络直到1986年才开始渐渐发挥作用,很大一部分原因是在此之前梯度计算比较困难,多层网络的梯度计算非常耗时且容易出错,直到1986年Hinton等人提出了反向传播算法才使得多层神经网络的训练变得可行。只是关于更多的发展历史、算法细节、代码实现等不在本文的讨论范围内,大家可以自行参考更多资料。因为我认为对于这些流程,ai已经发展的比绝大多数人更清楚代码实现和相关细节了,在了解基础概念之后应该多用ai解决问题。