1.ReLU
ReLU函数的数学表达式为:ReLU(x)=max(0,x)。这意味着,当输入x为正时,ReLU函数的输出就是x本身;当输入x为负或0时,ReLU函数的输出为0。
数学表达式
数学图像
特性与优势
- 非线性特性:尽管ReLU函数在正数区间内是线性的,但由于它在负数区间内输出为0,因此整体上表现为非线性函数。这种非线性特性使得神经网络能够学习和模拟复杂的函数关系。
- 计算简单高效:ReLU函数的计算只涉及简单的比较和阈值判断,不涉及任何指数运算,因此计算量小,适合大规模神经网络。
- 加速收敛:在实际应用中,使用ReLU激活函数的神经网络往往比使用其他激活函数的网络收敛更快。这是因为ReLU在正区间内的梯度恒为1,有利于梯度下降法在参数空间中快速移动。
- 缓解梯度消失问题:传统的激活函数(如Sigmoid和Tanh)在输入值较大或较小时,梯度可能会非常接近0,导致梯度在多层网络中反向传播时逐渐消失。而ReLU函数在正输入值上保持恒定的梯度,有效避免了这一问题。
- 稀疏激活:ReLU函数在输入小于0时直接输出0,这种特性可以导致网络中的隐藏层神经元只有一部分被激活,产生稀疏激活现象。稀疏性可以提高网络的表达能力并减少过拟合的风险。
局限性
尽管ReLU函数具有诸多优势,但它也存在一些局限性:
- “死亡ReLU”问题:在训练过程中,如果某个神经元的权重或偏置使得输出始终为负数,则该神经元输出始终为0,无法更新梯度,导致神经元“死亡”,永远无法激活。这会影响模型的表示能力。
- 非零中心性:ReLU函数的输出是非负的,这意味着其输出不是以零为中心的。这可能会影响梯度下降的效率,因为关于权重的梯度在反向传播过程中可能总是正的或总是负的。
2.Sigmoid
Sigmoid函数,也称为逻辑函数或S型函数,其数学表达式为:f(x) = 1 / (1 + e^(-x))。其中,e是自然对数的底数,x是函数的输入,通常是神经元输入的加权和。Sigmoid函数可以将任何实数输入映射到0和1之间的输出,输出值越接近于1表示神经元激活程度越高,越接近于0表示神经元激活程度越低。
数学表达式
数学图像
特性与优势
- 非线性:Sigmoid函数引入了非线性特性,使得神经网络能够学习和表示复杂的输入输出关系。这是神经网络能够解决非线性问题的关键所在。
- 平滑连续:Sigmoid函数是一个平滑连续的函数,具有良好的可微性。这有利于梯度的计算和反向传播算法的实现,使得神经网络在训练过程中能够稳定地更新权重。
- 输出范围限制:Sigmoid函数的输出范围在0到1之间,可以被看作是一个概率值。这一特性使得Sigmoid函数在二分类问题和输出层的概率预测中常被使用。
局限性
尽管Sigmoid函数具有诸多优势,但它也存在一些局限性:
- 梯度消失问题:在Sigmoid函数的两端(即输入值非常大或非常小时),梯度接近于0。这会导致反向传播时梯度逐渐消失,使得深层网络的训练变得困难。
- 输出非均衡:当输入值较大或较小时,Sigmoid函数的输出接近于0或1,导致输出值分布不均衡。这可能会影响模型的收敛速度和性能。
- 计算开销大:Sigmoid函数涉及指数运算,相对于其他激活函数(如ReLU)来说计算开销较大。在大规模数据和深层网络中,这可能会影响计算效率。
应用场景
- 二分类问题:Sigmoid函数可以将输出值映射到0和1之间,用于表示某个事件发生的概率。因此,它特别适用于二分类问题,如判断图像中是否包含某个目标等。
- 输出层概率预测:在神经网络的输出层中,Sigmoid函数可以用于预测概率分布。例如,在多类别分类问题中,可以使用Sigmoid函数来预测各类别的概率。
- 逻辑回归:Sigmoid函数在逻辑回归中被广泛应用。逻辑回归是一种广义线性回归,通过引入Sigmoid函数将线性回归的输出映射到0和1之间,从而实现对二分类问题的建模和预测。
代码
import torch
import torchvision.datasets
from torch import nn
from torch.nn import MaxPool2d, ReLU, Sigmoid
from torch.utils.data import DataLoader
input = torch.tensor([[1, -0.5],
[-1, 3]])
input = torch.reshape(input, (-1, 1, 2, 2))
print(input.shape)
# dataset = torchvision.datasets.CIFAR10("./dataset", train = False,
# transform = torchvision.transforms.ToTensor(),
# download = True)
# dataloader = DataLoader(dataset, batch_size = 64)
class non_linear(nn.Module) :
def __init__(self) :
super(non_linear, self).__init__()
self.relu1 = ReLU()
self.sigmoid1 = Sigmoid()
def forward(self, input) :
# output = self.relu1(input)
output = self.sigmoid1(input)
return output
non_linear = non_linear()
output = non_linear(input)
print(output)
# for data in dataloader :
# imgs, target = data
# output = non_linear(imgs)
# print(output)