树叶分类竞赛(Baseline)以及kaggle的GPU使用

树叶分类竞赛(Baseline)-kaggle的GPU使用

文章目录

  • 树叶分类竞赛(Baseline)-kaggle的GPU使用
    • 竞赛的步骤
    • 代码实现
      • 创建自定义dataset
      • 定义data_loader
      • 模型定义
      • 超参数
      • 训练模型
      • 预测和保存结果
    • kaggle使用

竞赛的步骤

本文来自于Neko Kiku提供的Baseline,感谢大佬提供代码,来自于https://www.kaggle.com/nekokiku/simple-resnet-baseline

总结一下数据处理步骤:

  1. 先观察数据,发现数据有三类,测试和训练两类csv文件,以及image文件。

csv文件处理:读取训练文件,观察种类个数,同时将种类和标签相绑定

image文件:可以利用tensorboard进行图片的观察,也可以用image图片展示

  1. 创建自定义的dataset,自定义不同的类型;接着创建DataLoader定义一系列参数
  2. 模型定义,利用选定好的模型restnet34,记得最后接一个全连接层将数据压缩至种类个数
  3. 超参数可以有效提高辨别概率,自己电脑GPU太拉跨,选定好参数再进行跑模型,提高模型效率
  4. 训练模型
  5. 预测和保存结果

学习到的优化方法:

  1. 数据增强: 在数据加载阶段,可以使用数据增强技术来增加数据的多样性,帮助模型更好地泛化。可以使用 torchvision.transforms 来实现。
  2. 调整超参数: 尝试不同的超参数,如学习率、batch size、weight decay 等,找到最佳组合。

代码实现

  • 文件处理
# 首先导入包
import torch
import torch.nn as nn
import pandas as pd
import numpy as np
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms
from PIL import Image
import os
import matplotlib.pyplot as plt
import torchvision.models as models
# This is for the progress bar.
from tqdm import tqdm
import seaborn as sns
  • 观察给出的几个文件类型以及内容,得出标签类型以及频度
# 看看label文件长啥样,先了解训练集,再看对应的标签类型
labels_dataframe = pd.read_csv('../input/classify-leaves/train.csv')
labels_dataframe.head(5)
# pd.describe()函数生成描述性统计数据,统计数据集的集中趋势,分散和行列的分布情况,不包括 NaN值。
labels_dataframe.describe()
  • 坐标展示数据,可视化种类的分布情况
#function to show bar lengthdef barw(ax): for p in ax.patches:val = p.get_width() #height of the barx = p.get_x()+ p.get_width() # x- position y = p.get_y() + p.get_height()/2 #y-positionax.annotate(round(val,2),(x,y))#finding top leaves
plt.figure(figsize = (15,30))
ax0=sns.countplot(y=labels_dataframe['label'],order=labels_dataframe['label'].value_counts().index)
barw(ax0)
plt.show()
  • 将label和数字相对应,建立字典
# 把label文件排个序
leaves_labels = sorted(list(set(labels_dataframe['label'])))
n_classes = len(leaves_labels)
print(n_classes)
leaves_labels[:10]
# 把label转成对应的数字
class_to_num = dict(zip(leaves_labels, range(n_classes)))
class_to_num
# 再转换回来,方便最后预测的时候使用
num_to_class = {v : k for k, v in class_to_num.items()}
'abies_concolor': 0,'abies_nordmanniana': 1,'acer_campestre': 2,'acer_ginnala': 3,'acer_griseum': 4,'acer_negundo': 5,'acer_palmatum': 6,'acer_pensylvanicum': 7,'acer_platanoides': 8,'acer_pseudoplatanus': 9,'acer_rubrum': 10,

创建自定义dataset

dataset分为init,getitem,len三部分

init函数:定义照片尺寸和文件路径,根据不同模式对数据进行不同的处理。

getitem函数:获取文件的函数,同样对于不同模式的请求对数据有不同的处理。学习train中数据增强的手段

len函数:返回真实长度

# 继承pytorch的dataset,创建自己的
class LeavesData(Dataset):def __init__(self, csv_path, file_path, mode='train', valid_ratio=0.2, resize_height=256, resize_width=256):"""Args:csv_path (string): csv 文件路径img_path (string): 图像文件所在路径mode (string): 训练模式还是测试模式valid_ratio (float): 验证集比例"""# 需要调整后的照片尺寸,我这里每张图片的大小尺寸不一致#self.resize_height = resize_heightself.resize_width = resize_widthself.file_path = file_pathself.mode = mode# 读取 csv 文件# 利用pandas读取csv文件self.data_info = pd.read_csv(csv_path, header=None)  #header=None是去掉表头部分# 计算 lengthself.data_len = len(self.data_info.index) - 1self.train_len = int(self.data_len * (1 - valid_ratio))if mode == 'train':# 第一列包含图像文件的名称self.train_image = np.asarray(self.data_info.iloc[1:self.train_len, 0])  #self.data_info.iloc[1:,0]表示读取第一列,从第二行开始到train_len# 第二列是图像的 labelself.train_label = np.asarray(self.data_info.iloc[1:self.train_len, 1])self.image_arr = self.train_image self.label_arr = self.train_labelelif mode == 'valid':self.valid_image = np.asarray(self.data_info.iloc[self.train_len:, 0])  self.valid_label = np.asarray(self.data_info.iloc[self.train_len:, 1])self.image_arr = self.valid_imageself.label_arr = self.valid_labelelif mode == 'test':self.test_image = np.asarray(self.data_info.iloc[1:, 0])self.image_arr = self.test_imageself.real_len = len(self.image_arr)print('Finished reading the {} set of Leaves Dataset ({} samples found)'.format(mode, self.real_len))def __getitem__(self, index):# 从 image_arr中得到索引对应的文件名single_image_name = self.image_arr[index]# 读取图像文件img_as_img = Image.open(self.file_path + single_image_name)#如果需要将RGB三通道的图片转换成灰度图片可参考下面两行
#         if img_as_img.mode != 'L':
#             img_as_img = img_as_img.convert('L')#设置好需要转换的变量,还可以包括一系列的nomarlize等等操作if self.mode == 'train':transform = transforms.Compose([transforms.Resize((224, 224)),transforms.RandomHorizontalFlip(p=0.5),   #随机水平翻转 选择一个概率transforms.ToTensor()])else:# valid和test不做数据增强transform = transforms.Compose([transforms.Resize((224, 224)),transforms.ToTensor()])img_as_img = transform(img_as_img)if self.mode == 'test':return img_as_imgelse:# 得到图像的 string labellabel = self.label_arr[index]# number labelnumber_label = class_to_num[label]return img_as_img, number_label  #返回每一个index对应的图片数据和对应的labeldef __len__(self):return self.real_len
# 设置文件路径,读取文件
train_path = '../input/classify-leaves/train.csv'
test_path = '../input/classify-leaves/test.csv'
# csv文件中已经images的路径了,因此这里只到上一级目录
img_path = '../input/classify-leaves/'train_dataset = LeavesData(train_path, img_path, mode='train')
val_dataset = LeavesData(train_path, img_path, mode='valid')
test_dataset = LeavesData(test_path, img_path, mode='test')
print(train_dataset)
print(val_dataset)
print(test_dataset)

定义data_loader

# 定义data loader,如果报错的话,改变num_workers为0
train_loader = torch.utils.data.DataLoader(dataset=train_dataset,batch_size=8, shuffle=False,num_workers=5)val_loader = torch.utils.data.DataLoader(dataset=val_dataset,batch_size=8, shuffle=False,num_workers=5)
test_loader = torch.utils.data.DataLoader(dataset=test_dataset,batch_size=8, shuffle=False,num_workers=5)
# 给大家展示一下数据长啥样
def im_convert(tensor):""" 展示数据"""image = tensor.to("cpu").clone().detach()image = image.numpy().squeeze()image = image.transpose(1,2,0)image = image.clip(0, 1)return imagefig=plt.figure(figsize=(20, 12))
columns = 4
rows = 2dataiter = iter(val_loader)
inputs, classes = dataiter.next()for idx in range (columns*rows):ax = fig.add_subplot(rows, columns, idx+1, xticks=[], yticks=[])ax.set_title(num_to_class[int(classes[idx])])plt.imshow(im_convert(inputs[idx]))
plt.show()
  • 可以自己尝试一下用tensorboard展示一下图片,我贴出我的代码
from torch.utils.tensorboard import SummaryWriter
from PIL import Image
import numpy as np
import os# 注意这个图片的路径和之前的路径不同
image_path = './dataset/images'
writer = SummaryWriter("logs")
image_filenames = os.listdir(image_path)
batch_size = 10for i in range(0, int(len(image_filenames)/1000), batch_size):batch_images = image_filenames[i:i + batch_size]for j, img_filename in enumerate(batch_images):img_concise = os.path.join(image_path, img_filename)img = Image.open(img_concise)img_array = np.array(img)# writer.add_image(f"test/batch_{i // batch_size}/img_{j}", img_array, j, dataformats='HWC')writer.add_image(f"test_batch{i}", img_array, j, dataformats='HWC')writer.close()
# 观察是否在GPU上运行
def get_device():return 'cuda' if torch.cuda.is_available() else 'cpu'device = get_device()
print(device)

模型定义

在查阅下了解到利用了迁移学习,通过不改变模型前面一些层的参数可以加快训练速度,也称作冻结层,我在下面贴上冻结层的目的;模型利用上节课学到的resnet模型,模型全封装好了直接调用,只需要在最后一层添加一个全连接层,使得最后的输出结果为模型的类型即可。

  • 减少训练时间:通过不更新某些层的参数,可以减少计算量,从而加快训练速度。
  • 防止过拟合:冻结一些层的参数可以避免模型在小数据集上过拟合,特别是在迁移学习中,预训练的层通常已经学到了良好的特征。
# 是否要冻住模型的前面一些层
def set_parameter_requires_grad(model, feature_extracting):if feature_extracting:model = modelfor param in model.parameters():param.requires_grad = False
# resnet34模型
def res_model(num_classes, feature_extract = False, use_pretrained=True):model_ft = models.resnet34(pretrained=use_pretrained)set_parameter_requires_grad(model_ft, feature_extract)num_ftrs = model_ft.fc.in_featuresmodel_ft.fc = nn.Sequential(nn.Linear(num_ftrs, num_classes))return model_ft

超参数

# 超参数
learning_rate = 3e-4
weight_decay = 1e-3
num_epoch = 50
model_path = './pre_res_model.ckpt'

训练模型

  • 训练和验证分类模型的模版,需要很大时间去训练,可以利用kaggle的GPU来跑模型
# Initialize a model, and put it on the device specified.
model = res_model(176) # 之前观察到树叶的类别有176个
model = model.to(device)
model.device = device
# For the classification task, we use cross-entropy as the measurement of performance.
criterion = nn.CrossEntropyLoss()# Initialize optimizer, you may fine-tune some hyperparameters such as learning rate on your own.
optimizer = torch.optim.Adam(model.parameters(), lr = learning_rate, weight_decay=weight_decay)# The number of training epochs.
n_epochs = num_epochbest_acc = 0.0
for epoch in range(n_epochs):# ---------- Training ----------# Make sure the model is in train mode before training.model.train() # These are used to record information in training.train_loss = []train_accs = []# Iterate the training set by batches.for batch in tqdm(train_loader):# A batch consists of image data and corresponding labels.imgs, labels = batchimgs = imgs.to(device)labels = labels.to(device)# Forward the data. (Make sure data and model are on the same device.)logits = model(imgs)# Calculate the cross-entropy loss.# We don't need to apply softmax before computing cross-entropy as it is done automatically.loss = criterion(logits, labels)# Gradients stored in the parameters in the previous step should be cleared out first.optimizer.zero_grad()# Compute the gradients for parameters.loss.backward()# Update the parameters with computed gradients.optimizer.step()# Compute the accuracy for current batch.acc = (logits.argmax(dim=-1) == labels).float().mean()# Record the loss and accuracy.train_loss.append(loss.item())train_accs.append(acc)# The average loss and accuracy of the training set is the average of the recorded values.train_loss = sum(train_loss) / len(train_loss)train_acc = sum(train_accs) / len(train_accs)# Print the information.print(f"[ Train | {epoch + 1:03d}/{n_epochs:03d} ] loss = {train_loss:.5f}, acc = {train_acc:.5f}")# ---------- Validation ----------# Make sure the model is in eval mode so that some modules like dropout are disabled and work normally.model.eval()# These are used to record information in validation.valid_loss = []valid_accs = []# Iterate the validation set by batches.for batch in tqdm(val_loader):imgs, labels = batch# We don't need gradient in validation.# Using torch.no_grad() accelerates the forward process.with torch.no_grad():logits = model(imgs.to(device))# We can still compute the loss (but not the gradient).loss = criterion(logits, labels.to(device))# Compute the accuracy for current batch.acc = (logits.argmax(dim=-1) == labels.to(device)).float().mean()# Record the loss and accuracy.valid_loss.append(loss.item())valid_accs.append(acc)# The average loss and accuracy for entire validation set is the average of the recorded values.valid_loss = sum(valid_loss) / len(valid_loss)valid_acc = sum(valid_accs) / len(valid_accs)# Print the information.print(f"[ Valid | {epoch + 1:03d}/{n_epochs:03d} ] loss = {valid_loss:.5f}, acc = {valid_acc:.5f}")# if the model improves, save a checkpoint at this epochif valid_acc > best_acc:best_acc = valid_acctorch.save(model.state_dict(), model_path)print('saving model with acc {:.3f}'.format(best_acc))

预测和保存结果

saveFileName = './submission.csv'
## predict
model = res_model(176)# create model and load weights from checkpoint
model = model.to(device)
model.load_state_dict(torch.load(model_path))# Make sure the model is in eval mode.
# Some modules like Dropout or BatchNorm affect if the model is in training mode.
model.eval()# Initialize a list to store the predictions.
predictions = []
# Iterate the testing set by batches.
for batch in tqdm(test_loader):imgs = batchwith torch.no_grad():logits = model(imgs.to(device))# Take the class with greatest logit as prediction and record it.predictions.extend(logits.argmax(dim=-1).cpu().numpy().tolist())preds = []
for i in predictions:preds.append(num_to_class[i])test_data = pd.read_csv(test_path)
test_data['label'] = pd.Series(preds)
submission = pd.concat([test_data['image'], test_data['label']], axis=1)
submission.to_csv(saveFileName, index=False)
print("Done!!!!!!!!!!!!!!!!!!!!!!!!!!!")

kaggle使用

  1. 创建kaggle账户
  2. 创建一个Dataset,将树叶信息导入/还可以通过kaggle自身的数据集进行数据的导入
  3. 创建一个Notebook

在这里插入图片描述

  1. 导入的文件放在了/kaggle/input,将导入的文件放在根目录下使得代码中的导入文件路径不会变
cp -r /文件 命名
cp -r /kaggle/input/leaf-dataset dataset

在这里插入图片描述

  1. 打开右侧边栏,将其修改为GPUP100,每周有30个小时的运行时间

在这里插入图片描述

  1. 运行代码,发现输出的结果都在根目录下,将输出的结果导出到/kaggle/Working
 cp -r submission.csv /kaggle/working        导出输出文件即可

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

与C语言的旅程之分支与循环(2)

与C语言的旅程之分支与循环 C语⾔是结构化的程序设计语⾔,这⾥的结构指的是顺序结构、选择结构、循环结构, 目录 与C语言的旅程之分支与循环 1. if语句 1.1 if ​编辑1.2 else 1.3 分⽀中包含多条语句 1.4 嵌套if 1.5 悬空else问题 2. 关系操作符…

springBoot 自动配置与starter

目录 一、自动配置 Springboot实现自动配置的核心机制 Conditional的作用是什么? 如何自定义自动配置? 步骤 例子分析 自动配置的优先级 如何禁用特定的自动配置? 二、starter 如何理解Spring Boot中的starter? 如何自…

《Python编程实训快速上手》第三天--字典和结构化数据

一、字典 1、字典数据类型介绍 myCat {"size":"fat","color":"gray"} 特征: 字典输入时带上{}字典中每一个值是以键值对形式存在,先写键,再写值 2、字典与列表 列表索引必须是整数,字…

Pinia小菠萝(状态管理器)

Pinia 是一个专为 Vue 3 设计的状态管理库,它借鉴了 Vuex 的一些概念,但更加轻量灵活。下面将详细介绍如何使用 Pinia 状态管理库: 安装 Pinia 使用 npm:在项目目录下运行npm install pinia。使用 yarn:在项目目录下运…

【智能算法应用】哈里斯鹰算法优化二维栅格路径规划问题

摘要 本文研究了基于哈里斯鹰优化算法(Harris Hawks Optimization, HHO)的二维栅格路径规划方法。HHO算法模拟哈里斯鹰的猎食行为,通过迭代搜索过程找到从起点到终点的最优路径,避开栅格中的障碍物。实验结果表明,HHO…

vue/react做多语言国际化的时候,在语言配置中不同的语言配置不同的字体,动态引入scss里面

如果想直接在vue文件的css里面使用,就可以使用i18n的t函数,注意t外层也有引号: font-size: v-bind("t(style.teamCurModelFontSize)"); 前提是要引入t函数:

优衣库在淘宝平台的全方位竞品分析与店铺表现研究:市场定位与竞争策略透视

优衣库品牌在淘宝平台的全方位竞品与店铺表现分析 一、品牌商品分析 1.商品列表与分类分析(数据来源:关键词商品搜索接口;获取时间:2024.08.30) 商品类别分布柱状图: 根据关键词商品搜索接口获取到的优衣…

spark新能源汽车推荐系统-计算机设计毕业源码42422

摘要 本论文致力于探讨基于Spark技术的新能源汽车推荐系统新能源汽车分析及可视化内容。系统将严格按照软件开发流程进行各个阶段的工作,利用Python编程语言中的爬虫功能,实现对懂车帝的汽车信息数据的爬取,作为系统的数据来源,并…

Element UI组件Dialog显示闪动问题【解决方案】

在ElementUI中,el-dialog弹窗确实有时会导致页面出现抖动或闪动的问题。这通常是由于弹窗出现时对页面布局的影响,特别是滚动条的出现或消失,导致了页面的重新布局和渲染。以下是一些解决或缓解这一问题的方法: 解决方案 1. 关闭…

SpringBoot技术在企业资产管理中的应用

4系统概要设计 4.1概述 系统设计原则 以技术先进、系统实用、结构合理、产品主流、低成本、低维护量作为基本建设原则,规划系统的整体构架. 先进性: 在产品设计上,整个系统软硬件设备的设计符合高新技术的潮流,媒体数字化、压缩、…

月GMV2000W+,在视频号“开超市”也太赚了吧!

今年的视频号双11,似乎更低调了。 ▲ 图片来源:视频号 从官方的双11专栏来看,今年改叫“微信小店11.11好物节”。 今年618时候,还有专门的带货榜单,并且细分为“今日带货榜单、带货总榜、品牌带货榜、达人带货榜”&…

xlsx.js 读取excel文件

需求:读取一个excel文件。 一、 使用antd的Upload组件的 【customRequest】方法。 互斥。此方法跟【onChange】方法互斥,即:不可同时出现。调用次数不一样。onChange方法会根据文件当前的上传状态从而被调用多次(读取中&#xff…

华为云创建ECS前台展示规格类型选项是怎么做到的?

前台展示很多规格可选,怎么做到的?先了解规格其实都是管理员在后台service_OM创建好规格 1.规格 1.1设置自定义标签打通规格和主机组还能体验调度功能 引申:AZ可用分区(为了做容灾) 为什么在界面可以让我√az0.dc0,在填工程参数openstack region信息已写 AZ间存储不能共…

我们来学mysql -- 同时使用 AND 和 OR 查询错误(填坑篇)

AND 和 OR 一同使用问题 现象分析处理扩展 现象 业务上在“锁定”当前零件所在出口国的所有零件时,出现其他国家零件 问题定位 分析 or 切断了操作符之间的连续性,从union角度分析 where k1 Td621 and k1 Vda96 or k3 P00009等同 select * fr…

Python入门:了解 Python 中 globals() 和 types 的用法

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 文章内容 📒📝 使用 `globals()` 获取当前作用域信息📝 使用 `types` 模块判断函数类型📝 `globals()` 与 `types` 结合使用📢 综合示例📝 总结⚓️ 相关链接 ⚓️📖 介绍 📖 在 Python 中,动态获取当前作用域…

InsectaIntel 智能昆虫识别平台

项目介绍 InsectaIntel智能昆虫识别平台是一款革命性的软件,它将尖端的计算机视觉和深度学习技术融入昆虫识别领域,为用户提供了一个前所未有的工具。该平台通过集成先进的技术,不仅提高了昆虫识别的准确性,还极大地增强了用户体…

Python数据分析NumPy和pandas(二十六、数据整理--连接、合并和重塑 之三:重塑和透视)

对表格数据的重新排列操作,称为 reshape 或 pivot 。有很多种方法对表格数据进行重塑。 一、使用分层索引进行reshape 分层索引提供了一种在 DataFrame 中重新排列数据的方法。主要有两个函数方法: stack:将数据中的列旋转或透视到行。 u…

新能源行业必会基础知识-----电力现货市场理论篇-----电力现货市场价格机制-----电力市场价格体系

新能源行业必会基础知识-----电力现货市场理论篇-----主目录-----持续更新https://blog.csdn.net/grd_java/article/details/143364261 这本书是2023年出版的,是当下了解国内电力市场最好的途径了。还是推荐大家买来这本书进行阅读观看,最好作为随身携带…

使用免费的飞书机器人,实现消息推送实时通知

大家好,我是小悟。 实际工作中,我们会经常遇到需要给用户发送业务通知的功能需求,如果是小程序端,那么就使用小程序提供的模板消息通知,如果是APP端,一般就是使用个推、极光等第三方平台。 当然还有个万能…

SPIRE: Semantic Prompt-Driven Image Restoration 论文阅读笔记

这是一篇港科大学生在google research 实习期间发在ECCV2024的语义引导生成式修复的文章,港科大陈启峰也挂了名字。从首页图看效果确实很惊艳,尤其是第三行能用文本调控修复结果牌上的字。不过看起来更倾向于生成,对原图内容并不是很复原&…