动手撸个自己的数据集进行训练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)






相关实践学习
在云上部署ChatGLM2-6B大模型(GPU版)
ChatGLM2-6B是由智谱AI及清华KEG实验室于2023年6月发布的中英双语对话开源大模型。通过本实验,可以学习如何配置AIGC开发环境,如何部署ChatGLM2-6B大模型。
相关文章
|
12月前
|
机器学习/深度学习 PyTorch 测试技术
从训练到推理:Intel Extension for PyTorch混合精度优化完整指南
PyTorch作为主流深度学习框架,凭借动态计算图和异构计算支持,广泛应用于视觉与自然语言处理。Intel Extension for PyTorch针对Intel硬件深度优化,尤其在GPU上通过自动混合精度(AMP)提升训练与推理性能。本文以ResNet-50在CIFAR-10上的实验为例,详解如何利用该扩展实现高效深度学习优化。
577 0
|
机器学习/深度学习 监控 算法
利用PyTorch处理个人数据集
如此看来,整个处理个人数据集的过程就像进行一场球赛。你设立球场,安排队员,由教练训练,最后你可以看到他们的表现。不断地学习,不断地调整,你的模型也会越来越厉害。 当然,这个过程看似简单,但在实际操作时可能会奇怪各种问题。需要你在实践中不断摸索,不断学习。可是不要怕,只要你热爱,不怕困难,你一定能驯服你的数据,让他们为你所用!
271 35
|
机器学习/深度学习 人工智能 PyTorch
使用PyTorch实现GPT-2直接偏好优化训练:DPO方法改进及其与监督微调的效果对比
本文将系统阐述DPO的工作原理、实现机制,以及其与传统RLHF和SFT方法的本质区别。
1610 22
使用PyTorch实现GPT-2直接偏好优化训练:DPO方法改进及其与监督微调的效果对比
|
机器学习/深度学习 PyTorch 算法框架/工具
探索PyTorch:张量的类型转换,拼接操作,索引操作,形状操作
探索PyTorch:张量的类型转换,拼接操作,索引操作,形状操作
|
并行计算 PyTorch 算法框架/工具
基于CUDA12.1+CUDNN8.9+PYTORCH2.3.1,实现自定义数据集训练
文章介绍了如何在CUDA 12.1、CUDNN 8.9和PyTorch 2.3.1环境下实现自定义数据集的训练,包括环境配置、预览结果和核心步骤,以及遇到问题的解决方法和参考链接。
1217 4
基于CUDA12.1+CUDNN8.9+PYTORCH2.3.1,实现自定义数据集训练
|
机器学习/深度学习 并行计算 PyTorch
GPU 加速与 PyTorch:最大化硬件性能提升训练速度
【8月更文第29天】GPU(图形处理单元)因其并行计算能力而成为深度学习领域的重要组成部分。本文将介绍如何利用PyTorch来高效地利用GPU进行深度学习模型的训练,从而最大化训练速度。我们将讨论如何配置环境、选择合适的硬件、编写高效的代码以及利用高级特性来提高性能。
2760 1
|
机器学习/深度学习 并行计算 PyTorch
优化技巧与策略:提高 PyTorch 模型训练效率
【8月更文第29天】在深度学习领域中,PyTorch 是一个非常流行的框架,被广泛应用于各种机器学习任务中。然而,随着模型复杂度的增加以及数据集规模的增长,如何有效地训练这些模型成为了一个重要的问题。本文将介绍一系列优化技巧和策略,帮助提高 PyTorch 模型训练的效率。
1277 0
|
机器学习/深度学习 PyTorch 测试技术
深度学习入门:使用 PyTorch 构建和训练你的第一个神经网络
【8月更文第29天】深度学习是机器学习的一个分支,它利用多层非线性处理单元(即神经网络)来解决复杂的模式识别问题。PyTorch 是一个强大的深度学习框架,它提供了灵活的 API 和动态计算图,非常适合初学者和研究者使用。
602 0
|
机器学习/深度学习 并行计算 PyTorch
PyTorch与DistributedDataParallel:分布式训练入门指南
【8月更文第27天】随着深度学习模型变得越来越复杂,单一GPU已经无法满足训练大规模模型的需求。分布式训练成为了加速模型训练的关键技术之一。PyTorch 提供了多种工具来支持分布式训练,其中 DistributedDataParallel (DDP) 是一个非常受欢迎且易用的选择。本文将详细介绍如何使用 PyTorch 的 DDP 模块来进行分布式训练,并通过一个简单的示例来演示其使用方法。
2727 2

热门文章

最新文章

推荐镜像

更多