11.26 深度学习-激活函数
# 激活函数的作用是在隐藏层引入非线性,使得神经网络能够学习和表示复杂的函数关系,使网络具备**非线性能力**,增强其表达能力。
# 没有激活函数的话 每次神经元做的都是线性变换 (矩阵相乘)换为图像就是一直在旋转 放大 缩小 这样就始终相当于 一层
# 常见激活函数
# 激活函数通过引入非线性来增强神经网络的表达能力,对于解决线性模型的局限性至关重要。由于反向传播算法(BP)用于更新网络参数,因此激活函数必须是可微的,也就是说能够求导的。
# sigmoid 常用于二分类 输出层
# Sigmoid激活函数是一种常见的非线性激活函数,特别是在早期神经网络中应用广泛。它将输入映射到0到1之间的值,因此非常适合处理概率问题。
# 表达式 f(x) = \sigma(x) = \frac{1}{1 + e^{-x}}
# 定义域 R 值域 (0,1) 比较适用于概率事件
# 可以求导
# 函数图像
# 缺点
# - 梯度消失: 两端变化慢 梯度更新不了一点
# - 在输入非常大或非常小时,Sigmoid函数的梯度会变得非常小,接近于0。这导致在反向传播过程中,梯度逐渐衰减。
# - 最终使得早期层的权重更新非常缓慢,进而导致训练速度变慢甚至停滞。
# - 信息丢失:输入100和输入10000经过sigmoid的激活值几乎都是等于 1 的,但是输入的数据却相差 100 倍。
# - 计算成本高: 由于涉及指数运算,Sigmoid的计算比ReLU等函数更复杂,尽管差异并不显著
import torch
import torch.nn.functional as F
import torch.nn as nn
def demo1():
x=torch.linspace(10,20,100)
# torch.sigmoid() 使用sigmoid函数进行变换
y=torch.sigmoid(x)
# 双曲正切 隐藏层
# tanh(双曲正切)是一种常见的非线性激活函数,常用于神经网络的隐藏层。tanh 函数也是一种S形曲线,输出范围为$$(−1,1)$$。
# 值域(-1,1) 图像跟sig很像 不过是0中心
# 1. 输出范围: 将输入映射到$$(-1, 1)$$之间,因此输出是零中心的。相比于Sigmoid函数,这种零中心化的输出有助于 加速收敛。
# 2. 对称性 : Tanh函数关于原点对称,因此在输入为0时,输出也为0。这种对称性有助于在训练神经网络时使数据更平衡。
# 3. 平滑性: Tanh函数在整个输入范围内都是连续且可微的,这使其非常适合于使用梯度下降法进行优化。
# 1. 梯度消失: 虽然一定程度上改善了梯度消失问题,但在输入值非常大或非常小时导数还是非常小,这在深层网络中仍然是个问题。 两端变化慢 梯度更新不了一点
# 2. 计算成本: 由于涉及指数运算,Tanh的计算成本还是略高,尽管差异不大。
def demo2():
x=torch.linspace(10,20,100)
# torch.tanh() 使用tanh函数进行变换
y=torch.tanh(x)
# ReLU(Rectified Linear Unit)是深度学习中最常用的激活函数之一,它的全称是**修正线性单元**。ReLU 激活函数的定义非常简单,但在实践中效果非常好。
# 隐藏层
# 有点线性 但不是一条直线
# ReLU(x)= x>0 x
# x<0 0
# 导函数两段
# y大于0 导数为1 小于0 为0
# 计算简单:ReLU 的计算非常简单,只需要对输入进行一次比较运算,这在实际应用中大大加速了神经网络的训练。
# 1. 缓解梯度消失问题:相比于 Sigmoid 和 Tanh 激活函数,ReLU 在正半区的导数恒为 1,这使得深度神经网络在训练过程中可以更好地传播梯度,不存在饱和问题。
# 2. 稀疏激活:ReLU在输入小于等于 0 时输出为 0,这使得 ReLU 可以在神经网络中引入稀疏性(即一些神经元不被激活),这种稀疏性可以提升网络的泛化能力。
# 神经元死亡:由于$$ReLU$$在$$x≤0$$时输出为$$0$$,如果某个神经元输入值是负,那么该神经元将永远不再激活,成为“死亡”神经元。随着训练的进行,网络中可能会出现大量死亡神经元,从而会降低模型的表达能力。
# 训练的次数多了神经元死的就多了 降低了模型的表达模型
def test006():
# 使用relu()import torch.nn.functional as F 的relu
x = torch.linspace(-20, 20, 1000)
y = F.relu(x)
def test007():
x = torch.linspace(-5, 5, 200)
# 设置leaky_relu的
slope = 0.03
y = F.leaky_relu(x, slope)
# LeakyReLU 对relu的优化
# 当x<0时 给一个值 ax a可以任意设置但不为1 比如0.001
# 保证了神经元没有死亡 小于0时 还是有点斜率
# 缺点 要人为的取调a的值 a调的好不好
# Softmax激活函数通常用于分类问题的**输出层**,它能够将网络的输出转换为概率分布,使得输出的各个类别的概率之和为 1。Softmax 特别适合用于多分类问题。
# 输出是一个全概率公式 输出一组概率 每个概率对应 一个结果的可能概率
# 突出差异:$$Softmax$$会放大差异,使得概率最大的类别的输出值更接近$$1$$,而其他类别更接近$$0$$ 不会出现 两个概率接近的情况
# 缺点
# 数值不稳定性:在计算过程中,如果$$z_i$$的数值过大,$$e^{z_i}$$可能会导致数值溢出。因此在实际应用中,经常会对$$z_i$$进行调整,如减去最大值以确保数值稳定。传入的数据太大 e的多少次方
# 可以对传入数据进行处理 的同时不会影响概率分布
def demo3():
input_tensor = torch.tensor([[-1.0, 2.0, -3.0, 4.0], [-2, 3, -3, 9]])
softmax = nn.Softmax()
output_tensor = softmax(input_tensor) # 输出了一组概率分布数据 和为1
"""
### 3.1 隐藏层
1. 优先选ReLU;
2. 如果ReLU效果不咋地,那么尝试其他激活,如Leaky ReLU等;
3. 使用ReLU时注意神经元死亡问题, 避免出现过多神经元死亡;
4. 不使用sigmoid,尝试使用tanh;
### 3.2 输出层
1. 二分类问题选择sigmoid激活函数;
2. 多分类问题选择softmax激活函数;
3. 回归问题选择identity激活函数;
"""