不同标签和数据类型匹配的数据集在PyTorch的加载(超详细保姆级别教学)

本篇文章主要借鉴学习了b站视频教学添加链接描述,并加入了自己的笔记,同时也算是复习了python,对于一些脚本代码进行了注释,去掉脚本记号即可运行。

第一种 标签在文件夹上的数据集加载

直接上代码,笔记也在代码上有注释

# 导入torch 包
import torch
import torch.nn as nn
from torchvision import transforms
import matplotlib.pyplot as plt

import os
from torch.utils.data import  DataLoader,Dataset
from torchvision import transforms, utils, datasets
import pandas as pd
import numpy as np


data_transform = transforms.Compose(
    [
        transforms.Resize(32),  # 缩放图片,长宽比不变,最短边为32像素
        transforms.CenterCrop(32),  # 从图片中间切出32*32的图片
        transforms.ToTensor(),  # 将图片(Image)转换成Tensor,归一化至[0,1]
        transforms.Normalize(mean=[0.492, 0.461, 0.417], std=[0.256, 0.248, 0.251])  # 正则化操作,标准化至[-1,1],规定均值和标准差
    ]
)


import numpy
import cv2
import os
'''
计算均值和标准差的脚本代码

img_h, img_w = 32, 32   # 经过处理后图片的尺寸
means, stdevs = [], []
img_list = []

imgs_path = "D:\\dogcatdata\\cnn_data\\cnn_data\\dataset\\training_data"  # 数据集路径的绝对引用
imgs_path_list = os.listdir(imgs_path)  # img_path里的所有文件列在img_path_list列表中

len = len(imgs_path_list)  # 列表长度
i = 0
for item in imgs_path_list:
    img = cv2.imread(os.path.join(imgs_path, item))  # 拼接操作
    img = cv2.resize(img, (img_w, img_h))
    img = img[:, :, :, np.newaxis]
    img_list.append(img)
    i += 1
    # print(i, '/', len)

imgs = np.concatenate(img_list, axis=3)
imgs = imgs.astype(np.float32) / 255.

for i in range(3):
    pixels = imgs[:, :, i, :].ravel()  # 拉成一行
    means.append(np.mean(pixels))
    stdevs.append(np.std(pixels))

# BGR --> RGB, cv读取的需要转换,PIL读取的不用转换
means.reverse()
stdevs.reverse()
'''




# print("normMean = {}".format(means))
# print("normStd = {}".format(stdevs))
# 知道均值和标准差后,正则化格式如下,output[channel] = (input[channel] - mean[channel]) / std[channel]

'''调用ImageFolder进行数据集的加载'''
train_dataset = datasets.ImageFolder(root="D:\\dogcatdata\\cnn_data\\cnn_data\\dataset\\training_data",
                               transform=data_transform)  # 第一次使用把data_transform调成None,然后运行下面的第一个脚本文件

'''
#1.测试脚本代码,看是否读取正确图片(只有上面的transform设置为None才可以运行的脚本)
img, label = train_dataset[0]  # 将启动魔法方程__getitem__(0)
print(label)
print(img.size)
plt.imshow(img)
plt.show()
'''

'''
#2.还是脚本代码,用于验证是否数据集加载正确,也可以查看图片尺寸和标签,break去掉后显示所有图片信息
for img, label in train_dataset:
    print("图像的形状{},图像的标签{}".format(img.shape,label))
    print("图像数据预处理后:\n", img)
    break
'''

dataset_loader = torch.utils.data.DataLoader(train_dataset, batch_size=4, shuffle=True)  # batch_size是每次送入的图片数据数量,shuffle是选择是否打乱顺序送数据


# 可以使用显示图片与对应标签的方式进行查验
import torchvision
import matplotlib.pyplot as plt
import numpy as np

# 定义一个显示图像的函数
def imshow(img):
    img = img / 2 + 0.5 #unnormalize
    npimg = img.numpy()
    plt.imshow(np.transpose(npimg, (1,2,0)))
    plt.show()

# 随机获取部分训练数据
dataiter = iter(dataset_loader)
images, labels = dataiter.next()
# 显示图像
imshow(torchvision.utils.make_grid(images))
# 打印标签
print(''.join('%s' % ["小狗" if labels[m].item()==1 else "小猫" for m in range(4)]))  # 如果标签是1就是小狗,如果标签是0就是小猫

第二种 标签在文件名中(即标签就是在图片名中)的数据集加载

import os
import torch
import torch.nn as nn
from torchvision import transforms
import matplotlib.pyplot as plt
from torch.utils.data import  DataLoader,Dataset
from torchvision import transforms, utils, datasets
import pandas as pd
import numpy as np
from PIL import Image
from torchvision import transforms, utils, datasets
import torchvision


path_dir = "D:\\dogcatdata\\train\\train"
# 通过继承Dataset类来进行数据加载
class MyDataset(Dataset): # 继承Dataset
    def __init__(self, path_dir, transform=None):  # 初始化一些属性,获取数据集所在路径的数据列表
        self.path_dir = path_dir  # 文件路径
        self.transform = transform  # 对象进行数据处理
        self.images = os.listdir(self.path_dir)  # 把路径下的所有文件放在一个列表里;即在self.images这个张量中存储path_dir路径的所有文件的名称和后缀名

    def __len__(self): # 返回整个数据集的大小
        return len(self.images)

    def __getitem__(self, index):  # 根据索引index返回图像及标签,索引是根据文件夹内的文件顺序进行排列,从0开始递增
        image_index = self.images[index]  # 根据索引获取图像文件名称
        img_path = os.path.join(self.path_dir, image_index)  # 获取index在确定数值下图片的路径或者目录
        img = Image.open(img_path).convert('RGB')  # 读取图像

        # 根据目录名称获取图像标签(猫还是狗)
        label = img_path.split('\\')[-1].split('.')[0]  # 绝对路径后加\\, '\\'的后一位, '.'的前一位就是标签,如cat.0.jpg, 标签就是cat
        # 把字符转换成数字,猫为0,dog为1
        label = 1 if 'dog' in label else 0

        if self.transform is not None:
            img = self.transform(img)
        return img, label

path_dir = "D:\\dogcatdata\\train\\train"
images = os.listdir(path_dir)
#print(images)
len(images) # 读取数据集长度
#print(len(images))
'''
# 来查看验证图像和数据是否匹配的脚本代码
# 利用dataset进行加载
dataset = MyDataset(path_dir, transform=None)  # transform设置为None,没有进行数据处理,可以查看数据尺寸和标签等信息

img, label = dataset[15000] # 启动魔法__getitem(0)
print(img)
print(label)
plt.imshow(img)
plt.show()
'''

from torchvision import transforms as T
transform = T.Compose(
    [
        T.Resize(32),  # 缩放图片,保持长宽比不变,最短边为32像素
        T.CenterCrop(32),  # 从图片中间开始切出224*224的图片
        T.ToTensor(),  # 将图片(Image)转成Tensor,归一化至[0,1]
        T.Normalize(mean=[0.492, 0.461, 0.417], std=[0.256, 0.248, 0.251])  # 正则化操作,标准化至[-1,1],规定均值和标准差
    ]
)

# 再加载数据集,此时要进行数据增强处理
dataset = MyDataset(path_dir, transform=transform)
'''
# 对处理后数据进行查看的脚本代码
for img, label in dataset:
    print("图像的形状为:{},图像的标签为:{}".format(img.shape,label))
    print("图像数据预处理后:\n", img)
    break  # break去掉后显示所有图片信息
'''

# 使用DataLoader加载数据
datasetloader = DataLoader(dataset, batch_size=4, shuffle=True)  # batch_size是每次送入的图片数据数量,shuffle是选择是否打乱顺序送数据
'''
#查看Dataloader之后的数据及标签的脚本代码
for batch_datas, batch_labels in dataloader:
    print(batch_datas.size(),batch_labels.size())
    break
'''
# 可以使用显示图片与对应标签的方式进行查验
import torchvision
import matplotlib.pyplot as plt
import numpy as np

# 定义一个显示图像的函数
def imshow(img):
    img = img / 2 + 0.5
    npimg = img.numpy()
    plt.imshow(np.transpose(npimg, (1, 2, 0)))
    plt.show()
# 随机获取部分训练数据
dataiter = iter(datasetloader)
images, labels = dataiter.next()
# 显示图像
imshow(torchvision.utils.make_grid(images))
# 打印标签
print(''.join('%s' % ["小狗" if labels[m].item()==1 else "小猫" for m in range(4)]))  # 如果标签是1就是小狗,如果标签是0就是小猫

遇到的问题 :

1)在images, labels = dataiter.next()这一命令中忘记了(),导致程序报错
2)对label = img_path.split('\\')[-1].split('.')[0]这一语句要理解含义,打好python基础。

将数据集划分为训练集,验证集和测试集的方法

大体上是以第二种方法作为加载数据的方式,然后把transforms直接内化到dataset,添加了数据集的划分

import os
import torch
import torch.nn as nn
from torchvision import transforms
import matplotlib.pyplot as plt
from torch.utils.data import  DataLoader,Dataset
from torchvision import transforms, utils, datasets
import pandas as pd
import numpy as np
from PIL import Image
import torchvision
from torchvision import transforms as T
import torch.optim as optim


class MyDataset(Dataset):  # 继承Dataset
    def __init__(self, root, transforms=None, train=True, test=False):  # 初始化一些属性
        self.test = test  # 将test变量赋值
        imgs = [os.path.join(root, img) for img in os.listdir(root)]  # 数据的路径列表,把主路径root和img拼接起来,精确到每张图的路径
        if self.test:
            imgs = sorted(imgs, key=lambda x: int(x.split('.')[-2].split('\\')[-1]))
            # 对测试集进行排序
        else:
            imgs = sorted(imgs, key=lambda x: int(x.split('.')[-2]))
            # 对非测试集的数据进行排序,排序的目的是为了后面的分割

        imgs_num = len(imgs)  # 获取数据的长度便于划分数据集
        if self.test:
            self.imgs = imgs  # 将测试集的数据直接导入
        elif train:
            self.imgs = imgs[:int(0.7 * imgs_num)]  # 将数据的70%给train

        else:
            self.imgs = imgs[int(0.7 * imgs_num):]  # 将剩余的30%给验证集,通过上面的定义,如果test和train都为False,则会跳到这个语句

        if transforms is None:  # 对数据进行增强处理
            normalize = T.Normalize(mean=[0.492, 0.461, 0.417], std=[0.261, 0.255, 0.257])  # 正则化操作,标准化至[-1,1],规定均值和标准差

            if self.test or not train:
                self.transforms = T.Compose(
                              [
                    T.Resize(28),  # 缩放图片,保持长宽比不变,最短边为32像素
                    T.CenterCrop(28),  # 从图片中间开始切出224*224的图片
                    T.ToTensor(),  # 将图片(Image)转成Tensor,归一化至[0,1]
                    normalize  # 正则化操作,标准化至[-1,1],规定均值和标准差
                              ])
            else:
                self.transforms = T.Compose(
                    [
                        T.Resize(28),  # 缩放图片,保持长宽比不变,最短边为32像素
                        T.CenterCrop(28),  # 从图片中间开始切出224*224的图片
                        T.RandomHorizontalFlip(),  # 任意水平翻转
                        T.ToTensor(),  # 将图片(Image)转成Tensor,归一化至[0,1]
                        normalize  # 正则化操作,标准化至[-1,1],规定均值和标准差
                    ])

    def __len__(self):  # 返回整个数据集大小
        return len(self.imgs)

    def __getitem__(self, index): # 根据索引index返回图像及标签
        img_path = self.imgs[index]
        if self.test:
            label = int(self.imgs[index].split('.')[-2].split('\\')[-1])
            # 测试集是没有标签的,获取测试集文件名的部分作为标签
        else:
            label = 1 if 'dog' in img_path.split('\\')[-1] else 0
            # label = img_path.split('\\')[-1].split('.')[0]
            # label = 1 if 'dog' in label else 0
            # 获取train中文件名的标签并进行数字化,dog为1,cat为0

        data = Image.open(img_path)
        data = self.transforms(data)
        return data, label

path_dir = "D:\\dogcatdata\\train\\train"
train_data = MyDataset(path_dir, train=True)
val_data = MyDataset(path_dir, train=False)  # 上面提到过,如果test和train都为False,则会跳到测试集执行语句,不懂再看class中的代码

# 由于在初始化中设定了transforms为None,则会自动跳到transforms为None执行的语句(看class中代码),如果要获得未进行数据加强操作的dataset,则把transforms的代码注释掉,或者把None改成True
'''
# 训练集数据验证和查看的脚本
img,label = train_data[17000]
for img, label in train_data:
    print("图片的形状为:{},标签label的值为:{}".format(img.shape, label))
    print("数据预处理后:\n", img)
    break
'''
# 使用Dataloader加载训练集数据
train_dataloader = DataLoader(train_data, batch_size=4, shuffle=True)
for batch_datas, batch_labels in train_dataloader:
    print(batch_datas.size(), batch_labels.size())
    break

# 同样的方法,使用Dataloader加载验证集数据

val_dataloader = DataLoader(val_data, batch_size=4, shuffle=True)
for batch_datas, batch_labels in val_dataloader:
    print(batch_datas.size(), batch_labels.size())
    break
'''
# 查验训练集数据的脚本
# 可以使用显示图片与对应标签的方式进行查验
import torchvision
import matplotlib.pyplot as plt
import numpy as np

# 定义一个显示图像的函数
def imshow(img):
    img = img / 2 + 0.5
    npimg = img.numpy()
    plt.imshow(np.transpose(npimg, (1, 2, 0)))
    plt.show()
# 随机获取部分训练数据
dataiter = iter(train_dataloader)   # 以后调用只改变这个地方就Ok,如果改成val_datalodaer就是查看验证集数据
images, labels = dataiter.next()
# 显示图像
imshow(torchvision.utils.make_grid(images))
# 打印标签
print(''.join('%s' % ["小狗" if labels[m].item()==1 else "小猫" for m in range(4)]))  # 如果标签是1就是小狗,如果标签是0就是小猫
'''



'''
# 查验验证集数据的脚本
# 可以使用显示图片与对应标签的方式进行查验
import torchvision
import matplotlib.pyplot as plt
import numpy as np

# 定义一个显示图像的函数
def imshow(img):
    img = img / 2 + 0.5
    npimg = img.numpy()
    plt.imshow(np.transpose(npimg, (1, 2, 0)))
    plt.show()
# 随机获取部分训练数据
dataiter = iter(val_dataloader)   # 以后调用只改变这个地方就Ok,val_datalodaer就是查看验证集数据
images, labels = dataiter.next()
# 显示图像
imshow(torchvision.utils.make_grid(images))
# 打印标签
print(''.join('%s' % ["小狗" if labels[m].item()==1 else "小猫" for m in range(4)]))  # 如果标签是1就是小狗,如果标签是0就是小猫
'''

遇到的问题 :

在划分验证集时,不知道如何提取30%作为验证集,最后用self.imgs = imgs[int(0.7 * imgs_num):] # 将剩余的30%给验证集解决

CSV文件存储标签的数据集的记载方法

由于本类数据集本人还没有遇到和使用过,故等到需要使用时在做学习。

数据加载是程序编写的基石,目前只能掌握猫狗数据导入,之后多分类情况下,要该学习更多的导入方式,也会不断更新,拓展笔记。

  • 6
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值