pytorch--CIFAR-10

1. CIFAR-10简介

CIFAR-10指的是加拿大计算机科学家Alex Krizhevsky、Vinod Nair和Geoffrey Hinton在2009年发布的一个数据集。这个数据集中一共有60000幅32x32的彩色图片,其中50000张用作训练集,另外10000张作为测试集。图片分为10个分类,每个分类有6000张图。具体分类包括:飞机(airplane)、汽车(automobile)、鸟(bird)、猫(cat)、鹿(deer)、狗(dog)、青蛙(frog)、马(horse)、船(ship)和卡车(truck)。

2. pytorch中的CIFAR-10数据集加载

2.1 安装torchvision

首先需要安装torchvision,它是pytorch中专门用于处理图像相关任务的工具包。可以通过以下命令进行安装:

pip install torchvision

若pip安装速度过慢,可以尝试使用清华源:

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple torchvision

2.2 加载CIFAR-10数据集

在pytorch中,可以使用torchvision.datasets.CIFAR10()函数轻松加载CIFAR-10数据集。加载方式如下:

import torchvision.transforms as transforms

import torchvision.datasets as datasets

transform = transforms.Compose([

transforms.Resize((224, 244)),

transforms.ToTensor(),

transforms.Normalize(mean=[0.485, 0.456, 0.406],

std=[0.229, 0.224, 0.225])

])

train_dataset = datasets.CIFAR10(root='./data', train=True,

download=True, transform=transform)

test_dataset = datasets.CIFAR10(root='./data', train=False,

download=True, transform=transform)

从代码中可以看出,我们使用了transforms模块中的Compose函数,它能将多个图像增强操作组合在一起,并以相同的顺序应用于输入图像。这里的Compose函数包括了resize、ToTensor和Normalize三个步骤。resize用于将图像尺寸缩放到(224, 244),使其匹配预训练的神经网络模型要求的输入尺寸;ToTensor将图像转换成pytorch中的tensor格式;Normalize对图像进行标准化处理。

接下来,我们使用datasets.CIFAR10()函数分别加载训练集和测试集,并将处理后的数据存于train_dataset和test_dataset两个变量中。

3. CIFAR-10数据集可视化

在加载CIFAR-10数据集后,我们可以在控制台中输出一些样本图像进行可视化。因为这里每个图像都是3通道的,我们需要对每个通道进行还原,然后再把这三个通道合并成一个彩色图像。代码示例如下:

import matplotlib.pyplot as plt

import numpy as np

def imshow(img):

img = img / 2 + 0.5 # 将图像像素值还原成[0,1]范围内

npimg = img.numpy() # 将图像转换成numpy数组

plt.imshow(np.transpose(npimg, (1, 2, 0))) # 将[3,224,224]的图像转换成[224,224,3],再进行可视化

plt.show()

# 获取随机一张训练集图像

dataiter = iter(train_dataset)

images, labels = dataiter.next()

# 显示图像

imshow(torchvision.utils.make_grid(images))

运行上述代码后,将随机从训练集中取出一张图像,其对应的标签在labels变量中。我们可以将图像可视化显示到控制台中,如下图所示:

4. pytorch中使用预训练模型进行物体识别

pytorch提供了很多常用的预训练模型,可以在已经处理好的图像上进行测试。这里我们选取了pytorch的ResNet18模型进行预测。ResNet18是一个经典的卷积神经网络模型,它的结构非常简单,但在ImageNet上的表现非常优秀。

4.1 加载预训练模型

我们可以通过以下代码来加载ResNet18模型:

import torch.nn as nn

import torch.optim as optim

import torchvision.models as models

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# 加载预训练模型

net = models.resnet18(pretrained=True)

# 将模型转移到GPU上

net.to(device)

通过设置pretrained=True,可以将模型加载为ImageNet上的预训练模型。由于这里使用了ResNet18模型,因此输出层包含1000个神经元,不符合CIFAR-10的要求,因此我们需要修改ResNet18模型的最后一层,使其符合CIFAR-10的类别数要求。修改后的代码如下:

# 修改ResNet18模型的最后一层,使其符合CIFAR-10的类别数要求

num_ftrs = net.fc.in_features

net.fc = nn.Linear(num_ftrs, 10) # 这里10表示CIFAR-10数据集中的类别数

4.2 训练网络

首先,我们需要定义损失函数和优化器。这里我们选用交叉熵损失函数和随机梯度下降优化器:

criterion = nn.CrossEntropyLoss()  # 定义损失函数

optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9) # 定义优化器

接下来,我们使用CIFAR-10的训练集进行模型训练:

from tqdm import tqdm

for epoch in range(10): # 循环10个epochs

running_loss = 0.0

for i, data in tqdm(enumerate(train_dataset, 0)): # 从训练集中迭代一个batch

# 获取训练集图像和标签

inputs, labels = data[0].to(device), data[1].to(device)

optimizer.zero_grad() # 梯度清零

# 计算模型预测结果

outputs = net(inputs)

# 计算损失值

loss = criterion(outputs, labels)

# 反向传播

loss.backward()

# 更新模型参数

optimizer.step()

# 输出统计信息

running_loss += loss.item()

if i % 2000 == 1999:

print('[%d, %5d] loss: %.3f' %

(epoch + 1, i + 1, running_loss / 2000))

running_loss = 0.0

4.3 测试网络

模型训练完之后,我们使用CIFAR-10的测试集对其进行测试:

correct = 0  # 统计预测正确的样本数

total = 0 # 总样本数

with torch.no_grad():

for data in test_dataset: # 迭代测试集

# 获取测试集图像和标签

images, labels = data[0].to(device), data[1].to(device)

# 计算模型预测结果

outputs = net(images)

# 统计总样本数和预测正确的样本数

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

total += labels.size(0)

correct += (predicted == labels).sum().item()

# 输出测试集上的准确率

print('Accuracy of the network on the 10000 test images: %d %%' % (

100 * correct / total))

最终的测试准确率可以达到81%以上,效果还是相当不错的。

后端开发标签