PyTorch 激活函数及非线性变换详解

devtools/2024/9/24 19:15:30/

激活函数是深度学习模型的重要组成部分,它们引入非线性,从而使模型能够更好地拟合复杂的数据模式。本文将详细介绍激活函数的作用、常见类型、经典应用示例,并比较它们的优缺点。

激活函数的作用

激活函数的主要作用是引入非线性变换,使神经网络能够拟合复杂的数据模式。为了理解这句话的含义,我们需要详细探讨以下几个方面:

  1. 线性变换的局限性
  2. 非线性变换的必要性
  3. 激活函数的作用
  4. 实际应用中的激活函数
1. 线性变换的局限性

线性变换是指一种保持向量加法和标量乘法的运算。在几何上,线性变换通常包括旋转、缩放、平移等操作。线性变换可以用矩阵乘法来表示。对于一个输入向量 x \mathbf{x} x 和一个线性变换矩阵 A \mathbf{A} A,线性变换的输出 y \mathbf{y} y 可以表示为:

y = A x + b \mathbf{y} = \mathbf{A} \mathbf{x} + \mathbf{b} y=Ax+b

其中, A \mathbf{A} A 是一个矩阵, b \mathbf{b} b 是一个偏置向量。

特性

  • 线性变换的输出是输入的线性组合。
  • 线性变换不会改变输入数据的线性关系。
  • 线性变换的图形表示通常是直线或平面。

示例
假设我们有一个向量 x = [ x 1 , x 2 ] T \mathbf{x} = [x_1, x_2]^T x=[x1,x2]T,一个线性变换矩阵 A = [ a 11 a 12 a 21 a 22 ] \mathbf{A} = \begin{bmatrix} a_{11} & a_{12} \\ a_{21} & a_{22} \end{bmatrix} A=[a11a21a12a22] 和一个偏置向量 b = [ b 1 , b 2 ] T \mathbf{b} = [b_1, b_2]^T b=[b1,b2]T,线性变换的结果是:

y = A x + b = [ a 11 a 12 a 21 a 22 ] [ x 1 x 2 ] + [ b 1 b 2 ] \mathbf{y} = \mathbf{A} \mathbf{x} + \mathbf{b} = \begin{bmatrix} a_{11} & a_{12} \\ a_{21} & a_{22} \end{bmatrix} \begin{bmatrix} x_1 \\ x_2 \end{bmatrix} + \begin{bmatrix} b_1 \\ b_2 \end{bmatrix} y=Ax+b=[a11a21a12a22][x1x2]+[b1b2]

2. 非线性变换的必要性

现实世界中的数据往往具有复杂的非线性关系。例如,图像中的物体识别、语音识别和自然语言处理等任务,数据的模式通常是高度非线性的。为了捕捉这些复杂的关系,我们需要引入非线性变换。

非线性变换是指一种不保持向量加法和标量乘法的运算。非线性变换可以引入复杂的关系,使得模型能够拟合复杂的数据模式。在神经网络中,非线性变换通常由激活函数实现。

特性

  • 非线性变换的输出不是输入的线性组合。
  • 非线性变换可以改变输入数据的线性关系,捕捉到更复杂的模式。
  • 非线性变换的图形表示通常是曲线或复杂的几何形状。

示例
假设我们有一个输入向量 x = [ x 1 , x 2 ] T \mathbf{x} = [x_1, x_2]^T x=[x1,x2]T 和一个非线性变换函数 f f f,非线性变换的结果是:

y = f ( x ) \mathbf{y} = f(\mathbf{x}) y=f(x)

如果 f f f 是 ReLU 激活函数,那么非线性变换可以表示为:

y = max ⁡ ( 0 , x ) \mathbf{y} = \max(0, \mathbf{x}) y=max(0,x)

3. 激活函数的作用

激活函数的主要作用是引入非线性变换,从而使神经网络能够拟合复杂的数据模式。激活函数在每个神经元的输出上进行非线性变换,使得整个网络能够学习和表示复杂的非线性关系。

在没有激活函数的情况下,神经网络的每一层都只是对上一层的线性变换。无论网络有多少层,这种线性组合的结果仍然是线性的。因此,没有激活函数的深度网络实际上等价于一个线性模型,无法有效地处理复杂的非线性关系。

通过在每一层之间引入激活函数,神经网络能够在每一层进行非线性变换,使得整个网络可以表示高度复杂的非线性函数。这种非线性变换赋予了神经网络强大的表达能力,使其能够拟合复杂的数据模式。

常见的激活函数
1. ReLU(Rectified Linear Unit)

数学表达式
ReLU ( x ) = max ⁡ ( 0 , x ) \text{ReLU}(x) = \max(0, x) ReLU(x)=max(0,x)

优点

  • 计算简单,速度快。
  • 缓解梯度消失问题,尤其在深层网络中表现良好。
  • 稀疏激活:大部分神经元的输出为零,有助于网络的稀疏性。

缺点

  • “神经元死亡”问题:在训练过程中,如果神经元的输出一直为零,那么这个神经元将永远不会激活。
  • 负值部分梯度为零,可能导致部分神经元无法更新。

适用场景

  • 广泛应用于各种深度学习模型,尤其是卷积神经网络(CNN)。

代码示例

python">import torch
import torch.nn as nn# 定义 ReLU 激活函数
relu = nn.ReLU()# 示例输入张量
input_tensor = torch.tensor([-1.0, 0.0, 1.0, 2.0])# 应用 ReLU 激活函数
output_tensor = relu(input_tensor)
print(output_tensor)
2. Sigmoid

数学表达式
Sigmoid ( x ) = 1 1 + e − x \text{Sigmoid}(x) = \frac{1}{1 + e^{-x}} Sigmoid(x)=1+ex1

优点

  • 输出范围在 (0, 1) 之间,适用于输出概率的场景。
  • 平滑且连续,适用于某些需要概率输出的任务。

缺点

  • 容易导致梯度消失问题,尤其在深层网络中。
  • 输出不以零为中心,可能导致训练过程中的梯度不平衡。

适用场景

  • 适用于二分类问题的输出层。

代码示例

python">import torch
import torch.nn as nn# 定义 Sigmoid 激活函数
sigmoid = nn.Sigmoid()# 示例输入张量
input_tensor = torch.tensor([-1.0, 0.0, 1.0, 2.0])# 应用 Sigmoid 激活函数
output_tensor = sigmoid(input_tensor)
print(output_tensor)
3. Tanh(Hyperbolic Tangent)

数学表达式
Tanh ( x ) = e x − e − x e x + e − x \text{Tanh}(x) = \frac{e^x - e^{-x}}{e^x + e^{-x}} Tanh(x)=ex+exexex

优点

  • 输出范围在 (-1, 1) 之间,输出以零为中心,有助于梯度的平衡。
  • 平滑且连续,能够捕捉到输入的细微变化。

缺点

  • 容易导致梯度消失问题,尤其在深层网络中。

适用场景

  • 适用于需要对称输出的场景,如生成对抗网络(GAN)中的生成器。

代码示例

python">import torch
import torch.nn as nn# 定义 Tanh 激活函数
tanh = nn.Tanh()# 示例输入张量
input_tensor = torch.tensor([-1.0, 0.0, 1.0, 2.0])# 应用 Tanh 激活函数
output_tensor = tanh(input_tensor)
print(output_tensor)
4. LeakyReLU

数学表达式
LeakyReLU ( x ) = { x if  x ≥ 0 α x if  x < 0 \text{LeakyReLU}(x) = \begin{cases} x & \text{if } x \geq 0 \\ \alpha x & \text{if } x < 0 \end{cases} LeakyReLU(x)={xαxif x0if x<0

其中, α \alpha α 是一个小的常数,通常取值为 0.01。

优点

  • 缓解了 ReLU 的“神经元死亡”问题。
  • 保持了 ReLU 的大部分优点,如计算简单和稀疏激活。

缺点

  • 需要额外的超参数 α \alpha α,可能需要进行调优。

适用场景

  • 适用于需要避免“神经元死亡”问题的场景。

代码示例

python">import torch
import torch.nn as nn# 定义 LeakyReLU 激活函数,负斜率为 0.01
leaky_relu = nn.LeakyReLU(negative_slope=0.01)# 示例输入张量
input_tensor = torch.tensor([-1.0, 0.0, 1.0, 2.0])# 应用 LeakyReLU 激活函数
output_tensor = leaky_relu(input_tensor)
print(output_tensor)
激活函数的比较
特性ReLUSigmoidTanhLeakyReLU
数学表达式 max ⁡ ( 0 , x ) \max(0, x) max(0,x) 1 1 + e − x \frac{1}{1 + e^{-x}} 1+ex1 e x − e − x e x + e − x \frac{e^x - e^{-x}}{e^x + e^{-x}} ex+exexex { x if  x ≥ 0 α x if  x < 0 \begin{cases} x & \text{if } x \geq 0 \\ \alpha x & \text{if } x < 0 \end{cases} {xαxif x0if x<0
输出范围 [ 0 , ∞ ) [0, \infty) [0,) ( 0 , 1 ) (0, 1) (0,1) ( − 1 , 1 ) (-1, 1) (1,1) ( − ∞ , ∞ ) (-\infty, \infty) (,)
优点计算简单,缓解梯度消失问题输出范围固定,适合概率输出输出以零为中心,梯度平衡缓解“神经元死亡”问题
缺点“神经元死亡”问题梯度消失,输出不以零为中心梯度消失需要调优超参数 α \alpha α
适用场景广泛应用于各种模型二分类问题的输出层对称输出的场景避免“神经元死亡”的场景

请添加图片描述

激活函数的经典应用示例

激活函数在深度学习中的应用非常广泛。下面介绍几个经典的应用示例,包括卷积神经网络(CNN)、循环神经网络(RNN)、生成对抗网络(GAN)和全连接神经网络(FCNN)中的激活函数应用。

1. 卷积神经网络(CNN)

卷积神经网络广泛应用于图像分类、目标检测等任务中。ReLU 激活函数是 CNN 中最常用的激活函数。

示例:使用 ReLU 激活函数的简单 CNN

python">import torch
import torch.nn as nn
import torch.nn.functional as Fclass SimpleCNN(nn.Module):def __init__(self):super(SimpleCNN, self).__init__()self.conv1 = nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3, stride=1, padding=1)self.conv2 = nn.Conv2d(in_channels=32, out_channels=64, kernel_size=3, stride=1, padding=1)self.fc1 = nn.Linear(in_features=64*7*7, out_features=128)self.fc2 = nn.Linear(in_features=128, out_features=10)def forward(self, x):x = F.relu(self.conv1(x))x = F.max_pool2d(x, 2)x = F.relu(self.conv2(x))x = F.max_pool2d(x, 2)x = x.view(-1, 64*7*7)x = F.relu(self.fc1(x))x = self.fc2(x)return x# 创建模型实例
model = SimpleCNN()
print(model)
2. 循环神经网络(RNN)

循环神经网络广泛应用于序列数据,如自然语言处理和时间序列预测。Tanh 和 Sigmoid 激活函数常用于 RNN 的隐藏层和输出层。

示例:使用 Tanh 和 Sigmoid 激活函数的简单 RNN

python">import torch
import torch.nn as nnclass SimpleRNN(nn.Module):def __init__(self, input_size, hidden_size, output_size):super(SimpleRNN, self).__init__()self.hidden_size = hidden_sizeself.i2h = nn.Linear(input_size + hidden_size, hidden_size)self.i2o = nn.Linear(input_size + hidden_size, output_size)self.sigmoid = nn.Sigmoid()self.tanh = nn.Tanh()def forward(self, input, hidden):combined = torch.cat((input, hidden), 1)hidden = self.tanh(self.i2h(combined))output = self.sigmoid(self.i2o(combined))return output, hiddendef init_hidden(self):return torch.zeros(1, self.hidden_size)# 创建模型实例
input_size = 10
hidden_size = 20
output_size = 1
model = SimpleRNN(input_size, hidden_size, output_size)
print(model)
3. 生成对抗网络(GAN)

生成对抗网络由生成器和判别器组成,用于生成高质量的图像。生成器通常使用 Tanh 激活函数,而判别器使用 LeakyReLU 激活函数。

示例:使用 Tanh 和 LeakyReLU 激活函数的简单 GAN

python">import torch
import torch.nn as nnclass Generator(nn.Module):def __init__(self, input_size, output_size):super(Generator, self).__init__()self.fc1 = nn.Linear(input_size, 128)self.fc2 = nn.Linear(128, 256)self.fc3 = nn.Linear(256, output_size)self.tanh = nn.Tanh()def forward(self, x):x = F.relu(self.fc1(x))x = F.relu(self.fc2(x))x = self.tanh(self.fc3(x))return xclass Discriminator(nn.Module):def __init__(self, input_size):super(Discriminator, self).__init__()self.fc1 = nn.Linear(input_size, 256)self.fc2 = nn.Linear(256, 128)self.fc3 = nn.Linear(128, 1)self.leaky_relu = nn.LeakyReLU(0.2)self.sigmoid = nn.Sigmoid()def forward(self, x):x = self.leaky_relu(self.fc1(x))x = self.leaky_relu(self.fc2(x))x = self.sigmoid(self.fc3(x))return x# 创建生成器和判别器实例
input_size = 100
output_size = 28*28
generator = Generator(input_size, output_size)
discriminator = Discriminator(output_size)
print(generator)
print(discriminator)
4. 全连接神经网络(FCNN)

全连接神经网络广泛应用于各种分类和回归任务中。不同的激活函数可以在不同的层中使用,具体取决于任务的需求。

示例:使用 ReLU 和 Sigmoid 激活函数的简单 FCNN

python">import torch
import torch.nn as nnclass SimpleFCNN(nn.Module):def __init__(self, input_size, hidden_size, output_size):super(SimpleFCNN, self).__init__()self.fc1 = nn.Linear(input_size, hidden_size)self.fc2 = nn.Linear(hidden_size, hidden_size)self.fc3 = nn.Linear(hidden_size, output_size)self.relu = nn.ReLU()self.sigmoid = nn.Sigmoid()def forward(self, x):x = self.relu(self.fc1(x))x = self.relu(self.fc2(x))x = self.sigmoid(self.fc3(x))return x# 创建模型实例
input_size = 784  # 28x28 图像展平后的尺寸
hidden_size = 128
output_size = 10  # 10 个类别
model = SimpleFCNN(input_size, hidden_size, output_size)
print(model)

线性变换与非线性变换在神经网络中的应用

线性变换在神经网络中的应用

线性变换在神经网络中的应用主要体现在每一层的加权求和操作。对于一个输入向量 x \mathbf{x} x 和权重矩阵 W \mathbf{W} W,线性变换的输出 z \mathbf{z} z 可以表示为:

z = W x + b \mathbf{z} = \mathbf{W} \mathbf{x} + \mathbf{b} z=Wx+b

非线性变换在神经网络中的应用

非线性变换在神经网络中的应用主要体现在激活函数的使用。激活函数对每一个神经元的输出进行非线性变换,使得整个网络能够表示复杂的非线性关系。

示例
假设我们有一个简单的前馈神经网络,包含一个输入层、一个隐藏层和一个输出层。隐藏层的输出 h \mathbf{h} h 可以表示为:

h = f ( W 1 x + b 1 ) \mathbf{h} = f(\mathbf{W}_1 \mathbf{x} + \mathbf{b}_1) h=f(W1x+b1)

其中, W 1 \mathbf{W}_1 W1 是输入层到隐藏层的权重矩阵, b 1 \mathbf{b}_1 b1 是偏置向量, f f f 是激活函数(如 ReLU)。

输出层的输出 y \mathbf{y} y 可以表示为:

y = g ( W 2 h + b 2 ) \mathbf{y} = g(\mathbf{W}_2 \mathbf{h} + \mathbf{b}_2) y=g(W2h+b2)

其中, W 2 \mathbf{W}_2 W2 是隐藏层到输出层的权重矩阵, b 2 \mathbf{b}_2 b2 是偏置向量, g g g 是激活函数(如 Sigmoid)。

多次函数与神经网络中的非线性变换

多次函数(多项式函数)确实是非线性的,它们可以表示为变量的多次幂及其线性组合的形式。例如,一个二次函数可以表示为:

y = a x 2 + b x + c y = ax^2 + bx + c y=ax2+bx+c

尽管多次函数是非线性的,但在神经网络中并不常用来实现非线性变换。下面我们详细讨论为什么在神经网络中更常用激活函数(如 ReLU、Sigmoid、Tanh 等)来实现非线性,而不是多次函数。

多次函数的局限性
  1. 计算复杂度
    多次函数的计算复杂度较高,尤其是高次多项式。每个神经元需要计算输入的多次幂,这在计算上会非常耗时,尤其是对于大规模神经网络。

  2. 梯度爆炸和梯度消失
    多次函数的导数是幂函数的形式,高次幂函数的导数在输入较大或较小时会导致梯度爆炸或梯度消失。这使得训练深度神经网络变得非常困难。

  3. 参数量和过拟合
    多次函数需要更多的参数来表示复杂的非线性关系。这增加了模型的复杂度,容易导致过拟合,尤其是在训练数据量较少的情况下。

  4. 表达能力有限
    尽管多次函数可以表示某些非线性关系,但它们的表达能力在高维空间中受到限制。激活函数如 ReLU、Sigmoid 和 Tanh 可以通过简单的非线性变换实现更强的表达能力,适用于更广泛的非线性模式。

为什么选择常用的激活函数
  1. 计算简单
    常用的激活函数(如 ReLU、Sigmoid、Tanh)计算简单,计算开销较低,适合大规模神经网络的训练和推理。

  2. 缓解梯度消失和梯度爆炸
    激活函数如 ReLU 在输入大于 0 时的导数恒为 1,有效缓解了梯度消失问题。LeakyReLU 等变种激活函数通过在负值区域引入小斜率,进一步缓解了梯度消失问题。

  3. 通用性强
    常用的激活函数在各种任务和网络结构中表现良好,具有广泛的适用性。它们能够通过简单的非线性变换实现复杂的非线性关系,增强神经网络的表达能力。

  4. 经验验证
    大量的研究和实践表明,常用的激活函数在训练深度神经网络时表现出色,能够有效提升模型的性能和稳定性。

结论

激活函数在深度学习模型中起着关键作用,通过引入非线性,使得模型能够更好地拟合复杂的数据模式。不同的激活函数适用于不同的任务和网络结构,选择合适的激活函数可以显著提升模型的性能。本文详细介绍了 ReLU、Sigmoid、Tanh 和 LeakyReLU 激活函数的作用、优缺点及其经典应用示例,希望能帮助读者更好地理解和应用这些激活函数。

线性变换和非线性变换在神经网络中扮演着不同但互补的角色。线性变换通过权重矩阵和偏置向量实现输入的加权求和,而非线性变换通过激活函数引入非线性,使得神经网络能够拟合复杂的数据模式。理解这两种变换的区别和应用,对于构建和优化神经网络至关重要。

尽管多次函数是非线性的,但由于其计算复杂度高、容易导致梯度爆炸或梯度消失、参数量大且容易过拟合等问题,它们在神经网络中并不常用。相反,常用的激活函数如 ReLU、Sigmoid 和 Tanh 计算简单、能够有效缓解梯度问题且具有强大的表达能力,因此在深度学习中得到了广泛应用。理解这些激活函数的优缺点和适用场景,有助于构建和优化高效的深度学习模型。

PyTorch概述
Pytorch :张量(Tensor)详解
PyTorch 卷积层详解
PyTorch 全连接层(Fully Connected Layer)详解
PyTorch 池化层详解
PyTorch 激活函数及非线性变换详解


http://www.ppmy.cn/devtools/116630.html

相关文章

穿透式薪酬监管,红海云打造“三全”数智化薪酬管理系统

近年来&#xff0c;三项制度改革一直是国企改革的重点方向&#xff0c;推动企业收入分配与激励制度的完善成为重要任务。 &#xff08;央国企薪酬管理改革政策与指导文件&#xff09; 为实现中央企业薪酬管理的有效监管与数据互联互通&#xff0c;国务院国资委在2024年7月31日…

Vue学习记录之八(局部组件,全局组件,递归组件,动态组件)

一、局部组件 在src\components\Card.vue 建立一个文件&#xff0c;代码如下&#xff1a; <template><div class"card"><header><div>标题</div><div>副标题</div></header><section>内容</section>&…

sklearn特征选取之SelectFromModel

sklearn.feature_selection.SelectFromModel 是一种基于模型的重要性权重进行特征选择的工具&#xff0c;允许我们根据学习器的权重或特征重要性自动选择特征。它通过从模型中提取特征的重要性来选择特征&#xff0c;常用于与那些具有 coef_ 或 feature_importances_ 属性的模型…

LeetCode[中等]

给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 思路&#xff1a; 计算链表长度num&#xff0c;num - n就是需要删去结点的索引 其中若删去第一个结点&#xff0c;返回head.next; /*** Definition for singly-linked list.* public …

电商安全新挑战:筑起数字防御长城,守护业务与数据安全

在当今这个数字化时代&#xff0c;电商行业正以前所未有的速度发展&#xff0c;大数据、人工智能等技术的融入不仅重塑了消费模式&#xff0c;更激发了行业新的增长点。然而&#xff0c;这片繁荣景象之下&#xff0c;隐藏着一个不容忽视的暗流——网络安全威胁。从数据泄露到恶…

Spring Boot框架在高校心理辅导中的实践

2 相关技术简介 2.1Java技术 Java是一种非常常用的编程语言&#xff0c;在全球编程语言排行版上总是前三。在方兴未艾的计算机技术发展历程中&#xff0c;Java的身影无处不在&#xff0c;并且拥有旺盛的生命力。Java的跨平台能力十分强大&#xff0c;只需一次编译&#xff0c;任…

npm install --force or --legacy-peer-deps

这个命令中的 --force 和 --legacy-peer-deps 是用于控制包管理器&#xff08;如 npm 或 yarn&#xff09;在安装依赖时的行为的选项。 --force --force 选项通常用于强制包管理器执行某些操作&#xff0c;即使这可能会导致一些不期望的副作用。在安装依赖时&#xff0c;使用…

Spring MVC 基本配置步骤 总结

1.简介 本文记录Spring MVC基本项目拉起配置步骤。 2.步骤 在pom.xml中导入依赖&#xff1a; <dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>6.0.6</version><scope>…