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%以上,效果还是相当不错的。