一、数据集
此任务采用CIFAR-10数据集,CIFAR-10数据集由10个类的60000个32x32彩色图像组成,每个类有6000个图像。有50000个训练图像和10000个测试图像
二、实现过程
2.1 导入必要的库
import time
import torch
import torchvision.datasets
from torch import nn
from torch.utils.data import DataLoader
from torch.utils.tensorboard import SummaryWriter
2.2 数据集的装载和处理
# 装载数据集
train_dataset = torchvision.datasets.CIFAR10("./dataset1", train=True, transform=torchvision.transforms.ToTensor())
test_dataset = torchvision.datasets.CIFAR10("./dataset1", train=False, transform=torchvision.transforms.ToTensor())
# 计算数据集的长度,用于计算正确率
train_data_size = len(train_dataset)
test_data_size = len(test_dataset)
print("训练数据集长度:{}".format(train_data_size))
print("测试数据集长度:{}".format(test_data_size))
trian_dataloader = DataLoader(train_dataset, batch_size=64)
test_dataloader = DataLoader(test_dataset, batch_size=64)
2.3 构建卷积神经网络
对于图像数据,卷积神经网络利用了卷积和池化层,能够高效的提取图像的重要特征,再通过最后的全连接层处理压缩后的图像信息,同时输出结果。与线性神经网络相比,卷积神经网络的参数大幅度减少。
class LYTNN(nn.Module):
def __init__(self):
super(LYTNN, self).__init__()
self.model = nn.Sequential(
nn.Conv2d(in_channels=3, out_channels=32, kernel_size=5, stride=1, padding=2),
nn.MaxPool2d(2),
nn.Conv2d(in_channels=32, out_channels=32, kernel_size=5, stride=1, padding=2),
nn.MaxPool2d(2),
nn.Conv2d(in_channels=32, out_channels=64, kernel_size=5, stride=1, padding=2),
nn.MaxPool2d(2),
nn.Flatten(),
nn.Linear(64 * 4 * 4, 64),
nn.Linear(64, 10)
)
def forward(self, x):
x = self.model(x)
return x
2.4 训练过程
训练过程包括确认学习率,损失函数,优化方法,其中损失函数使用交叉熵损失函数,学习率为0.01,优化方法为随机梯度下降法。
lytnn = LYTNN()
lytnn = lytnn.to(device)
lossfuction = nn.CrossEntropyLoss()
lossfuction = lossfuction.to(device)
# 定义优化器的方法和学习速率
learning_rating = 1e-2
optimizer = torch.optim.SGD(lytnn.parameters(), lr=learning_rating)
# 训练过程
total_train_step = 0
total_test_step = 0
epcho = 10
writer = SummaryWriter("nntrain")
start_time = time.time()
lytnn.train()
for i in range(epcho):
print("第{}轮训练开始".format(i+1))
for data in test_dataloader:
imgs, targets = data
imgs = imgs.to(device)
targets = targets.to(device)
opput = lytnn(imgs)
rest_loss = lossfuction(opput, targets)
optimizer.zero_grad()
rest_loss.backward()
optimizer.step()
total_train_step = total_train_step + 1
if total_train_step % 100 == 0:
end_time = time.time()
print(end_time-start_time)
print("训练次数{},loss={}".format(total_train_step, rest_loss.item()))
writer.add_scalar("train_loss", rest_loss.item(), total_test_step)
total_test_loss = 0
total_accuracy = 0
# 测试开始
lytnn.eval()
with torch.no_grad():
for data in test_dataloader:
imgs, targets = data
imgs = imgs.to(device)
targets = targets.to(device)
outputs = lytnn(imgs)
rest_loss1 = lossfuction(outputs, targets) # 计算损失
total_test_loss = total_test_loss + rest_loss1.item()
accuracy = (outputs.argmax(1) == targets).sum() # 计算单个图片正确率
total_accuracy = total_accuracy + accuracy # 总体正确率
print("整体测试集上的loss:{}".format(total_test_loss))
print("整体测试集上的正确率{}".format(total_accuracy/test_data_size))
writer.add_scalar("test_loss", total_test_loss, total_test_step)
total_test_step = total_test_step + 1
# torch.save(lytnn.state_dict(),"lyt{}.pth".format(i))
torch.save(lytnn, "lyt{}.pth".format(i))
print("模型已经保存")
使用Google colab实验室的线上设备进行训练,在训练了76轮后在模型在测试集上的正确率可以达到百分之86,学习率为0.01
为了提高准确率将训练轮数提升到了140次,经过训练后显示此时在整体测试集上的正确率达到了百分之百,那么是否在测试集上的正确率为百分之百就表示此时的模型可以准确的对10种类别的物体进行分类呢?
三、测试过程
随机选取了部分CIFAR-10数据集的图片进行测试,基本所有图片的类别模型都能准确无误的识别出,结果如下
在互联网上找到了一些图片进行测试
选择不同物体类别的图片进行测试时能够准确的判断类别并输出结果,但在选择多张鹿的图片进行测试时,大多数时候模型能够判断准确,但仍然存在不准确的情况,如对下图鹿的图片进行判断时,没有判断出这是一只鹿而是判断为狗,并没有达到百分之百的准确率,而且如果将图片截图范围变小,截取不同部分,判断的结果也会出现偏差,甚至判断为船,这种现象的出现是由于模型选取导致的?还是数据集的限制目前我还不得而知。
四、总结
此次图像识别任务,在测试集上可以达成较高的识别率,在测试集和验证集外互联网上的图片中,部分较好区分的类别如青蛙,鸟之类的也可以达到较高的准确率,但是在鹿,狗,这种相类似的种类上的区分时识别准确率不高,可能在选择更好的数据集时此类状况可以达到改变,本文没有加深卷积网络的层数,对学习率的调整也较少因为仅仅只在增加了训练轮数之后,模型在测试集上的准确率就达到了惊人的百分之百,如果采用图像扩增技术,是否可以提升在测试集之外图形的识别准确率呢?如果不修改数据集,还有什么方法可以提升测试集之外图形的识别准确率呢?