基于pytorch搭建AlexNet神经网络用于花类识别_alxnett实现102花卉

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

	- [6、开始训练网络✨✨✨](#6_219)
	- [7、开始测试网络✨✨✨](#7_250)
	- [8、保存模型](#8_274)
	- [9、模型训练结果](#9_288)
+ [使用训练模型进行物体识别✨✨✨](#_299)
+ [小结](#_378)

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

写在前面

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

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

完整网络模型训练步骤

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

1、准备数据集

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

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

image-20220418104121981

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

img

2、加载数据集

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

image-20220418110116902

​  这里直接使用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这个函数的输出,如下图所示:

image-20220418142804948

​  可以看出,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网络的构建:

img

# 搭建网络模型
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

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

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

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

image-20220418152105966

可以看出输出是符合要求的,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))


![img](https://img-blog.csdnimg.cn/img_convert/7f0fa0a26cffaa96d126449751a6dda6.png)
![img](https://img-blog.csdnimg.cn/img_convert/691f18f92ff6bfa948c9bf800813ec93.png)

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618668825)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

rate))


[外链图片转存中...(img-1hemH08A-1715802573316)]
[外链图片转存中...(img-ZMY8P0FV-1715802573317)]

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618668825)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值