树叶分类竞赛(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.mzph.cn/bicheng/59424.shtml

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

相关文章

服务器作业(2)

架设一台NFS服务器,并按照以下要求配置 关闭防火墙 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 配置文件设置: [rootlocalhost ~]# vim /etc/exports 1、开放/nfs/shared目录,供所有用户查询资料 共享…

014:无人机遥控器操作

摘要:本文详细介绍了无人机遥控器及其相关操作。首先,解释了油门、升降舵、方向舵和副翼的概念、功能及操作方式,这些是控制无人机飞行姿态的关键部件。其次,介绍了美国手、日本手和中国手三种不同的操作模式,阐述了遥…

Redis的持久化以及性能管理

目录 一、Redis持久化概述 1.什么是Redis持久化 2.持久化方式 3.RDB持久化 3.1概念 3.2触发条件 3.3执行流程 3.4启动时加载 4. AOF持久化 4.1概念 4.2启动AOF 4.3执行流程 4.4启动时加载 5.RDB和AOF的优缺点 二、Redis性能管理 1.查看Redis内存使用 2…

什么是JS的垃圾回收机制?

在JavaScript中,垃圾回收(Garbage Collection,简称GC)是一种自动内存管理机制。它的主要任务是识别并回收不再被使用的对象,以释放内存空间。以下是关于JavaScript垃圾回收机制的详细解释: 标记清除算法 …

Java项目实战II基于Java+Spring Boot+MySQL的高校办公室行政事务管理系统(源码+数据库+文档)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发,CSDN平台Java领域新星创作者,专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 在高等教育…

HTB:PermX[WriteUP]

目录 连接至HTB服务器并启动靶机 1.How many TCP ports are listening on PermX? 使用nmap对靶机TCP端口进行开放扫描 2.What is the default domain name used by the web server on the box? 使用curl访问靶机80端口 3.On what subdomain of permx.htb is there an o…

nginx安装ssl模块教程

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一、openssl是什么?二、ssl证书免费申请地址三、安装步骤1.nginx安装ssl模块 总结 一、openssl是什么? OpenSSL 不仅是一个独立的工具包,它…

在Vue和OpenLayers中使用移动传感器实现飞机航线飞行模拟

项目实现的核心代码 项目概述 该项目的目标是使用Vue.js作为前端框架,结合OpenLayers用于地图显示,实时获取来自手机传感器的数据(如经纬度、高度、速度)来模拟飞机在地图上的飞行轨迹。整体架构如下: Vue.js 用于构建…

分析 SQL 语句的一般步骤

analyse-sql 数据库的性能调优是一个很大的话题。但是对于开发人员来讲,掌握一些常用的 SQL 优化手段却不是什么难事。 从本章节开始,将连载总结常用的适合于开发人员的 SQL 优化手段与大家分享。 要想解决性能优化的问题,首先要想办法发现哪…

数据库基础(2) . 安装MySQL

0.增加右键菜单选项 添加 管理员cmd 到鼠标右键 运行 reg文件 在注册表中添加信息 这样在右键菜单中就有以管理员身份打开命令行的选项了 1.获取安装程序 网址: https://dev.mysql.com/downloads/mysql/ 到官网下载MySQL8 的zip包, 然后解压 下载后的包为: mysql-8.0.16-…

文心一言 VS 讯飞星火 VS chatgpt (383)-- 算法导论24.5 3题

三、对引理 24.10 的证明进行改善,使其可以处理最短路径权重为 ∞ ∞ ∞ 和 − ∞ -∞ −∞ 的情况。引理 24.10(三角不等式)的内容是:设 G ( V , E ) G(V,E) G(V,E) 为一个带权重的有向图,其权重函数由 w : E → R w:E→R w:E→R 给出&…

深度学习基础知识-损失函数

目录 1. 均方误差(Mean Squared Error, MSE) 2. 平均绝对误差(Mean Absolute Error, MAE) 3. Huber 损失 4. 交叉熵损失(Cross-Entropy Loss) 5. KL 散度(Kullback-Leibler Divergence&…

2024 CSS保姆级教程二 - BFC详解

前言 - CSS中的文档流 在介绍BFC之前,需要先给大家介绍一下文档流。​ 我们常说的文档流其实分为定位流、浮动流、普通流三种。​ ​ 1. 绝对定位(Absolute positioning)​ 如果元素的属性 position 为 absolute 或 fixed,它就是一个绝对定位元素。​ 在…

Qt5 读写共享内存,已验证,支持汉字的正确写入和读取

Qt5,读写共享内存,Windows下同一个进程下可测试; 通过查看控制台输出即可看到写入和读出的内容; 相比网上其他介绍的方法,大部分均不支持汉字的正常读取,下面方法已经做了汉字存储的支持,可以…

Java图片转word

该方法可以控制一页是否只显示存放一张图片 第一步 <dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.2.3</version></dependency><dependency><groupId>org.apache…

VueSSR详解 VueServerRenderer Nutx

SSR Vue中的SSR&#xff08;Server-Side Rendering&#xff0c;服务器端渲染&#xff09;是一种将页面的渲染工作从客户端转移到服务器端的技术。以下是对Vue中SSR的详细解释&#xff1a; 一、SSR的工作原理 在传统的客户端渲染&#xff08;CSR&#xff09;中&#xff0c;页面的…

指针(c语言)

一.指针的定义 1.内存被划分为一个一个内存单元&#xff0c;对内存单元进行编号&#xff0c;这些编号称为内存单元的地址&#xff0c; 其中指针就是存放地址的容器 2.平常说的指针&#xff0c;其实就是指针变量 注意&#xff1a; 1个内存单元的大小是1个字节&#xff0c;如果是…

一篇文章了解TCP/IP模型

TCP/IP模型&#xff0c;即传输控制协议/互联网协议模型&#xff08;Transmission Control Protocol/Internet Protocol Model&#xff09;&#xff0c;是互联网及许多其他网络上使用的分层通信模型。以下是对TCP/IP模型的详细介绍&#xff1a; 一、定义与组成TCP/IP模型是一个四…

AI开发-三方库-torchvision

1 需求 2 torchvision.datasets CLASS torchvision.datasets.MNIST(root: Union[str, Path], train: bool True, transform: Optional[Callable] None, target_transform: Optional[Callable] None, download: bool False) roottraintransformdownload MNIST — Torchv…

动手学深度学习67 自注意力

1. 自注意力 k 窗口的大小 每个kernel窗口都可以并行计算&#xff0c;GPU计算 最长路径&#xff1a;信息是怎么传递的 filed–视野 自注意力适合处理比较长的文本&#xff0c;无视距离&#xff0c;可以看比较长的文本&#xff0c;但是计算复杂度高【代价】 位置信息加到输入数…