机器学习面试题汇总与解析——激活函数

本章讲解知识点

    1. 什么是激活函数?
    1. 为什么要使用激活函数?
    1. 详细讲解激活函数


  • 本专栏适合于Python已经入门的学生或人士,有一定的编程基础。
  • 本专栏适合于算法工程师、机器学习、图像处理求职的学生或人士。
  • 本专栏针对面试题答案进行了优化,尽量做到好记、言简意赅。这才是一份面试题总结的正确打开方式。这样才方便背诵
  • 如专栏内容有错漏,欢迎在评论区指出或私聊我更改,一起学习,共同进步。
  • 相信大家都有着高尚的灵魂,请尊重我的知识产权,未经允许严禁各类机构和个人转载、传阅本专栏的内容。

  • 关于机器学习算法书籍,我强烈推荐一本《百面机器学习算法工程师带你面试》,这个就很类似面经,还有讲解,写得比较好。

  • 关于深度学习算法书籍,我强烈推荐一本《解析神经网络——深度学习实践手册》,简称 CNN book,通俗易懂。



1. 什么是激活函数?

1.1 定义与作用

激活函数是一种用于神经网络和其他机器学习模型中的非线性函数。它被应用于神经网络的每个神经元上,将输入信号进行转换,产生输出信号。激活函数的作用是引入非线性性质,使神经网络能够学习和表示更复杂的函数关系

在神经网络中,每个神经元接收来自上一层神经元的加权输入,然后通过激活函数对这个加权输入进行非线性变换,生成神经元的输出。这个输出被传递到下一层神经元作为输入。

激活函数的主要作用有以下几点:

  • 引入非线性:激活函数能够将线性变换后的输入转换为非线性输出,使得神经网络具备非线性建模能力。这对于解决复杂的非线性问题至关重要。

  • 改善模型的表达能力:通过引入非线性性质,激活函数能够增加神经网络的表达能力,使其能够学习和表示更加复杂的函数关系。

  • 增强网络的稳定性:激活函数能够限制神经元输出的范围,防止信号的过度扩散或衰减,从而增强神经网络的稳定性和收敛性。

1.2 常见的激活函数包括

  • Sigmoid函数(逻辑斯蒂函数)
  • 双曲正切函数(Tanh函数)
  • ReLU函数(修正线性单元)
  • Leaky ReLU函数
  • Parametric ReLU函数(PReLU)
  • ELU函数(指数线性单元)
  • Softmax函数(用于多分类任务)

选择适当的激活函数取决于具体的问题和网络架构。不同的激活函数具有不同的性质和适用场景,因此在设计神经网络时需要根据实际情况进行选择。


2. 为什么要使用激活函数?

下图是神经元模型:

img

其中 xix_i 为第 i 个输入,wiw_i 为第 i 个神经元的权重,θθ 为门限。可以看到,yy 为线性函数,线性函数就只能处理线性问题,非线性的问题没办法处理了。所以为了让神经网络也能处理非线性的问题,才需要引入非线性激活函数,把线性函数给非线性化。这就是使用激活函数的意义

让我们以一个简单的线性函数和一个非线性函数作为例子,来说明为什么要使用激活函数。

假设我们有一个神经网络,其中包含一个输入层和一个输出层。我们使用一个线性函数作为激活函数,并尝试使用这个网络进行二分类任务。

  • 线性函数作为激活函数: 如果我们选择线性函数作为激活函数(例如f(x) = ax),那么整个神经网络的输出就是一个线性函数。无论我们网络有多少层,它仍然只能表示线性关系。这意味着网络无法学习和表示复杂的非线性模式,对于解决复杂的问题效果会非常有限。

  • 非线性函数作为激活函数: 现在,我们选择一个非线性函数作为激活函数,例如ReLU函数(f(x) = max(0, x))。这个非线性函数引入了非线性性质,使得神经网络能够学习和表示更复杂的函数关系。ReLU函数在输入为负数时输出为0,在输入为正数时输出与输入相等,这样的非线性特性可以帮助网络区分不同类别的数据,并提高分类准确性。

举个例子,假设我们的二分类任务是将两类数据点分开,这两类数据点在输入空间中呈现出一个圆环状的分布。如果我们使用线性函数作为激活函数,无论多少层网络,它只能拟合一条直线,无法切割出圆环形状的区域。但是,如果我们使用ReLU等非线性函数作为激活函数,神经网络可以通过学习组合多个线性函数,来逼近并拟合出圆环形状的边界,从而更好地进行分类。

如下图数据,线性函数是没办法很好二分类的,但是非线性函数可以逼近并拟合出圆环形状的边界,从而更好地进行分类,例如数据被分类成蓝色部分和黄色部分。

img

3. 详细讲解激活函数

从激活函数的发展历史开始讲起:

3.1 sigmoid 函数

1.定义

sigmoid 函数sigmoid(x) 型函数也称 Logistic 函数,公式如下:

σ(x)=11+exp(x)(.)\sigma(x)=\frac{1}{1+exp(-x)} \\ \tag{.}

sigmoid 型函数是第一个被广泛应用于神经网络激活函数。经过 sigmoid 型函数作用后,输出的值范围在 [0,1] 之间。但是 sigmoid 型函数的输出存在均值不为 0 的情况,并且存在梯度消失的问题,在深层网络中被其他激活函数替代。在逻辑回归中使用的该激活函数用于输出分类

2.期望

函数图形如下:

img

从函数和公式可以很清楚地看到,sigmoid 函数将输入映射到了 [0,1] 之间,因为输出都大于 0,所以 sigmoid 函数期望(均值)大于 0 的。什么意思呢?简单理解就是 (0+1)/2=0.5,均值大于 0。如果输出区间在 [-1,1] 之间,那么均值就是 (-1+1)/2=0 了。

当然这只是简单理解,期望计算公式如下:

E(x)=k=1xkpk(.)E(x)=\sum_{k=1}^ \infty x_kp_k \tag{.}

这个 xkx_k 表示取值,如 1,2,3,4.....;pkp_k 表示取值的概率,按照上面的公式加和,就得到我们的期望 E(x)E(x) 了。

然后在神经网络中,我们希望当前一层的神经元输出均值为 0,为什么要均值为 0 呢?有以下几点原因:

  • 均值中心化:将激活函数的期望值设置为 0 可以使得网络的输出更容易进行归一化处理。通过均值中心化,可以减少输入数据的偏移和不平衡,有助于提高网络的稳定性和收敛速度。

  • 梯度传播:激活函数的期望为 0 可以促使梯度在反向传播过程中更好地传播。当激活函数的期望为非零值时,梯度的平均值可能会发生偏移,导致梯度传播过程中的不稳定性。而期望为 0 的激活函数可以使得梯度在不同层之间的传播更加一致和稳定。

  • 防止梯度爆炸和梯度消失:激活函数的期望为 0 有助于缓解梯度爆炸和梯度消失的问题。如果激活函数的期望值较大,网络的参数更新可能会导致梯度变得非常大,造成梯度爆炸。相反,如果激活函数的期望值较小,梯度可能会在反向传播过程中逐渐消失,导致梯度消失问题。通过将激活函数的期望设置为0,可以在一定程度上避免这些问题。

sigmoid 函数期望显然不满足以上原则。

3.梯度消失

sigmoid 函数存在梯度消失的问题。

那怎么又存在梯度消失的问题呢?梯度是啥啊?梯度就是曲线斜率吧,曲线斜率就是切线吧,大家可以回忆一下高中的知识哈,在函数图形上画切线就可以看到 sigmoid 函数两边的斜率已经越来越趋向 0 了,如图:

img

都趋向 0 了,我们神经网络反向传播参数的时候参数就不更新了呀,不更新就代表网络没有继续学习了,这就是梯度消失

4.Sigmoid 函数的特点如下

  • 输出范围:Sigmoid 函数的输出范围在 0 和 1 之间,可以将输出解释为概率值,表示某个事件发生的概率

  • 平滑性:Sigmoid 函数具有平滑的连续性质,其曲线在整个定义域内都是光滑且单调递增的。方便求导,能求导就可以使用梯度下降的方式来优化

  • 中心对称性:Sigmoid函数关于 y=0.5y = 0.5 对称,即对于任意 xx,有 f(x)=1f(x)f(-x) = 1 - f(x)

  • 饱和性:当输入值非常大或非常小时,Sigmoid 函数的输出接近于 1 或 0,导致梯度接近于 0。这种饱和性可能导致梯度消失的问题,在深度神经网络中容易出现梯度衰减问题。

3.2 tanh 函数

tanh 函数。tanh(x) 型函数可以解决 sigmoid 型函数的期望(均值)不为 0 的情况。函数输出范围为 (-1,+1)。但 tanh(x) 型函数依然存在梯度消失的问题。公式如下:

tanh(x)=exexex+ex=e2x1e2x+1=2sigmoid(2x)1(.)tanh(x)=\frac{e^x-e^{-x}}{e^x+e^{-x}}=\frac{e^{2x}-1}{e^{2x}+1}=2 \cdot sigmoid(2x)-1 \\ \tag{.}

在 LSTM 中使用了 tanh(x) 型函数。

可以看到函数曲线:

img

输出范围成了 [-1,1],期望(均值)为 0。梯度消失的问题同sigmoid。

tanh 函数的特点如下

  • 输出范围:tanh函数的输出范围在 -1 和 1 之间,可以将输出解释为样本属于不同类别的置信度或概率。

  • 平滑性:tanh函数具有平滑的连续性质,其曲线在整个定义域内都是光滑且单调递增的。

  • 中心对称性:tanh 函数关于原点对称,即对于任意 xx,有 f(x)=f(x)f(-x) = -f(x)。输出期望为 0。

  • 饱和性:当输入值非常大或非常小时,tanh 函数的输出接近于 1 或 -1,导致梯度接近于 0。这种饱和性可能导致梯度消失的问题,在深度神经网络中容易出现梯度衰减问题。

3.3 ReLU 函数

ReLU 函数。ReLU(x) 型函数可以有效避免梯度消失的问题,公式如下:

ReLU(x)={x,ifx00,ifx<0(.)ReLU(x)=\begin{cases}x,\quad if \quad x\geq 0 \\ 0, \quad if \quad x< 0 \\ \end{cases} \\ \tag{.}

函数如图:

img

可以看到,ReLU 在大于 0 时,斜率固定,不存在梯度消失的问题,这有助于网络训练。再看看梯度函数:

img

ReLU 梯度稳定,值还比 sigmoid 大,所以可以加快网络训练不过 ReLU 的缺点就是小于 0 的值不再得到响应,这又不利于网络训练。我们在输入图像时就要注意,应该使用 Min-Max 归一化,而不能使用 Z-score 归一化。

ReLU 函数的特点如下

  • 线性性质:在输入为正时,ReLU 函数是线性函数,直接将输入值传递给输出。这使得 ReLU 函数具有较强的表达能力。

  • 非线性性质:在输入为负时,ReLU 函数输出为 0,引入了非线性特性,可以帮助神经网络学习更复杂的模式和表示。

  • 稀疏激活:ReLU 函数的输出为 0 的特性使得神经网络中的神经元具有稀疏激活性。对于给定的输入样本,只有部分神经元会被激活,从而减少了参数的冗余性,提高了网络的效率。

  • 消失梯度问题的缓解:相比于 Sigmoid 函数和 tanh 函数,在反向传播过程中,ReLU 函数的梯度计算更简单且不会出现饱和现象,因此更不容易出现梯度消失的问题。

  • 死区现象:ReLU 函数在输入为负时输出为 0,可能导致神经元死亡的问题,即一旦激活为 0,对应的权重将不再更新,该神经元很可能包含重要特征。

  • 梯度爆炸:ReLU 不会对数据做幅度压缩,如果数据的幅度不断扩张,模型层数越深,幅度扩张越厉害,出现梯度爆炸,最终会影响模型性能。

3.4 ReLU6 函数

大家可以注意到 ReLU 的正值输出为 [0,无穷大],关键是我们计算机内存有限,能存储无穷大的数吗?当然不能,同时为了对 ReLU 的数据做幅度压缩,所以将 ReLU 应用到实际中时需要限定输出的最大值,所以就成了 ReLU6 了,如图:

img

就是因为最大输出限定在 6,所以称为 ReLU6 了。

3.5 Leaky ReLU 函数

Leaky ReLU 函数。Leaky ReLU(x) 型函数为负值增加了一个斜率,缓解了“死区”现象,公式如下:

LeakyReLU(x)={x,ifx0αx,ifx<0(.)Leaky\quad ReLU(x)=\begin{cases}x,\quad if \quad x\geq 0 \\ \alpha \cdot x, \quad if \quad x< 0 \\ \end{cases} \\ \tag{.}

α\alpha 是一个小的正数,通常取接近于 0 的小值,如 0.01。

Leaky ReLU函数如图:

img

可以看到,0 的左边存在斜率,那么负值也可以得到响应,有利于网络学习到更多的信息。Leaky ReLU(x) 型函数缺点是,超参数 α\alpha 合适的值不好设定。当我们想让神经网络能够学到负值信息,那么使用该激活函数。

Leaky ReLU函数的特点如下:

  • 线性性质:在输入为正时,Leaky ReLU 函数与 ReLU 函数一样,直接输出输入值,具有线性性质。

  • 非线性性质:在输入为负时,Leaky ReLU 函数乘以斜率 α\alpha,引入了非线性特性,可以帮助神经网络学习更复杂的模式和表示。

  • 缓解神经元死亡问题:通过引入一个小的斜率 α\alpha,Leaky ReLU 函数使得负值部分不再完全变为 0,从而缓解了神经元死亡问题。即使输入为负,梯度仍然可以传播并更新相关的权重。

  • 零中心性:当斜率 α\alpha 取较小的正数时,Leaky ReLU 函数在整个定义域上保持零中心性,有助于网络的稳定性和收敛性。

3.6 Mish 函数

Mish 激活函数。Mish 激活函数同样允许负值有一定的梯度流入。公式如下:

Mish(x)=xtanh(log(1+ex))(.)Mish(x)=x \cdot tanh(log(1+e^x)) \\ \tag{.}

应用场景同 Leaky ReLU(x) 型函数。

如图:

img

可以看出,在负值中,允许有一定的梯度流入。

3.7 PReLU 函数

参数化 ReLU(P-ReLU)。参数化 ReLU 为了解决超参数 α\alpha 合适的值不好设定的问题,干脆将这个参数也融入模型的整体训练过程中。也使用误差反向传播和随机梯度下降的方法更新参数。

3.8 RReLU 函数

随机化 ReLU(R-ReLU)。顾名思义,就是超参数 α\alpha 随机化,让不同的层自己学习不同的超参数,但随机化的超参数的分布符合均值分布或高斯分布,如图:

img

3.9 指数化线性单元(ELU)

指数化线性单元(ELU)。也是为了解决死区问题,公式如下:

ELU(x)={x,ifx0λ(ex1),ifx<0(.)ELU(x)=\begin{cases}x,\quad if \quad x\geq 0 \\ \lambda \cdot (e^x-1), \quad if \quad x< 0 \\ \end{cases} \\ \tag{.}

如图:

img

缺点是指数计算量大

3.10 Maxout

Maxout。与常规的激活函数不同,Maxout 是一个可以学习的分段线性函数。其原理是,任何 ReLU 及其变体等激活函数都可以看成分段的线性函数,而 Maxout 加入的一层神经元正是一个可以学习参数的分段线性函数。Maxout 是深度学习网络中的一层网络,就像池化层、卷积层一样等,我们可以把