【PytorchLearning】构建自己的数据集

利用本地数据构建自己的数据集

以猫狗大战数据集为例

1 猫狗大战数据集

Cats vs. Dogs(猫狗大战)数据集是Kaggle与泰坦尼克号并列的一个入门任务,利用给定的数据结合不同的算法实现猫和狗的识别。
原始数据集其中包含了训练集和测试集,训练集中猫和狗的图片数量都是12500张且按顺序排序,测试集中猫和狗混合乱序图片一共12500张。
为了简化任务,在这里我只使用猫狗图像各4000张、共8000张数据,链接如下:
链接:https://pan.baidu.com/s/1cJ-f-q5CQV5rdgQVAGv72Q
提取码:ultv
在这里插入图片描述

2 数据预处理

数据在神经网络的模型中进行传播前首先需要保证尺寸相同(部分金字塔模型也可以处理不同尺寸的输入,本次不做讨论)。在MNIST案例中,数据的格式、尺寸都已经集成好,我们只需要进行下载、加载。但是对于本任务,猫狗图像的格式虽然都是jpg,但是尺寸并不统一,所以需要进行初步的转化。例如,可以对图像进行resize、crop等操作。
这里,只提供一种比较简单的方法:resize
对于所有图像,我们将其Resize到100x100的尺寸,代码如下

import cv2
import os
from tqdm import tqdm

DataPath=r'TrainingData'# 训练数据
SavePath=r'ResizedData'

for img_dir in os.listdir(DataPath):
    # 包含类别信息的文件夹
    img_label_path=os.path.join(DataPath,img_dir)
    # 存储处理后的图片的文件夹
    save_label_path=os.path.join(SavePath,img_dir)
    if not os.path.exists(save_label_path):
        os.mkdir(save_label_path)

    # 使用tqdm查看每一类别图片处理进度
    tbar = tqdm(os.listdir(img_label_path), ncols=100)
    for image in tbar:
        # 进入到文件夹下进行图片遍历
        image_path=os.path.join(img_label_path,image)
        # 使用cv2读取图片
        image_old=cv2.imread(image_path)
        image_new=cv2.resize(image_old,(100,100))
        # 保存图像
        save_path=os.path.join(save_label_path,image)
        cv2.imwrite(save_path,image_new)
    print("当前处理的图片类别为{},保存路径为{},已处理完成".format(img_dir, save_label_path))

3 创建自己的Dataset

3.1 Dataset与DataLoader

在Pytroch中创建数据集主要使用两个类:Dataset和DataLoader。
其中,Dataset既是一个集成数据集的库(例如MNIST、CIFAR都集成在Datasets中),又是一个用来表示数据集的抽象类,我们的数据集可以用这个类来构建;
而DataLoader本质上就是一个 iterable(内部定义了 __ iter __ 方法),通过读取Datasets中的数据,组装成一个batch后返回一个tensor。
总而言之,Dataset是构建Dataloader的重要实例参数之一。

3.2 如何定义Dataset

Dataset类是Pytorch中所有数据集加载类中应该继承的父类,其中父类中的两个私有成员函数必须被重载,否则将会触发错误提示:

def __getitem__(self,index):
	# 编写支持数据集索引的函数
def __len__(self):
	# 返回数据集的大小

重点是 getitem函数,getitem接收一个index,然后返回图片数据和标签,这个index通常指的是一个list的index,这个list的每个元素就包含了图片数据的路径标签信息。 所以这里我将介绍一种比较普遍的做法:

1-制作存储了图片的路径和标签信息的txt
2-将这些信息转化为list,该list每一个元素对应一个样本
3-通过getitem函数,读取数据和标签,并返回数据和标签

3.3 制作包含路径和标签的txt文件

路径建议使用绝对路径,以防文件相对位置发生变化时读取失败。
标签一定要是整型变量(张量求梯度),一定要从0开始。
标签一定要是整型变量(张量求梯度),一定要从0开始。
标签一定要是整型变量(张量求梯度),一定要从0开始。
重要的事说三遍,大家一定记住,否则会触发Assertion cur_target >= 0 && cur_target < n_classes‘ failed. 特效…


import os
import random

DataPath=r'ResizedData'# 训练数据
absolutePath=r'D:\Code\pytorch\Pytorch_Train\catvsdog\data'# 这里需要替换成catvsdog的绝对路径
label=0

if __name__ == '__main__':

    for dataClass in os.listdir(DataPath):

        # 读取猫狗数据
        data=os.listdir(os.path.join(DataPath,dataClass))

        # 打乱顺序
        random.shuffle(data)

        # 训练集占所有数据的4/5
        train_len=len(data)*4//5

        # 将图片按照8:2划分为训练、验证
        train_list,val_list=data[:train_len],data[train_len:]


        # 将训练集写入train.txt
        with open(os.path.join(absolutePath,'train.txt'), 'a')as f:
            for img in train_list:
                f.write(os.path.join(absolutePath,DataPath,dataClass,img)+ ' ' + str(label)+'\n')
        print("标签为{}的训练集图片处理完毕".format(dataClass))

        # 将验证集写入val.txt
        with open(os.path.join(absolutePath,'val.txt'), 'a+')as f:
            for img in val_list:
                f.write(os.path.join(absolutePath,DataPath,dataClass,img) + ' ' + str(label)+'\n')
        print("标签为{}的验证集图片处理完毕".format(dataClass))

        label+=1

3.4 读取txt文件,继承Dataset

困难的任务前边已经解决了,这部分并不是很难理解,直接上代码

import torch
import numpy as np
from PIL import Image
from torch.utils.data.dataset import Dataset
import torchvision.transforms as transforms

def read_txt(path):
    # 读取txt文件,将图像路径和标签写入到列表中并返回
    ims,labels=[],[]
    with open(path,'r') as f:
        for sample in f.readlines():
            im,label=sample.strip().split(" ")
            ims.append(im)
            labels.append(label)
    return ims,labels

class ImageDataset(Dataset):
    # 重载DataLoader

    def __init__(self, txtpath, transform=None):

        super().__init__()
        self.ims, self.labels = read_txt(txtpath)
        self.transform = transform


    def __getitem__(self, index):

        im_path=self.ims[index]
        label=self.labels[index]

        # 使用Image库处理图片,将其转化为张量
        image=Image.open(im_path)
        transf = transforms.ToTensor()
        image = transf(image)

        # image = self.transform(image).float().cuda()
        label=torch.from_numpy(np.asarray(label,dtype=np.int32)).long()

        return image,label

    def __len__(self):
        return len(self.ims)


后续的model及train文件之前已经介绍,这里不再赘述

附录:项目链接

链接:https://pan.baidu.com/s/1f-Gy4CAzrB0c7fUhvsKing
提取码:lo59

每日一诗

归去来兮辞
陶渊明

   归去来兮,田园将芜胡不归?既自以心为形役,奚惆怅而独悲?悟已往之不谏,知来者之可追。 实迷途其未远,觉今是而昨非。舟遥遥以轻飏,风飘飘而吹衣。问征夫以前路,恨晨光之熹微。

   乃瞻衡宇,载欣载奔。僮仆欢迎,稚子候门。三径就荒,松菊犹存。携幼入室,有酒盈樽。引壶觞以自酌,眄庭柯以怡颜。倚南窗以寄傲,审容膝之易安。园日涉以成趣,门虽设而常关。策扶老以流憩,时矫首而遐观。云无心以出岫,鸟倦飞而知还。景翳翳以将入,抚孤松而盘桓。

   归去来兮,请息交以绝游。世与我而相违,复驾言兮焉求?悦亲戚之情话,乐琴书以消忧。农人告余以春及,将有事于西畴。或命巾车,或棹孤舟。既窈窕以寻壑,亦崎岖而经丘。木欣欣以向荣,泉涓涓而始流。善万物之得时,感吾生之行休。

   已矣乎!寓形宇内复几时?曷不委心任去留?胡为乎遑遑欲何之?富贵非吾愿,帝乡不可期。怀良辰以孤往,或植杖而耘耔。登东皋以舒啸,临清流而赋诗。聊乘化以归尽,乐夫天命复奚疑!

猜你喜欢

转载自blog.csdn.net/weixin_43427721/article/details/122673634