MENU

【RethinkAI】神经元与反向传播

2025 年 08 月 08 日 •

前言

本篇主要记录激活函数、基本的神经元模型以及反向传播。

激活函数的引入与神经元模型

在神经网络中,一个神经元象征着这样的运算:

$$ \text{BaseNeuron}(\mathbf{I})=\mathbf{WI}+\mathbf{B} $$

其中,$\mathbf{I}$代表输入的矩阵(本文只讨论二维情况),$\mathbf{W}$和$\mathbf{B}$是神经网络的两个参数——权重和偏置。

当然只依靠$\text{BaseNeuron}$是不够的,因为多层这样的结构和一层无异,比如,两层的计算可以变成:

$$ \text{BaseNeuron}_1(\text{BaseNeuron}_2(\mathbf{I}))=\mathbf{W}_1(\mathbf{W}_2\mathbf{I}+\mathbf{B}_2)+\mathbf{B_1} $$

根据矩阵乘法的分配律,上式可变成:

$$ \text{BaseNeuron}_1(\text{BaseNeuron}_2(\mathbf{I}))=\mathbf{W}_1\mathbf{W}_2\mathbf{I}+\mathbf{W}_1\mathbf{B}_2+\mathbf{B}_1 $$

这依然符合$\text{BaseNeuron}$的基本形式,两层的计算,可以通过一个新的层达成目的,新层的权重为$\mathbf{W}_1\mathbf{W}_2$,偏置为$\mathbf{W}_1\mathbf{B}_2+\mathbf{B}_1$即可。

这背后的原理是:“线性变换的线性变换依然是一个线性变换”,这一点可以通过线性变换的概念进行证明——因为线性变换是在一个线性空间内做的运算,没有办法“逃出”这个空间。

在现实世界中,并非所有的事物都可以用线性变换来解释,比如线性变换没有办法解释异或,也没有办法拟合正余弦等函数。这个时候,我们就需要一个工具,来创造出非线性变换——这便是激活函数。借用这个工具,我们的神经元模型变成了:

$$ \text{Neuron}(\mathbf{I})=f(\mathbf{WI}+\mathbf{B}) $$

其中,$f(\cdot)$是一个非线性的函数,是我们的激活函数。其作用很简单——向一个线性模型中引入非线性。只要是非线性函数,就可以用作激活函数,只是具体的效果有待考量而已。

反向传播

模型的层数可以很多,那么,在梯度下降训练过程中,就需要一种方法来计算出每一层的梯度。比如我们的模型有两层:

$$ \text{Model}(\mathbf{I})=\text{Neuron}_2\text{Neuron}_1(\mathbf{I})=f_2(\mathbf{W}_2f_1\mathbf{(\mathbf{W}_1\mathbf{I}+\mathbf{B}}_1)+\mathbf{B}_2) $$

我们需要求取每一层的梯度,具体来说,是针对于权重和偏置的梯度。

当然,只有输出还不够,按照梯度下降的思想,我们需要一个损失函数,求损失函数对每一个参数的导数,亦即$\frac{\partial{L}}{\partial \mathbf{W}_1}$之类。这里,我们要用到的工具是——链式法则。

对于$\frac{\partial{L}}{\partial \mathbf{W}_2}$而言,它等于:

$$ \frac{\partial{L}}{\partial \mathbf{W}_2}=\frac{\partial{L}}{\partial f_2}\frac{\partial{f_2}}{\partial \mathbf{W}_2} $$

所以,我们可以从输出层向输入层逐层求导,因为,前面的层,需要后面层的参数做运算。

反向传播就是这么简单的东西——先求出后面一层的全部参数值,然后通过链式法则进行运算。

激活函数的几个例子

一个好的激活函数需要满足几个条件:

  1. 形式简单。
  2. 求导方便。

其中,这两点都是因为,我们常用的训练架构,依然是基于梯度下降的。一个形式简单的激活函数,不仅方便理解、分析和编码,也能让计算速度变快;一个求导方便的激活函数,就利于梯度下降。

比较常用的激活函数是Sigmoid函数,其公式为:

$$ \text{Sigmoid}(x)=\frac{1}{1+e^{-x}} $$

易知其导数为:

$$ S'(x)=S(x)(1-S(x)) $$

其中,$S(x)$即$\text{Sigmoid}(x)$。这个函数的值域为$[0,1]$,常用于二分类任务输出层。因为二分类通常以0、1为标签。

对于多分类来说,通常使用Softmax函数,其公式为:

$$ \text{Softmax}(\mathbf{X})=\frac{e^{x_k}}{\sum_{i=1}^ne^{x_i}} $$

其实,这个函数通常和交叉熵损失函数一起求导。交叉熵损失函数的公式为:

$$ L(p,y) = -\sum_{i=1}^ny_iln(p_i) $$

其中,$p,y$分别是预测值和真实值,其中,$p_i=\text{Softmax}(\mathbf{X}_i)$。

如果求$\frac{\partial L}{\partial \mathbf{X}}$,那么:

$$ \frac{\partial L}{\partial \mathbf{X}} = \frac{\partial L}{\partial \text{Softmax}}\frac{\partial \text{Softmax}}{\partial \mathbf{X}} $$

又可以变为:

$$ [\frac{\partial L}{\partial \mathbf{X}}]_k = [0,0,\cdots,-\frac{1}{\text{Softmax}(x_k)},\cdots0,0]\times \mathbf{M} $$

那么,$\mathbf{M}$是个什么,其实,它是一个矩阵!而且是一个只有一列有元素的矩阵,具体的推导参考我的另一篇blog。这个矩阵只有第$k$列有元素,且:

  • 当$k\neq i$时,元素为$-a_ka_i$
  • 当$k=i$时,元素为$a_k-a_k^2$。

其中,$a_i$为$\text{Softmax}(x_i)$,所以,最后我们得到了一个行向量,拼凑起来:

$$ \frac{\partial L}{\partial \mathbf{X}} = \text{Softmax}(\mathbf{X})-\mathbf{Y} $$

还有一类很常用的激活函数,是以$\text{ReLU}$为基础的:

$$ \text{ReLU}(x)=\max(0,x) $$

这个函数很简单,但是有一个问题,就是会出现一个无法求导的点——$(0,0)$。此外,这种函数由于在负数区,梯度始终为0,会出现一个神经元梯度为0,后面所有的梯度都为0的情况。

在这个函数的基础上,有了很多改进,比如,将负数区从0变为$0.01x$,就可以规避梯度为0带来的影响。

这些函数的作用,都是为线性系统带来非线性。