pytorch实现深度学习常用图像分类数据集的划分与读取(Oxford-102flower,CIFAR10/CIFAR100)

本文详细介绍了Oxford-102flower花分类数据集的结构、下载及划分方法,包括如何依据imagelabels.mat和setid.mat文件进行训练集、验证集和测试集的划分。同时,文章也概述了CIFAR10和CIFAR100数据集的构成,以及它们在图像识别任务中的应用,包括数据读取、预处理和加载过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Oxford-102flower花分类数据集,CIFAR10/CIFAR100数据集,

Oxford-102flower

Oxford-102flower是牛津工程大学于2008年发布的用于图像分类的数据集,总共分为102个类,每个类包含40-258张图像,一共8189张图像。

数据下载地址https://www.robots.ox.ac.uk/~vgg/data/flowers/102/

下载图中1.4.5对应的文件,分别为数据的文件,标签的文件和划分的文件。

 数据下载解压后显示如下:

数据中个别图像展示:

 下载好的图像放在一个jpg文件夹中,该文件夹中包含了所有的图像,但其图像排列顺序是有规律,每一类的图像放在一起,然后再放下一类的所有图像,因此我们可以将数据集划分为训练集、验证集和测试集。

 数据集的划分主要依据imagelabels.mat文件和setid.mat文件完成。imagelabels.mat文件主要包换数据的标签信息。

导入头文件:

# encoding:utf-8
import scipy.io
import numpy as np
import os
from PIL import Image

依据imagelabels.mat文件读取图像的标签信息,该文件一共包含8189列,每一个数即代表的该图像所属的类别。在使用时修改imagelabels.mat文件的位置,使程序能够顺利读取。

labels = scipy.io.loadmat('./imagelabels.mat.txt')
labels = np.array(labels['labels'][0]) - 1
print("labels:", labels)

根据setid.mat文件将数据划分为训练集,验证集和测试集。setid.mat文件主要包含每一个类对应的图片信息文件,读取该文件,配合imagelabels.mat文件可实现数据的划分。在使用时修改setid.mat文件的位置,使程序能够顺利读取。

setid = scipy.io.loadmat('./setid.mat.txt')

validation = np.array(setid['valid'][0]) - 1
np.random.shuffle(validation)

train = np.array(setid['trnid'][0]) - 1
np.random.shuffle(train)

test = np.array(setid['tstid'][0]) - 1
np.random.shuffle(test)

将数据存储在fflower_dir中:注意修改图片存储的位置。
 

flower_dir = list()
for img in os.listdir("./102flowers/jpg"):
    flower_dir.append(os.path.join("./102flowers/jpg", img))
flower_dir.sort()

根据setid划分出train并放入train文件夹中:

des_folder_train = "./train"  # 该地址可为新建的训练数据集文件夹的相对地址
for tid in train:
    # 打开图片并获取标签
    img = Image.open(flower_dir[tid])
    print(img)
    # print(flower_dir[tid])
    img = img.resize((256, 256), Image.ANTIALIAS)
    lable = labels[tid]
    # print(lable)
    path = flower_dir[tid]
    print("path:", path)
    base_path = os.path.basename(path)
    print("base_path:", base_path)
    classes = "c" + str(lable)
    class_path = os.path.join(des_folder_train, classes)
    # 判断结果
    if not os.path.exists(class_path):
        os.makedirs(class_path)
    print("class_path:", class_path)
    despath = os.path.join(class_path, base_path)
    print("despath:", despath)
    img.save(despath)

根据setid划分出val并放入val文件夹中:

des_folder_validation = "./val"#该地址为新建的验证数据集文件夹的相对地址

for tid in validation:
    img = Image.open(flower_dir[tid])
    # print(flower_dir[tid])
    img = img.resize((256, 256), Image.ANTIALIAS)
    lable = labels[tid]
    # print(lable)
    path = flower_dir[tid]
    print("path:", path)
    base_path = os.path.basename(path)
    print("base_path:", base_path)
    classes = "c" + str(lable)
    class_path = os.path.join(des_folder_validation, classes)
    # 判断结果
    if not os.path.exists(class_path):
        os.makedirs(class_path)
    print("class_path:", class_path)
    despath = os.path.join(class_path, base_path)
    print("despath:", despath)
    img.save(despath)

根据setid划分出test并放入test文件夹中:

des_folder_test = "./test"#该地址为新建的测试数据集文件夹的绝对地址

for tid in test:
    img = Image.open(flower_dir[tid])
    # print(flower_dir[tid])
    img = img.resize((256, 256), Image.ANTIALIAS)
    lable = labels[tid]
    # print(lable)
    path = flower_dir[tid]
    print("path:", path)
    base_path = os.path.basename(path)
    print("base_path:", base_path)
    classes = "c" + str(lable)
    class_path = os.path.join(des_folder_test, classes)
    # 判断结果
    if not os.path.exists(class_path):
        os.makedirs(class_path)
    print("class_path:", class_path)
    despath = os.path.join(class_path, base_path)
    print("despath:", despath)
    img.save(despath)

划分好的数据集如下所示:

CIFAR10/CIFAR100

CIFAR-10 数据集由 10 个类中的 60000 张 32x32 彩色图像组成,每类 6000 张图像。有50000个训练图像和10000个测试图像。

数据集分为五个训练批次和一个测试批次,每个批次包含 10000 张图像。测试批处理包含来自每个类的 1000 个随机选择的图像。训练批次以随机顺序包含剩余的图像,但某些训练批次可能包含来自一个类的图像多于另一个类的图像。在它们之间,训练批次恰好包含来自每个类的5000张图像。

 

 CIFAR-100与CIFAR-10类似,只是它有 100 个类,每个类包含 600 张图像。每类有 500 张训练图像和 100 张测试图像。CIFAR-100 中的 100 个类被分为 20 个超类。每个图像都带有一个“精细”标签(它所属的类)和一个“粗”标签(它所属的超类)。其标签具有两种,一种是粗粒度标签,一种是细粒度标签,如下:

 官方的读取方法:

def unpickle(file):
    import pickle
    with open(file, 'rb') as fo:
        dict = pickle.load(fo, encoding='bytes')
    return dict
  • 数据 -- 一个 10000x3072 的 uint8s 的 numpy 数组。阵列的每一行都存储一个 32x32 的彩色图像。前 1024 个条目包含红色通道值,接下来的 1024 个条目包含绿色通道值,最后 1024 个条目包含蓝色通道值。图像按行主顺序存储,因此数组的前 32 个条目是图像第一行的红色通道值。
  • 标签 -- 0-9 范围内的 10000 个数字的列表。索引 i 处的数字表示数组数据中第 i个图像的标签。

数据集包含另一个文件,称为批处理.meta。它也包含一个Python字典对象。它具有以下条目:

  • label_names -- 一个包含 10 个元素的列表,它为上述 labels 数组中的数字标签提供了有意义的名称。例如,label_names[0] == “飞机”,label_names[1] == “汽车”等。

在实际应用过程中已经封装好的数据,所以我们也可以直接调用封装函数实现数据的读取。

预处理方式:我这里没有做数据增强,也可以添加翻转,旋转,缩放等数据增强操作。

data_transform = {
        "train": transforms.Compose([
                                    
                                     transforms.ToTensor(),
                                     transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))
                                     ]),
        "val": transforms.Compose([
                                    
                                   transforms.ToTensor(),
                                   transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))
                                   ])}

数据读取与载入:

    train_dataset=torchvision.datasets.CIFAR100(root='./data/cifar100',train=True,download=True,transform=data_transform['train'])
    val_dataset=torchvision.datasets.CIFAR100(root='./data/cifar100',train=False,download=False,transform=data_transform['val'])

    train_num=len(train_dataset)
    val_num=len(val_dataset)

    train_loader=torch.utils.data.DataLoader(train_dataset,batch_size=128,shuffle=True)
    val_loader=torch.utils.data.DataLoader(val_dataset,batch_size=128,shuffle=False)

    print("using {} images for training, {} images for val.".format(train_num,
                                                                           val_num))

其中train_loader 和val_loader可以直接送入网络训练。

    for step,data in enumerate(train_loader):
        img,lable=data
        print(len(data))
        print(step,lable)

查看其标签:结果如下

2是表示data的长度,data是一个list数据,第一位是图像信息,第二位是标签信息,371是指数据按128的大小分好之后的第371份,由于是标签,所以有128个数字,每个数字表示该batch中对应图像的标签 。可以用这个标签信息去算loss。

当你想要更改数据集路径或将现有的数据替换为其他图像时,你需要修改 `ImageFolder` 的 `root` 参数并确保新目录结构满足 PyTorch 的 `ImageFolder` 数据加载器的要求。以下是详细的步骤及代码示例: --- ### 修改数据集路径的步骤 1. **理解 `ImageFolder` 的需求** - `ImageFolder` 期望目标文件夹按类别分好,即每个类别有一个单独的子文件夹。 ``` dataset/ class_1/ img1.jpg img2.jpg class_2/ img3.jpg img4.jpg ``` 2. **指定新的根目录** - 确保将 `train_dataset` 和 `test_dataset` 分别指向两个独立的数据集(如训练集和测试集),避免两者混淆。 3. **转换操作不变** - 如果已有合适的 `transform` 函数,可以直接复用它;否则可以根据新数据的需求定制新的变换规则。 --- ### 示例代码 假设我们现在想使用全新的图像集,并将其分别分配给训练集和测试集。我们可以这样做: ```python from torchvision.datasets import ImageFolder import os # 自定义路径 (替换成你的实际路径) TRAIN_ROOT = 'E:\\自定义训练集\\images' # 替换为你训练图片所在的文件夹路径 TEST_ROOT = 'E:\\自定义测试集\\images' # 替换为你测试图片所在的文件夹路径 # 已有的 transform 操作保持一致 (或者自行调整以适配新图尺寸/属性等) train_dataset = ImageFolder(root=TRAIN_ROOT, transform=transform) test_dataset = ImageFolder(root=TEST_ROOT, transform=transform) print(f"Train Dataset Size: {len(train_dataset)}") # 查看数据规模是否正常 print(f"Test Dataset Size: {len(test_dataset)}") # 验证一下分类标签是否正确读取 classes_train = train_dataset.classes classes_test = test_dataset.classes assert classes_train == classes_test, "训练集和测试集的类别应完全匹配!" print("检测完成:", classes_train) ``` 注意这里用了双斜杠 `\\` 或者单正斜杠 `/` 来书写 Windows 下的绝对路径以防转义字符错误导致找不到对应位置的问题发生! --- ### 特殊情况处理 如果你希望进一步分离出验证集合的话,可以通过如下方式实现随机划分原大块数据的一部分出来做交叉检验用途: ```python from torch.utils.data.dataset import random_split ratio = [int(len(dataset)*0.8), int(len(dataset)*0.2)] # 八二开比例设定 training_data, validation_data = random_split(dataset , ratio ) loader_training = DataLoader(training_data , batch_size=batchsize , shuffle=True ) loader_validation = DataLoader(validation_data , batch_size=batchsize , shuffle=False ) ``` 这样就得到了由同一初始数据源生成的不同用途的小型分割版实例供后续任务调用啦~
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值