神经网络—非线性激活
在PyTorch中,非线性激活函数通常用于神经网络的隐藏层,以引入网络的非线性。非线性激活函数在神经网络中的作用主要有两个方面:
1、引入非线性:
线性变换的组合仍然是线性的,如果没有非线性激活函数,多层神经网络将等效于单一的线性变换。非线性激活函数通过对神经元的输出进行非线性变换,使网络能够学习和表示更加复杂的函数关系。这是神经网络能够逼近任意复杂函数的关键。
2、增加网络的表达能力:
非线性激活函数扩展了神经网络的表达能力,使其能够学习和表示更复杂的映射关系。通过引入非线性变换,神经网络可以捕捉数据中的非线性模式、交互和复杂特征,从而提高模型的拟合能力。这对于处理实际复杂任务,如图像分类、语音识别等,非常重要。
在神经网络中,通常将多个线性层(全连接层或卷积层)与非线性激活函数交替使用,形成层次化的表示。以下是一些常用的非线性激活函数:
a、ReLU激活函数:
ReLU是一种简单而有效激活函数,它将所有负数值为零,对正数值保持不变。ReLU的主要优势在于它的计算简单且不容易导致梯度消失问题:
import torch
import torch.nn as nn
# 使用ReLU激活函数
relu = nn.ReLU()
output = relu(input_data)
b、Sigmoid激活函数:
Sigmoid是一种将输入映射到(0,1)范围的激活函数。它通常用于二分类问题,输出可以被解释为概率。
import torch
import torch.nn as nn
# 使用Sigmoid激活函数
sigmoid = nn.Sigmoid()
output = sigmoid(input_data)
c、Tanh激活函数:
Tanh是一种将输入映射到(-1,1)范围的激活函数。它与Sigmoid类似,输出范围更广。
import torch
import torch.nn as nn
# 使用Tanh激活函数
tanh = nn.Tanh()
output = tanh(input_data)
d、Softmax激活函数:
Softmax是一种用于多类别分类问题的激活函数,将输入转换为概率分布。
import torch
import torch.nn as nn
# 使用Softmax激活函数
softmax = nn.Softmax(dim=1)
output = softmax(input_data)
神经网络—线性层
在PyTorch中,线性层也称为全连接层或稠密层,是神经网络中一种基本的层类型。它执行输入特征与权重矩阵的线性变换,并添加偏置,通常用于从输入数据中学习到输出数据的映射,以下是‘torch.nn.Linear'的主要参数和解释:
torch.nn.Linear(in_features, out_features, bias=True)
1、in_features:输入特征的数量。即输入张量的大小(第一维的大小)。
2、out_features:输出特征的数量。即线性层的神经元数量,决定了输出张量的大小。
3、bias:决定是否使用偏置。如果设置为’False‘,线性层不包含可学习的偏置项。
线性层的计算过程可以表示为:
out_features=in_features×weights+bias
其中weights是权重矩阵。这个计算过程实现了输入特征与权重的线性组合,并添加了偏执项。这种线性变换是神经网络中最基本的操作之一。以下是一个例子,演示如何使用’torch.nn.Linear‘层:
import torch
import torch.nn as nn
# 定义线性层,输入特征为5,输出特征为3
linear_layer = nn.Linear(in_features=5, out_features=3)
# 输入数据,假设是大小为 (batch_size, 5) 的张量
input_data = torch.randn(10, 5)
# 使用线性层进行前向计算
output = linear_layer(input_data)
sequential的使用
在PyTorch中,Sequential是一个模型容器,用于按顺序组织多个神经网络层。它允许我们将多个层连接在一起,形成一个有序地网络结构。
sequential类可以通过传递一个有序的层列表或使用'.add_module()'方法逐个添加层来构建。下面是一个简单实例:
import torch
import torch.nn as nn
# 定义两个全连接层
layer1 = nn.Linear(10, 5)
layer2 = nn.ReLU()
# 使用Sequential容器组合层
model = nn.Sequential(layer1, layer2)
# 使用add_module()逐个添加层
model = nn.Sequential()
model.add_module('layer1', layer1)
model.add_module('layer2', layer2)
Sequential对象可以像普通的神经网络模型一样进行前向传播。当我们将输入数据传递给Sequential模型时,数据会按照层的顺序依次通过每个层进行计算。
input_data = torch.randn(32, 10) # 输入数据维度为(32, 10)
output = model(input_data) # 通过Sequential模型进行前向传播
在使用Sequential时,需要注意的是,每个层的输入和输出尺寸必须是匹配的。这意味着前一层的输出尺寸必须与后一层的输入尺寸相对应,以确保数据的流动和正确计算。此外,Sequential还可以通过索引访问各个层,以及使用'.named_modules()'方法获取模型中所有层的名称和参数,这为模型的调试和分析提功了便利。
总结来说,PyTorch中的Sequential是一个用于按顺序组合多个神经网络层的容器类。它可以简化模型的构建和前向传播过程,并提供方便的方法来访问和管理模型中的层。
以对数据集cifar10进行分类构建简单的神经网络为例:
CIFAR10的模型结构:
卷积前后尺寸的计算公式:
代码:
from torch import nn
from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential
from torch.utils.tensorboard import SummaryWriter
class My_model1(nn.Module):
def __init__(self):
super().__init__()
# self.conv1=Conv2d(3,32,5,padding=2)
# self.maxpool1=MaxPool2d(2)
# self.conv2=Conv2d(32,32,5,padding=2)
# self.maxpool2=MaxPool2d(2)
# self.conv3=Conv2d(32,64,5,padding=2)
# self.maxpool3=MaxPool2d(2)
# self.flatten=Flatten()
# self.linear1=Linear(1024,64)
# self.linear2=Linear(64,10)
#使用sequential,将以上代码注释掉
self.my_model2=Sequential(
Conv2d(3, 32, 5, padding=2),
MaxPool2d(2),
Conv2d(32, 32, 5, padding=2),
MaxPool2d(2),
Conv2d(32, 64, 5, padding=2),
MaxPool2d(2),
Linear(1024, 64),
Linear(64, 10)
)
def forward(self,x):
# x=self.conv1(x)
# x=self.maxpool1(x)
# x=self.conv2(x)
# x=self.maxpool2(x)
# x=self.conv3(x)
# x=self.maxpool3(x)
# x=self.flatten(x)
# x=self.linear1(x)
# x=self.linear2(x)
#使用sequential,将以上代码注释掉
x=self.my_model2(x)
return x
my_model=My_model1()
print(my_model)
#可视化方法
writer=SummaryWriter("../logs_sequential")
writer.add_graph(my_model,input)
writer.close()
损失函数
在PyTorch中,损失函数用于衡量模型预测结果与真实标签之间的差异,是优化过程中的关键组成部分。PyTorch提供了丰富的损失函数,适用于不同类型的任务,以下是一些常见的损失函数及其用途:
1、绝对值损失函数:
绝对值损失函数通常用于回归任务,度量模型输出与目标之间的绝对差异。在PyTorch中,可以使用'torch.nn.L1Loss'实现绝对值损失。
尺寸要求:
以下是一个使用绝对值损失函数的简单示例:
import torch
import torch.nn as nn
# 模型输出
output = torch.randn(3, requires_grad=True)
# 目标值
target = torch.randn(3)
# 定义绝对值损失
criterion = nn.L1Loss()
# 计算损失
loss = criterion(output, target)
# 打印损失
print(loss.item())
在这个例子中,output是模型的输出,target是目标值。通过'nn.L1Loss()'定义了绝对值损失函数,然后计算了模型输出与目标之间的绝对值损失。注意:绝对值损失对异常值不敏感,因为它使用了绝对值,而不是平方,如果希望模型对异常值更加敏感可以考虑使用均方误差损失。
2、均方误差损失:
用于回归任务,度量模型输出与目标之间的平方差的平均值。
尺寸要求:
简单示例:
import torch
import torch.nn as nn
# 模型输出
output = torch.randn(3, requires_grad=True)
# 目标值
target = torch.randn(3)
# 定义均方误差损失
criterion = nn.MSELoss()
# 计算损失
loss = criterion(output, target)
# 打印损失
print(loss.item())
3、交叉熵损失:
用于多分类任务,结合了LogSoftmax 和 NLL Loss。
尺寸要求:
简单示例:
import torch
import torch.nn as nn
# 模型输出(类别概率)
output = torch.randn(3, 5, requires_grad=True)
# 目标类别
target = torch.randint(5, (3,))
# 定义交叉熵损失
criterion = nn.CrossEntropyLoss()
# 计算损失
loss = criterion(output, target)
# 打印损失
print(loss.item())
反向传播
反向传播是深度学习中用于计算梯度并更新模型参数的关键算法。在pytorch中,反向传播通过计算图的链式法则来实现,自动计算梯度并更新模型参数。
步骤:
1、前向传播:将输入数据通过模型进行前向计算,得到模型的预测输出。
2、计算损失:将模型的输出与目标值进行比较,计算损失函数的值。
3、反向传播:使用损失函数计算模型参数关于损失的梯度。
4、更新模型参数:使用梯度下降等优化算法,根据梯度更新模型参数。
示例代码:
import torch
import torch.nn as nn
# 定义一个简单的线性模型
class SimpleModel(nn.Module):
def __init__(self):
super(SimpleModel, self).__init__()
self.linear = nn.Linear(1, 1)
def forward(self, x):
return self.linear(x)
# 创建模型实例和损失函数实例
model = SimpleModel()
criterion = nn.MSELoss()
# 随机生成输入数据和目标数据
input_data = torch.randn(5, 1, requires_grad=True)
target_data = torch.randn(5, 1)
# 前向传播
output = model(input_data)
# 计算损失
loss = criterion(output, target_data)
# 反向传播
loss.backward()
# 查看模型参数的梯度
print("模型参数的梯度:", model.linear.weight.grad)
# 手动更新模型参数,通常优化器会自动完成这个步骤
learning_rate = 0.01
with torch.no_grad():
model.linear.weight -= learning_rate * model.linear.weight.grad
# 清零梯度,以便下一次反向传播
model.zero_grad()
# 查看更新后的模型参数
print("更新后的模型参数:", model.linear.weight)
优化器
在PyTorch中,优化器用于自动更新神经网络模型的参数,以最小化损失函数。优化器使用模型参数的梯度信息,通过梯度下降等算法来调整参数。以下是一些常用的优化器及其示例代码:
1、梯度下降优化器:
'torch.optim.SGD'
import torch
import torch.nn as nn
import torch.optim as optim
# 定义一个简单的线性模型
class SimpleModel(nn.Module):
def __init__(self):
super(SimpleModel, self).__init__()
self.linear = nn.Linear(1, 1)
def forward(self, x):
return self.linear(x)
# 创建模型实例和损失函数实例
model = SimpleModel()
criterion = nn.MSELoss()
# 创建梯度下降优化器
optimizer = optim.SGD(model.parameters(), lr=0.01)
# 随机生成输入数据和目标数据
input_data = torch.randn(5, 1, requires_grad=True)
target_data = torch.randn(5, 1)
# 迭代训练
for epoch in range(100):
# 前向传播
output = model(input_data)
# 计算损失
loss = criterion(output, target_data)
# 反向传播
optimizer.zero_grad() # 清零梯度
loss.backward() # 计算梯度
optimizer.step() # 更新模型参数
# 打印每10轮迭代的损失
if epoch % 10 == 0:
print(f"Epoch {epoch}, Loss: {loss.item()}")
# 查看训练后的模型参数
print("训练后的模型参数:", model.linear.weight)
2、Adm优化器:
'torch.optim.Adm'
import torch
import torch.nn as nn
import torch.optim as optim
# 定义一个简单的线性模型
class SimpleModel(nn.Module):
def __init__(self):
super(SimpleModel, self).__init__()
self.linear = nn.Linear(1, 1)
def forward(self, x):
return self.linear(x)
# 创建模型实例和损失函数实例
model = SimpleModel()
criterion = nn.MSELoss()
# 创建Adam优化器
optimizer = optim.Adam(model.parameters(), lr=0.01)
# 随机生成输入数据和目标数据
input_data = torch.randn(5, 1, requires_grad=True)
target_data = torch.randn(5, 1)
# 迭代训练
for epoch in range(100):
# 前向传播
output = model(input_data)
# 计算损失
loss = criterion(output, target_data)
# 反向传播
optimizer.zero_grad() # 清零梯度
loss.backward() # 计算梯度
optimizer.step() # 更新模型参数
# 打印每10轮迭代的损失
if epoch % 10 == 0:
print(f"Epoch {epoch}, Loss: {loss.item()}")
# 查看训练后的模型参数
print("训练后的模型参数:", model.linear.weight)