非线性激活函数
常见的非线性激活函数包括 Sigmoid、ReLU(Rectified Linear Unit)、Tanh(双曲正切函数)等
非线性激活函数在神经网络中的作用是引入非线性变换,从而增加神经网络的表达能力和拟合能力。它们通常被应用在神经元的输出上,用于对输入信号进行非线性映射,使得神经网络能够学习和表示更加复杂的函数关系。他的作用:
-
解决线性不可分问题:线性激活函数(如线性函数)的组合只能产生线性变换,无法处理非线性问题。通过引入非线性激活函数,神经网络可以学习和表示非线性关系,从而解决线性不可分的问题。
-
增加模型的表达能力:非线性激活函数使得神经网络可以逼近任意复杂的函数,从而增加了模型的表达能力,可以更好地拟合数据。
-
提高网络的稳定性:非线性激活函数在输入空间的某些区域具有较小的梯度,这有助于缓解梯度消失和梯度爆炸的问题,提高了网络的稳定性和训练效果
ReLU函数
ReLU(Rectified Linear Unit)作为一种激活函数,主要用于神经网络中的隐藏层。它的功能:
-
引入非线性变换:ReLU函数是一种非线性的激活函数,将输入的加权和进行非线性变换,使得神经网络可以学习和表示复杂的非线性关系。
-
解决梯度消失问题:与一些传统的激活函数(如Sigmoid和Tanh)相比,ReLU函数在正区间的梯度始终为1,这有助于缓解梯度消失的问题,使得在深层神经网络中更容易进行梯度传播和学习。
-
提高网络的稀疏性:当输入值为负时,ReLU函数的输出为0,这意味着一些神经元可能会被激活,而另一些可能不会。这种稀疏性有助于减少模型的复杂度,降低过拟合的风险,并且能够提高网络的泛化能力。
-
计算简单高效:ReLU函数的计算非常简单,只需要比较输入值与0的大小,因此计算速度较快,适用于大规模的神经网络,并且能够有效地降低训练成本。
(模型对数据的拟合能力:一个拥有更强拟合能力的模型可以更准确地捕捉数据中的复杂模式和关系,它能够准确地预测或表示数据中的特征)
下面的代码中,因为输入入张量中包含负值,ReLU 激活函数会将所有负值变为零,因此输出张量中的负值都被截断为零
import torch
import torchvision
from torch import nn
input = torch.tensor([[1, -0.5],
[-1, 3]])
input = torch.reshape(input, (-1, 1, 2, 2))
print(input.shape) # 使输入格式满足要求
class Si(nn.Module):
def __init__(self):
super(Si, self).__init__()
self.relu1 = ReLU() # inplace默认为False
def forward(self, input):
output = self.relu1(input)
return output
si = Si()
output = si(input)
print(output) # 结果会被截断 tensor([[[[1., 0.],
# [0., 3.]]]])
Sigmoid、ReLU
在深度学习中,ReLU函数通常被优先选择用于隐藏层的激活函数,因为它的计算速度快、不存在梯度饱和问题,并且在实践中效果良好。
相比之下,Sigmoid函数更适合用于输出层或者某些特殊需要的情况,比如需要将输出映射到(0, 1)范围内作为概率值时。
Sigmoid的使用
import torch
import torchvision
from torch import nn
from torch.nn import ReLU, Sigmoid
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
input = torch.tensor([[1,-0.5],
[-1,3]])
input = torch.reshape(input,(-1,1,2,2))
print(input.shape)#使输入格式满足要求
dataset = torchvision.datasets.CIFAR10('../data',train=False,download=True,transform=torchvision.transforms.ToTensor())
dataloader = DataLoader(dataset,batch_size=64)
class Si(nn.Module):
def __init__(self):
super(Si, self).__init__()
self.relu1 = ReLU() #inplace默认为False
self.sigmoid1 = Sigmoid() #修改网络
def forward(self,input):
output = self.sigmoid1(input)
return output
si = Si()
step = 0
writer = SummaryWriter('logs')
for data in dataloader:
imgs,targets = data
writer.add_images('input0',imgs,global_step=step)
output = si(imgs)
writer.add_images('output0',output,step)
step = step+1
writer.close()
inplace 表示是否对原位置进行替换,inplace=Ture 表示原地修改输入张量而不是返回一个新的张量,inplace = False,输入值不变,而在输出值上改变
线性层
线性网络图图示
x1,x2...通过不同的表达式的和组成g1,g2...
基础的线性层运用
import torch
import torchvision
from torch import nn
from torch.nn import Linear
from torch.utils.data import DataLoader
dataset = torchvision.datasets.CIFAR10('../data',train=False,transform=torchvision.transforms.ToTensor(),download=True)
dataloader = DataLoader(dataset,batch_size=64,drop_last=True)
class Si(nn.Module):
def __init__(self):
super(Si, self).__init__()
# 创建线性层 (in_features,out_features)
self.linear1 = Linear(196608,10)
def forward(self,input):
output = self.linear1(input)
return output
si = Si()
for data in dataloader:
imgs,targets = data
print(imgs.shape)
# output = torch.reshape(imgs,(1,1,1,-1))
output = torch.flatten(imgs)
print(output.shape)
output = si(output)
print(output.shape)
in_features(输入特征数量):指的是线性层接收的输入特征的数量。
out_features(输出特征数量):指的是线性层产生的输出特征的数量
# 生成随机输入数据
input_data = torch.randn(3, 10) # batch_size=3, input_dim=10 分别表示的输入模型的样本数量,和输入数据的特征数量或者维度
flatten函数 将输入的多维改写成一行
最后 的效果