神经网络数学原理(4)激活函数
神经网络的核心目的是能够处理复杂的模式和关系。如果没有激活函数,神经网络中的每一层实际上只是对输入进行线性变换。例如,如果没有激活函数,输出就是一个线性组合。无论层数如何增加,整个网络的输出仍然是一个线性变换,这就意味着无论网络有多少层,最终网络的表达能力与单层网络等效,无法拟合复杂的非线性关系。激活函数的作用就是通过引入非线性,使得网络能够学习到复杂的模式。只有当网络引入非线性激活函数时,才能通过多层网络组合成非线性变换,从而拟合复杂的决策边界。
激活函数介绍
激活函数是神经网络中的重要组成部分,它决定了神经元的输出,从而帮助网络学习复杂的非线性关系。不同的激活函数有不同的特点,适用于不同的场景。下面是一些常见的激活函数,它们的介绍、使用场景、优缺点。
1. Sigmoid 函数
公式:
优点:
- 输出在 (0, 1) 之间,可以解释为概率,特别适用于二分类任务,如二元分类问题中的输出层。
- 数学简单,计算容易,导数也很简单,便于优化。
缺点:
- 梯度消失问题:在输入值很大或很小时,Sigmoid 函数趋向于平坦区域,函数的导数会变得非常小,接近于 0,这会导致在训练时梯度几乎消失,从而使得网络很难更新参数,尤其是在深层网络中。
- 例如,当输入值非常大时(正或负),Sigmoid 函数的输出趋近于 1 或 0,此时其导数非常小。
- 非零中心化:Sigmoid 的输出总是为正数(介于 0 和 1 之间),这意味着权重的更新始终有偏移,这使得数据不能在负数和正数之间对称分布,可能导致训练过程中梯度更新效率较低。训练过程的震荡或收敛速度慢。
左侧是Sigmoid函数图像,右侧他得导函数图,由图可见,输入值很大或很小时,Sigmoid 函数趋向于平坦区域,函数的导数会变得非常小,接近于 0,导致梯度消失,使得网络很难更新参数。

import numpy as np import matplotlib.pyplot as plt # Sigmoid 函数定义 def sigmoid(x): return 1 / (1 + np.exp(-x)) # Sigmoid 导数的定义 def sigmoid_derivative(x): return sigmoid(x) * (1 - sigmoid(x)) # 生成 x 值 x = np.linspace(-10, 10, 400) # 计算 Sigmoid 函数的输出 y_sigmoid = sigmoid(x) # 计算 Sigmoid 导数的输出 y_derivative = sigmoid_derivative(x) # 绘制图像 plt.figure(figsize=(12, 6)) # Sigmoid 函数图 plt.subplot(1, 2, 1) plt.plot(x, y_sigmoid, label='Sigmoid Function', color='blue', alpha=0.6) # 让线条变淡 plt.title('Sigmoid Function') plt.xlabel('x') plt.ylabel('sigmoid(x)') plt.grid(True) plt.axhline(0, color='black',linewidth=1.5) # 原点的水平线加粗 plt.axvline(0, color='black',linewidth=1.5) # 原点的垂直线加粗 plt.xlim(-10, 10) plt.ylim(-0.1, 1.1) plt.legend() # Sigmoid 导数图 plt.subplot(1, 2, 2) plt.plot(x, y_derivative, label='Sigmoid Derivative', color='red', alpha=0.6) # 让线条变淡 plt.title('Sigmoid Derivative') plt.xlabel('x') plt.ylabel("sigmoid'(x)") plt.grid(True) plt.axhline(0, color='black',linewidth=1.5) # 原点的水平线加粗 plt.axvline(0, color='black',linewidth=1.5) # 原点的垂直线加粗 plt.xlim(-10, 10) plt.ylim(-0.1, 0.3) plt.legend() # 显示图像 plt.tight_layout() plt.show()
2. Tanh 函数
公式:
优点:
- 输出范围在 (-1, 1) 之间,相较于 Sigmoid 的 (0, 1),Tanh 是零中心化的,这有助于加速梯度下降过程,因为其输出值的正负分布较为对称。
- 梯度较大:当输入在合理范围内时,Tanh 的梯度较大,能更有效地更新参数。
缺点:
- 梯度消失问题:尽管 Tanh 比 Sigmoid 的输出范围更大,但当输入值过大或过小时,它也会出现梯度消失问题。输入值很大的时候,Tanh 输出接近 ±1,梯度趋近于 0,导致训练时遇到梯度消失。
- 计算较复杂:Tanh 的计算涉及指数运算,相比 Sigmoid 函数的简单计算,Tanh 的计算会稍微更慢,尽管差别不是很大。
左侧是 Tanh 函数图像,右侧他得导函数图,由图可见 :和Sigmoid相比Tanh 输出范围在 (-1, 1) 之间,使得数据分布更对称,有助于加速梯度下降,两者导函数图像相似,都会当输入值过大或过小时,它也会出现梯度消失问题

import numpy as np import matplotlib.pyplot as plt # Tanh 函数定义 def tanh(x): return np.tanh(x) # Tanh 导数的定义 def tanh_derivative(x): return 1 - np.tanh(x)**2 # 生成 x 值 x = np.linspace(-10, 10, 400) # 计算 Tanh 函数的输出 y_tanh = tanh(x) # 计算 Tanh 导数的输出 y_derivative = tanh_derivative(x) # 绘制图像 plt.figure(figsize=(12, 6)) # Tanh 函数图 plt.subplot(1, 2, 1) plt.plot(x, y_tanh, label='Tanh Function', color='blue', alpha=0.6) # 让线条变淡 plt.title('Tanh Function') plt.xlabel('x') plt.ylabel('tanh(x)') plt.grid(True) plt.axhline(0, color='black',linewidth=1.5) # 原点的水平线加粗 plt.axvline(0, color='black',linewidth=1.5) # 原点的垂直线加粗 plt.xlim(-10, 10) plt.ylim(-1.1, 1.1) plt.legend() # Tanh 导数图 plt.subplot(1, 2, 2) plt.plot(x, y_derivative, label='Tanh Derivative', color='red', alpha=0.6) # 让线条变淡 plt.title('Tanh Derivative') plt.xlabel('x') plt.ylabel("tanh'(x)") plt.grid(True) plt.axhline(0, color='black',linewidth=1.5) # 原点的水平线加粗 plt.axvline(0, color='black',linewidth=1.5) # 原点的垂直线加粗 plt.xlim(-10, 10) plt.ylim(-0.1, 1.1) plt.legend() # 显示图像 plt.tight_layout() plt.show()
3. ReLU (Rectified Linear Unit)
公式:
优点:
- 计算简单:ReLU 函数仅仅是对输入值进行阈值化处理(大于 0 输出原值,小于 0 输出 0),因此计算速度非常快。
- 缓解梯度消失问题:对于输入大于 0 的区域,ReLU 的导数始终为 1,避免了梯度消失问题,因此在深层神经网络中能有效加速训练过程。
缺点:
- 死神经元问题:当输入小于 0 时,ReLU 的输出始终为 0,如果 ReLU 的输入值总是小于 0,输出为 0,那么梯度总为 0,意味着该神经元在训练过程中没有激活,因此它的权重不会得到更新,导致神经元“死掉”。。
- 不对称性:ReLU 只对正数输入有效,对负数输入没有响应。这可能导致模型学习不到负数区域的特征。
ReLU函数
ReLU导函数

import numpy as np import matplotlib.pyplot as plt # ReLU 函数定义 def relu(x): return np.maximum(0, x) # ReLU 导数定义 def relu_derivative(x): return np.where(x > 0, 1, 0) # 生成 x 值 x = np.linspace(-10, 10, 400) # 计算 ReLU 函数的输出 y_relu = relu(x) # 计算 ReLU 导数的输出 y_relu_derivative = relu_derivative(x) # 绘制图像 plt.figure(figsize=(12, 6)) # ReLU 函数图 plt.subplot(1, 2, 1) plt.plot(x, y_relu, label='ReLU Function', color='green') plt.title('ReLU Function') plt.xlabel('x') plt.ylabel('ReLU(x)') plt.grid(True) plt.axhline(0, color='black', linewidth=1.5) # 原点的水平线加粗 plt.axvline(0, color='black', linewidth=1.5) # 原点的垂直线加粗 plt.xlim(-10, 10) plt.ylim(-1, 10) plt.xticks(np.arange(-10, 11, 2)) # x轴刻度步长为2 plt.yticks(np.arange(0, 11, 2)) # y轴刻度步长为2 plt.legend() # ReLU 导数图 plt.subplot(1, 2, 2) plt.plot(x, y_relu_derivative, label="ReLU Derivative", color='red') plt.title('ReLU Derivative') plt.xlabel('x') plt.ylabel("ReLU'(x)") plt.grid(True) plt.axhline(0, color='black', linewidth=1.5) # 原点的水平线加粗 plt.axvline(0, color='black', linewidth=1.5) # 原点的垂直线加粗 plt.xlim(-10, 10) plt.ylim(-0.1, 1.1) plt.xticks(np.arange(-10, 11, 2)) # x轴刻度步长为2 plt.yticks([0, 1]) # y轴只显示0和1 plt.legend() # 显示图像 plt.tight_layout() plt.show()
4. Leaky ReLU
公式:
导函数
其中 α 是一个很小的常数,通常设为 0.01。
优点:
- 缓解死神经元问题:当输入小于 0 时,Leaky ReLU 仍然允许输出小于 0 的值(通过一个小的斜率 α),这保证了神经元的梯度不会完全消失。
- 计算简单:与 ReLU 类似,Leaky ReLU 也计算非常简单,不会增加太多的计算负担。
缺点:
- 可能会导致“过于激进”的更新:如果 α 选择得太大,负值部分的梯度会变得较大,可能导致参数更新过于剧烈, 造成梯度爆炸,从而影响收敛过程。
- 仍然存在某些情况下的梯度消失:尽管 Leaky ReLU 能缓解死神经元问题,但在极小的 α 值下,负区域的梯度仍然很小,无法有效更新参数。
如图所示是a=0.05 Leaky ReLU的函数图和导数图,在x<0的情况,梯度=a=0.05, 缓解死神经元问题。
5. Softmax 函数
函数常用于多分类任务的输出层,将输出值转换为概率分布。Softmax 函数的形式如下:
公式:
其中 zi 是类别 i 的得分(通常是神经网络的输出) ,分母中的求和是对所有类别的得分进行指数运算后求和
优点:
- 生成概率分布:Softmax 函数可以将模型的输出转化为一个概率分布,适用于多分类问题。每个输出代表某个类别的概率,所有概率的和为 1。
- 广泛应用于分类任务:多分类问题(如图像分类、文本分类)通常使用 Softmax 激活函数。
缺点:
- 计算开销大:Softmax 需要计算每个类别的指数值,然后进行归一化处理,这对于类别较多的任务来说,计算量较大。
- 容易受到异常值影响:如果某个类别的得分远远大于其他类别,Softmax 会将大部分概率分配给这个类别,导致其他类别的概率接近 0,从而影响多分类任务的效果。
举一个简单的例子,帮助你理解Softmax函数的数学原理。
假设我们有一个二分类问题,类别 1 和 类别 2。对于一个输入,神经网络会输出两个得分: z1 和 z2 ,它们代表每个类别的得分。Softmax函数会将这些得分转换为一个概率分布,表示输入属于每个类别的概率。
5.1. Softmax 函数公式(2分类情况)
Softmax 函数的定义如下:
这两个概率分别表示输入属于类别 1 和类别 2 的概率。
5.2. 举例说明
假设我们有以下得分:
- 类别 1 的得分 z1=2
- 类别 2 的得分 z2=1
我们将这些得分输入到 Softmax 函数中,计算每个类别的概率。
5.3. 结果解读
- 类别 1 的概率约为 0.731
- 类别 2 的概率约为 0.269
Softmax 的核心作用是将神经网络的原始得分(通常是实数)转换为概率分布,这些概率表示了各个类别的相对可能性。通过指数函数(ezi),Softmax 强调了得分较高的类别,从而增加了其对应的概率。而通过将所有类别的指数和作为分母,确保所有类别的概率和为 1。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库