基于pytorch搭建AlexNet神经网络用于花类识别

简介: 基于pytorch搭建AlexNet神经网络用于花类识别

基于pytorch搭建AlexNet神经网络用于花类识别

写在前面

  最近打算出一个基于pytorch搭建各种经典神经网络的系列。首先先谈谈关于这部分你需要哪些先验知识,如下:

  • 对神经网络有一定的了解,当然了,本节针对AlexNet,那么你应对其有较深入的了解,不明白的请看我之前关于此部分的介绍,详情戳此图标☞☞☞
  • 对pytorch有一定的了解,同样的,不了解的请移步至我之前的文章,详情戳此图标☞☞☞

完整网络模型训练步骤

  读到这里,我就当你对我前面的要求的两点都明白了,一些基础的地方将不再叙述⛳⛳⛳

1、准备数据集

深度学习没有数据一切都是空谈,因此我们的第一步就是要准备数据集。看了我前面使用pytorch自己构建网络模型实战文章的同学应该可以发现,在那篇文章中我们的数据集使用的是CIFAR10,而这个数据集我们不需要额外准备,通过指定pytorch的函数参数就可以实现下载。而本篇文章使用的是花类数据集,一共有五个类别,分别是daisy(雏菊)、dandelion(蒲公英)、roses(玫瑰)、sunflowers(向日葵)和 tulips(郁金香)。我将数据集放在了gitee上,需要自取。

下面来看看这个数据集的结构,入下图所示:9fccc786c69a259bb82a49fe45f85266.png

接着我们来说一下此脚本的使用方法:在data_set文件夹内使用shift + 右键 打开 PowerShell ,执行 “split_data.py” 分类脚本会自动将数据集划分成训练集train 和 验证集val。【我给的文件中已经划分好了,这一步可以不进行】faaa172c803454f58997e0632dd49401.png

2、加载数据集

  书写这篇文章的思路我想的是尽可能的和之前的使用pytorch自己构建网络模型实战文章做一个对比,这样可能会对训练网络的步骤有一个更清晰的认识,因此再阅读此文章前建议先看一下之前的文章。在前文构建网络模型实战中,还记得我们是怎么加载数据集的吗?如下图所示:b37155bc54942d08f9fc967f8160c3bd.png

这里直接使用DataLoader函数来加载,这是因为pytorch中有CIFAR10这个数据集。而本文中的数据集并不包含在pytorch中,我们需要先使用datasets.ImageFolder()导入数据集,这个函数返回的对象是一个包含数据集所有图像及对应标签构成的二维元组容器,第一个元素为图像的张量表示形式,第二个元素为该图像所对应的标签。

# 对传入的数据进行处理,分为训练集和验证集
# 对这里的ToTensor和Normalize不理解的请看文章:https://blog.csdn.net/qq_47233366/article/details/124225860?spm=1001.2014.3001.5502
data_transform = {
    "train": transforms.Compose([transforms.RandomResizedCrop(227),    #随机剪裁
                                 transforms.RandomHorizontalFlip(),    #随机水平翻转
                                 transforms.ToTensor(),
                                 transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]),
    "val": transforms.Compose([transforms.Resize((227, 227)),  # cannot 224, must (224, 224)
                               transforms.ToTensor(),
                               transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])}
#下面三行为获取数据的路径
data_root = os.path.abspath(os.path.join(os.getcwd(), "../.."))  # get data root path
image_path = os.path.join(data_root, "data_set", "flower_data")  # flower data set path
assert os.path.exists(image_path), "{} path does not exist.".format(image_path)
#使用ImageFolder导入数据集  【第一个参数root表示数据集路径 ; 第二个参数transform表示对图像数据进行变换】
train_dataset = datasets.ImageFolder(root=os.path.join(image_path, "train"),
                                         transform=data_transform["train"])

  我们可以来看一下train_dataset中第一个元素train_dataset[0]的内容来理解ImageFolder这个函数的输出,如下图所示:b6c7a1de14c765a1a14d2cbbb608fa82.png

  可以看出,train_dataset[0]的第一个元素为tensor的张量,即图像数据,第二个元素为对应标签0,即daisy(雏菊)。得到了ImageFolder函数的返回结果train_dataset,就可以将这个返回结果传入DataLoader中进行加载,如下:

#设置batch_size大小
batch_size = 32
#使用DataLoader加载数据集
train_loader = torch.utils.data.DataLoader(train_dataset,
                                           batch_size=batch_size, shuffle=True,
                                           num_workers=0)

  这里在强调一下加载数据集的含义,其实就类似于打包,比如这里的第二个参数设置的是batch_size=32,则表示把train_dataset中的32个数据打包一起放入Dataloader中。


  上文已经对训练集进行了加载,验证集的思路和其一致,如下:

#导入验证集
validate_dataset = datasets.ImageFolder(root=os.path.join(image_path, "val"),
                                        transform=data_transform["val"])
#加载验证集
validate_loader = torch.utils.data.DataLoader(validate_dataset,
                                              batch_size=batch_size, shuffle=True,
                                              num_workers=0)

对ImageFolder函数和Dataloader函数的详情见链接:ImageFolder函数和Dataloader函数🍍🍍🍍

3、搭建神经网络✨✨✨

  加载好数据后我们就可以搭建神经网络了,本次使用的神经网络结构为AlexNet,不了解的戳此图标☞☞☞了解详细。我们按照下图进行ALexNet网络的构建:56d0f7fb8dea82861c85b466d1a52124.png

# 搭建网络模型
class AlexNet(nn.Module):
    def __init__(self, num_classes=10000):
        super(AlexNet, self).__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 96, 11, 4, padding=0),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(3, 2, padding=0),
            nn.Conv2d(96, 256, 5, padding=2),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(3, 2, padding=0),
            nn.Conv2d(256, 384, 3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(384, 384, 3, padding=1),
            nn.ReLU(inplace=True),
            nn.Conv2d(384, 256, 3, padding=1),
            nn.ReLU(inplace=True),
            nn.MaxPool2d(3, 2, padding=0),
        )
        self.classifier = nn.Sequential(
            nn.Flatten(),
            nn.Dropout(),
            nn.Linear(256 * 6 * 6, 4096),
            nn.ReLU(inplace=True),
            nn.Dropout(),
            nn.Linear(4096, 4096),
            nn.ReLU(inplace=True),
            nn.Linear(4096, num_classes)
        )
    def forward(self, x):
        x = self.features(x)
        x = self.classifier(x)
        return x

  这部分是不难的,完全是照葫芦画瓢,只是本文在卷积层和全连接层后都加上了Relu激活函数并加上了Dropout函数。

4、创建网络模型

这步只要一行代码,其实就是实列化了一个对象。

# 创建网络模型
net = AlexNet(num_classes=5)   #因为我们的数据有五个类别因此需要设置num_classes=5

我们可以打印出来看一看我们自己创建的网络模型,如下图。可以看出和前文的结构是一致的。

image.png

到这里我们已经创建好了自己的模型,这个模型输入是3x227x227的图片【可以认为就是一个3x227x227的张量】,输出是1x10000的向量。每当我们创建好一个模型后,应该检测一下模型的输入输出是否是我们所期待的,若不是则即使调整模型。我们可以用以下代码来检测输出是否符合要求。

net = AlexNet()
input = torch.ones((64, 3, 227, 227))  #64为batch_size,3x32x32表示张量尺寸
output = net(input)
print(output.shape)

image.png

可以看出输出是符合要求的,64是输入的batch_size,相当于输入64张图片。


5、设置损失函数、优化器等参数

# 用于GPU训练
net.to(device)
# 设置损失函数
loss_function = nn.CrossEntropyLoss()
# 设置优化器
optimizer = optim.Adam(net.parameters(), lr=0.0002)
# 设置epoch
epochs = 10
# 设置模型保持地址
save_path = './AlexNet.pth'
# 设置此参数,用于后期只保存最优的模型
best_acc = 0.0

6、开始训练网络✨✨✨

train_steps = len(train_loader)
    for epoch in range(epochs):
        # train
        net.train()   # 开始训练,此网络有dropout,必须加
        running_loss = 0.0
        #tqdm用于显示训练进度
        train_bar = tqdm(train_loader, file=sys.stdout)
        for step, data in enumerate(train_bar):
            images, labels = data
            optimizer.zero_grad()
            outputs = net(images.to(device))
            loss = loss_function(outputs, labels.to(device))
            loss.backward()
            optimizer.step()
            # print statistics
            running_loss += loss.item()
            train_bar.desc = "train epoch[{}/{}] loss:{:.3f}".format(epoch + 1,
                                                                     epochs,
                                                                     loss)

7、开始测试网络✨✨✨

# validate
net.eval()   # 开始测试,验证过程中关闭 Dropout
acc = 0.0  # accumulate accurate number / epoch
with torch.no_grad():     #这句表示测试不需要进行反向传播,即不需要梯度变化
    val_bar = tqdm(validate_loader, file=sys.stdout)
    for val_data in val_bar:
        val_images, val_labels = val_data
        outputs = net(val_images.to(device))
        predict_y = torch.max(outputs, dim=1)[1]
        acc += torch.eq(predict_y, val_labels.to(device)).sum().item()
        val_accurate = acc / val_num
        print('[epoch %d] train_loss: %.3f  val_accuracy: %.3f' %
              (epoch + 1, running_loss / train_steps, val_accurate))

8、保存模型

# 保存当前的最优模型
if val_accurate > best_acc:
    best_acc = val_accurate
    torch.save(net.state_dict(), save_path)

9、模型训练结果

  本次训练我是在GPU上训练,训练的结果如下图所示:

f121e9a292be3f09cde63819d1862e4f.png

  可以看出,在验证集上的准确率达到了0.701🥝🥝🥝


使用训练模型进行物体识别✨✨✨

import os
import json
import torch
from PIL import Image
from torchvision import transforms
import matplotlib.pyplot as plt
from model import AlexNet
def main():
    device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
    data_transform = transforms.Compose(
        [transforms.Resize((227, 227)),
         transforms.ToTensor(),
         transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
    # load image
    img_path = "./tulip.jpg"
    assert os.path.exists(img_path), "file: '{}' dose not exist.".format(img_path)
    img = Image.open(img_path)
    plt.imshow(img)
    # [N, C, H, W]
    img = data_transform(img)
    # expand batch dimension
    img = torch.unsqueeze(img, dim=0)
    # read class_indict
    json_path = './class_indices.json'
    assert os.path.exists(json_path), "file: '{}' dose not exist.".format(json_path)
    json_file = open(json_path, "r")
    class_indict = json.load(json_file)
    # create model
    model = AlexNet(num_classes=5).to(device)
    # load model weights
    weights_path = "./AlexNet.pth"
    assert os.path.exists(weights_path), "file: '{}' dose not exist.".format(weights_path)
    # 这里我因为是在GPU上训练的模型,然后拿到自己电脑上运行的(cpu),因此要加上map_location='cpu'
    model.load_state_dict(torch.load(weights_path, map_location='cpu'))  
    model.eval()
    with torch.no_grad():
        # predict class
        output = torch.squeeze(model(img.to(device))).cpu()   # 将输出压缩,即压缩掉 batch 这个维度
        predict = torch.softmax(output, dim=0)
        predict_cla = torch.argmax(predict).numpy()
    print_res = "class: {}   prob: {:.3}".format(class_indict[str(predict_cla)],
                                                 predict[predict_cla].numpy())
    print(print_res)
    plt.show()
if __name__ == '__main__':
    main()

运行结果如下:可以看出检测到此图片是郁金香的概率为0.977🥗🥗🥗

1e1dbaf111df72fcce32e3961ae9f659.png

小结

  似乎也没什么好小结的,总之希望大家都能够有所收获叭🍚🍚🍚需要注意的是我们不可能对上述代码的每一个函数都无比熟悉,不明白的可以自己去查查资料,使用pycharm的调试功能或许也能够让你获益匪浅🌻🌻🌻


 这部分谈谈一个使用GPU训练的小技巧,即让服务器后台进行训练,不必一直处于链接状态,方法如下:


  1. screen -S xxx xxx为建立的窗口名称,可修改
  2. pyt hon xxx.py 执行训练文件
  3. Ctrl + A + D 退出screen窗口
  4. screen -ls 查看有哪些窗口
  5. screen -r + 窗口编号 进入某个窗口
  6. screen -X -S 窗口编号 quit 杀死某个窗口

参考视频:https://www.bilibili.com/video/BV1W7411T7qc?spm_id_from=333.851.header_right.history_list.click🌸🌸🌸

这是一个宝藏UP主霹雳吧啦Wz,大家快去看🍏🍏🍏

相关实践学习
在云上部署ChatGLM2-6B大模型(GPU版)
ChatGLM2-6B是由智谱AI及清华KEG实验室于2023年6月发布的中英双语对话开源大模型。通过本实验,可以学习如何配置AIGC开发环境,如何部署ChatGLM2-6B大模型。
相关文章
|
机器学习/深度学习 算法 PyTorch
【Pytorch框架搭建神经网络】基于DQN算法、优先级采样的DQN算法、DQN + 人工势场的避障控制研究(Python代码实现)
【Pytorch框架搭建神经网络】基于DQN算法、优先级采样的DQN算法、DQN + 人工势场的避障控制研究(Python代码实现)
380 1
|
机器学习/深度学习 算法 PyTorch
Perforated Backpropagation:神经网络优化的创新技术及PyTorch使用指南
深度学习近年来在多个领域取得了显著进展,但其核心组件——人工神经元和反向传播算法自提出以来鲜有根本性突破。穿孔反向传播(Perforated Backpropagation)技术通过引入“树突”机制,模仿生物神经元的计算能力,实现了对传统神经元的增强。该技术利用基于协方差的损失函数训练树突节点,使其能够识别神经元分类中的异常模式,从而提升整体网络性能。实验表明,该方法不仅可提高模型精度(如BERT模型准确率提升3%-17%),还能实现高效模型压缩(参数减少44%而无性能损失)。这一革新为深度学习的基础构建模块带来了新的可能性,尤其适用于边缘设备和大规模模型优化场景。
639 16
Perforated Backpropagation:神经网络优化的创新技术及PyTorch使用指南
|
机器学习/深度学习 PyTorch 算法框架/工具
基于Pytorch 在昇腾上实现GCN图神经网络
本文详细讲解了如何在昇腾平台上使用PyTorch实现图神经网络(GCN)对Cora数据集进行分类训练。内容涵盖GCN背景、模型特点、网络架构剖析及实战分析。GCN通过聚合邻居节点信息实现“卷积”操作,适用于非欧氏结构数据。文章以两层GCN模型为例,结合Cora数据集(2708篇科学出版物,1433个特征,7种类别),展示了从数据加载到模型训练的完整流程。实验在NPU上运行,设置200个epoch,最终测试准确率达0.8040,内存占用约167M。
基于Pytorch 在昇腾上实现GCN图神经网络
|
机器学习/深度学习 算法 PyTorch
【DQN实现避障控制】使用Pytorch框架搭建神经网络,基于DQN算法、优先级采样的DQN算法、DQN + 人工势场实现避障控制研究(Matlab、Python实现)
【DQN实现避障控制】使用Pytorch框架搭建神经网络,基于DQN算法、优先级采样的DQN算法、DQN + 人工势场实现避障控制研究(Matlab、Python实现)
523 0
|
机器学习/深度学习 搜索推荐 PyTorch
基于昇腾用PyTorch实现CTR模型DIN(Deep interest Netwok)网络
本文详细讲解了如何在昇腾平台上使用PyTorch训练推荐系统中的经典模型DIN(Deep Interest Network)。主要内容包括:DIN网络的创新点与架构剖析、Activation Unit和Attention模块的实现、Amazon-book数据集的介绍与预处理、模型训练过程定义及性能评估。通过实战演示,利用Amazon-book数据集训练DIN模型,最终评估其点击率预测性能。文中还提供了代码示例,帮助读者更好地理解每个步骤的实现细节。
|
机器学习/深度学习 自然语言处理 PyTorch
基于Pytorch Gemotric在昇腾上实现GAT图神经网络
本实验基于昇腾平台,使用PyTorch实现图神经网络GAT(Graph Attention Networks)在Pubmed数据集上的分类任务。内容涵盖GAT网络的创新点分析、图注意力机制原理、多头注意力机制详解以及模型代码实战。实验通过两层GAT网络对Pubmed数据集进行训练,验证模型性能,并展示NPU上的内存使用情况。最终,模型在测试集上达到约36.60%的准确率。
|
算法 PyTorch 算法框架/工具
PyTorch 实现FCN网络用于图像语义分割
本文详细讲解了在昇腾平台上使用PyTorch实现FCN(Fully Convolutional Networks)网络在VOC2012数据集上的训练过程。内容涵盖FCN的创新点分析、网络架构解析、代码实现以及端到端训练流程。重点包括全卷积结构替换全连接层、多尺度特征融合、跳跃连接和反卷积操作等技术细节。通过定义VOCSegDataset类处理数据集,构建FCN8s模型并完成训练与测试。实验结果展示了模型在图像分割任务中的应用效果,同时提供了内存使用优化的参考。
|
机器学习/深度学习 算法 PyTorch
基于Pytorch Gemotric在昇腾上实现GraphSage图神经网络
本实验基于PyTorch Geometric,在昇腾平台上实现GraphSAGE图神经网络,使用CiteSeer数据集进行分类训练。内容涵盖GraphSAGE的创新点、算法原理、网络架构及实战分析。GraphSAGE通过采样和聚合节点邻居特征,支持归纳式学习,适用于未见节点的表征生成。实验包括模型搭建、训练与验证,并在NPU上运行,最终测试准确率达0.665。
|
机器学习/深度学习 JavaScript PyTorch
9个主流GAN损失函数的数学原理和Pytorch代码实现:从经典模型到现代变体
生成对抗网络(GAN)的训练效果高度依赖于损失函数的选择。本文介绍了经典GAN损失函数理论,并用PyTorch实现多种变体,包括原始GAN、LS-GAN、WGAN及WGAN-GP等。通过分析其原理与优劣,如LS-GAN提升训练稳定性、WGAN-GP改善图像质量,展示了不同场景下损失函数的设计思路。代码实现覆盖生成器与判别器的核心逻辑,为实际应用提供了重要参考。未来可探索组合优化与自适应设计以提升性能。
1396 7
9个主流GAN损失函数的数学原理和Pytorch代码实现:从经典模型到现代变体

热门文章

最新文章

推荐镜像

更多