人工神经网络入门

从生物结构到数学结构

对于一个神经元而言,其他神经元的信号会通过轴突突触处传递给这个神经元的树突(高中生物知识)。放在人工神经网络上,一般地,我们认为,信号是一个数,设为 xi(i=1,,n)x_i \pod{i = 1, \ldots, n}(可见有 nn 个神经元的信息传给了这个神经元)。这个神经元将下面的数作为输出:
output=f(b+i=1nwixi) \text{output} = f\left(b + \sum\limits_{i = 1}^n w_i x_i \right)

其中,b,wi(i=1,,n)b, w_i \pod{i = 1, \ldots, n}n+1n + 1 个数是这个神经元自身的属性。ff 称为**函数,可见,**函数的引入为神经元引入了非线性成分。

神经元模型

二值阈神经元模型

对于一个神经元,如果它的**函数是:
f(x)={0,x<tv,xt(v>0) f(x) = \begin{cases} 0, & x < t \\ v, & x \ge t \end{cases} \pod{v > 0}

则称之为二值阈神经元模型,称 tt阈值。显然,如果可以调整神经元自身的属性 bb,使得 b=tb = t(假设之前 bb00),则可以重新令**函数为以下形式而达到相同的效果:
f(x)={0,x<0v,x0(v>0) f(x) = \begin{cases} 0, & x < 0 \\ v, & x \ge 0 \end{cases} \pod{v > 0}

使用二值阈神经元模型,可以作为对一个命题的真假判断,从而可以利用多个神经元整合各个命题的真值以形成逻辑。

线性阈值神经元

利用二值阈神经元,我们可以进行一个简单的分类工作。以下面的神经元模型为例。
人工神经网络入门
对于上面的由单个神经元 N 构成的单层神经网络,我们规定其**函数为 f(x)=cxf(x) = cx,称这样的神经元为线性神经元。规定这样利用输出数据:当输出大于等于 00 时,认为输入 (x1,x2,x3)(x_1, x_2, x_3) 属于类型 1;当输出小于 00 时,认为输入 (x1,x2,x3)(x_1, x_2, x_3) 属于类型 2。

这样的一个神经元,如果再加上一个二值阈神经元,就可以在超平面上进行分类线性可分数据:以二维为例,线性可分数据指能用一条直线分成两半,每一半中的所有点属于同一类的数据。通过调整参数 w1,w2,w3w_1, w_2, w_3bb,可以训练这个神经网络以达到更好的分类效果。对于一个分类失误的点,令 (w1,w2,w3)(w_1, w_2, w_3) 减去 α(x1,x2,x3)\alpha(x_1, x_2, x_3),其中 α\alpha 是一个参数,即达到了训练的效果。可以证明,对于线性可分数据,该算法能在有限步内结束。

非线性**函数

线性阈值神经元模型最大的局限性在于,对于非线性可分数据,无法得到一个能正确分类的神经网络。由于多个线性矩阵运算总是可以合并为一个矩阵运算,因此多个线性神经元构成的神经网络也无法得到高于单个神经元的表达能力。解决方法是引入非线性**函数。为了使得非线性**函数发挥作用,往往还需要引入额外的神经网络层,称它们为隐藏层

常见的非线性**函数:Sigmoid,ReLU(整流线性**函数)。Sigmoid 函数在计算概论中记过;ReLU 指:
f(x)={x,z00,z<0 f(x) = \begin{cases} x, & z \ge 0 \\ 0, & z < 0 \end{cases}

多层神经网络的训练

对于单个神经元组成的网络,我们对这个神经元的参数有明确的训练目的。然而对于多层神经网络,隐藏层中的参数我们并不知道该如何取值才好,才能使得输出与我们的目标一致,这就是多层神经网络训练的问题。

计算概论中学习了神经网络的正向传播,上面的单个神经元的概念即是正向传播的简单例子,这里不再赘述。下面重点看反向传播

损失函数

考虑对于一组用于训练的数据,我们的输出数据一般都会和真实数据有一定差别。我们可以规定一个损失函数,用来表示一组训练数据的输出值与真实值相差的情况。

损失函数一般要满足三个性质:

  1. 非负性;
  2. 是凸函数;
  3. 单调性。

常用的损失函数:

  1. 均方误差(MSE):L=(yiy~i)2L = \sum(y_i - \tilde y_i)^2
    显然 MSE 满足非负性、凸函数和单调性。常用于回归。
  2. 交叉熵(Cross Entropy)。常用于分类。

定义交叉熵损失函数为:
L=iYilogyi(Yi 表示第 i 个数据分类是否错误,值为 0(正确)或 1(错误)) L = - \sum_i Y_i \log y_i \pod{\text{$Y_i$ 表示第 $i$ 个数据分类是否错误,值为 $0$(正确)或 $1$(错误)}}

这里的 yiy_i 是神经网络的输出,不是最终分类结果(即:不是 0 或 1),而是一个与分类结果有关的数。一般而言,这个数是经过 Softmax 函数的一个输出。

Softmax 函数:
fi(x1,,xn)=exii=1nexi(i=1,,n) f_i(x_1, \ldots, x_n) = \dfrac{\mathrm e^{x_i}}{\sum\limits_{i = 1}^n \mathrm e^{x_i}} \pod{i = 1, \ldots, n}

一般而言,对于 kk 分类问题,我们会得到一个大小为 kk 的输出,一般输出的数越大表示某一类的概率越大。利用 Softmax 函数可以把概率进行归一化并且使得最大项得到突出。

规定:最后一层是一个 Softmax 函数,设 Softmax 之前的输入为 xix_i,则写到交叉熵中有:
Li=Yilogexii=1nexi=Yi(xilogi=1nexi) L_i = - Y_i \log \dfrac{\mathrm e^{x_i}}{\sum\limits_{i = 1}^n \mathrm e^{x_i}} = - Y_i (x_i - \log \sum\limits_{i = 1}^n \mathrm e^{x_i})

这是第 ii 类对交叉熵的贡献。

梯度下降法

现在的目标是:尽量降低损失函数。我们采用梯度下降的方式,求出 LL 关于每个神经元的每个参数的偏导,沿偏导反方向按一定速率对参数进行修改。

首先找到神经网络的输出,是 yiy_i。显然 Lyi=i=1nLiyi\dfrac{\partial L}{\partial y_i} = \sum\limits_{i = 1}^n \dfrac{\partial L_i}{\partial y_i},所以下面我们只讨论与 Liyi\dfrac{\partial L_i}{\partial y_i} 有关的计算。并且,下面的计算是以交叉熵损失函数为例的。

Yi=0Y_i = 0 时,Li=0L_i = 0,从而 Liyi=0\dfrac{\partial L_i}{\partial y_i} = 0。当 Yi0Y_i \ne 0 时,Li=logyiL_i = -\log y_i(规定底数为 e\mathrm e,即实际上是 ln\ln),从而 Liyi=1yi\dfrac{\partial L_i}{\partial y_i} = -\dfrac{1}{y_i}

进一步地,我们要调整参数,就要求 LL 偏参数的导。假设上一层到这一层是一个全连接层,连接到 yiy_i 的其中一个参数是 wjiw_{ji},要求 Lwji\dfrac{\partial L}{\partial w_{ji}},有:
Lwji=Lyiyiwji \dfrac{\partial L}{\partial w_{ji}} = \dfrac{\partial L}{\partial y_i} \dfrac{\partial y_i}{\partial w_{ji}}

也就是说,我们只需要记录下一层的偏导,然后求一个非复合的一元函数偏导,相乘即得答案。由于是全连接层,有:
yi=w1ix1+w2ix2+ y_i = w_{1i} x_1 + w_{2i} x_2 + \cdots

假设 j=1j = 1,则 yiw1i=x1\dfrac{\partial y_i}{\partial w_{1i}} = x_1。这样,我们就求出了 Lwji\dfrac{\partial L}{\partial w_{ji}}。以此类推,可以求出 LL 偏任意参数的偏导。之后,根据学习率设定步长,沿偏导反方向前进相应距离,就达到了梯度下降的效果。