百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

用PyTorch进行图像分类的基础知识Python完整实例

toyiye 2024-08-16 05:12 27 浏览 0 评论

过去几年已经发布了许多深度学习框架。其中,来自Facebook AI Research的PyTorch非常独特,因其优雅,灵活,速度和简单性而获得广泛采用。如果没有足够的研究支持,大多数深度学习框架对于应用程序开发来说太具体,或者对于没有足够支持应用程序开发的研究来说太具体。

但是,PyTorch通过提供对应用程序开发人员非常友好的API来模糊两者之间的界限,同时提供了轻松定义自定义图层并全面控制训练过程(包括梯度传播)的功能。这使它非常适合开发人员和研究人员。

PyTorch所有功能的主要特点是其逐个运行的方法,这使得可以即时更改神经网络的结构,而不像其他依赖不灵活静态图形的深度学习库。

在这篇文章中,您将从头学习如何使用Pytorch构建完整的图像分类管道。

安装PyTorch

由于预构建的二进制文件在所有系统中都能正常工作,因此安装Pytorch是一件轻而易举的事情(注意Python版本,及对于的GPU)。

安装在WINDOWS上

仅限CPU:

pip3 install http://download.Pytorch.org/whl/cpu/torch-0.4.0-cp35-cp35m-win_amd64.whl

pip3 install torchvision

GPU支持

pip3 install http://download.Pytorch.org/whl/cu80/torch-0.4.0-cp35-cp35m-win_amd64.whl

pip3 install torchvision

安装在LINUX上

仅限CPU:

pip3 install torch torchvision

GPU支持

pip3 install http://download.Pytorch.org/whl/cpu/torch-0.4.0-cp35-cp35m-linux_x86_64.whl

pip3 install torchvision

在OSX上安装

仅限CPU:

pip3 install torch torchvision

GPU支持

有关在OSX上安装gpu支持的说明,请访问Pytorch.org。

卷积神经网络简介

我们将在这篇文章中使用的模型属于一类称为卷积神经网络(CNN)的神经网络。CNN主要是一堆卷积层,通常与标准化层和激活层交织。卷积神经网络的组成部分总结如下。

  • CNN ?- 一堆卷积层

  • 卷积层 ?- 一个检测某些特征的层。有特定数量的通道。

  • 通道 ?- 检测图像中的特定功能。

  • 内核/过滤器 ?- 每个通道中要检测的功能。它有一个固定的大小,通常是3 x 3。

简要解释一下,卷积层只是一个特征检测层。每个卷积层都有特定数量的通道; 每个通道检测图像中的特定功能。要检测的每个功能通常称为内核或过滤器。内核的大小是固定的,通常使用大小为3 x 3的内核。

例如,具有64个通道和3×3的内核大小的卷积层将检测64个不同的特征,每个大小为3×3。

定义模型结构

模型在PyTorch中由扩展Module类的自定义类定义。torch.nn包中可以找到模型的所有组件。因此,我们只需导入这个包。这里我们将建立一个简单的CNN模型,用于对来自CIFAR 10数据集的RGB图像进行分类。CIFAR10数据集包含50,000个训练图像和10,000个尺寸为32 x 32的测试图像。Python代码如下

# Import needed packages

import torch

import torch.nn as nn

class SimpleNet(nn.Module):

def __init__(self, num_classes=10):

super(SimpleNet, self).__init__()

self.conv1 = nn.Conv2d(in_channels=3, out_channels=12, kernel_size=3, stride=1, padding=1)

self.relu1 = nn.ReLU()

self.conv2 = nn.Conv2d(in_channels=12, out_channels=12, kernel_size=3, stride=1, padding=1)

self.relu2 = nn.ReLU()

self.pool = nn.MaxPool2d(kernel_size=2)

self.conv3 = nn.Conv2d(in_channels=12, out_channels=24, kernel_size=3, stride=1, padding=1)

self.relu3 = nn.ReLU()

self.conv4 = nn.Conv2d(in_channels=24, out_channels=24, kernel_size=3, stride=1, padding=1)

self.relu4 = nn.ReLU()

self.fc = nn.Linear(in_features=16 * 16 * 24, out_features=num_classes)

def forward(self, input):

output = self.conv1(input)

output = self.relu1(output)

output = self.conv2(output)

output = self.relu2(output)

output = self.pool(output)

output = self.conv3(output)

output = self.relu3(output)

output = self.conv4(output)

output = self.relu4(output)

output = output.view(-1, 16 * 16 * 24)

output = self.fc(output)

return output

在上面的Python代码中,我们首先定义一个名为SimpleNet的新类,它扩展了nn.Module类。在这个类的构造函数中,我们指定了网络中的所有层。我们的网络结构为卷积- relu -卷积- relu - pool -卷积- relu -卷积- relu - linear。

为了弄清楚每一层发生了什么,让我们逐一检查。

卷积层

nn.Conv2d(in_channels=3, out_channels=12, kernel_size=3, stride=1, padding=1)

假设我们的输入是具有3个通道(RED-GREEN-BLUE)的RGB图像,我们将数量指定in_channels为3.接下来,我们要将12个特征检测器应用于图像,因此我们指定的数量为out_channels 12。这里我们使用标准的3x3内核大小(简单定义为3)。步幅设置为1,并且应该始终如此,除非您打算缩小图像的尺寸。通过将步幅(stride )设置为1,卷积一次将移动1个像素。最后,我们将padding设置为1:这确保我们的图像填充零以保持输入和输出大小相同。

基本上,你目前不需要太担心步幅和padding。把重点放在in_channels和out_channels。

请注意,out_channels在这一层,作为in_channels下一层,如下所示。

nn.Conv2d(in_channels = 12,out_channels = 12,kernel_size = 3,stride = 1,padding = 1)

Relu

这是标准的Relu激活函数,它基本上将所有传入的特征阈值设为0或更大。简单来说,当将Relu应用于传入特征时,小于0的任何数字都变为零,而其他数保持不变。

MaxPool2d

此图层通过将图像的尺寸设置kernel_size为2来减少图像的尺寸,从而将图像的宽度和高度减少2倍。实质上是使图像的2 x 2区域中的像素达到最大值,并使用该图像代表整个地区; 因此4个像素成为一个。

线性(linear)

我们网络的最后一层几乎总是线性层。它是一个标准的、全连接层,计算我们每个类的分数——在本例中是10个类。

请注意,我们必须在将最后一个conv-relu层的整个feature map传递到图像之前,将其flatten 。最后一层有24个输出通道,由于2×2的max汇聚,此时我们的图像已经变成16 x 16(32/2 = 16)。我们的平面图像是16 x 16 x 24。我们用Python代码来做这个:

output = output.view(-1, 16 * 16 * 24)

在我们的线性层中,我们必须指定数量为input_features16 x 16 x 24,并且数量output_features应该与我们期望的类数相对应。

请注意PyTorch中定义模型的简单规则。在构造函数中定义层,并在forward函数中传入所有输入。

模块化

上面的代码很酷但不够酷 - 如果我们要编写非常深的网络,它看起来很麻烦。更简洁的代码的关键是模块化。在上面的例子中,我们可以将卷积和relu放在一个单独的模块中,并将大部分这个模块堆叠在我们的SimpleNet中。

为此,我们首先定义一个新模块,Python代码如下所示

class Unit(nn.Module):

def __init__(self, in_channels, out_channels):

super(Unit, self).__init__()

self.conv = nn.Conv2d(in_channels=in_channels, kernel_size=3, out_channels=out_channels, stride=1, padding=1)

self.bn = nn.BatchNorm2d(num_features=out_channels)

self.relu = nn.ReLU()

def forward(self, input):

output = self.conv(input)

output = self.bn(output)

output = self.relu(output)

return output

把上面的内容看作是一个迷你网络,它是我们更大的SimpleNet的一部分。

正如您可以看到的,这个单元由卷积-batchnormaliz -relu组成。

不像第一个例子,这里我在ReLU之前包含了BatchNorm2d。

批量归一化将所有输入归一化,以具有零均值和单位方差。这大大提高了CNN模型的准确性。

定义了上面的单元后,我们现在可以将它们堆在一起。

class Unit(nn.Module):

def __init__(self,in_channels,out_channels):

super(Unit,self).__init__()

self.conv = nn.Conv2d(in_channels=in_channels,kernel_size=3,out_channels=out_channels,stride=1,padding=1)

self.bn = nn.BatchNorm2d(num_features=out_channels)

self.relu = nn.ReLU()

def forward(self,input):

output = self.conv(input)

output = self.bn(output)

output = self.relu(output)

return output

class SimpleNet(nn.Module):

def __init__(self,num_classes=10):

super(SimpleNet,self).__init__()

#Create 14 layers of the unit with max pooling in between

self.unit1 = Unit(in_channels=3,out_channels=32)

self.unit2 = Unit(in_channels=32, out_channels=32)

self.unit3 = Unit(in_channels=32, out_channels=32)

self.pool1 = nn.MaxPool2d(kernel_size=2)

self.unit4 = Unit(in_channels=32, out_channels=64)

self.unit5 = Unit(in_channels=64, out_channels=64)

self.unit6 = Unit(in_channels=64, out_channels=64)

self.unit7 = Unit(in_channels=64, out_channels=64)

self.pool2 = nn.MaxPool2d(kernel_size=2)

self.unit8 = Unit(in_channels=64, out_channels=128)

self.unit9 = Unit(in_channels=128, out_channels=128)

self.unit10 = Unit(in_channels=128, out_channels=128)

self.unit11 = Unit(in_channels=128, out_channels=128)

self.pool3 = nn.MaxPool2d(kernel_size=2)

self.unit12 = Unit(in_channels=128, out_channels=128)

self.unit13 = Unit(in_channels=128, out_channels=128)

self.unit14 = Unit(in_channels=128, out_channels=128)

self.avgpool = nn.AvgPool2d(kernel_size=4)

#Add all the units into the Sequential layer in exact order

self.net = nn.Sequential(self.unit1, self.unit2, self.unit3, self.pool1, self.unit4, self.unit5, self.unit6

,self.unit7, self.pool2, self.unit8, self.unit9, self.unit10, self.unit11, self.pool3,

self.unit12, self.unit13, self.unit14, self.avgpool)

self.fc = nn.Linear(in_features=128,out_features=num_classes)

def forward(self, input):

output = self.net(input)

output = output.view(-1,128)

output = self.fc(output)

return output

这是一个完整的15层网络,由14个卷积层、14个Relu层、14个批量归一化层、4个汇集层和1个线性层组成,共计62层。这是通过使用子模块和顺序类来实现的。

上面的代码是由单元的堆栈和中间的池层组成的。

请注意,如何使代码更紧凑,把所有层,除了完全连接层到一个连续的类。这进一步简化了前向函数中的代码。

self.net = nn.Sequential(self.unit1, self.unit2, self.unit3, self.pool1, self.unit4, self.unit5, self.unit6, self.unit7, self.pool2, self.unit8, self.unit9, self.unit10, self.unit11, self.pool3,self.unit12, self.unit13, self.unit14, self.avgpool)

最后一个单元之后的AvgPooling层计算每个通道中所有激活的平均值。该单元的输出具有128个通道,并且在共用3次后,我们的32×32图像变为4×4。我们应用内核大小为4的AvgPool2D,将我们的特征映射为1×1×128。

self.avgpool = nn.AvgPool2d(kernel_size = 4)

因此,线性层将具有1×1×128 = 128个输入特征。

self.fc = nn.Linear(in_features = 128,out_features = num_classes)

我们还将网络的输出平铺为128个特征。

output = output.view(-1,128)

加载和增加数据

由于采用torchvision软件包,PyTorch中的数据加载非常简单。为了演示这一点,我将加载我们将在本教程中使用的CIFAR10数据集。

首先,我们需要三个额外的导入语句

from torchvision.datasets import CIFAR10

from torchvision.transforms import transforms

from torch.utils.data import DataLoader

要加载数据集,我们执行以下操作:

  • 定义要在图像上应用的转换

  • 使用torchvision加载数据集

  • 创建一个DataLoader的实例来保存图像

我们做的训练集如下:

#Define transformations for the training set, flip the images randomly, crop out and apply mean and std normalization

train_transformations = transforms.Compose([

transforms.RandomHorizontalFlip(),

transforms.RandomCrop(32,padding=4),

transforms.ToTensor(),

transforms.Normalize((0.5,0.5,0.5), (0.5,0.5,0.5))

])

#Load the training set

train_set =CIFAR10(root="./data",train=True,transform=train_transformations,download=True)

#Create a loder for the training set

train_loader = DataLoader(train_set,batch_size=32,shuffle=True,num_workers=4)

首先,我们使用transform.Compose传递一系列转换。RandomHorizontalFlip会水平地随机翻转图像。RandomCrop随机裁剪图像。以下是一个水平翻转的例子。

最后,两个最重要的; ToTensor将图像转换为PyTorch可用的格式。使用下面给出的值进行归一化将使我们所有的像素范围在-1到+1之间。请注意,在说明转换时,ToTensor和Normalize必须按照上述定义的顺序排列。其主要原因是其他变换应用于PIL图像的输入,但是,在应用归一化之前,必须将其转换为pytorch张量。

数据增强有助于模型正确分类图像,而不考虑其显示的角度。

接下来,我们使用CIFAR10类加载训练集,最后我们为训练集创建一个加载器,指定批量大小为32的图像。

对于下面的测试集重复该操作,只是转换只包括ToTensor和Normalize。我们不在测试集上应用其他类型的转换。

# Define transformations for the test set

test_transformations = transforms.Compose([

transforms.ToTensor(),

transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))

])

# Load the test set, note that train is set to False

test_set = CIFAR10(root="./data", train=False, transform=test_transformations, download=True)

# Create a loder for the test set, note that both shuffle is set to false for the test loader

test_loader = DataLoader(test_set, batch_size=32, shuffle=False, num_workers=4)

您第一次运行此代码时,约170 mb的数据集将被下载到您的系统中

训练模型

使用Pytorch训练神经网络是一个非常明确的过程,可以让您完全控制训练过程中发生的情况。让我们一步一步地完成这个过程。

您应该将Adam优化器导入为:

from torch.optim import Adam

步骤1:实例化模型,创建优化器和损失函数

from torch.optim import Adam

# Check if gpu support is available

cuda_avail = torch.cuda.is_available()

# Create model, optimizer and loss function

model = SimpleNet(num_classes=10)

#if cuda is available, move the model to the GPU

if cuda_avail:

model.cuda()

#Define the optimizer and loss function

optimizer = Adam(model.parameters(), lr=0.001, weight_decay=0.0001)

loss_fn = nn.CrossEntropyLoss()

步骤2:编写一个函数来调整学习率

# Create a learning rate adjustment function that divides the learning rate by 10 every 30 epochs

def adjust_learning_rate(epoch):

lr = 0.001

if epoch > 180:

lr = lr / 1000000

elif epoch > 150:

lr = lr / 100000

elif epoch > 120:

lr = lr / 10000

elif epoch > 90:

lr = lr / 1000

elif epoch > 60:

lr = lr / 100

elif epoch > 30:

lr = lr / 10

for param_group in optimizer.param_groups:

param_group["lr"] = lr

这个功能在每30个epochs之后基本上将学习率分成10倍。

第3步:编写功能来保存和评估模型

def save_models(epoch):

torch.save(model.state_dict(), "cifar10model_{}.model".format(epoch))

print("Chekcpoint saved")

def test():

model.eval()

test_acc = 0.0

for i, (images, labels) in enumerate(test_loader):

if cuda_avail:

images = Variable(images.cuda())

labels = Variable(labels.cuda())

# Predict classes using images from the test set

outputs = model(images)

_, prediction = torch.max(outputs.data, 1)

test_acc += torch.sum(prediction == labels.data)

# Compute the average acc and loss over all 10000 test images

test_acc = test_acc / 10000

return test_acc

为了评估模型在测试集上的精度,我们遍历了测试加载器。在每一步中,我们都会将图像和标签移动到GPU(如果可用)并将其包装在变量中。图像被传递到模型中以获得预测。选取最大预测值,然后与实际类别进行比较以获得精度。最后我们返回平均精度。

第四步:编写训练功能

def train(num_epochs):

best_acc = 0.0

for epoch in range(num_epochs):

model.train()

train_acc = 0.0

train_loss = 0.0

for i, (images, labels) in enumerate(train_loader):

# Move images and labels to gpu if available

if cuda_avail:

images = Variable(images.cuda())

labels = Variable(labels.cuda())

# Clear all accumulated gradients

optimizer.zero_grad()

# Predict classes using images from the test set

outputs = model(images)

# Compute the loss based on the predictions and actual labels

loss = loss_fn(outputs, labels)

# Backpropagate the loss

loss.backward()

# Adjust parameters according to the computed gradients

optimizer.step()

train_loss += loss.cpu().data[0] * images.size(0)

_, prediction = torch.max(outputs.data, 1)

train_acc += torch.sum(prediction == labels.data)

# Call the learning rate adjustment function

adjust_learning_rate(epoch)

# Compute the average acc and loss over all 50000 training images

train_acc = train_acc / 50000

train_loss = train_loss / 50000

# Evaluate on the test set

test_acc = test()

# Save the model if the test acc is greater than our current best

if test_acc > best_acc:

save_models(epoch)

best_acc = test_acc

# Print the metrics

print("Epoch {}, Train Accuracy: {} , TrainLoss: {} , Test Accuracy: {}".format(epoch, train_acc, train_loss,

上面的训练功能是高度注释的; 但是,您仍然可能会因为几件事而感到困惑。仔细检查上面详细说明的内容非常重要。

首先我们循环训练集的加载器:

for i, (images,labels) in enumerate(train_loader):

接下来,如果支持gpu,我们将图像和标签移动到GPU:

if cuda_avail:

images = Variable(images.cuda())

labels = Variable(labels.cuda())

下一行是清除当前所有累积的梯度。

optimizer.zero_grad()

这很重要,因为神经网络中的权重是根据每个批次累积的梯度进行调整的,因此对于每个新批次,梯度必须重置为零,因此之前批次中的图像不会将梯度传播到新批次。

在接下来的步骤中,我们将图像传递到模型中。它返回预测,然后我们将预测和实际标签都传递给损失函数。

我们调用loss.backward() 传播梯度,然后我们调用optimizer.step() 修改我们的模型参数根据传播的梯度。

这些是训练的主要步骤。

其余的代码是计算指标:

train_loss += loss.cpu().data[0] * images.size(0)

_, prediction = torch.max(outputs.data, 1)

train_acc += torch.sum(prediction == labels.data)

在这里,我们检索实际损失,然后获得最大预测等级。最后,我们总结批次中正确预测的数量并将其添加到总数中train_acc。

每个epoch之后,我们称之为学习率调整函数,计算训练损失和训练精度的平均值,找出测试精度并记录结果。

更重要的是,我们追踪最佳精度,并且如果当前测试精度比我们目前最好的精度要高,我们会调用保存模型函数。

推理与保存的模型

模型经过训练后,可以用来对新图像进行推理。

要执行推理,您需要经过以下步骤:

  • 定义并实例化在训练期间构建的相同模型。

  • 将保存的检查点加载到模型中。

  • 从文件系统中选择一个图像。

  • 通过模型运行图像并获取最高的预测。

  • 将预测的类号转换为类名。

为了说明这一点,我们将使用具有预训练ImageNet权重的Squeezenet模型。这使我们能够拍摄几乎任何图像并对其进行预测。由于ImageNet模型有1000个类,因此支持许多不同种类的对象。

Torchvision提供了预定义的模型,涵盖了广泛的流行体系结构。

首先,导入所有需要的包和类,并创建Squeezenet模型的一个实例。

# Import needed packages

import torch

import torch.nn as nn

from torchvision.transforms import transforms

from torch.autograd import Variable

from torchvision.models import squeezenet1_1

import requests

import shutil

from io import open

import os

from PIL import Image

import json

model = squeezenet1_1(pretrained=True)

model.eval()

请注意,在上面的代码中,通过将预训练设置为true,首次运行此功能时将下载Squeezenet模型。模型的大小只有4.7 mb。

接下来,创建一个预测函数,如下所示:

def predict_image(image_path):

print("Prediction in progress")

image = Image.open(image_path)

# Define transformations for the image, should (note that imagenet models are trained with image size 224)

transformation = transforms.Compose([

transforms.CenterCrop(224),

transforms.ToTensor(),

transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))

])

# Preprocess the image

image_tensor = transformation(image).float()

# Add an extra batch dimension since pytorch treats all images as batches

image_tensor = image_tensor.unsqueeze_(0)

if torch.cuda.is_available():

image_tensor.cuda()

# Turn the input into a Variable

input = Variable(image_tensor)

# Predict the class of the image

output = model(input)

index = output.data.numpy().argmax()

return index

上面的代码包含了我们在训练和评估过程中使用的相同组件。为清晰起见,请参阅上述代码中的注释。

最后,在运行我们的预测的主要功能中,我们应该从网上下载一个图像并将其存储在磁盘上。我们还应该下载将所有类索引映射到实际类名的类映射。这是因为我们的模型会返回预测类的索引,这取决于类名是如何编码的,然后将从索引类映射中检索实际名称。

之后,我们使用保存的图像运行预测功能,并使用保存的类图获取确切的类名。

if __name__ == "__main__":

imagefile = "image.png"

imagepath = os.path.join(os.getcwd(), imagefile)

# Donwload image if it doesn't exist

if not os.path.exists(imagepath):

data = requests.get(

"https://github.com/OlafenwaMoses/ImageAI/raw/master/images/3.jpg", stream=True)

with open(imagepath, "wb") as file:

shutil.copyfileobj(data.raw, file)

del data

index_file = "class_index_map.json"

indexpath = os.path.join(os.getcwd(), index_file)

# Donwload class index if it doesn't exist

if not os.path.exists(indexpath):

data = requests.get('https://github.com/OlafenwaMoses/ImageAI/raw/master/imagenet_class_index.json')

with open(indexpath, "w", encoding="utf-8") as file:

file.write(data.text)

class_map = json.load(open(indexpath))

# run prediction function annd obtain prediccted class index

index = predict_image(imagepath)

prediction = class_map[str(index)][1]

print("Predicted Class ", prediction)

这里是完整的python推理代码:

# Import needed packages

import torch

import torch.nn as nn

from torchvision.transforms import transforms

import matplotlib.pyplot as plt

import numpy as np

from torch.autograd import Variable

from torchvision.models import squeezenet1_1

import torch.functional as F

import requests

import shutil

from io import open

import os

from PIL import Image

import json

""" Instantiate model, this downloads tje 4.7 mb squzzene the first time it is called.

To use with your own model, re-define your trained networks ad load weights as below

checkpoint = torch.load("pathtosavemodel")

model = SimpleNet(num_classes=10)

model.load_state_dict(checkpoint)

model.eval()

"""

model = squeezenet1_1(pretrained=True)

model.eval()

def predict_image(image_path):

print("Prediction in progress")

image = Image.open(image_path)

# Define transformations for the image, should (note that imagenet models are trained with image size 224)

transformation = transforms.Compose([

transforms.CenterCrop(224),

transforms.ToTensor(),

transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))

])

# Preprocess the image

image_tensor = transformation(image).float()

# Add an extra batch dimension since pytorch treats all images as batches

image_tensor = image_tensor.unsqueeze_(0)

if torch.cuda.is_available():

image_tensor.cuda()

# Turn the input into a Variable

input = Variable(image_tensor)

# Predict the class of the image

output = model(input)

index = output.data.numpy().argmax()

return index

if __name__ == "__main__":

imagefile = "image.png"

imagepath = os.path.join(os.getcwd(), imagefile)

# Donwload image if it doesn't exist

if not os.path.exists(imagepath):

data = requests.get(

"https://github.com/OlafenwaMoses/ImageAI/raw/master/images/3.jpg", stream=True)

with open(imagepath, "wb") as file:

shutil.copyfileobj(data.raw, file)

del data

index_file = "class_index_map.json"

indexpath = os.path.join(os.getcwd(), index_file)

# Donwload class index if it doesn't exist

if not os.path.exists(indexpath):

data = requests.get('https://github.com/OlafenwaMoses/ImageAI/raw/master/imagenet_class_index.json')

with open(indexpath, "w", encoding="utf-8") as file:

file.write(data.text)

class_map = json.load(open(indexpath))

# run prediction function annd obtain prediccted class index

index = predict_image(imagepath)

prediction = class_map[str(index)][1]

print("Predicted Class ", prediction)

上面的例子中的图片是这只鸟的图片:

该图像来自ImageAI存储库。如果要使用自己的自定义网络(即刚刚创建的SimpleNet)执行推理,则只需用此替换模型加载部分即可。

checkpoint = torch.load("pathtosavemodel")

model = SimpleNet(num_classes=10)

model.load_state_dict(checkpoint)

model.eval()

请注意,如果您的模型是在ImageNet上进行培训的,那么您的模型num_classes 必须是1000而不是10。

代码的所有其他方面保持不变 - 只有一个区别 - 如果我们用cifar10训练模型进行预测,那么在变换中,更改transforms.CenterCrop(224) 为transforms.Resize(32)

但是,如果您的模型是在ImageNet上进行培训的,则不应该执行此更改。

相关推荐

# Python 3 # Python 3字典Dictionary(1)

Python3字典字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在花括号({})中,格式如...

Python第八课:数据类型中的字典及其函数与方法

Python3字典字典是另一种可变容器模型,且可存储任意类型对象。字典的每个键值...

Python中字典详解(python 中字典)

字典是Python中使用键进行索引的重要数据结构。它们是无序的项序列(键值对),这意味着顺序不被保留。键是不可变的。与列表一样,字典的值可以保存异构数据,即整数、浮点、字符串、NaN、布尔值、列表、数...

Python3.9又更新了:dict内置新功能,正式版十月见面

机器之心报道参与:一鸣、JaminPython3.8的热乎劲还没过去,Python就又双叒叕要更新了。近日,3.9版本的第四个alpha版已经开源。从文档中,我们可以看到官方透露的对dic...

Python3 基本数据类型详解(python三种基本数据类型)

文章来源:加米谷大数据Python中的变量不需要声明。每个变量在使用前都必须赋值,变量赋值以后该变量才会被创建。在Python中,变量就是变量,它没有类型,我们所说的"类型"是变...

一文掌握Python的字典(python字典用法大全)

字典是Python中最强大、最灵活的内置数据结构之一。它们允许存储键值对,从而实现高效的数据检索、操作和组织。本文深入探讨了字典,涵盖了它们的创建、操作和高级用法,以帮助中级Python开发...

超级完整|Python字典详解(python字典的方法或操作)

一、字典概述01字典的格式Python字典是一种可变容器模型,且可存储任意类型对象,如字符串、数字、元组等其他容器模型。字典的每个键值key=>value对用冒号:分割,每个对之间用逗号,...

Python3.9版本新特性:字典合并操作的详细解读

处于测试阶段的Python3.9版本中有一个新特性:我们在使用Python字典时,将能够编写出更可读、更紧凑的代码啦!Python版本你现在使用哪种版本的Python?3.7分?3.5分?还是2.7...

python 自学,字典3(一些例子)(python字典有哪些基本操作)

例子11;如何批量复制字典里的内容2;如何批量修改字典的内容3;如何批量修改字典里某些指定的内容...

Python3.9中的字典合并和更新,几乎影响了所有Python程序员

全文共2837字,预计学习时长9分钟Python3.9正在积极开发,并计划于今年10月发布。2月26日,开发团队发布了alpha4版本。该版本引入了新的合并(|)和更新(|=)运算符,这个新特性几乎...

Python3大字典:《Python3自学速查手册.pdf》限时下载中

最近有人会想了,2022了,想学Python晚不晚,学习python有前途吗?IT行业行业薪资高,发展前景好,是很多求职群里严重的香饽饽,而要进入这个高薪行业,也不是那么轻而易举的,拿信工专业的大学生...

python学习——字典(python字典基本操作)

字典Python的字典数据类型是基于hash散列算法实现的,采用键值对(key:value)的形式,根据key的值计算value的地址,具有非常快的查取和插入速度。但它是无序的,包含的元素个数不限,值...

324页清华教授撰写【Python 3 菜鸟查询手册】火了,小白入门字典

如何入门学习python...

Python3.9中的字典合并和更新,了解一下

全文共2837字,预计学习时长9分钟Python3.9正在积极开发,并计划于今年10月发布。2月26日,开发团队发布了alpha4版本。该版本引入了新的合并(|)和更新(|=)运算符,这个新特性几乎...

python3基础之字典(python中字典的基本操作)

字典和列表一样,也是python内置的一种数据结构。字典的结构如下图:列表用中括号[]把元素包起来,而字典是用大括号{}把元素包起来,只不过字典的每一个元素都包含键和值两部分。键和值是一一对应的...

取消回复欢迎 发表评论:

请填写验证码