如何用PyTorch训练图像分类器

简介: 如果你刚刚开始使用PyTorch并想学习如何进行基本的图像分类,那么你可以参考本教程。
TB1bRLXr9zqK1RjSZPcXXbTepXa.jpg

本文为 AI 研习社编译的技术博客,原标题 :

How to Train an Image Classifier in PyTorch and use it to Perform Basic Inference on Single Images

作者 | Chris Fotache

翻译 | shunshun

校对 | 酱番梨        整理 | 菠萝妹

原文链接:

https://medium.com/@chrisfotache/how-to-train-an-image-classifier-in-pytorch-and-use-it-to-perform-basic-inference-on-single-images-99465a1e9bf5

如果你刚刚开始使用PyTorch并想学习如何进行基本的图像分类,那么你可以参考本教程。它将介绍如何组织训练数据,使用预训练神经网络训练模型,然后预测其他图像。

为此,我将使用由Google地图中的地图图块组成的数据集,并根据它们包含的地形特征对它们进行分类。我会在另一篇文章中介绍如何使用它(简而言之:为了识别无人机起飞或降落的安全区域)。但是现在,我只想使用一些训练数据来对这些地图图块进行分类。

下面的代码片段来自Jupyter Notebook。你可以将它们拼接在一起以构建自己的Python脚本,或从GitHub下载。这些Notebook是基于Udacity的PyTorch课程的。如果你使用云端虚拟机进行深度学习开发并且不知道如何远程打开notebook,请查看我的教程。

  组织训练数据集

PyTorch希望数据按文件夹组织,每个类对应一个文件夹。大多数其他的PyTorch教程和示例都希望你先按照训练集和验证集来组织文件夹,然后在训练集和验证集中再按照类别进行组织。但我认为这非常麻烦,必须从每个类别中选择一定数量的图像并将它们从训练集文件夹移动到验证集文件夹。由于大多数人会通过选择一组连续的文件作为验证集,因此选择可能存在很多偏差。

因此,这儿有一个将数据集快速分为训练集和测试集的更好的方法,就像Python开发人员习惯使用sklearn一样。首先,让我们导入模块:

%matplotlib inline

%config InlineBackend.figure_format = 'retina'

import matplotlib.pyplot as plt

import numpy as np

import torch

from torch import nn

from torch import optim

import torch.nn.functional as F

from torchvision import datasets, transforms, models

接下来,我们将定义train/validation数据集加载器,使用SubsetRandomSampler进行拆分:

data_dir = '/data/train'

def load_split_train_test(datadir, valid_size = .2):

   train_transforms = transforms.Compose([transforms.Resize(224),

                                      transforms.ToTensor(),

                                      ])

   test_transforms = transforms.Compose([transforms.Resize(224),

                                     transforms.ToTensor(),

                                     ])

   train_data = datasets.ImageFolder(datadir,      

                   transform=train_transforms)

   test_data = datasets.ImageFolder(datadir,

                   transform=test_transforms)

   num_train = len(train_data)

   indices = list(range(num_train))

   split = int(np.floor(valid_size * num_train))

   np.random.shuffle(indices)

   from torch.utils.data.sampler import SubsetRandomSampler

   train_idx, test_idx = indices[split:], indices[:split]

   train_sampler = SubsetRandomSampler(train_idx)

   test_sampler = SubsetRandomSampler(test_idx)

   trainloader = torch.utils.data.DataLoader(train_data,

                  sampler=train_sampler, batch_size=64)

   testloader = torch.utils.data.DataLoader(test_data,

                  sampler=test_sampler, batch_size=64)

   return trainloader, testloader

trainloader, testloader = load_split_train_test(data_dir, .2)

print(trainloader.dataset.classes)

接下来我们将确定是否有GPU。我假设你有一台GPU机器,否则代码将至少慢10倍。但是,检查GPU可用性是个好主意。

我们还将加载预训练模型。对于这种情况,我选择ResNet 50:

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

                                 else "cpu")

model = models.resnet50(pretrained=True)

print(model)

打印模型将显示ResNet模型的图层体系结构。这可能超出了我的意识或你的理解,但看到那些深层隐藏层内的东西仍然很有趣。

这取决于你选择什么样的模型,根据你的特定数据集模型可能会不同。这里列出了所有的PyTorch模型。

现在我们进入深度神经网络的有趣部分。首先,我们必须冻结预训练过的层,因此在训练期间它们不会进行反向传播。然后,我们重新定义最后的全连接层,即使用我们的图像来训练的图层。我们还创建了标准(损失函数)并选择了一个优化器(在这种情况下为Adam)和学习率。

for param in model.parameters():

   param.requires_grad = False

   

model.fc = nn.Sequential(nn.Linear(2048, 512),

                                nn.ReLU(),

                                nn.Dropout(0.2),

                                nn.Linear(512, 10),

                                nn.LogSoftmax(dim=1))

criterion = nn.NLLLoss()

optimizer = optim.Adam(model.fc.parameters(), lr=0.003)

model.to(device)

现在完成了,让我们训练模型吧!在这个例子中只有一个epoch,但在大多数情况下你需要更多。从代码中可以看出基本过程非常直观:加载批量图像并执行前向传播循环。然后计算损失函数,并使用优化器在反向传播中应用梯度下降。

PyTorch就这么简单。下面的大多数代码是每10个批次显示损失并计算的准确度,所以你在训练运行时得到更新。在验证期间,不要忘记将模型设置为eval()模式,然后在完成后返回train()。

epochs = 1

steps = 0

running_loss = 0

print_every = 10

train_losses, test_losses = [], []

for epoch in range(epochs):

   for inputs, labels in trainloader:

       steps += 1

       inputs, labels = inputs.to(device), labels.to(device)

       optimizer.zero_grad()

       logps = model.forward(inputs)

       loss = criterion(logps, labels)

       loss.backward()

       optimizer.step()

       running_loss += loss.item()

       

       if steps % print_every == 0:

           test_loss = 0

           accuracy = 0

           model.eval()

           with torch.no_grad():

               for inputs, labels in testloader:

                   inputs, labels = inputs.to(device),

                                     labels.to(device)

                   logps = model.forward(inputs)

                   batch_loss = criterion(logps, labels)

                   test_loss += batch_loss.item()

                   

                   ps = torch.exp(logps)

                   top_p, top_class = ps.topk(1, dim=1)

                   equals =

                       top_class == labels.view(*top_class.shape)

                   accuracy +=

                  torch.mean(equals.type(torch.FloatTensor)).item()

           train_losses.append(running_loss/len(trainloader))

           test_losses.append(test_loss/len(testloader))                    

           print(f"Epoch {epoch+1}/{epochs}.. "

                 f"Train loss: {running_loss/print_every:.3f}.. "

                 f"Test loss: {test_loss/len(testloader):.3f}.. "

                 f"Test accuracy: {accuracy/len(testloader):.3f}")

           running_loss = 0

           model.train()

torch.save(model, 'aerialmodel.pth')

等待几分钟后(或更长时间后,取决于数据集的大小和时期数量),完成训练并保存模型以供以后预测!

现在还有一件事可以做,即绘制训练和验证损失图:

plt.plot(train_losses, label='Training loss')

plt.plot(test_losses, label='Validation loss')

plt.legend(frameon=False)

plt.show()

TB1FhPor4TpK1RjSZFGXXcHqFXa.png

如你所见,在我的一个epoch的特定例子中,验证损失(这是我们感兴趣的)在第一个epoch结束时的平坦线条甚至开始有上升趋势,所以可能1个epoch就足够了。正如预期的那样,训练损失非常低。

现在进入第二部分。你训练模型,保存模型,并需要在应用程序中使用它。为此,你需要能够对图像执行简单推理。你也可以在我们的存储库中找到此演示notebook。我们导入与训练笔记本中相同的模块,然后再次定义变换(transforms)。我只是再次声明图像文件夹,所以我可以使用那里的一些例子:

data_dir = '/datadrive/FastAI/data/aerial_photos/train'

test_transforms = transforms.Compose([transforms.Resize(224),

                                     transforms.ToTensor(),

                                    ])

然后我们再次检查GPU可用性,加载模型并将其置于评估模式(因此参数不会改变):

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

model=torch.load('aerialmodel.pth')

model.eval()

预测特定图像的类的功能非常简单。请注意,它需要Pillow图像,而不是文件路径。

def predict_image(image):

   image_tensor = test_transforms(image).float()

   image_tensor = image_tensor.unsqueeze_(0)

   input = Variable(image_tensor)

   input = input.to(device)

   output = model(input)

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

   return index

现在为了便于测试,我还创建了一个从数据集文件夹中选择大量随机图像的函数:

def get_random_images(num):

   data = datasets.ImageFolder(data_dir, transform=test_transforms)

   classes = data.classes

   indices = list(range(len(data)))

   np.random.shuffle(indices)

   idx = indices[:num]

   from torch.utils.data.sampler import SubsetRandomSampler

   sampler = SubsetRandomSampler(idx)

   loader = torch.utils.data.DataLoader(data,

                  sampler=sampler, batch_size=num)

   dataiter = iter(loader)

   images, labels = dataiter.next()

   return images, labels

最后,为了演示预测函数,我得到随机图像样本,预测它们并显示结果:

to_pil = transforms.ToPILImage()

images, labels = get_random_images(5)

fig=plt.figure(figsize=(10,10))

for ii in range(len(images)):

   image = to_pil(images[ii])

   index = predict_image(image)

   sub = fig.add_subplot(1, len(images), ii+1)

   res = int(labels[ii]) == index

   sub.set_title(str(classes[index]) + ":" + str(res))

   plt.axis('off')

   plt.imshow(image)

plt.show()

以下是Google地图图块上此类预测的一个示例。标签是预测的类,我也在显示它是否是正确的预测。

TB1.Zfnr4TpK1RjSZR0XXbEwXXa.jpg

这就是它。继续尝试数据集。只要你正确组织图像,此代码应该按原样运行。很快我就会有更多关于神经网络和PyTorch可以做的很酷的文章。

Chris Fotache是位于 New Jersey的 CYNET.ai的人工智能研究员。他涵盖了与生活中的人工智能,Python编程,机器学习,计算机视觉,自然语言处理等相关的主题。雷锋网雷锋网雷锋网(公众号:雷锋网)

想要继续查看该篇文章相关链接和参考文献?

长按链接点击打开或点击【如何使用PyTorch训练图像分类器】:

http://ai.yanxishe.com/page/TextTranslation/1272

AI研习社每日更新精彩内容,观看更多精彩内容:

使用Python来图像增强

新手必看:手把手教你入门 Python

多目标追踪器:用OpenCV实现多目标追踪(C++/Python)

数据科学家应当了解的五个统计基本概念:统计特征、概率分布、降维、过采样/欠采样、贝叶斯统计

等你来译:

基于图像的路径规划:Dijkstra算法

掌握机器学习必须要了解的4个概念

正向和反向运动学:雅可比和微分运动

取得自然语言处理SOA结果的分层多任务学习模型(HMTL) 

相关实践学习
在云上部署ChatGLM2-6B大模型(GPU版)
ChatGLM2-6B是由智谱AI及清华KEG实验室于2023年6月发布的中英双语对话开源大模型。通过本实验,可以学习如何配置AIGC开发环境,如何部署ChatGLM2-6B大模型。
目录
相关文章
|
7月前
|
机器学习/深度学习 PyTorch API
PyTorch量化感知训练技术:模型压缩与高精度边缘部署实践
本文深入探讨神经网络模型量化技术,重点讲解训练后量化(PTQ)与量化感知训练(QAT)两种主流方法。PTQ通过校准数据集确定量化参数,快速实现模型压缩,但精度损失较大;QAT在训练中引入伪量化操作,使模型适应低精度环境,显著提升量化后性能。文章结合PyTorch实现细节,介绍Eager模式、FX图模式及PyTorch 2导出量化等工具,并分享大语言模型Int4/Int8混合精度实践。最后总结量化最佳策略,包括逐通道量化、混合精度设置及目标硬件适配,助力高效部署深度学习模型。
1087 21
PyTorch量化感知训练技术:模型压缩与高精度边缘部署实践
|
5月前
|
机器学习/深度学习 PyTorch 测试技术
从训练到推理:Intel Extension for PyTorch混合精度优化完整指南
PyTorch作为主流深度学习框架,凭借动态计算图和异构计算支持,广泛应用于视觉与自然语言处理。Intel Extension for PyTorch针对Intel硬件深度优化,尤其在GPU上通过自动混合精度(AMP)提升训练与推理性能。本文以ResNet-50在CIFAR-10上的实验为例,详解如何利用该扩展实现高效深度学习优化。
287 0
|
7月前
|
算法 PyTorch 算法框架/工具
PyTorch 实现FCN网络用于图像语义分割
本文详细讲解了在昇腾平台上使用PyTorch实现FCN(Fully Convolutional Networks)网络在VOC2012数据集上的训练过程。内容涵盖FCN的创新点分析、网络架构解析、代码实现以及端到端训练流程。重点包括全卷积结构替换全连接层、多尺度特征融合、跳跃连接和反卷积操作等技术细节。通过定义VOCSegDataset类处理数据集,构建FCN8s模型并完成训练与测试。实验结果展示了模型在图像分割任务中的应用效果,同时提供了内存使用优化的参考。
|
7月前
|
算法 PyTorch 算法框架/工具
昇腾910-PyTorch 实现 Vggnet图像分类
本实验基于昇腾平台,使用PyTorch实现Vggnet模型对CIFAR10数据集进行图像分类。内容涵盖Vggnet模型创新点(小卷积核堆叠、深层网络结构)、网络架构剖析及代码实战分析。通过定义`blockVGG`函数构建卷积块,实现VGG11网络,并结合数据预处理、训练与测试模块完成分类任务。实验展示了深度学习中增加网络深度对性能提升的重要性。
|
11月前
|
机器学习/深度学习 算法 PyTorch
昇腾910-PyTorch 实现 ResNet50图像分类
本实验基于PyTorch,在昇腾平台上使用ResNet50对CIFAR10数据集进行图像分类训练。内容涵盖ResNet50的网络架构、残差模块分析及训练代码详解。通过端到端的实战讲解,帮助读者理解如何在深度学习中应用ResNet50模型,并实现高效的图像分类任务。实验包括数据预处理、模型搭建、训练与测试等环节,旨在提升模型的准确率和训练效率。
532 54
|
11月前
|
机器学习/深度学习 算法 PyTorch
PyTorch 实现MobileNetV1用于图像分类
本实验基于PyTorch和昇腾平台,详细讲解了如何使用MobileNetV1模型对CIFAR10数据集进行图像分类。内容涵盖MobileNetV1的特点、网络架构剖析(尤其是深度可分离卷积)、代码实现及训练过程。通过该实验,读者可以掌握轻量级CNN模型在移动端或嵌入式设备中的应用,并了解其在资源受限环境下的高效表现。实验包括数据预处理、模型训练与测试等环节,帮助用户快速上手并优化模型性能。
399 53
|
机器学习/深度学习 并行计算 PyTorch
优化技巧与策略:提高 PyTorch 模型训练效率
【8月更文第29天】在深度学习领域中,PyTorch 是一个非常流行的框架,被广泛应用于各种机器学习任务中。然而,随着模型复杂度的增加以及数据集规模的增长,如何有效地训练这些模型成为了一个重要的问题。本文将介绍一系列优化技巧和策略,帮助提高 PyTorch 模型训练的效率。
1056 0
|
12月前
|
机器学习/深度学习 人工智能 PyTorch
使用PyTorch实现GPT-2直接偏好优化训练:DPO方法改进及其与监督微调的效果对比
本文将系统阐述DPO的工作原理、实现机制,以及其与传统RLHF和SFT方法的本质区别。
921 22
使用PyTorch实现GPT-2直接偏好优化训练:DPO方法改进及其与监督微调的效果对比
|
11月前
|
机器学习/深度学习 算法 PyTorch
昇腾910-PyTorch 实现 GoogleNet图像分类
本实验基于PyTorch在昇腾平台上实现GoogleNet模型,针对CIFAR-10数据集进行图像分类。内容涵盖GoogleNet的创新点(如Inception模块、1x1卷积、全局平均池化等)、网络架构解析及代码实战分析。通过详细讲解模型搭建、数据预处理、训练与测试过程,帮助读者掌握如何使用经典CNN模型进行高效图像分类。实验中还介绍了辅助分类器、梯度传播优化等技术细节,并提供了完整的训练和测试代码示例。
|
11月前
|
机器学习/深度学习 算法 PyTorch
昇腾910-PyTorch 实现 Alexnet图像分类
本文介绍了在昇腾平台上使用PyTorch实现AlexNet对CIFAR-10数据集进行图像分类的实战。内容涵盖AlexNet的创新点、网络架构解析及代码实现,包括ReLU激活函数、Dropout、重叠最大池化等技术的应用。实验中详细展示了如何构建模型、加载数据集、定义训练和测试模块,并通过60个epoch的训练验证模型性能。

热门文章

最新文章

推荐镜像

更多