动手撸个自己的数据集进行训练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大模型。
相关文章
|
6月前
|
机器学习/深度学习 PyTorch 测试技术
从训练到推理:Intel Extension for PyTorch混合精度优化完整指南
PyTorch作为主流深度学习框架,凭借动态计算图和异构计算支持,广泛应用于视觉与自然语言处理。Intel Extension for PyTorch针对Intel硬件深度优化,尤其在GPU上通过自动混合精度(AMP)提升训练与推理性能。本文以ResNet-50在CIFAR-10上的实验为例,详解如何利用该扩展实现高效深度学习优化。
384 0
|
3月前
|
机器学习/深度学习 PyTorch TensorFlow
66_框架选择:PyTorch vs TensorFlow
在2025年的大语言模型(LLM)开发领域,框架选择已成为项目成功的关键决定因素。随着模型规模的不断扩大和应用场景的日益复杂,选择一个既适合研究探索又能支持高效部署的框架变得尤为重要。PyTorch和TensorFlow作为目前市场上最主流的两大深度学习框架,各自拥有独特的优势和生态系统,也因此成为开发者面临的经典选择难题。
|
4月前
|
机器学习/深度学习 算法 PyTorch
【Pytorch框架搭建神经网络】基于DQN算法、优先级采样的DQN算法、DQN + 人工势场的避障控制研究(Python代码实现)
【Pytorch框架搭建神经网络】基于DQN算法、优先级采样的DQN算法、DQN + 人工势场的避障控制研究(Python代码实现)
135 1
|
4月前
|
机器学习/深度学习 算法 PyTorch
【DQN实现避障控制】使用Pytorch框架搭建神经网络,基于DQN算法、优先级采样的DQN算法、DQN + 人工势场实现避障控制研究(Matlab、Python实现)
【DQN实现避障控制】使用Pytorch框架搭建神经网络,基于DQN算法、优先级采样的DQN算法、DQN + 人工势场实现避障控制研究(Matlab、Python实现)
231 0
|
8月前
|
机器学习/深度学习 监控 算法
利用PyTorch处理个人数据集
如此看来,整个处理个人数据集的过程就像进行一场球赛。你设立球场,安排队员,由教练训练,最后你可以看到他们的表现。不断地学习,不断地调整,你的模型也会越来越厉害。 当然,这个过程看似简单,但在实际操作时可能会奇怪各种问题。需要你在实践中不断摸索,不断学习。可是不要怕,只要你热爱,不怕困难,你一定能驯服你的数据,让他们为你所用!
165 35
|
机器学习/深度学习 人工智能 PyTorch
使用PyTorch实现GPT-2直接偏好优化训练:DPO方法改进及其与监督微调的效果对比
本文将系统阐述DPO的工作原理、实现机制,以及其与传统RLHF和SFT方法的本质区别。
1112 22
使用PyTorch实现GPT-2直接偏好优化训练:DPO方法改进及其与监督微调的效果对比
|
人工智能 安全 PyTorch
SPDL:Meta AI 推出的开源高性能AI模型数据加载解决方案,兼容主流 AI 框架 PyTorch
SPDL是Meta AI推出的开源高性能AI模型数据加载解决方案,基于多线程技术和异步事件循环,提供高吞吐量、低资源占用的数据加载功能,支持分布式系统和主流AI框架PyTorch。
641 10
SPDL:Meta AI 推出的开源高性能AI模型数据加载解决方案,兼容主流 AI 框架 PyTorch
|
机器学习/深度学习 并行计算 PyTorch
TorchOptimizer:基于贝叶斯优化的PyTorch Lightning超参数调优框架
TorchOptimizer 是一个基于贝叶斯优化方法的超参数优化框架,专为 PyTorch Lightning 模型设计。它通过高斯过程建模目标函数,实现智能化的超参数组合选择,并利用并行计算加速优化过程。该框架支持自定义约束条件、日志记录和检查点机制,显著提升模型性能,适用于各种规模的深度学习项目。相比传统方法,TorchOptimizer 能更高效地确定最优超参数配置。
636 7
|
11月前
|
机器学习/深度学习 PyTorch TensorFlow
深度学习工具和框架详细指南:PyTorch、TensorFlow、Keras
在深度学习的世界中,PyTorch、TensorFlow和Keras是最受欢迎的工具和框架,它们为研究者和开发者提供了强大且易于使用的接口。在本文中,我们将深入探索这三个框架,涵盖如何用它们实现经典深度学习模型,并通过代码实例详细讲解这些工具的使用方法。
1043 0

推荐镜像

更多