深度学习(Sequential、损失函数与反向传播、优化器、模型的保存和读取)

目录

 

Sequential

一、Sequential模块简介

二、Sequential的使用

1. 导入必要的库

2. 定义模型

3. 实例化模型并测试

​编辑

参数讲解:

损失函数与反向传播

损失函数

 反向传播

参数介绍:

损失函数:

CrossEntropyLoss(交叉熵损失)

优化器:

参数介绍:

现有网络模型的使用及修改

加载VGG16模型

修改模型结构

打印模型结构

注意:

网络模型的保存与读取

保存模型

读取模型


 

Sequential

一、Sequential模块简介

“Sequential”是PyTorch中的一个容器,用于按顺序包含一系列子模块。

二、Sequential的使用

1. 导入必要的库

首先,需要导入PyTorch及其相关的模块:

 import torch
 import torch.nn as nn
 from torch.nn import Conv2d, MaxPool2d, Flatten, Linear, Sequential

2. 定义模型

接下来,可以使用Sequential来定义模型。以下是一个简单的卷积神经网络(CNN)的例子,该网络用于处理图像数据:

 
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.model1 = 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),
            Flatten(),
            Linear(1024, 64), 
            Linear(64, 10))

    def forward(self, x):
        x = self.model1(x)
        return x

3. 实例化模型并测试

最后,可以实例化模型并传入一些随机数据来测试其输出:

 # 实例化模型
 
tudui = Tudui()
print(tudui)
input = torch.ones((64, 3, 32, 32))
output = tudui(input)
print(output.shape)

writer = SummaryWriter('logs_seq')
writer.add_graph(tudui,input)
writer.close()

5ffa463f5fe44268b179d5eed1339bbd.png

注意:padding理解:如果不padding,5*5的kernel按步长为1走,输出的尺寸就会比之前少4,所以肯定要把这个4用padding补上,所以两边都是2,所以padding就是2。

padding设置成 kernel_size//2 就是保持原通道了=卷积核中心对准边缘。

公式:same padding时,p=(f-1)\2   f是过滤器的尺寸,也是卷积核的尺寸,也就是kernel的大小。

池化:池化的stide默认为kernal_size,padding默认为0

conv2d的stride默认为1,maxpool的才是kernelsize。

参数讲解:

  • 初始化卷积层 (Conv2d):
    • 第一个 Conv2d(3, 32, 5, padding=2): 输入通道数为3(RGB图像),输出通道数为32,卷积核大小为5x5,使用padding=2来保持输入和输出特征图的空间维度不变。
    • 第二个和第三个 Conv2d 类似,但第二个卷积层保持输出通道数为32,第三个卷积层将输出通道数增加到64。
  • 池化层 (MaxPool2d):
    • 在每个卷积层之后,都跟着一个 MaxPool2d(2) 池化层,其核大小为2x2,用于降低特征图的空间维度(高度和宽度减半)。
  • 展平层 (Flatten):
    • 在所有卷积和池化层之后,使用 Flatten 层将多维的输入一维化,以便可以传递给全连接层。
  • 全连接层 (Linear):
    • 第一个 Linear(1024, 64): 输入特征数为1024(64*4*4),输出特征数为64。
    • 第二个 Linear(64, 10): 输入特征数为64,输出特征数为10。
  • Sequential 容器 (self.model1):
    • 将上述所有层封装在 Sequential 容器中,以简化模型的前向传播。
  • forward 方法
    • 定义模型的前向传播逻辑,即数据通过模型的方式。它简单地调用 self.model1(x),其中 x 是输入数据。

损失函数与反向传播

定义模型之后,通常需要指定一个损失函数(Loss Function)来评估模型预测值与真实值之间的差异,并通过反向传播算法来更新模型的权重,以最小化这个损失。

损失函数

均方误差损失(MSELoss)、交叉熵损失(CrossEntropyLoss)。对于分类问题,如果模型的输出层使用了softmax激活函数,则通常使用交叉熵损失。

 

 
import torch
from torch import nn
from torch.nn import L1Loss, MSELoss

inputs = torch.tensor([1,2,3],dtype = torch.float32) 
targets = torch.tensor([1,2,5],dtype = torch.float32)
inputs = torch.reshape(inputs, (1, 1, 1, 3))
targets = torch.reshape(targets,(1, 1, 1, 3))
loss = L1Loss(reduction='sum')
result = loss(inputs, targets)

loss_mse = nn.MSELoss()
result_mse = loss_mse(inputs, targets)

print(result)
print(result_mse)

x = torch.tensor([0.1,0.2,0.3], dtype = torch.float32)
y = torch.tensor([1])
x = torch.reshape(x, (1,3))
loss_cross = nn.CrossEntropyLoss()
result_loss = loss_cross()
print(result_loss)

 反向传播

调用了损失函数的.backward()方法,PyTorch就会自动计算图中所有可训练参数的梯度。

 
import torchvision
from torch import nn
from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

dataset = torchvision.datasets.CIFAR10(root='dataset', train=False, download=True,
                                       transform=torchvision.transforms.ToTensor())
dataloader = DataLoader(dataset, batch_size=1)
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.model1 = 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),
            Flatten(),
            Linear(1024, 64),
            Linear(64, 10))

    def forward(self, x):
        x = self.model1(x)
        return x


tudui = Tudui()
loss = nn.CrossEntropyLoss()

for data in dataloader:
    imgs, targets = data
    outputs = tudui(imgs)
    print(outputs)
    # print(targets)
    result_loss = loss(outputs, targets)
    print(result_loss)# 计算实际输出和目标之间的差距
    result_loss.backward()# 计算图中所有可训练参数的梯度
    print("ok")

e99beb8d6f4445bca94719722bfe4bd9.png

注意:

交叉熵公式的输入值是未经过softmax的,经过softmax之后的输入值进行交叉熵函数和这个表达不一样,但最后得到的值和这个公式差别很小,几乎相等。

-log(x)中的x取值范围是0-1, 那么当x越大,损失也就越小。也就是命中概率大,损失小。

科普:反向传播意思就是,尝试如何调整网络过程中的参数才会导致最终的loss变小(因为是从loss开始推导参数,和网络的顺序相反,所以叫反向传播),以及梯度(gradient)的理解可以直接当成“斜率”              反向传播是计算梯度下降的一种方式。

经过softmax之后,概率之和为1,x[class]表示想要预测类的概率,所以x[class]越大,交叉熵越小,表示越准确。

参数介绍:

损失函数:

  1. L1Loss(L1范数损失)
    • 计算输入和目标之间的绝对差值的平均值(当reduction='mean'时,默认设置),或者它们的总和(reduction='sum')。
    • 适用于回归问题,它衡量的是预测值与实际值之间的绝对距离。
  2. MSELoss(均方误差损失)
    • 计算输入和目标之间的平方差的平均值。
    • 同样适用于回归问题,但它对较大的误差给予更大的惩罚。

CrossEntropyLoss(交叉熵损失)

  • 用途:主要用于分类问题,特别是当输出层使用softmax激活函数时。
  • 输入要求
    • logits(网络原始输出):未经softmax处理的分数,形状通常为[batch_size, num_classes]
    • targets(真实标签):每个样本的类别索引,形状通常为[batch_size]

优化器:

用于更新神经网络的权重,以减少损失函数的值。

损失函数衡量了模型的预测值与真实值之间的差异,而优化器的目标则是通过调整模型的权重和偏置来最小化这个差异,从而提高模型的准确性和性能。

  
 
import torch
import torchvision
from torch import nn
from torch.nn import Sequential, Conv2d, MaxPool2d, Flatten, Linear
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter

dataset = torchvision.datasets.CIFAR10(root='dataset', train=False, download=True,
                                       transform=torchvision.transforms.ToTensor())
dataloader = DataLoader(dataset, batch_size=1)
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.model1 = 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),
            Flatten(),
            Linear(1024, 64),
            Linear(64, 10))

    def forward(self, x):
        x = self.model1(x)
        return x


tudui = Tudui()
loss = nn.CrossEntropyLoss()
optim = torch.optim.SGD(tudui.parameters(), lr=0.01)
for epoch in range(20):
    running_loss = 0.0
    for data in dataloader:
        imgs, targets = data
        outputs = tudui(imgs)
        result_loss = loss(outputs, targets)
        optim.zero_grad()
        result_loss.backward()
        optim.step()
        print(result_loss)
        running_loss +=result_loss
        print(running_loss)

参数介绍

  • nn.CrossEntropyLoss: 用于多分类问题的交叉熵损失。它结合了nn.LogSoftmax()nn.NLLLoss()在单个类中。
  • torch.optim.SGD: 随机梯度下降优化器,用于更新网络权重以最小化损失函数。
    • lr=0.01: 学习率,控制权重更新的步长。
    • tudui.parameters():这个方法返回了一个包含 Tudui 模型中所有可训练参数的迭代器。
  • 在每个epoch中,遍历数据加载器提供的所有样本。
  • 对于每个样本,执行前向传播计算输出,计算损失,执行反向传播计算梯度,更新权重。
  • optim.zero_grad(): 清除过往梯度。
  • result_loss.backward(): 计算当前梯度。
  • optim.step(): 根据梯度更新网络权重。

注意:

rho是人为设定的一个被乘数,episilon是一个保证分母不为0的很小值。

loss函数在其中只是起到了一个提供梯度的作用,而这个梯度就藏在optim中你对optim进行step操作时,step就会把它自身反向传播后的结果用进去。

现有网络模型的使用及修改

加载VGG16模型

  1. 加载具有默认预训练权重的VGG16模型

     vgg16_true = models.vgg16(weights=VGG16_Weights.DEFAULT)
  2. 加载无预训练权重的VGG16模型

     vgg16_false = models.vgg16(weights=None)

修改模型结构

在将VGG16模型用于不同的数据集(CIFAR10,它只有10个类别)时,你需要修改模型的分类器部分,以适应新的类别数。

  1. 修改vgg16_true的分类器

     vgg16_true.classifier.add_module('add_linear', nn.Linear(1000, 10))

    通过添加一个额外的全连接层来修改模型。

  2. 修改vgg16_true的分类器

     # 用三个全连接层替换原始的分类器
     new_classifier = nn.Sequential(
     nn.Linear(512 * 7 * 7, 4096),
     nn.ReLU(True),
     nn.Dropout(),
     nn.Linear(4096, 4096),
     nn.ReLU(True),
     nn.Dropout(),
     nn.Linear(4096, 10) # CIFAR10有10个类别
     )
     vgg16_true.classifier = new_classifier
  3. 修改vgg16_false的分类器

     vgg16_false.classifier[6] = nn.Linear(4096, 10)

    直接替换classifier中的最后一个线性层。特征图的大小与新的全连接层兼容。

打印模型结构

 print(vgg16_true)
 print(vgg16_false)

注意:

  • 当修改模型以用于新的数据集时,如何根据输入特征图的大小来调整全连接层的输入维度。
  • 加载CIFAR10数据集时,需要调整图像的大小和归一化参数,以匹配VGG16模型训练时使用的设置(CIFAR10通常不需要调整,因为CIFAR10的图像尺寸较小)。

网络模型的保存与读取

保存模型

保存模型的状态字典:

 
torch.save(vgg16.state_dict(),"vgg16_method2.pth")

保存整个模型

 torch.save(vgg16, "vgg16_method1.pth")

陷阱:

 
#陷阱
class Tudui(nn.Module):
    def __init__(self):
        super(Tudui, self).__init__()
        self.conv1 = nn.Conv2d(3, 64, kernel_size=3)

    def forward(self, x):
        x = self.conv1(x)
        return x

tudui =Tudui()
torch.save(tudui,"tudui_method1.pth")

读取模型

 import torch
 import torchvision.models as models
  
 # 实例化一个VGG16模型,不加载预训练权重
 vgg16 = models.vgg16(weights=None)
  
 # 加载状态字典
 vgg16.load_state_dict(torch.load(r"D:\pycharm\深度学习\learn_torch\tensorboard\vgg16_method2.pth"))
  
 # 打印模型结构(打印结构,不会显示参数值)
 print(vgg16)
  
 # 如果需要设置为评估模式
 vgg16.eval()

如果保存了整个模型,可以这样加载:

 import torch
  
 # 加载整个模型
 model = torch.load(r"D:\pycharm\深度学习\learn_torch\tensorboard\vgg16_method1.pth")
 print(model) 
  
 # 如果需要设置为评估模式
 model.eval()

陷阱:

 
# 陷阱
model3 = model_save.torch.load(r"D:\pycharm\深度学习\learn_torch\tensorboard\tudui_method1.pth")
print(model3)

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值