PyTorch 实现MobileNetV1用于图像分类

简介: 本实验基于PyTorch和昇腾平台,详细讲解了如何使用MobileNetV1模型对CIFAR10数据集进行图像分类。内容涵盖MobileNetV1的特点、网络架构剖析(尤其是深度可分离卷积)、代码实现及训练过程。通过该实验,读者可以掌握轻量级CNN模型在移动端或嵌入式设备中的应用,并了解其在资源受限环境下的高效表现。实验包括数据预处理、模型训练与测试等环节,帮助用户快速上手并优化模型性能。

PyTorch 实现MobileNetV1用于图像分类

本实验主要介绍了如何在昇腾上,使用pytorch对经典的MobileNetV1模型在公开的CIFAR10数据集进行分类训练的实战讲解。内容包括MobileNetV1模型特点介绍MobileNetV1网络架构剖析MobileNetV1网络模型代码实战分析等等。

本实验的目录结构安排如下所示:

  • MobileNetV1网络模型介绍
  • MobileNetV1的网络架构剖析
  • 深度可分离卷积
  • MobileNetV1网络模型代码实现分析
  • MobileNetV1网络用于cifar数据集分类实战

MobileNetV1网络模型介绍

卷积神经网络(CNN)被普遍应用在计算机视觉领域,并且已经取得了不错的效果。为了追求分类准确度,模型深度越来越深,模型复杂度也越来越高,如深度残差网络(ResNet)其层数已经多达152层。然而,在某些真实的应用场景如移动或者嵌入式设备,如此大而复杂的模型是难以被应用的。

首先是模型过于庞大,面临着内存不足的问题,其次这些场景要求低延迟,或者说响应速度要快,想象一下自动驾驶汽车的行人检测系统如果速度很慢会发生什么可怕的事情。所以,研究小而高效的CNN模型在这些场景至关重要。

1.jpg

MobileNetV1网络专注于移动端或者嵌入式设备中的轻量级CNN网络,该论文最大的创新点是,使用深度可分离卷积(深度卷积+点卷积)代替标准卷积来显著降低参数量的同时小幅度降低精度。

MobileNetV1的网络架构剖析

深度可分离卷积

MobileNet的基本单元是深度可分离卷积(depthwise separable convolution),下图中右侧部分,深度可分离卷积其实是一种可分解卷积操作,其可以分解为两个更小的操作:depthwise convolution和pointwise convolution。

2.jpg

Depthwise convolution和标准卷积不同,对于标准卷积其卷积核是作用在所有的输入通道上,而depthwise convolution针对每个输入通道采用不同的卷积核,就是说一个卷积核对应一个通道,所以说depthwise convolution是depth级别的操作。而pointwise convolution其实就是普通的卷积,只不过其采用1x1的卷积核。

深度可分离卷积为什么可以减少参数量

3.jpg

一个输入shape为FxFXM与卷积核大小为KxKxN执行一次卷积操作需要的乘法计算量:(KxK)xMxNxFxF。

常规卷积所需要的乘法计算量是:2x2x3x8x5x5 = 2400

深度可分离卷积所需要的乘法计算量:2x2x3x5x5 + 3x8x5x5 = 900

import torch
import torch.nn as nn
#  深度可分离卷积 DSC, 深度卷积 Depthwise + 逐点卷积 Pointwise  
class DSCconv(nn.Module):
    def __init__(self, in_ch, out_ch, stride=1):
        super(DSCconv, self).__init__()
        # 深度卷积, (DW+BN+ReLU)
        self.depthConv = nn.Sequential(
            nn.Conv2d(in_ch, in_ch, kernel_size=3, stride=stride,
                      padding=1, groups=in_ch, bias=False),
            nn.BatchNorm2d(in_ch),
            nn.ReLU6(inplace=True))
         # 逐点卷积, (PW+BN+ReLU)
        self.pointConv = nn.Sequential( 
            nn.Conv2d(in_ch, out_ch, kernel_size=1, stride=1, bias=False),
            nn.BatchNorm2d(out_ch),
            nn.ReLU6(inplace=True))

    def forward(self, x):
        x = self.depthConv(x)
        x = self.pointConv(x)
        return x

MobileNetV1网络代码实现分析

MobileNetV1简单的直筒型网络一条道走到黑,没有shortcut,唯一的黑科技也只有深度分离卷积了,但是这个也不是啥首创,Xception就用过这种技术了,之所以MobileNetV1能发论文,因为首次有人关注到Mobile AI领域,让Mobile能够流畅的运行一些简单的AI模型。

4.jpg

整个MobileNetV1网络用一个MobileNetV1类实现,'self.stage1'、'self.stage2'与'self.stage3'分别对应图中红框内模块,'self.avgpool'、self.linear与'self.softmax'与图中最后三个输出层相对应。

class MobileNetV1(nn.Module):
    def __init__(self, input_channel=3, num_classes=100):
        super(MobileNetV1, self).__init__()
        self.num_classes = num_classes
        self.entry = nn.Sequential(
            nn.Conv2d(input_channel, 32, kernel_size=3, stride=1, padding=1, bias=False),
            nn.BatchNorm2d(32),
            nn.ReLU6(inplace=True))
         # 
        self.stage1 = nn.Sequential(
            DSCconv(32, 64, 1),
            DSCconv(64, 128, 2),
            DSCconv(128, 128, 1),
            DSCconv(128, 256, 2),
            DSCconv(256, 256, 1))
         # 2
        self.stage2 = nn.Sequential(
            DSCconv(256, 512, 2),
            DSCconv(512, 512, 1),
            DSCconv(512, 512, 1),
            DSCconv(512, 512, 1),
            DSCconv(512, 512, 1),
            DSCconv(512, 512, 1))
         # 3
        self.stage3 = nn.Sequential(
            DSCconv(512, 1024, 2),
            DSCconv(1024, 1024, 1))

        self.avgpool = nn.AdaptiveAvgPool2d((1,1))  # torch.Size([batch, 1024, 1, 1])

        self.linear = nn.Linear(in_features=1024, out_features=num_classes)
        self.softmax = nn.Softmax(dim=1)

    def forward(self, x):
        x = self.entry(x)
        x = self.stage1(x)
        x = self.stage2(x)
        x = self.stage3(x)
        x = self.avgpool(x)
        x = x.view(x.size(0), -1)
        x = self.linear(x)
        out = self.softmax(x)
        return out

MobileNetV1网络用于cifar数据集分类实战

基于上述搭建好的网络模型,我们现在就可以正式来使用该模型开始训练cifir数据集。

导入昇腾npu相关库transfer_to_npu、该模块可以使能模型自动迁移至昇腾上。

import torch_npu
from torch_npu.contrib import transfer_to_npu

torchvision模块中集成了一些当今比较流行的数据集、模型架构和用于计算机视觉的常见图像转换功能,torchvision模块中含有本次实验所需要的CIFAR数据集,因此导入该模块用于数据集的下载。tqdm是用于训练过程中训练进度条,便于我们能够清晰的看到整个训练过程。

import torchvision
import torchvision.transforms as transforms
from tqdm import tqdm

数据集预处理功能定义: 对图像数据集进行不同程度的变化,包括裁剪、翻转等方式增加数据的多样性,防止过拟合现象的出现,以增强模型的泛化能力。

调用了torchvision中的transform库中的compose方法,使用裁剪(RandomCrop)、翻转(RandomHorizontalFlip)等组合成tensor形式后并对tensor进行正则化(Normalize)。

transform_train = transforms.Compose([
    transforms.RandomCrop(32, padding=4),
    transforms.RandomHorizontalFlip(),
    transforms.ToTensor(),
    transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),  
])  
transform_test = transforms.Compose([  
    transforms.ToTensor(),  
    transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),  
])

cifar数据集共有60000张彩色图像,这些图像是32*32,分为10个类,每类6000张图。有50000张用于训练,构成了5个训练批,每一批10000张图;另外10000用于测试,单独构成一批。测试批的数据里,取自10类中的每一类,每一类随机取1000张。抽剩下的就随机排列组成了训练批。注意一个训练批中的各类图像并不一定数量相同,总的来看训练批,每一类都有5000张图。

5.png

数据集加载: torchvision中集成了一些通用的开源数据集,其中也包含cifar,此处通过torchvision函数加载cifar数据集到工作目录上的指定路径,如果已经下载好了,会直接校验通过,不会二次进行下载。

trainset = torchvision.datasets.CIFAR10(  
    root='/home/ma-user/work/resnet50Experiments/dataset/cifar-10-batches-py', train=True, download=True, transform=transform_train)  
trainloader = torch.utils.data.DataLoader(  
    trainset, batch_size=128, shuffle=True)  
testset = torchvision.datasets.CIFAR10(  
    root='/home/ma-user/work/resnet50Experiments/dataset/cifar-10-batches-py', train=False, download=True, transform=transform_test)  
testloader = torch.utils.data.DataLoader(  
    testset, batch_size=100, shuffle=False)  
classes = ('plane', 'car', 'bird', 'cat', 'deer',  
           'dog', 'frog', 'horse', 'ship', 'truck')

训练模块: 根据传入的迭代次数'epoch'开始训练网络模型,这里需要在model开始前加入'net.train()',使用随机梯度下降算法是将梯度值初始化为0('zero_grad()'),计算梯度、通过梯度下降算法更新模型参数的值以及统计每次训练后的loss值(每隔100次打印一次)。

def train(epoch):  
    net.train()  
    train_loss = 0.0  
    epoch_loss = 0.0  
    for batch_idx, (inputs, targets) in enumerate(tqdm(trainloader, 0)):  
        inputs, targets = inputs.to(device), targets.to(device)  
        optimizer.zero_grad()  
        outputs = net(inputs)  
        loss = criterion(outputs, targets)  
        loss.backward()  
        optimizer.step()  
        lr_scheduler.step()

        train_loss += loss.item()  
        epoch_loss += loss.item()

        if batch_idx % 100 == 99:  # 每100次迭代打印一次损失  
            print(f'\[Epoch {epoch + 1}, Iteration {batch\_idx + 1}\] loss: {train\_loss / 100:.3f}')  
            train_loss = 0.0  
    return epoch_loss / len(trainloader)

测试模块: 每训练一轮将会对最新得到的训练模型效果进行测试,使用的是数据集准备时期划分得到的测试集,每类约为1000张。

def test():  
    net.eval()  
    test_loss = 0  
    correct = 0  
    total = 0  
    with torch.no_grad():  
        for batch_idx, (inputs, targets) in enumerate(tqdm(testloader)):  
            inputs, targets = inputs.to(device), targets.to(device)  
            outputs = net(inputs)  
            loss = criterion(outputs, targets)

            test_loss += loss.item()  
            _, predicted = outputs.max(1)  
            total += targets.size(0)  
            correct += predicted.eq(targets).sum().item()  
    return 100 * correct / total

主功能调用模块: 该模块用于开启模型在指定数据集(cifar)上训练,其中定义了硬件设备为昇腾npu(device = 'npu'),定义了损失函数为交叉熵损失'CrossEntropyLoss()',梯度下降优化算法为SGD并同时指定了学习率等参数。

import torch.optim as optim  
device = 'npu'  
net = MobileNetV1(num_classes=10)  
net = net.to(device)  
criterion = nn.CrossEntropyLoss()  
optimizer = optim.SGD(net.parameters(), lr=1.0, weight_decay=5e-4)  
lr_scheduler = torch.optim.lr_scheduler.OneCycleLR(optimizer,0.1,steps_per_epoch=len(trainloader),
                                                   epochs=150,div_factor=25,final_div_factor=10000,pct_start=0.3)

训练与测试的次数为60次,这里用户可以根据需要自行选择设置更高或更低,每个epoch的测试准确率都会被打印出来,如果不需要将代码注释掉即可。

for epoch in range(60):  
    epoch_loss = train(epoch)  
    test_accuray = test()  
    print(f'\\nTest accuracy for AlexNet at epoch {epoch + 1}: {test_accuray:.2f}%')  
    print(f'Epoch loss for AlexNet at epoch {epoch + 1}: {epoch_loss:.3f}')

Reference

[1] Howard A G. Mobilenets: Efficient convolutional neural networks for mobile vision applications[J]. arXiv preprint arXiv:1704.04861, 2017.

相关文章
|
9月前
|
机器学习/深度学习 PyTorch 算法框架/工具
【PyTorch实战演练】使用Cifar10数据集训练LeNet5网络并实现图像分类(附代码)
【PyTorch实战演练】使用Cifar10数据集训练LeNet5网络并实现图像分类(附代码)
568 0
|
11天前
|
机器学习/深度学习 算法 PyTorch
昇腾910-PyTorch 实现 ResNet50图像分类
本实验基于PyTorch,在昇腾平台上使用ResNet50对CIFAR10数据集进行图像分类训练。内容涵盖ResNet50的网络架构、残差模块分析及训练代码详解。通过端到端的实战讲解,帮助读者理解如何在深度学习中应用ResNet50模型,并实现高效的图像分类任务。实验包括数据预处理、模型搭建、训练与测试等环节,旨在提升模型的准确率和训练效率。
106 54
|
16天前
|
机器学习/深度学习 算法 PyTorch
昇腾910-PyTorch 实现 GoogleNet图像分类
本实验基于PyTorch在昇腾平台上实现GoogleNet模型,针对CIFAR-10数据集进行图像分类。内容涵盖GoogleNet的创新点(如Inception模块、1x1卷积、全局平均池化等)、网络架构解析及代码实战分析。通过详细讲解模型搭建、数据预处理、训练与测试过程,帮助读者掌握如何使用经典CNN模型进行高效图像分类。实验中还介绍了辅助分类器、梯度传播优化等技术细节,并提供了完整的训练和测试代码示例。
|
16天前
|
机器学习/深度学习 算法 PyTorch
昇腾910-PyTorch 实现 Alexnet图像分类
本文介绍了在昇腾平台上使用PyTorch实现AlexNet对CIFAR-10数据集进行图像分类的实战。内容涵盖AlexNet的创新点、网络架构解析及代码实现,包括ReLU激活函数、Dropout、重叠最大池化等技术的应用。实验中详细展示了如何构建模型、加载数据集、定义训练和测试模块,并通过60个epoch的训练验证模型性能。
|
8月前
|
机器学习/深度学习 自然语言处理 算法
【从零开始学习深度学习】49.Pytorch_NLP项目实战:文本情感分类---使用循环神经网络RNN
【从零开始学习深度学习】49.Pytorch_NLP项目实战:文本情感分类---使用循环神经网络RNN
|
8月前
|
机器学习/深度学习 人工智能 PyTorch
PyTorch 图像篇
计算机视觉是多学科交叉的科技,属人工智能关键分支,应用于智能安防、自动驾驶、医疗和制造。技术包括物体检测、语义分割、运动跟踪等。早期依赖手工特征,但深度学习尤其是卷积神经网络(CNN)的发展改变了这一状况,CNN通过自动学习特征,改善了图像分类效率。CNN包含卷积层、池化层和全连接层,解决传统方法参数多、易丢失空间信息的问题。卷积操作在图像处理中用于特征提取,通过二维互相关运算学习图像特征。
|
9月前
|
机器学习/深度学习 JSON PyTorch
图神经网络入门示例:使用PyTorch Geometric 进行节点分类
本文介绍了如何使用PyTorch处理同构图数据进行节点分类。首先,数据集来自Facebook Large Page-Page Network,包含22,470个页面,分为四类,具有不同大小的特征向量。为训练神经网络,需创建PyTorch Data对象,涉及读取CSV和JSON文件,处理不一致的特征向量大小并进行归一化。接着,加载边数据以构建图。通过`Data`对象创建同构图,之后数据被分为70%训练集和30%测试集。训练了两种模型:MLP和GCN。GCN在测试集上实现了80%的准确率,优于MLP的46%,展示了利用图信息的优势。
153 1
|
7月前
|
机器学习/深度学习 PyTorch TensorFlow
在深度学习中,数据增强是一种常用的技术,用于通过增加训练数据的多样性来提高模型的泛化能力。`albumentations`是一个强大的Python库,用于图像增强,支持多种图像变换操作,并且可以与深度学习框架(如PyTorch、TensorFlow等)无缝集成。
在深度学习中,数据增强是一种常用的技术,用于通过增加训练数据的多样性来提高模型的泛化能力。`albumentations`是一个强大的Python库,用于图像增强,支持多种图像变换操作,并且可以与深度学习框架(如PyTorch、TensorFlow等)无缝集成。
|
7月前
|
PyTorch 算法框架/工具 索引
pytorch实现水果2分类(蓝莓,苹果)
pytorch实现水果2分类(蓝莓,苹果)
|
8月前
|
机器学习/深度学习 算法 PyTorch
【从零开始学习深度学习】50.Pytorch_NLP项目实战:卷积神经网络textCNN在文本情感分类的运用
【从零开始学习深度学习】50.Pytorch_NLP项目实战:卷积神经网络textCNN在文本情感分类的运用

相关实验场景

更多