当前位置:   article > 正文

【pytorch深度学习】阶段性总结 ~ 看看自己这两个多礼拜学到些什么东西......_pretrained=true参数什么意思

pretrained=true参数什么意思

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

仔细想了想,这段时间我主要学会了以下几点:
(1)能够看懂网络模型并根据神经网络结构流程图自己写神经网络模型;
(2)学会如何加载官方模型和官方数据集,以及如何自定义数据集和损失函数;
(3)学会如何编写代码训练模型,并根据训练模型进行测试;
(3)学会拆分代码为model、train、test三步写,以及cpu和GPU的切换;
(4)学会运用文心一言来检验报错并修改。

ps: 能看懂,但叫我写还是不会... ...
  • 1

pytorch模型训练常规套路:http://t.csdnimg.cn/Z3H56

一、定义网络结构模型

1998年Yann LeCun在论文"Gradient-Based Learning Applied to Document Recognition"中提出了LeNet5,并在字母识别中取得了很好的效果。LeNet5是首个成功进行多层训练的卷积神经网络【CNN】,它极大的推动了深度学习领域的发展。

以LeNet5网络结构为例定义神经网络模型
在这里插入图片描述
输出大小N = (输入大小W - 卷积核大小F + 2倍填充值大小P)/步长大小S + 1

主要框架:

class LeNet5(nn.Module):
    #初始化网络
    def __init__(self):
        super(LeNet5,self).__init__()
        ... ...
    #向前传递输出
    def forward(self,x):
    	... ...
    	return x
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

完整源码model.py

import torch
from torch import nn

#定义LetNet5网络模型
class LeNet5(nn.Module):
    #初始化网络
    def __init__(self):
        super(LeNet5,self).__init__()
        # 输出大小N = (输入大小W - 卷积核大小F + 2倍填充值大小P)/步长大小S + 1
        # self.c1 = nn.Conv2d(in_channels=1,out_channels=6,kernel_size=5,padding=2)   #卷积 (28-5+2*2)/1 + 1 = 28  输出28X28
        # self.Sigmoid = nn.Sigmoid()     #激活函数 通常会使用其他类型的激活函数,如ReLU(Rectified Linear Unit)和Softmax。
        # self.s2 = nn.AvgPool2d(kernel_size=2,stride=2)      #平均池化
        # self.c3 = nn.Conv2d(in_channels=6,out_channels=16,kernel_size=5)    #(14-5+0)/1 +1 = 10  输出10X10
        # self.s4 = nn.AvgPool2d(kernel_size=2,stride=2)
        # self.c5 = nn.Conv2d(in_channels=16,out_channels=120,kernel_size=5)
        #
        # self.flatten = nn.Flatten()     #展平成一排
        # self.f6 = nn.Linear(120,84)     #全连接层
        # self.output = nn.Linear(84,10)  #输出层

        # 顺序结构写法
        self.model = nn.Sequential(

            # 输出大小N = (输入大小W - 卷积核大小F + 2倍填充值大小P)/步长大小S + 1
            nn.Conv2d(in_channels=1, out_channels=6, kernel_size=5, padding=2),  # 卷积 (28-5+2*2)/1 + 1 = 28  输出28X28
            nn.Sigmoid(),  # 激活函数
            nn.AvgPool2d(kernel_size=2, stride=2),  # 平均池化
            nn.Conv2d(in_channels=6, out_channels=16, kernel_size=5), # (14-5+0)/1 +1 = 10  输出10X10
            nn.AvgPool2d(kernel_size=2, stride=2),
            nn.Conv2d(in_channels=16, out_channels=120, kernel_size=5),

            nn.Flatten(),  # 展平成一排
            nn.Linear(120, 84),  # 全连接层
            nn.Linear(84, 10)  # 输出层
        )
        
	#forward方法 定义模型前向传播的地方,也就是输入数据如何在模型中流动并被处理的
    def forward(self,x):
    	#1、首先将输入x传递给名为c1的卷积层,然后将结果传递给名为Sigmoid的激活函数。输出被赋值回x
        # x = self.Sigmoid(self.c1(x))  
        #2、将x传递给名为s2的池化层。输出再次被赋值回x
        # x = self.s2(x)
        #3、类似第2行,但使用了不同的卷积层(c3)和同样的激活函数(Sigmoid)
        # x = self.Sigmoid(self.c3(x))
        #4、同第3行,但使用了不同的池化层(s4)
        # x = self.s4(x)
        #5、将x传递给名为c5的卷积层或全连接层
        # x = self.c5(x)
        #6、这行代码将x的形状从多维张量展平为一维张量,这在将卷积层的输出传递给全连接层之前是很常见的操作
        # x = self.flatten(x)
        #7、将展平后的x传递给名为f6的全连接层
        # x = self.f6(x)
        #8、将x传递给名为output的输出层。这通常是模型的最后一层,负责产生模型的最终预测
        # x = self.output(x)
        # return x  

        x = self.model(x)  # 使用Squential()简洁很多
        return x  #返回经过模型处理后的输出数据

if __name__ == '__main__':  #只在当前脚本作为主程序运行时被执行,可加可不加
    x = torch.rand([1,1,28,28]) #使用PyTorch的rand函数生成一个随机的张量(tensor)  1批次 、1通道 、28X28
    model = LeNet5()
    y = model(x)  #将前面生成的随机张量x传递给model进行前向传播,得到输出y
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63

在卷积神经网络中,通常在每个卷积层后面都会添加激活函数,以增加模型的非线性特性并提高模型的表达能力。因此,如果有多个卷积层,那么通常会在每个卷积层后面都添加激活函数。

然而,也有一些情况下可能会在不同的卷积层后面共享同一个激活函数,或者在某些特定的网络结构中不使用激活函数。具体的做法取决于模型的结构和需求。

另外,需要注意的是,在添加激活函数时,还需要考虑激活函数的类型和参数设置。不同的激活函数具有不同的特点和适用场景,需要根据具体问题和模型结构进行综合考虑。同时,对于某些激活函数,如sigmoid和tanh,还需要注意对输入进行归一化以防止饱和问题的出现。

以下是一些常见的激活函数及其用途的举例说明:

1.Sigmoid函数:Sigmoid函数将输入映射到0到1的范围内,因此它常常用于二分类问题中。比如,在图像识别任务中,可以使用Sigmoid函数来判断一张图片是否包含某个物体。如果输出接近1,则表示图片包含该物体;如果输出接近0,则表示图片不包含该物体。

2.Tanh函数:Tanh函数将输入映射到-1到1的范围内,它是Sigmoid函数的缩放版本。由于Tanh函数的输出以0为中心,因此它有时比Sigmoid函数更受欢迎。比如在循环神经网络(RNN)中,Tanh函数常常用于隐藏层的激活函数。

3.ReLU函数:ReLU函数是一个分段线性函数,当输入小于0时输出为0,当输入大于0时输出为输入值本身。由于ReLU函数在正值区域内不会出现梯度消失问题,因此它在深度学习中非常受欢迎。比如在卷积神经网络(CNN)中,ReLU函数常常用作卷积层和全连接层的激活函数。

二、加载模型和数据集

1.加载官方模型

加载预训练模型。PyTorch 官方提供了许多预训练模型,可以通过 torchvision.models 模块加载。例如,加载 ResNet-50 模型的代码如下:

import torchvision.models as models  
  
resnet50 = models.resnet50(pretrained=True)
  • 1
  • 2
  • 3

在这个例子中,resnet50 变量将包含一个预训练的 ResNet-50 模型。pretrained=True 参数表示加载预训练权重。

例如:

# 1.加载ResNet50模型
model = torchvision.models.resnet50(pretrained=True) # 加载预训练好的ResNet50模型
#model = torchvision.models.resnet50(weights=None) 

# 2.冻结模型参数
for param in model.parameters():
    param.requires_grad = False
    
# 3.修改最后一层的全连接层
# 假设你的分类任务是10个类别  
num_classes = 10  
model.fc = nn.Linear(model.fc.in_features, num_classes)

model.fc = nn.Sequential(
    nn.Linear(model.fc.in_features, 10),
    nn.Sigmoid()) 

# 4.将模型加载到cpu中
model = model.to('cpu')

criterion = nn.CrossEntropyLoss()  # 交叉熵损失函数
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)  # 优化器

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

model.fc = nn.Linear(model.fc.in_features, num_classes) 这行代码的意思是替换ResNet50模型的最后一层全连接层(fully connected layer),以便适应新的分类任务。

在原始的ResNet50模型中,最后一层全连接层是针对1000个类别的ImageNet数据集训练的,因此输出是1000个神经元。但是,如果你的分类任务只有num_classes个类别(例如10个类别),你就需要修改最后一层全连接层以适应你的任务。

这行代码做了以下几个事情:

1.model.fc:这是原始ResNet50模型的最后一层全连接层。
2.nn.Linear(model.fc.in_features, num_classes):这里创建了一个新的全连接层,输入特征数(in_features)与原始全连接层相同,但输出特征数变为num_classes个神经元。
3.model.fc = ...:这里将新的全连接层赋值给model.fc,从而替换了原始的全连接层。
现在,模型将输出num_classes个值,每个值代表一个类别的概率(通常使用Softmax激活函数将输出转换为概率分布)。这样,模型就可以针对你的特定分类任务进行预测了。

使用模型进行推理或训练。加载模型后,可以使用它进行推理或训练。例如,将一张图像输入模型进行分类的代码如下:

import torchvision.transforms as transforms  
from PIL import Image  
  
# 加载图像并进行预处理  
image = Image.open("image.jpg")  
preprocess = transforms.Compose([  
    transforms.Resize(256),  
    transforms.CenterCrop(224),  
    transforms.ToTensor(),  
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),  
])  
input_tensor = preprocess(image)  
input_batch = input_tensor.unsqueeze(0)  # 将图像转换为批次大小为 1 的张量  
  
# 在模型上运行推理  
output = resnet50(input_batch)  
probabilities = torch.softmax(output, dim=1)  # 将输出转换为概率分布
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

在这个例子中,output 变量将包含模型对输入图像的预测结果。可以根据需要对输出进行处理,例如选择概率最高的类别作为预测结果。

2.加载官方数据集

在 PyTorch 中加载官方数据集非常简单,可以使用 torchvision 库中的 datasets 模块。该模块提供了许多常用数据集的加载方法,例如 MNIST、CIFAR10、ImageNet 等。以下是加载 MNIST 数据集的示例代码:

import torch  
import torchvision  
import torchvision.transforms as transforms  
  
# 定义数据预处理操作  
transform = transforms.Compose([  
    transforms.ToTensor(),  # 将图像转换为 Tensor  
    transforms.Normalize((0.5,), (0.5,))  # 对 Tensor 进行标准化  
])  
  
# 加载训练数据集  
trainset = torchvision.datasets.MNIST(root='./data', train=True, download=True, transform=transform)  
trainloader = torch.utils.data.DataLoader(trainset, batch_size=32, shuffle=True)  
  
# 加载测试数据集  
testset = torchvision.datasets.MNIST(root='./data', train=False, download=True, transform=transform)  
testloader = torch.utils.data.DataLoader(testset, batch_size=32, shuffle=False)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

在这个示例中,我们首先定义了一个数据预处理操作 transform,它将图像转换为 Tensor 并进行标准化。然后,我们使用 torchvision.datasets.MNIST 方法加载 MNIST 数据集,指定数据集的根目录、是否下载数据集、是否进行训练以及数据预处理操作。最后,我们使用 torch.utils.data.DataLoader 方法创建一个数据加载器,指定数据集、每个批次的大小以及是否进行随机打乱。通过调用 trainloadertestloader__iter__方法,我们可以轻松地在训练和测试过程中获取数据批次。

MNIST、CIFAR10和ImageNet都是常用的图像数据集,它们各自有不同的用途:

1.MNIST数据集主要用于手写数字识别。这个数据集包含了大量的手写数字图像,每张图像的大小为28x28像素。由于图像较小且内容相对简单,MNIST数据集通常被用作机器学习模型的入门练习,例如卷积神经网络(CNN)的基础模型。

2.CIFAR10数据集主要用于普适物体识别。该数据集包含了10个不同类别的图像,每个类别的图像都有5000张训练图像和1000张测试图像。这些图像的大小为32x32像素,涵盖了动物、交通工具、自然物体等不同类别的物体。CIFAR10数据集通常被用作物体识别的基准测试,用于评估不同机器学习模型的性能。

3.ImageNet数据集主要用于大规模图像分类。该数据集包含了超过1400万个图像,涵盖了1000个不同的类别。这些图像的大小不一,涵盖了广泛的物体、场景和活动。由于ImageNet数据集的规模巨大且多样性强,它通常被用作深度学习模型的研究和基准测试,特别是卷积神经网络和深度神经网络等模型的研究。

总的来说,MNIST、CIFAR10和ImageNet数据集都是用于训练和评估机器学习模型的常用数据集,但它们的用途和特点各不相同。MNIST数据集主要用于手写数字识别,CIFAR10数据集主要用于普适物体识别,而ImageNet数据集主要用于大规模图像分类。

3.加载自定义数据集

使用datasets.ImageFolde获取自定义数据集

使用datasets.ImageFolder类加载自定义图像数据集非常方便。首先,确保您的自定义数据集目录结构符合ImageFolder的要求,即每个子目录的名称代表一个类标签,并且子目录中包含的图像是该类的样本。然后,按照以下步骤进行操作:

1.导入所需的库和模块:

import os  
from torchvision import datasets, transforms
  • 1
  • 2

2.设置数据集的根目录和预处理操作:

image_path = './path/to/your/dataset'  # 数据集的根目录  
  
# 定义数据预处理操作  
data_transform = {  
    'train': transforms.Compose([  
        transforms.RandomResizedCrop(224),  # 随机裁剪并缩放到指定大小  
        transforms.RandomHorizontalFlip(),  # 随机水平翻转  
        transforms.ToTensor(),  # 将图像转换为Tensor  
        transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))  # 标准化  
    ]),  
    'val': transforms.Compose([  
        transforms.Resize(256),  # 缩放图像大小  
        transforms.CenterCrop(224),  # 在中心裁剪图像  
        transforms.ToTensor(),  # 将图像转换为Tensor  
        transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))  # 标准化  
    ])  
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

这里我们定义了两个预处理操作,一个用于训练集,另一个用于验证集。您可以根据实际需求进行调整。

3.使用datasets.ImageFolder创建数据集对象:

train_dataset = datasets.ImageFolder(root=os.path.join(image_path, 'train'), transform=data_transform['train'])  
val_dataset = datasets.ImageFolder(root=os.path.join(image_path, 'val'), transform=data_transform['val'])
  • 1
  • 2

这里我们假设自定义数据集的目录结构中有名为train和val的子目录,分别包含训练集和验证集的图像。您可以根据实际情况更改这些子目录的名称。

现在,您已经成功地使用datasets.ImageFolder创建了自定义图像数据集的对象。接下来,可以使用DataLoader类创建一个数据加载器,以便在训练和验证过程中迭代访问这些数据集。例如:

train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)  
val_loader = DataLoader(val_dataset, batch_size=32, shuffle=False)
  • 1
  • 2

这样,您就可以通过迭代train_loader和val_loader来访问训练集和验证集中的数据批次。

重写Dataset类,实现读写数据加载自定义数据集`

在 PyTorch 中加载自定义数据集需要遵循以下步骤:

1.创建数据集类:创建一个继承自 torch.utils.data.Dataset 的数据集类,并实现 __len____getitem__ 方法。__len__ 方法应返回数据集的大小,__getitem__ 方法应返回指定索引处的数据样本。

2.实现数据预处理操作:根据实际需求,实现数据预处理操作,例如图像增强、标准化等。可以使用 torchvision.transforms 模块提供的各种预处理操作。

3.划分数据集:使用 torch.utils.data.random_split 方法将数据集划分为训练集、验证集和测试集等。

4.创建数据加载器:使用 torch.utils.data.DataLoader 方法创建一个数据加载器,指定数据集、每个批次的大小以及是否进行随机打乱等。

以下是一个简单的自定义数据集加载示例:

import os  
import torch  
from torch.utils.data import Dataset, DataLoader, random_split  
from torchvision import transforms  
  
# 定义自定义数据集类  
class MyDataset(Dataset):  
    def __init__(self, root_dir, transform=None):  
        self.root_dir = root_dir  
        self.transform = transform  
        self.files = os.listdir(root_dir)  
  
    def __len__(self):  
        return len(self.files)  
  
    def __getitem__(self, idx):  
        file_path = os.path.join(self.root_dir, self.files[idx])  
        image = Image.open(file_path).convert('RGB')  
        if self.transform:  
            image = self.transform(image)  
        return image, self.files[idx]  
  
# 定义数据预处理操作  
transform = transforms.Compose([  
    transforms.Resize((224, 224)),  
    transforms.ToTensor(),  
    transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))  
])  
  
# 创建自定义数据集实例  
dataset = MyDataset(root_dir='./data', transform=transform)  
  
# 划分数据集为训练集和测试集  
train_size = int(0.8 * len(dataset))  
test_size = len(dataset) - train_size  
train_dataset, test_dataset = random_split(dataset, [train_size, test_size])  
  
# 创建数据加载器  
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)  
test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

在这个示例中,我们首先定义了一个继承自 torch.utils.data.Dataset 的自定义数据集类 MyDataset,并实现了 __len____getitem__ 方法。__len__ 方法返回数据集的大小,__getitem__ 方法返回指定索引处的数据样本。在 __getitem__ 方法中,我们打开了指定路径的图像文件,并应用了定义好的数据预处理操作。然后,我们使用 MyDataset 类创建了一个数据集实例,并使用 torch.utils.data.random_split 方法将数据集划分为训练集和测试集。最后,我们使用 torch.utils.data.DataLoader 方法创建了一个数据加载器,指定数据集、每个批次的大小以及是否进行随机打乱等。通过调用 train_loadertest_loader 的 __iter__ 方法,我们可以轻松地在训练和测试过程中获取数据批次。

4.自定义损失函数

基本框架:

import torch.nn as nn  
  
class MyLoss(nn.Module):  
    def __init__(self):  
        super(MyLoss, self).__init__()  
          
    def forward(self, outputs, targets):  
        # 在这里实现你的损失函数计算逻辑  
        # outputs是模型的预测输出,targets是真实标签  
        # 返回损失值  
        loss = ...  # 计算损失  
        return loss
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

举例说明:

# 自定义损失函数,需要在forward中定义过程
class MyLoss(nn.Module):
    def __init__(self):
        super(MyLoss, self).__init__()
    
    # 参数为传入的预测值和真实值,返回所有样本的损失值,自己只需定义计算过程,反向传播PyTroch会自动记录,最好用PyTorch进行计算
    def forward(self, pred, label):
        # pred:[32, 3] label:[32, 3] 第一维度是样本数
        # 由于是二分类,使用BCE损失
        return F.binary_cross_entropy(pred, label)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

def forward(self, pred, label): 这是类的前向传播函数。在PyTorch中,损失函数也需要实现forward方法,该方法定义了如何根据模型的预测输出(pred)和真实标签(label)计算损失。
1.predlabel都是输入参数,分别代表模型的预测输出和真实标签。在这个例子中,它们的形状都是[32, 3],表示有32个样本,每个样本有3个类别的预测输出和真实标签。
2.由于这是一个二分类问题,代码中使用了二元交叉熵(Binary Cross Entropy,BCE)损失函数来计算损失。PyTorch提供了一个现成的BCE损失函数实现,即F.binary_cross_entropy。这个函数接受预测输出和真实标签作为输入,并返回损失值。
3.return F.binary_cross_entropy(pred, label)这行代码返回了计算得到的损失值。这个损失值将用于训练过程中的参数更新。

三、模型训练和预测

1.模型训练

num_epochs = 10  # 定义训练轮数  
  
for epoch in range(num_epochs):  
    # 训练阶段  
    model.train()  # 设置为训练模式  
    train_loss = 0.0  # 记录训练集损失值  
    for inputs, labels in train_loader:  
        optimizer.zero_grad()  # 清空梯度缓存  
        outputs = model(inputs)  # 前向传播,计算输出值  
        loss = criterion(outputs, labels)  # 计算损失值  
        loss.backward()  # 反向传播,计算梯度值  
        optimizer.step()  # 更新模型参数  
        train_loss += loss.item() * inputs.size(0)  # 累加训练集损失值  
    train_loss /= len(train_dataset)  # 计算训练集平均损失值  
    print('Epoch [{}/{}], Train Loss: {:.4f}'.format(epoch+1, num_epochs, train_loss))  
      
    # 验证阶段  
    model.eval()  # 设置为评估模式,关闭Dropout等操作  
    val_loss = 0.0  # 记录验证集损失值  
    with torch.no_grad():  # 关闭梯度计算,节省内存开销  
        for inputs, labels in val_loader:  
            outputs = model(inputs)  # 前向传播,计算输出值  
            loss = criterion(outputs, labels)  # 计算损失值  
            val_loss += loss.item() * inputs.size(0)  # 累加验证集损失值  
    val_loss /= len(val_dataset)  # 计算验证集平均损失值  
    print('Epoch [{}/{}], Val Loss: {:.4f}'.format(epoch+1, num_epochs, val_loss))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

在训练模型的过程中,通常使用循环来迭代数据集,每次迭代都会进行一次前向传播和反向传播,更新模型参数。在每个轮次结束后,还会对验证集进行评估,以评估模型的性能。在PyTorch中,可以使用model.train()model.eval()方法来切换模型的状态。model.train()方法会打开Dropout等操作,model.eval()方法则会关闭Dropout等操作。此外,在验证阶段,还可以使用torch.no_grad()方法来关闭梯度计算,以节省内存开销。

2.模型预测

①导入所需的库和模块:

import torch  
from torchvision import transforms  
from PIL import Image
  • 1
  • 2
  • 3

这里导入了PyTorch库、torchvision库和PIL库。PyTorch库是PyTorch深度学习框架的核心库,torchvision库是PyTorch官方提供的计算机视觉库,PIL库是Python Image Library,用于处理图像文件。

②加载模型:

model = ...  # 加载已经训练好的模型  
model.eval()  # 设置为评估模式,关闭Dropout等操作
  • 1
  • 2

这里首先加载已经训练好的模型,然后使用model.eval()方法将模型设置为评估模式。在评估模式下,模型会关闭Dropout等操作,以保证输出的稳定性。

③定义图像预处理操作:

preprocess = transforms.Compose([  
    transforms.Resize(256),  # 调整图像大小  
    transforms.CenterCrop(224),  # 在中心区域裁剪图像  
    transforms.ToTensor(),  # 将图像转换为张量  
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])  # 对图像进行归一化  
])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这里定义了一个preprocess变量,使用transforms.Compose()方法将多个图像预处理操作组合在一起。这些操作包括:调整图像大小、在中心区域裁剪图像、将图像转换为张量和对图像进行归一化。这些操作的目的是将输入的图像转换为模型所需的输入格式。

④加载图像并进行预处理:

image = Image.open('image.jpg')  # 加载图像文件  
input_tensor = preprocess(image)  # 对图像进行预处理,得到输入张量  
input_batch = input_tensor.unsqueeze(0)  # 将输入张量扩展为四维张量,以符合模型的输入要求
  • 1
  • 2
  • 3

这里首先使用Image.open()方法加载图像文件,然后使用preprocess变量对图像进行预处理,得到输入张量input_tensor。由于模型通常要求输入张量为四维张量,而input_tensor可能是三维张量,因此需要使用unsqueeze方法将input_tensor扩展为四维张量input_batch

⑤进行预测:

with torch.no_grad():  # 关闭梯度计算,节省内存开销  
    output = model(input_batch)  # 前向传播,得到输出张量  
    _, predicted = torch.max(output, 1)  # 对输出张量进行argmax操作,得到预测类别  
    print('Predicted:', predicted.item())  # 输出预测结果
  • 1
  • 2
  • 3
  • 4

这里首先使用torch.no_grad()方法关闭梯度计算,以节省内存开销。然后使用model变量对input_batch进行前向传播,得到输出张量output。由于模型的输出通常是多个类别的概率值,因此需要使用torch.max方法对输出张量进行argmax操作,得到预测类别predicted。最后,使用print方法输出预测结果。

另外,在TensorFlow框架中,可以使用以下代码进行模型预测:

import tensorflow as tf  
from tensorflow.keras.preprocessing import image  
import numpy as np  
  
# 加载模型  
model = ...  # 加载已经训练好的模型  
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])  
  
# 加载图像并进行预处理  
img_path = 'image.jpg'  # 图像文件路径  
img = image.load_img(img_path, target_size=(224, 224))  # 加载图像并进行大小调整  
x = image.img_to_array(img)  # 将图像转换为数组  
x = np.expand_dims(x, axis=0)  # 将数组扩展为四维张量,以符合模型的输入要求  
x = tf.keras.applications.vgg16.preprocess_input(x)  # 对输入张量进行归一化处理  
  
# 进行预测  
preds = model.predict(x)  # 前向传播,得到输出张量  
predicted = np.argmax(preds, axis=1)  # 对输出张量进行argmax操作,得到预测类别  
print('Predicted:', predicted)  # 输出预测结果
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

总结

学到现在了,叫我闭卷写出一个训练模型代码,我还是不会写,但是我已清楚基本框架能够看懂代码,使用文心一言我可以自己写出一个可以运行的训练模型代码。接下来我需要多练多敲熟悉代码,争取能够独立训练一个模型并预测准确。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/217590
推荐阅读
相关标签
  

闽ICP备14008679号