卷积神经网络与图像分类

随着机器学习人工智能需求的增长,越来越多的公司开始开发计算机系统和新技术以实现这一目标。人工智能已经成为全球增长最快的技术之一,据估计每天新增机器超过30,000台。目标检测和目标分类是人工智能的一部分,目前也呈现出显著的增长趋势。自动驾驶汽车越来越受欢迎,这些汽车能够实时检测道路上的物体,使用高效的目标检测模型。此外,使用智能驾驶技术检测行人也成为一个流行行业,一些公司如特斯拉正在引领这一潮流。

在本文中,将创建一个使用卷积神经网络图像分类模型,能够对10个不同类别的图像进行分类。还将讨论训练模型在测试集上的准确度和损失曲线。

数据集分析:

CIFAR-10数据集包含60,000张32×32彩色图像,每个类别包含6000张图像,共有十个类别。它由50,000张32×32彩色训练图像组成,跨越十个类别,以及10,000张测试图像。对于CIFAR-FS数据集,训练测试分割也是50000个样本用于训练,10000个用于测试。图像大小为32×32×3。

存在的不同类别包括:['飞机', '汽车', '鸟', '猫', '鹿', '狗', '青蛙', '马', '船', '卡车']。每个测试和训练数据集中不同类别的样本数量如下:

train_dataset class : {'青蛙': 5000, '卡车': 5000, '鹿': 5000, '汽车': 5000, '鸟': 5000, '马': 5000, '船': 5000, '猫': 5000, '狗': 5000, '飞机': 5000} test_dataset class : {'猫': 1000, '船': 1000, '飞机': 1000, '青蛙': 1000, '汽车': 1000, '卡车': 1000, '狗': 1000, '马': 1000, '鹿': 1000, '鸟': 1000}

实现:

在这一部分,将看到加载和预处理Cifar-10数据集的代码。首先,将使用torchvision库直接下载数据集,并将数据集分为训练集和测试集。

import torchvision import torch from torch.utils.data import DataLoader from torchvision import transforms # 设置 torch.manual_seed(42) # 加载数据集 train_dataset = torchvision.datasets.CIFAR10(root='data/', train=True, download=True, transform=transforms.ToTensor()) test_dataset = torchvision.datasets.CIFAR10(root='data/', download=True, train=False, transform=transforms.ToTensor()) # 分割数据集 my_list = [45000, 5000] train_ds, val_ds = torch.utils.data.random_split(train_dataset, my_list) # 配置 configs = {'random_seed': 42, 'val_size': 5000, 'train_size': 45000, 'pin_memory': True, 'optimizer': 'Adam', 'batch_size': 64, 'lr': 0.001} # 数据加载器 train_data = DataLoader(train_ds, configs['batch_size'], shuffle=True, pin_memory=configs['pin_memory'], num_workers=2) val_data = DataLoader(val_ds, configs['batch_size'], shuffle=True, pin_memory=configs['pin_memory'], num_workers=2)

将检查系统是否包含专用GPU。GPU可以加速训练过程,因为它包含特殊硬件。

def GPU_IsAvailable(): if torch.cuda.is_available(): temp = torch.device('cuda') return temp else: tmp1 = torch.device('cpu') return tmp1

下面,编写了一些基本函数,如evaluate,用于评估模型在测试数据上的准确度。另一个名为fit的函数用于拟合CNN模型内的训练数据。

import torch.nn as nn import torch.optim as optim channel = 3 num = 28 @torch.no_grad() def evaluate(model, val_loader, dt_load): model.eval() outputs = [] for i in val_loader: temp = model.val_func(i, num, channel) outputs.append(temp) var3 = model.valid_func(outputs, num) return var3 def fit(epochs, lr, model, train_loader, val_loader): lst1 = list() lst2 = list() opt_func = optim.Adam optimizer = opt_func(model.parameters(), lr) for epoch in range(epochs): lst3 = [] # 训练阶段 model.train() for batch in train_loader: loss = model.train_func(batch, num) lst3.append(loss) loss.backward() optimizer.step() optimizer.zero_grad() # 验证阶段 result = evaluate(model, val_loader, epoch) result['train_loss'] = torch.stack(lst3).mean().item() model.func(epoch, result, channel) lst1.append(result) return lst1

CNN模型将包含三层,每层包含一个卷积层和一个最大池化层。

two = 2 one = 1 class CnnModel1_2(nn.Module): def __init__(self): super().__init__() self.network = nn.Sequential( nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1), nn.ReLU(), nn.MaxPool2d(2, 2), nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1), nn.ReLU(), nn.MaxPool2d(2, 2), nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1), nn.ReLU(), nn.MaxPool2d(2, 2), nn.Flatten(), nn.Linear(4*4*128, 10) ) def forward(self, x): x = self.network(x) return x

将设置训练周期为20,然后将训练数据输入模型。

model1_2 = CnnModel1_2() train_data1_2 = DataLoader(GPU_IsAvailable(), train_data) val_data1_2 = DataLoader(GPU_IsAvailable(), val_data) GPU_Calculate(model1_2, GPU_IsAvailable()) # 训练20个周期 num_epochs = 20 lr = configs['lr'] history = fit(num_epochs, lr, model1_2, train_data1_2, val_data1_2)

将绘制训练和验证损失随周期数变化的曲线。

import matplotlib.pyplot as plt train_losses = [x.get('train_loss') for x in history] val_losses = [x['val_loss'] for x in history] plt.plot(train_losses, '-bx') plt.plot(val_losses, '-yx') plt.xlabel('周期') plt.ylabel('损失') plt.legend(['训练', '验证']) plt.title('损失与周期数') plt.show()

将绘制训练和验证准确度随周期数变化的曲线。

accuracies = [x['val_acc'] for x in history] plt.plot(accuracies, '-yx') plt.xlabel('周期') plt.ylabel('准确度') plt.title('准确度与周期数') plt.show()

讨论:

改变网络大小如何影响准确度?卷积神经网络由两个主要部分组成,即特征提取和分类。在这些类型的网络中,卷积操作负责特征提取,而全连接层负责分类。观察到,从I到iii的三次实验中改变网络大小,准确度趋于提高,这表明改变网络大小会影响准确度。然而,相反地,观察到在第三种架构中存在两个全连接层。

实验不同的池化大小,并对池化大小对网络的影响进行详细分析。池化是一个用户定义的操作。手头有不同类型的池化,如最大池化、求和池化和平均池化,各有利弊。但通常使用最大池化,因为它在给定的问题陈述上表现更好,因为试图根据它们的重要性提取特征。由于它包含更多的特征提取层,双卷积块(Conv-Conv-Pool-Conv-Conv-Pool)比其他模型表现更好。它的区分能力增强,使其能够更好地工作。还发现,增加一个以上的FC层并不影响性能,这意味着增加额外的FC层并不能保证更好的性能。它更多地依赖于特征提取层。当增加池化大小时,会发生两件事之一,即要么获得更多的泛化能力,要么在更多的收缩发生时丢失一些重要特征。

  • 讨论了CIFAR-10数据集。发现这个数据集包含60000张32×32大小的图像,分为十个不同的类别,如鸟、猫、狗、鹿等。
  • 之后,讨论了数据集的加载和预处理。在这一步,直接从torchvision库下载数据集,然后将数据分为训练集和测试集。
  • 然后,使用CNN训练了模型。在这一步,首先检查了机器中GPU的可用性。之后,构建了一个由多个CNN层组成的管道,训练模型后,得到了损失和准确度曲线。
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485