动手撸个自己的数据集进行训练Pytorch框架(索引式)

简介: 动手撸个自己的数据集进行训练Pytorch框架(索引式)

一.前言:


大家想要完成图像分类的时候,大多是想对自己构造的数据集进行分类,此时我们需要载入自己的数据集。因此需要借助Dataset类完成。


整体流程:


1.1 图像数据


1.2 图像索引文件


1.3 使用Dataset构建数据集


1.4 使用DataLoader读取数据


二.这里展示一下图像文件及其标签


2.1索引式标签数据格式文件:


image.png


image.png

2.2文件目录组织形式


image.png



三.制作自己的数据集


在大家自制数据集的时候往往是一个文件夹内都为同一标签图像,这样也便于收集整理图像,但是在这里划分数据的训练和测试,于是大家需要制作图像索引


3.1图像索引制作流程:


3.1.1 输入文件夹地址(该地址下的图像为同一类的图像)


3.1.2 选择生成txt文件的地址以及txt的名称


3.1.3 生成txt文件


3.1.4 构建for循环便于生成图像


3.1.5 设置标签的名字


3.1.6 每一行的索引构成:图像名称 + 逗号(英)+ 图像标签


3.1.7 索引行写入txt中


3.2参考代码:

import os
name = 9
img_path = './%s/' %name
TxtName = './data%s .txt' % name
f = open(TxtName, 'a')
img_path_Line = os.listdir(img_path)
for ImgName in img_path_Line:
    label = "%s" % name # 修改你标签的名字
    Name_Label = ImgName + ',' + label
    print(Name_Label)
    f.write(Name_Label)  # 格式化写入也可以
    f.write('\n')  # 显示写入换行
f.close()


3.3生成的样子:image.png


这里我们需要将各data1-9汇总一下即可得到All.txt文件。


此时我们还需要将总文件划分训练和测试文件,二者公用一个数据集文件夹(datas),在txt中划分。


3.4划分训练测试代码:

# -*- coding:utf-8 -*-
# 在txt文件中随机抽取行
import random
import math
All = open('All.txt', 'r', encoding='utf-8')  # 要被抽取的文件All.txt,共5000行
newf = open('train.txt', 'w', encoding='utf-8')  # 抽取的0.7倍写入train.txt
AllNum = 5000 # 总图像数
SetTestNum = 0.7 # 设置比例
TestNum = math.floor(SetTestNum * AllNum)
resultList = random.sample(range(0, AllNum), TestNum)  # sample(x,y)函数的作用是从序列x中,随机选择y个不重复的元素
lines = All.readlines()
for i in resultList:
    newf.write(lines[i])
All.close()



四.构建自己的Dataset


这里借鉴阿里天池云的教程,其步骤大致分如下几步:


4.1步骤4.1.1 初始化图像文件路径或文件名列表


4.1.2 根据索引index从文件中读取一个数据


4.1.3 预处理数据(可不要)


4.1.4 返回数据对


4.1.5 返回数据量


4.2轮子来了


from PIL import Image
import torch
from torch.utils.data import Dataset
from torchvision import transforms
##
class MnistDataset(Dataset):
    def __init__(self, image_path, image_label, transform=None):
        super(MnistDataset, self).__init__()
        self.image_path = image_path  # 初始化图像路径列表
        self.image_label = image_label  # 初始化图像标签列表
        self.transform = transform  # 初始化数据增强方法
    def __getitem__(self, index):
        """
        获取对应index的图像,并视情况进行数据增强
        """
        image = Image.open(self.image_path[index])
        image = np.asarray(image)
        label = float(self.image_label[index])
        if self.transform is not None:
            image = self.transform(image)
        return image, torch.tensor(label)
    def __len__(self):
        return len(self.image_path)
def get_path_label(img_root, label_file_path):
    """
    获取数字图像的路径和标签并返回对应的列表
    @ img_root:保存图像的根目路
    @ label_file_path 保存图像标签的文件路径,。cvs 或 。txt
    @ return:图像的路径列表和对应的标签列表
    """
    data = pd.read_csv(label_file_path, names=['img', 'label'])
    print(data)
    data['img'] = data['img'].apply(lambda x: img_root + x)
    return data['img'].tolist(), data['label'].tolist()

在使用轮子的过程中对阿里天池云中做出了细微的更改:

if __name__ == '__main__':
    ImgPath = './datas/AllData/'
    # 获取训练集路径列表和标签列表
    train_data_root = ImgPath
    train_label = './datas/train.txt'  # 输入训练集的txt
    train_img_list, train_label_list = get_path_label(train_data_root, train_label)
    # 训练集dataset
    train_dataset = MnistDataset(train_img_list, train_label_list,
                                 transform=transforms.Compose([transforms.ToTensor()]))
    # 获取测试集路径列表和标签列表
    test_data_root = ImgPath
    test_label = './datas/test.txt'  # 输入测试集的txt
    test_img_list, test_label_list = get_path_label(test_data_root, test_label)
    # 训练集dataset
    test_dataset = MnistDataset(test_img_list, test_label_list, transform=transforms.Compose([transforms.ToTensor()]))


我们可以运行的看一下train_dataset

从print中可以看见其基本结果为index编号+ img(名称) + label(名称)


                                           img  label
0     0f53988a-aa4c-11ec-98ee-0068ebc9b98d.jpg      5
1     12c269f2-aa4c-11ec-8c98-0068ebc9b98d.jpg      7
2     02bbb794-aa4c-11ec-a86d-0068ebc9b98d.jpg      2
3     0ad921d7-aa4c-11ec-aaf8-0068ebc9b98d.jpg      3
4     0f559308-aa4c-11ec-bfe7-0068ebc9b98d.jpg      5
...                                        ...    ...
3495  14853acd-aa4c-11ec-9214-0068ebc9b98d.jpg      8
3496  0ad68b8d-aa4c-11ec-bc3f-0068ebc9b98d.jpg      3
3497  f80a329d-aa4b-11ec-8e14-0068ebc9b98d.jpg      1
3498  02b8fa4c-aa4c-11ec-9598-0068ebc9b98d.jpg      2
3499  0acc322b-aa4c-11ec-a3f3-0068ebc9b98d.jpg      3
[3500 rows x 2 columns]
<__main__.MnistDataset object at 0x0000018075EFFFD0>
                                           img  label
0     12c8a739-aa4c-11ec-92ee-0068ebc9b98d.jpg      7
1     0ad6d970-aa4c-11ec-a49a-0068ebc9b98d.jpg      3
2     f809bdba-aa4b-11ec-877b-0068ebc9b98d.jpg      1
3     1111623a-aa4c-11ec-a3f9-0068ebc9b98d.jpg      6
4     12c5c308-aa4c-11ec-9f4e-0068ebc9b98d.jpg      7
...                                        ...    ...
1495  1640597c-aa4c-11ec-aa18-0068ebc9b98d.jpg      9
1496  0d2db729-aa4c-11ec-b385-0068ebc9b98d.jpg      4
1497  11188943-aa4c-11ec-8926-0068ebc9b98d.jpg      6
1498  0f508d5f-aa4c-11ec-996b-0068ebc9b98d.jpg      5
1499  147b5682-aa4c-11ec-bb98-0068ebc9b98d.jpg      8
[1500 rows x 2 columns]
Process finished with exit code 0


此时扔未开始读取图像文件,目前做的是准备工作!


可以看一下咱们的图像的通道数、像素大小、标签:

for i in train_dataset:
    img, label = i
    print(img.size(), label)

输出节选:

torch.Size([1, 20, 20]) tensor(0.)
torch.Size([1, 20, 20]) tensor(8.)
torch.Size([1, 20, 20]) tensor(5.)
torch.Size([1, 20, 20]) tensor(1.)
torch.Size([1, 20, 20]) tensor(7.)


4.3使用DataLoader这里需要使用的是DataLoader函数,其内部常用参数使用:


dataset=train_dataset:输入自己要加载的数据set


batch_size=3:一个批量的大小


shuffle=True:是否打乱顺序


num_workers=4:是否使用多进程,0代表不使用


pin_memory=True:是否将数据保存在pin_memory区, pin_memory数据转移到Gpu中会快一些


drop_last=True:当为Ture时,dataset中的数据个数不是batch_size整数倍


#接上
# 开始加载自己的数据
train_loader = DataLoader(dataset=train_dataset,  # 输入自己要加载的数据set
                          batch_size=3,  # 一个批量的大小
                          shuffle=True,  # 是否打乱顺序
                          num_workers=4,  # 是否使用多进程,0代表不使用
                          pin_memory=True,  # 是否将数据保存在pin_memory区, pin_memory数据转移到Gpu中会快一些
                          drop_last=True)  # 当为Ture时,dataset中的数据个数不是batch_size整数倍时,将多余出不足一个batch的数据丢弃
test_loader = DataLoader(dataset=test_dataset,  # 输入自己要加载的数据set
                         batch_size=3,  # 一个批量的大小
                         shuffle=True,  # 是否打乱顺序
                         num_workers=4,  # 是否使用多进程,0代表不使用
                         pin_memory=True,  # 是否将数据保存在pin_memory区, pin_memory数据转移到Gpu中会快一些
                         drop_last=True)  # 当为Ture时,dataset中的数据个数不是batch_size整数倍时,将多余出不足一个batch的数据丢弃


五.开始训练


结合juejin.cn/post/707783… 中GPU版本的分类,对自己下载的数据集进行分类,这里需要注意的地方有两个:


5.1 导入的库需要齐全


5.2 在卷积网络中需要将in_c=改为:400(因为20201)


5.3 在训练代码中的label改为:label.long()


demo:

import time
import pandas as pd
import numpy as np
import torch
import torch.nn as nn
import torch.backends.cudnn as cudnn
from PIL import Image
from torch import optim
from torch.autograd import Variable
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms
class Net(nn.Module):
    def __init__(self, in_c=400, out_c=10):
        super(Net, self).__init__()
        # 定义全连接层
        self.fc1 = nn.Linear(in_c, 512)
        # 定义激活层
        self.act1 = nn.ReLU(inplace=True)
        self.fc2 = nn.Linear(512, 256)
        self.act2 = nn.ReLU(inplace=True)
        self.fc3 = nn.Linear(256, 128)
        self.act3 = nn.ReLU(inplace=True)
        self.fc4 = nn.Linear(128, out_c)
    def forward(self, x):
        x = self.act1(self.fc1(x))
        x = self.act2(self.fc2(x))
        x = self.act3(self.fc3(x))
        x = self.fc4(x)
        return x
##
class MnistDataset(Dataset):
    def __init__(self, image_path, image_label, transform=None):
        super(MnistDataset, self).__init__()
        self.image_path = image_path  # 初始化图像路径列表
        self.image_label = image_label  # 初始化图像标签列表
        self.transform = transform  # 初始化数据增强方法
    def __getitem__(self, index):
        """
        获取对应index的图像,并视情况进行数据增强
        """
        image = Image.open(self.image_path[index])
        image = np.asarray(image)
        label = float(self.image_label[index])
        if self.transform is not None:
            image = self.transform(image)
        return image, torch.tensor(label)
    def __len__(self):
        return len(self.image_path)
def get_path_label(img_root, label_file_path):
    """
    获取数字图像的路径和标签并返回对应的列表
    @ img_root:保存图像的根目路
    @ label_file_path 保存图像标签的文件路径,。cvs 或 。txt
    @ return:图像的路径列表和对应的标签列表
    """
    data = pd.read_csv(label_file_path, names=['img', 'label'])
    data['img'] = data['img'].apply(lambda x: img_root + x)
    return data['img'].tolist(), data['label'].tolist()
if __name__ == '__main__':
    t1 = time.time()
    # 搭建网络
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    net = Net()
    cudnn.benchmark = True
    net = net.to(device)
    ImgPath = './datas/AllData/'
    # 获取训练集路径列表和标签列表
    train_data_root = ImgPath
    train_label = './datas/train.txt'  # 输入训练集的txt
    train_img_list, train_label_list = get_path_label(train_data_root, train_label)
    # 训练集dataset
    train_dataset = MnistDataset(train_img_list, train_label_list,
                                 transform=transforms.Compose([transforms.ToTensor()]))
    """
    for i in train_dataset:
        img, label = i
        print(img.size(), label)
    """
    # 获取测试集路径列表和标签列表
    test_data_root = ImgPath
    test_label = './datas/test.txt'  # 输入测试集的txt
    test_img_list, test_label_list = get_path_label(test_data_root, test_label)
    # 训练集dataset
    test_dataset = MnistDataset(test_img_list, test_label_list, transform=transforms.Compose([transforms.ToTensor()]))
    # 开始加载自己的数据
    train_data = DataLoader(dataset=train_dataset,  # 输入自己要加载的数据set
                            batch_size=16,  # 一个批量的大小
                            shuffle=True,  # 是否打乱顺序
                            num_workers=4,  # 是否使用多进程,0代表不使用
                            pin_memory=True,  # 是否将数据保存在pin_memory区, pin_memory数据转移到Gpu中会快一些
                            drop_last=True)  # 当为Ture时,dataset中的数据个数不是batch_size整数倍时,将多余出不足一个batch的数据丢弃
    test_data = DataLoader(dataset=test_dataset,  # 输入自己要加载的数据set
                           batch_size=8,  # 一个批量的大小
                           shuffle=True,  # 是否打乱顺序
                           num_workers=4,  # 是否使用多进程,0代表不使用
                           pin_memory=True,  # 是否将数据保存在pin_memory区, pin_memory数据转移到Gpu中会快一些
                           drop_last=True)  # 当为Ture时,dataset中的数据个数不是batch_size整数倍时,将多余出不足一个batch的数据丢弃
    # 定义损失函数 -- 交叉熵
    criterion = torch.nn.CrossEntropyLoss().to(device)
    # 定义优化器 -- 随机梯度下降
    optimizer = optim.SGD(net.parameters(), lr=0.01, weight_decay=0.00005)
    # 开始训练
    losses = []  # 记录训练损失
    acces = []  # 记录训练精度
    eval_losses = []  # 记录测试损失
    eval_acces = []  # 记录测试精度
    nums_epoch = 20  # 训练次数
    for epoch in range(nums_epoch):
        train_loss = 0  # 设置训练损失的初始值
        train_acc = 0  # 设置训练精度的初始值
        net.train()
        for batch, (img, label) in enumerate(train_data):
            img = img.reshape(img.size(0), -1)
            img = Variable(img)
            img = img.to(device)
            label = Variable(label)
            label = label.to(device)
            # 向前传播
            out = net(img)
            loss = criterion(out, label.long())
            # 反向传播
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
            # 记录误差
            train_loss += loss.item()
            # 计算分类正确率
            _, pred = out.max(1)
            num_correct = (pred == label.long()).sum().item()
            acc = num_correct / img.shape[0]
            if (batch + 1) % 200 == 0:
                print(
                    '[INFO] Epoch-{}-Batch-{}: Train: Loss-{:.4f},Accuracy-{:.4f}'.format(epoch + 1, batch + 1,
                                                                                          loss.item(),
                                                                                          acc))
                train_acc += acc
        losses.append(train_acc / len(train_data))
        acces.append(train_acc / len(train_data))
        eval_loss = 0
        eval_acc = 0
        # 测试集不训练
        for img, label in test_data:
            img = img.reshape(img.size(0), -1)
            img = Variable(img)
            img = img.to(device)
            label = Variable(label)
            label = label.to(device)
            out = net(img)
            loss = criterion(out, label.long())
            eval_loss += loss.item()
            _, pred = out.max(1)
            num_correct = (pred == label.long()).sum().item()
            acc = num_correct / img.shape[0]
            eval_acc += acc
        eval_losses.append(eval_loss / len(test_data))
        eval_acces.append(eval_acc / len(test_data))
        # 打印参数
        set_epoch = epoch + 1
        set_lossTrain = train_loss / len(train_data)
        set_AccTrain = train_acc / len(train_data)
        set_lossEval = eval_loss / len(test_data)
        set_AccEval = eval_acc / len(test_data)
        print('[INFO] Epoch-{}: Train: Loss-{:.4f},Accuracy-{:.4f} |Test:Loss-{:.4f}, Accuracy-{:.4f}'.format(set_epoch,
                                                                                                              set_lossTrain,
                                                                                                              set_AccTrain,
                                                                                                              set_lossEval,
                                                                                                              set_AccEval))
    torch.save(net.state_dict(), 'saveNet.pth')
    t2 = time.time()
    t = t2 - t1
    print(t)






相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
相关文章
|
1月前
|
机器学习/深度学习 人工智能 PyTorch
使用PyTorch实现GPT-2直接偏好优化训练:DPO方法改进及其与监督微调的效果对比
本文将系统阐述DPO的工作原理、实现机制,以及其与传统RLHF和SFT方法的本质区别。
89 22
使用PyTorch实现GPT-2直接偏好优化训练:DPO方法改进及其与监督微调的效果对比
|
10天前
|
机器学习/深度学习 并行计算 PyTorch
TorchOptimizer:基于贝叶斯优化的PyTorch Lightning超参数调优框架
TorchOptimizer 是一个基于贝叶斯优化方法的超参数优化框架,专为 PyTorch Lightning 模型设计。它通过高斯过程建模目标函数,实现智能化的超参数组合选择,并利用并行计算加速优化过程。该框架支持自定义约束条件、日志记录和检查点机制,显著提升模型性能,适用于各种规模的深度学习项目。相比传统方法,TorchOptimizer 能更高效地确定最优超参数配置。
57 7
|
1月前
|
人工智能 安全 PyTorch
SPDL:Meta AI 推出的开源高性能AI模型数据加载解决方案,兼容主流 AI 框架 PyTorch
SPDL是Meta AI推出的开源高性能AI模型数据加载解决方案,基于多线程技术和异步事件循环,提供高吞吐量、低资源占用的数据加载功能,支持分布式系统和主流AI框架PyTorch。
72 10
SPDL:Meta AI 推出的开源高性能AI模型数据加载解决方案,兼容主流 AI 框架 PyTorch
|
2月前
|
机器学习/深度学习 监控 PyTorch
深度学习工程实践:PyTorch Lightning与Ignite框架的技术特性对比分析
在深度学习框架的选择上,PyTorch Lightning和Ignite代表了两种不同的技术路线。本文将从技术实现的角度,深入分析这两个框架在实际应用中的差异,为开发者提供客观的技术参考。
61 7
|
4月前
|
并行计算 PyTorch 算法框架/工具
基于CUDA12.1+CUDNN8.9+PYTORCH2.3.1,实现自定义数据集训练
文章介绍了如何在CUDA 12.1、CUDNN 8.9和PyTorch 2.3.1环境下实现自定义数据集的训练,包括环境配置、预览结果和核心步骤,以及遇到问题的解决方法和参考链接。
203 4
基于CUDA12.1+CUDNN8.9+PYTORCH2.3.1,实现自定义数据集训练
|
3月前
|
机器学习/深度学习 PyTorch 算法框架/工具
探索PyTorch:张量的类型转换,拼接操作,索引操作,形状操作
探索PyTorch:张量的类型转换,拼接操作,索引操作,形状操作
|
5月前
|
机器学习/深度学习 并行计算 PyTorch
GPU 加速与 PyTorch:最大化硬件性能提升训练速度
【8月更文第29天】GPU(图形处理单元)因其并行计算能力而成为深度学习领域的重要组成部分。本文将介绍如何利用PyTorch来高效地利用GPU进行深度学习模型的训练,从而最大化训练速度。我们将讨论如何配置环境、选择合适的硬件、编写高效的代码以及利用高级特性来提高性能。
1043 1
|
5月前
|
机器学习/深度学习 并行计算 PyTorch
PyTorch与DistributedDataParallel:分布式训练入门指南
【8月更文第27天】随着深度学习模型变得越来越复杂,单一GPU已经无法满足训练大规模模型的需求。分布式训练成为了加速模型训练的关键技术之一。PyTorch 提供了多种工具来支持分布式训练,其中 DistributedDataParallel (DDP) 是一个非常受欢迎且易用的选择。本文将详细介绍如何使用 PyTorch 的 DDP 模块来进行分布式训练,并通过一个简单的示例来演示其使用方法。
678 2
|
5月前
|
机器学习/深度学习 人工智能 PyTorch
AI智能体研发之路-模型篇(五):pytorch vs tensorflow框架DNN网络结构源码级对比
AI智能体研发之路-模型篇(五):pytorch vs tensorflow框架DNN网络结构源码级对比
97 1
|
5月前
|
UED 开发者
哇塞!Uno Platform 数据绑定超全技巧大揭秘!从基础绑定到高级转换,优化性能让你的开发如虎添翼
【8月更文挑战第31天】在开发过程中,数据绑定是连接数据模型与用户界面的关键环节,可实现数据自动更新。Uno Platform 提供了简洁高效的数据绑定方式,使属性变化时 UI 自动同步更新。通过示例展示了基本绑定方法及使用 `Converter` 转换数据的高级技巧,如将年龄转换为格式化字符串。此外,还可利用 `BindingMode.OneTime` 提升性能。掌握这些技巧能显著提高开发效率并优化用户体验。
78 0

热门文章

最新文章