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






相关实践学习
基于阿里云DeepGPU实例,用AI画唯美国风少女
本实验基于阿里云DeepGPU实例,使用aiacctorch加速stable-diffusion-webui,用AI画唯美国风少女,可提升性能至高至原性能的2.6倍。
相关文章
|
2天前
|
存储 人工智能 PyTorch
基于PyTorch/XLA的高效分布式训练框架
基于PyTorch/XLA的高效分布式训练框架
44 2
|
2天前
|
机器学习/深度学习 数据采集 PyTorch
使用PyTorch解决多分类问题:构建、训练和评估深度学习模型
使用PyTorch解决多分类问题:构建、训练和评估深度学习模型
使用PyTorch解决多分类问题:构建、训练和评估深度学习模型
|
2天前
|
机器学习/深度学习 PyTorch 算法框架/工具
【PyTorch实战演练】AlexNet网络模型构建并使用Cifar10数据集进行批量训练(附代码)
【PyTorch实战演练】AlexNet网络模型构建并使用Cifar10数据集进行批量训练(附代码)
96 0
|
2天前
|
机器学习/深度学习 PyTorch 算法框架/工具
【PyTorch实战演练】使用Cifar10数据集训练LeNet5网络并实现图像分类(附代码)
【PyTorch实战演练】使用Cifar10数据集训练LeNet5网络并实现图像分类(附代码)
104 0
|
2天前
|
机器学习/深度学习 数据可视化 PyTorch
TensorFlow与PyTorch框架的深入对比:特性、优势与应用场景
【5月更文挑战第4天】本文对比了深度学习主流框架TensorFlow和PyTorch的特性、优势及应用场景。TensorFlow以其静态计算图、高性能及TensorBoard可视化工具适合大规模数据处理和复杂模型,但学习曲线较陡峭。PyTorch则以动态计算图、易用性和灵活性见长,便于研究和原型开发,但在性能和部署上有局限。选择框架应根据具体需求和场景。
|
2天前
|
PyTorch 算法框架/工具 Python
【pytorch框架】对模型知识的基本了解
【pytorch框架】对模型知识的基本了解
|
2天前
|
机器学习/深度学习 负载均衡 PyTorch
PyTorch分布式训练:加速大规模数据集的处理
【4月更文挑战第18天】PyTorch分布式训练加速大规模数据集处理,通过数据并行和模型并行提升训练效率。`torch.distributed`提供底层IPC与同步,适合定制化需求;`DistributedDataParallel`则简化并行过程。实际应用注意数据划分、通信开销、负载均衡及错误处理。借助PyTorch分布式工具,可高效应对深度学习的计算挑战,未来潜力无限。
|
2天前
|
机器学习/深度学习 并行计算 PyTorch
PyTorch与CUDA:加速深度学习训练
【4月更文挑战第18天】本文介绍了如何使用PyTorch与CUDA加速深度学习训练。CUDA是NVIDIA的并行计算平台,常用于加速深度学习中的矩阵运算。PyTorch与CUDA集成,允许开发者将模型和数据迁移到GPU,利用`.to(device)`方法加速计算。通过批处理、并行化策略及优化技巧,如混合精度训练,可进一步提升训练效率。监控GPU内存和使用调试工具确保训练稳定性。PyTorch与CUDA的结合对深度学习训练的加速作用显著。
|
2天前
|
机器学习/深度学习 数据可视化 PyTorch
利用PyTorch实现基于MNIST数据集的手写数字识别
利用PyTorch实现基于MNIST数据集的手写数字识别
27 2
|
2天前
|
机器学习/深度学习 并行计算 PyTorch
【多GPU炼丹-绝对有用】PyTorch多GPU并行训练:深度解析与实战代码指南
本文介绍了PyTorch中利用多GPU进行深度学习的三种策略:数据并行、模型并行和两者结合。通过`DataParallel`实现数据拆分、模型不拆分,将数据批次在不同GPU上处理;数据不拆分、模型拆分则将模型组件分配到不同GPU,适用于复杂模型;数据和模型都拆分,适合大型模型,使用`DistributedDataParallel`结合`torch.distributed`进行分布式训练。代码示例展示了如何在实践中应用这些策略。
141 2
【多GPU炼丹-绝对有用】PyTorch多GPU并行训练:深度解析与实战代码指南