【一起深度学习——kaggle叶子分类】

kaggle 叶子分类

  • 目的:将叶子进行分类。
  • 实现步骤:
    • 1、数据处理:
    • 2、加载数据
    • 3、 定义残差块
    • 4、定义Resnet模型。
    • 5、定义训练以及评估函数:
    • 6、开始训练:
    • 7、输出结果:

目的:将叶子进行分类。

实现步骤:

1、数据处理:

对数据进行处理。由于数据图片(测试集,训练集,验证集全都放在了images中,应将其进行分开)
处理步骤:
1、 读取csv文件,解析其中的地址信息。
2、 创建 训练集 和 测试集 的文件夹,用于存放对应的图片数据。
3、 遍历 训练数据 和 测试数据 中的图片地址,从images复制到对应文件夹中

定义数据处理函数:

#定义读取数据的函数
def read_images():# 读取 csv文件。train_df = pd.read_csv("train.csv")test_df = pd.read_csv("test.csv")# 创建 保存训练集和测试集的文件夹os.makedirs(name="train_images",exist_ok=True)  #训练集os.makedirs(name="val_images",exist_ok=True)    #验证集os.makedirs(name="test_images",exist_ok=True)   #测试集#设置验证集的占比val_ration = 0.2#获取训练集的样本数量。num_samples = len(train_df)#验证集的样本数量。num_val_samples = int(num_samples * val_ration)# 取出验证集的所有索引val_indices = random.sample(range(num_samples),num_val_samples)# print(val_indices)#复制images中的数据到 训练集中for index,row in train_df.iterrows():# print(row[1])  #打印看一下数据格式# print(index)# print(row['image'])image_path = row['image']label = row['label']# 若下标在验证集的索引中:if index in val_indices:target_dir = os.path.join("val_images",label)else:target_dir = os.path.join("train_images", label)os.makedirs(target_dir,exist_ok=True)shutil.copy(image_path,target_dir)#复制images中的数据到 训练集中for row in train_df.iterrows():#print(row[1])  #打印看一下数据格式# print(row[1]['image'])image_path = row[1]['image']label = row[1]['label']target_dir = os.path.join("train_images",label)os.makedirs(target_dir,exist_ok=True)shutil.copy(image_path,target_dir)#复制images中的数据到 测试集 中for row in test_df.iterrows():#print(row[1])  #打印看一下数据格式# print(row[1]['image'])image_path = row[1]['image']target_dir = os.path.join("test_images/test_data")os.makedirs(target_dir,exist_ok=True)shutil.copy(image_path,target_dir)
# read_images()

对于读取测试集时,
target_dir = os.path.join(“test_images/test_data”) 这里的路径我为啥要设置多一个/test_data呢,因为如果不设置这个文件夹的话,后续使用Dataloader.datasets.ImageFolder 就读取不了,但是我现在不知道如何直接加载一个文件夹中图片,所以暂时只能这样。

2、加载数据

tran = torchvision.transforms.Compose([torchvision.transforms.ToTensor(),# torchvision.transforms.Resize((96,96))]
)#读取数据
train_data = torchvision.datasets.ImageFolder(root="train_images",transform=torchvision.transforms.ToTensor())
val_data = torchvision.datasets.ImageFolder(root="val_images",transform=torchvision.transforms.ToTensor())
test_data = torchvision.datasets.ImageFolder(root="test_images",transform=torchvision.transforms.ToTensor())batch_sz = 256
#加载数据
train_loader = DataLoader(train_data,batch_sz,shuffle=True,drop_last=True)
val_loader = DataLoader(val_data,batch_sz,shuffle=False,drop_last=False)
test_loader = DataLoader(test_data,batch_sz,shuffle=False,drop_last=False)
# for (images,labels) in train_loader:
#     print(images.shape)
# 从上边这段代码可知 images维度torch.Size([128, 3, 224, 224])  (样本数量,通道,高度,宽度)

3、 定义残差块

class ResidualBlock(nn.Module):def __init__(self,in_channels,out_channels,strides=1):super(ResidualBlock,self).__init__()# 设置卷积核为3,padding =1能够保持大小不变self.conv1 = nn.Conv2d(in_channels,out_channels,kernel_size=3,stride=strides,padding=1)self.bn1 = nn.BatchNorm2d(out_channels)self.relu = nn.ReLU(inplace=True)self.conv2 = nn.Conv2d(out_channels,out_channels,kernel_size=3,stride=1,padding=1)self.bn2 = nn.BatchNorm2d(out_channels)#如果self.downsample = None# 因为步幅不为 1 的话 就会导致形状大小发生变化。if strides != 1 or in_channels != out_channels:self.downsample = nn.Sequential(nn.Conv2d(in_channels,out_channels,kernel_size=1,stride=strides),nn.BatchNorm2d(out_channels))def forward(self,X):Y = self.relu(self.bn1(self.conv1(X)))Y = self.bn2(self.conv2(Y))if self.downsample is not  None:X = self.downsample(X)Y += Xreturn self.relu(Y)

4、定义Resnet模型。

原理图:
在这里插入图片描述

定义Resnet18模型。
第一层:7x7 的卷积层,64 个输出通道,步幅为 2。
最大池化层:3x3 的池化核,步幅为 2,用于下采样。
4 个阶段(layers),每个阶段包含若干个残差块(ResidualBlock)。
第一个阶段:2 个残差块。 每个残差块包括两个卷积。
第二个阶段:2 个残差块。
第三个阶段:2 个残差块。
第四个阶段:2 个残差块。
全局平均池化层:对特征图进行全局平均池化,将每个通道的特征图变成一个值。
全连接层:将全局平均池化层的输出连接到输出类别数量的全连接层,用于分类

class Resnet18(nn.Module):def __init__(self):super(Resnet18, self).__init__()# H2 = (224- 7 + 3 * 2) / 2 +1 =112# [128,3,224,224] => [128,64,112,112]self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False)self.bn1 = nn.BatchNorm2d(64)self.relu = nn.ReLU(inplace=True)# H2 = (112 - 3 + 2*1 )/2 +1 = 56# [128,64,112,112] => [128,64,56,56]self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)# 添加残缺块 1,每个残缺块呢,当block2为2时,会产生2个残缺块,执行四次卷积。# H2 = (56 - 3+2*1)/1 +1 = 56# 第一个残缺块:[128,64,56,56] => [128,64,56,56]#             [128,64,56,56] => [128,64,56,56]# 第二个残缺块:[128,64,56,56] => [128,64,56,56]#             [128,64,56,56] => [128,64,56,56]self.layer1 = self.make_layer(64, 64, 2)# 添加残缺块 2# 第一个残缺块:H2 = (56 - 3 +2*1)/2+1 = 28#            [128,64,56,56] => [128,128,28,28]#            H2 = (28 - 3 + 2*1)/1 +1 =28#            [128,128,56,56] => [128,128,28,28]#     X :    [128,64,56,56] => [128,128,28,28]  只是将X的通道数和形状变为与 Y一致,可相加。#第二个残缺块:[128,128,28,28] => [128,128,28,28]#            [128,128,28,28] => [128,128,28,28]self.layer2 = self.make_layer(64, 128, 2, stride=2)# 添加残缺块 3# 第一个残缺块:H2 = (28-3 + 2*1)/2 +1 = 14#               [128,128,28,28] => [128,256,14,14]#               [128,256,14,14] => [128,256,14,14]#       x:      [128,128,28,28] => [128,256,14,14]# 第二个残缺块:H2 = (14-3 +2*1) /1 +1 = 14#                [128,256,14,14] => [128,256,14,14]#                 [128,256,14,14] => [128,256,14,14]self.layer3 = self.make_layer(128, 256, 2, stride=2)# 添加残缺块 4# 第一个残缺块:H2 = (14 - 3 +2*1)/2 +1 = 7#               [128,256,14,14] =>[128,512,7,7]#               [128,512,7,7] => [128,512,7,7]#       X :     [[128,256,14,14]] => [128,512,7,7]# 第二个残缺块:H2 = (7-3+2*1)/1+1 =7#               [128,512,7,7] => [128,512,7,7]#               [128,512,7,7] => [128,512,7,7]self.layer4 = self.make_layer(256, 512, 2, stride=2)# 池化层,采用自适应池化(指定特征图的高度,宽度)# [128,512,7,7] => [128,512,1,1]self.avgpool = nn.AdaptiveAvgPool2d((1, 1))# 全连接层#  [128,512] => [128,176]self.fc = nn.Linear(512, 176)def make_layer(self, in_channels, out_channels, blocks, stride=1):layers = []layers.append(ResidualBlock(in_channels, out_channels, stride))for _ in range(1, blocks):# 这里的stride 默认为1layers.append(ResidualBlock(out_channels, out_channels))return nn.Sequential(*layers)def forward(self, x):x = self.conv1(x)x = self.bn1(x)x = self.relu(x)x = self.maxpool(x)x = self.layer1(x)x = self.layer2(x)x = self.layer3(x)x = self.layer4(x)x = self.avgpool(x)#   [128,512,1,1] => [128,512*1*1]x = torch.flatten(x, 1)x = self.fc(x)return x

5、定义训练以及评估函数:

device = torch.device('cuda')
def train(model, train_loader, val_loader, criterion, optimizer, num_epochs):for epoch in range(num_epochs):model.train()  # 设置模型为训练模式train_loss = 0.0correct = 0total = 0# 训练模型for x, y in train_loader:x, y = x.to(device), y.to(device)optimizer.zero_grad()  # 梯度清零outputs = model(x)  # 前向传播loss = criterion(outputs, y)  # 计算损失loss.backward()  # 反向传播optimizer.step()  # 更新参数train_loss += loss.item() * x.size(0)_,predicted = outputs.max(1)   #这里_ 表示占位符,outputs.max(1)返回的是最大值,和最大值的索引total += y.size(0)correct += predicted.eq(y).sum().item()# 计算训练集上的平均损失和准确率train_loss = train_loss / len(train_loader.dataset)train_acc = 100. * correct / total# 在验证集上评估模型val_loss, val_acc = evaluate(model, val_loader, criterion)# 打印训练信息print(f'Epoch [{epoch + 1}/{num_epochs}], Train Loss: {train_loss:.4f}, Train Acc: {train_acc:.2f}%, Val Loss: {val_loss:.4f}, Val Acc: {val_acc:.2f}%')def evaluate(model, val_loader, criterion):model.eval()  # 设置模型为评估模式val_loss = 0.0correct = 0total = 0with torch.no_grad():  # 禁止梯度计算for x, y in val_loader:x, y = x.to(device), y.to(device)outputs = model(x)loss = criterion(outputs, y)val_loss += loss.item() * x.size(0)_, predicted = outputs.max(1)total += y.size(0)correct += predicted.eq(y).sum().item()# 计算验证集上的平均损失和准确率val_loss = val_loss / len(val_loader.dataset)val_acc = 100. * correct / totalreturn val_loss, val_acc

6、开始训练:

model = Resnet18().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=1e-3)
num_epochs = 10train(model,train_loader,val_loader,criterion=criterion,optimizer=optimizer,num_epochs=num_epochs)

7、输出结果:

好家伙,直接过拟合了,应该对数据进一步处理,避免过拟合。
Epoch [1/10], Train Loss: 4.0659, Train Acc: 10.37%, Val Loss: 7.2078, Val Acc: 9.92%
Epoch [2/10], Train Loss: 2.5477, Train Acc: 32.15%, Val Loss: 22.1796, Val Acc: 3.00%
Epoch [3/10], Train Loss: 1.8311, Train Acc: 47.40%, Val Loss: 10.9325, Val Acc: 6.52%
Epoch [4/10], Train Loss: 1.3895, Train Acc: 58.54%, Val Loss: 2.5158, Val Acc: 33.61%
Epoch [5/10], Train Loss: 1.0679, Train Acc: 67.53%, Val Loss: 13.1189, Val Acc: 8.95%
Epoch [6/10], Train Loss: 0.8598, Train Acc: 73.25%, Val Loss: 5.0033, Val Acc: 20.12%
Epoch [7/10], Train Loss: 0.7152, Train Acc: 77.59%, Val Loss: 1.3642, Val Acc: 59.86%
Epoch [8/10], Train Loss: 0.5771, Train Acc: 81.43%, Val Loss: 0.6216, Val Acc: 79.32%
Epoch [9/10], Train Loss: 0.5036, Train Acc: 83.70%, Val Loss: 3.3536, Val Acc: 34.62%
Epoch [10/10], Train Loss: 0.4170, Train Acc: 86.52%, Val Loss: 8.0067, Val Acc: 21.36%

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/7337.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

知识图谱:人工智能的“核心驱动力”

知识图谱:人工智能的“核心驱动力” 一、人工智能与知识图谱二、知识图谱的定义与重要性三、知识图谱工程师的薪资情况四、知识图谱的应用领域六、知识图谱的未来展望七、总结 一、人工智能与知识图谱 人工智能(AI)作为21世纪的前沿技术&…

设备树与/sys/bus/platform/devices与/sys/devices目录关系

设备树与sys/bus/platform/devices sysfs文件系统中/sys/bus/platform/devices下的设备是由设备树生成, 根节点下有compatible的子节点都会在/bus/platform/devices生成节点 总线 I2C、SPI 等控制器会在/bus/platform/devices生成节点 总线 I2C、SPI 节点下的子节点…

牛客网刷题 | BC78 KiKi说祝福语

目前主要分为三个专栏,后续还会添加: 专栏如下: C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读! 初来乍到,如有错误请指出,感谢! 描述 2020年来到了&#…

【Qt】按钮类控件

文章目录 1 :peach:Push Button:peach:2 :peach:Radio Buttion:peach:3 :peach:Check Box:peach:4 :peach:Tool Button:peach: 1 🍑Push Button🍑 使⽤ QPushButton 表⽰⼀个按钮,这也是当前我们最熟悉的⼀个控件了,QPushButton …

SOL链DApp智能合约代币质押挖矿分红系统开发

随着区块链技术的不断发展和普及,越来越多的项目开始探索基于区块链的去中心化应用(DApp)。Solana(SOL)作为一条高性能、低成本的区块链网络,吸引了众多开发者和项目,其中包括了各种类型的DApp&…

Altium Designer——检查原理图库正确性并生成报告

一、方法: 1.打开原理图库: 2.点击菜单栏的报告选项: 3.选择器件规则检查: 根据需求勾选,一般都是全部勾选: 二、问题: 1.缺少封装会导致什么问题: 1.首先: 封装是…

MWeb Pro for Mac:功能强大的Markdown博客编辑器

MWeb Pro for Mac是一款功能强大的Markdown博客编辑器,专为Mac用户设计,提供了一站式的博客写作和发布体验。这款软件不仅支持Markdown语法,还提供了丰富的编辑和排版功能,让用户能够轻松创建出精美的博客内容。 MWeb Pro的即时预…

重庆事业编5月7号开始报名⚠️报名照需审核

24年第二季度重庆事业编招聘 本次招聘实行网上报名。考生应按照招聘岗位要求,诚信、准确填写报考信息,并按网页提示上传电子材料(含电子登记照,jpg格式,20kb以下)。招聘方按照岗位报考要求,对考…

深度学习中的优化算法:选择现有的还是自创?

深度学习中的优化算法 深度学习中的优化算法:选择现有的还是自创?现有优化算法的优势**优点包括**: 开发新的优化算法的考虑**开发新算法的原因**:**开发新算法的风险**: 实用建议结论 深度学习中的优化算法&#xff1…

Mac跑llama.cpp过程中遇到的问题

原repo 在华为手机上安装termux、下载库:顺利在电脑上安装Android NDK:先下载Android Studio,再在里面下载Android SDK 安装Android Studio时,SDK的某些组件总是下载不成功。后来关了梯子、改了hosts,重新安装就成功了…

Ansible---自动化运维工具

一、Ansible概述 1.1 Ansible简介 Ansible是一款自动化运维工具,通过ssh对目标主机进行配置、应用部署、任务执行、编排调度等操作。它简化了复杂的环境管理和自动化任务,提高了工作效率和一致性,同时,Ansible的剧本(playbooks)…

53. 【Android教程】Socket 网络接口

Socket 网络接口 大家在学习计算机网络的时候一定学习过 TCP/IP 协议以及最经典的 OSI 七层结构,简单的回忆一下这 7 层结构: 从下到上依次是: 物理层数据链路层互联层网络层会话层表示层应用层 TCP/IP 协议对这 7 层了做一点精简&#xff…

三岁孩童被家养大型犬咬伤 额部撕脱伤达10公分

近期,一名被家养大型犬咬伤了面部的3岁小朋友,在被家人紧急送来西安国际医学中心医院,通过24小时急诊门诊简单救治后,转至整形外科,由主治医师李世龙为他实施了清创及缝合手术。 “患者额部撕脱伤面积约为10公分&…

Python3中Richdem包遇到问题

Python3中Richdem包遇到问题 文章目录 Python3中Richdem包遇到问题问题一报错解决 问题二报错解决 参考 问题一 报错 RichDEM 是一套数字高程模型 (DEM) 水文分析工具,这次打算用richdem进行地形分析,尝试在conda里面安装richde…

【华为】NAT的分类和实验配置

【华为】NAT的分类和实验配置 NAT产生的技术背景IP地址分类NAT技术原理NAT分类静态NAT动态NATNAPTEasy IP(PAT)NAT Server 配置拓扑静态NAT测试抓包 动态NAT测试抓包 NAPT测试抓包 PAT测试抓包 NAT Server检测抓包 PC1PC2服务器 NAT产生的技术背景 随着…

【管理篇】管理三步曲:团队建设(二)

目录标题 如何着手团队建设提升个人能力1、要提升员工的什么能力2、提升员工个人能力的初衷是什么?3、如何达成上述目标4、应该如何激发员工学习的动力和意愿呢5、关于提升员工的能力,有两个信念特别重要: 提升员工的工作意愿和积极性1、管理…

Spring与AI结合-spring boot3整合AI组件

⛰️个人主页: 蒾酒 🔥系列专栏:《spring boot实战》 目录 写在前面 spring ai简介 单独整合al接口 整合Spring AI组件 起步条件 ​编辑 进行必要配置 写在最后 写在前面 本文介绍了springboot开发后端服务中,AI组件(Spring A…

软件工程案例学习-图书管理系统-面向对象方法

文档编号:LMS_1 版 本 号:V1.0 ** ** ** ** ** ** 文档名称:需求分析规格说明书 项目名称:图书管理系统 项目负责人:计敏 胡杰 ** ** …

使用Docker安装MySql数据库

大家好,今天给大家分享一下如何使用docker安装MySql数据库,关于docker的安装和常用命令,大家可以参考下面两篇文章,本文中不做过多描述。 Docker在Windows与CentOS上的安装 Docker常用命令 一、拉取MySql数据库镜像 docker pul…

IIS部署vue项目 IIS重写URL

【第一步】安装IIS {1)打开控制面板 -> 打开程序和功能 -> 打开启用或关闭windows功能 (2)找到 Internet Information Services 勾选【web管理工具】和【万维网服务】,然后 确定 【第二步】安装URL重写模块 1). 安装URL …