如何从 Food101 整理出 train/test 文件夹结构并打包成 PyTorch 课程用的自定义数据集?
2026/9/14 8:44:28 网站建设 项目流程

如何从 Food101 整理出 train/test 文件夹结构并打包成 PyTorch 课程用的自定义数据集?

【免费下载链接】pytorch-deep-learningMaterials for the Learn PyTorch for Deep Learning: Zero to Mastery course.项目地址: https://gitcode.com/GitHub_Trending/py/pytorch-deep-learning

在 pytorch-deep-learning 仓库(Learn PyTorch for Deep Learning 课程材料)中,notebook 04 使用的是一份 Food101 子集数据集:只保留pizzasteaksushi三个类别,按标准的图像分类目录格式(train/test/下各按类别名建文件夹)组织,并打包成 zip 以便随课程分发。如果你想为自己整理出同样结构的数据集,仓库中的 extras/04_custom_data_creation.ipynb 提供了完整的制作流程:从torchvision.datasets.Food101下载原始数据、随机抽取目标类别的图片、复制到目标目录、校验数量,最后压缩成 zip。

环境与前提条件

使用 Food101 数据集有版本要求,创作 notebook 开头明确说明:需要 PyTorch 1.11+ 和torchvision0.12.0+。notebook 用下面这段代码做版本自检,不满足时断言会直接报错:

import torch import torchvision # Note: Required to have PyTorch > 1.11.0 & torchvision > 0.12.0 for Food101 dataset assert int(torch.__version__.split(".")[1]) >= 11 assert int(torchvision.__version__.split(".")[1]) >= 11

下载本身需要磁盘与网络空间:文档说明通过 PyTorch 下载 Food101大约需要 10–15 分钟,会向指定的root目录下载约 5GB 数据

整理完成后的目标结构如下(文件名仅为示意,来自 notebook 原文):

pizza_steak_sushi/ train/ pizza/ image01.jpeg image02.jpeg ... steak/ image04.jpeg ... sushi/ image07.jpeg ... test/ pizza/ image101.jpeg ... steak/ ... sushi/ ...

后续类别名可以换成任意 Food101 中存在的类别。全部 101 个类别名(小写、下划线分隔,如pizzasteaksushi)可以在 extras/food101_class_names.txt 中查到,target_classes里的名字必须和food-101/images/下的目录名一致。

第一步:下载 Food101 的 train 与 test 数据

下面的代码设置数据目录,并分别用split="train"split="test"获取两个划分。注意data_dir在 notebook 中是相对路径"../data",指向课程使用的 data 目录;运行时请把它替换成你自己准备好的数据目录(后文路径均相对此目录解析)。

import torchvision.datasets as datasets import torchvision.transforms as transforms import pathlib data_dir = pathlib.Path("../data") # 替换为你自己的数据目录 # Get training data train_data = datasets.Food101(root=data_dir, split="train", # transform=transforms.ToTensor(), download=True) # Get testing data test_data = datasets.Food101(root=data_dir, split="test", # transform=transforms.ToTensor(), download=True)

download=True触发约 5GB 的下载。下载完成后,数据在data_dir下的组织方式是:

../data/food-101/images/CLASS_NAME/IMAGES.jpg

此外还有food-101/meta/train.txtfood-101/meta/test.txt两个标签文件,每行是一个相对路径(类别名/图片ID.jpg形式)。后面的子集抽取就依赖这两个文件。

下载完成后可以先看一下类别名和第一个样本,确认数据可用:

class_names = train_data.classes class_names[:10] # View first sample (PIL Image format) print(class_names[train_data[0][1]]) train_data[0][0]

第二步:按类别随机抽取 10% 或 20% 的图片

notebook 定义了get_subset():读取meta/{train,test}.txt,只保留target_classes中类别的行,再用random.sample随机抽取round(amount * len(labels))张图片,返回完整的图片路径列表。amount控制抽取比例:0.1表示随机取 10%,0.2取 20%。随机种子固定在 42,保证结果可复现。

import random data_path = data_dir / "food-101" / "images" target_classes = ["pizza", "steak", "sushi"] # Change amount of data to get (e.g. 0.1 = random 10%, 0.2 = random 20%) amount_to_get = 0.2 # Create function to separate a random amount of data def get_subset(image_path=data_path, data_splits=["train", "test"], target_classes=["pizza", "steak", "sushi"], amount=0.1, seed=42): random.seed(42) label_splits = {} # Get labels for data_split in data_splits: print(f"[INFO] Creating image split for: {data_split}...") label_path = data_dir / "food-101" / "meta" / f"{data_split}.txt" with open(label_path, "r") as f: labels = [line.strip("\n") for line in f.readlines() if line.split("/")[0] in target_classes] # Get random subset of target classes image ID's number_to_sample = round(amount * len(labels)) print(f"[INFO] Getting random subset of {number_to_sample} images for {data_split}...") sampled_images = random.sample(labels, k=number_to_sample) # Apply full paths image_paths = [pathlib.Path(str(image_path / sample_image) + ".jpg") for sample_image in sampled_images] label_splits[data_split] = image_paths return label_splits label_splits = get_subset(amount=amount_to_get) label_splits["train"][:10]

运行时会打印每个 split 实际抽取的图片数量(文档示例中的[INFO] Getting random subset of ...输出,具体数值取决于amount_to_get)。

第三步:把抽中的图片复制到 train/test/类别 目录

目标目录名由抽取比例自动拼接而成,例如 20% 时得到pizza_steak_sushi_20_percent。这一步只复制文件(shutil.copy2),不会删除food-101下的原始图片。

# Create target directory path target_dir_name = f"../data/pizza_steak_sushi_{str(int(amount_to_get*100))}_percent" print(f"Creating directory: '{target_dir_name}'") # Setup the directories target_dir = pathlib.Path(target_dir_name) # Make the directories target_dir.mkdir(parents=True, exist_ok=True)

然后遍历label_splits,按目标目录/split/类别名/文件名逐张复制:

import shutil for image_split in label_splits.keys(): for image_path in label_splits[str(image_split)]: dest_dir = target_dir / image_split / image_path.parent.stem / image_path.name if not dest_dir.parent.is_dir(): dest_dir.parent.mkdir(parents=True, exist_ok=True) print(f"[INFO] Copying {image_path} to {dest_dir}...") shutil.copy2(image_path, dest_dir)

其中image_path.parent.stem取的是类别目录名(如pizza),所以最终路径自然形成train/pizza/xxx.jpgtest/sushi/xxx.jpg这样的层级。

验证文件夹结构与图片数量

复制完成后用walk_through_dir()逐级打印目录数和图片数,这是文档给出的检查方式:

def walk_through_dir(dir_path): """ Walks through dir_path returning its contents. Args: dir_path (str): target directory Returns: A print out of: number of subdiretories in dir_path number of images (files) in each subdirectory name of each subdirectory """ import os for dirpath, dirnames, filenames in os.walk(dir_path): print(f"There are {len(dirnames)} directories and {len(filenames)} images in '{dirpath}'.") walk_through_dir(target_dir)

文档给出的预期数量是:抽 10% 时每个类别约 75 张训练图、约 25 张测试图;抽 20% 时约为每类 150 张训练图、50 张测试图。文档说明这个量级已经够作为起步数据集,之后需要时可以增加。

把数据集打包成 zip

确认数量无误后,用shutil.make_archive将目标目录压缩到数据目录里,zip 名与目录名一致:

# Zip pizza_steak_sushi images zip_file_name = data_dir / f"pizza_steak_sushi_{str(int(amount_to_get*100))}_percent" shutil.make_archive(zip_file_name, format="zip", root_dir=target_dir)

可以用 shell 命令确认压缩包已生成:

ls -la ../data/

仓库自带的成品就是按同样流程产出的:amount_to_get = 0.1对应的 data/pizza_steak_sushi.zip 和 20% 版本 data/pizza_steak_sushi_20_percent.zip。

课程 notebook 04 如何消费这个数据集

打包好的 zip 就是 04_pytorch_custom_datasets.ipynb 的输入。该 notebook 的数据准备逻辑是:如果data/pizza_steak_sushi目录不存在,就从课程仓库的 data 地址下载pizza_steak_sushi.zip并解压到data/pizza_steak_sushi/;随后设置训练/测试路径并用walk_through_dir复核结构:

# Setup path to data folder data_path = Path("data/") image_path = data_path / "pizza_steak_sushi" # ...(目录不存在时下载并解压 zip,见 notebook) # Setup train and testing paths train_dir = image_path / "train" test_dir = image_path / "test"

notebook 中的说明指出,解压后应看到每类约 75 张训练图、约 25 张测试图(10% 版本)。结构符合预期后,train_dir/test_dir可以直接交给torchvision.datasets.ImageFolder加载成Dataset,进入训练流程。

限制与注意事项

  • 下载规模datasets.Food101(download=True)会下载约 5GB 原始数据,且文档提示需要 10–15 分钟,请在有足够磁盘空间和稳定网络的环境下执行。
  • 版本门槛:Food101 需要 PyTorch 1.11+ 与torchvision0.12.0+,版本断言不通过时应先升级环境。
  • 类别名必须精确匹配get_subset()通过meta/*.txt每行第一个字段(类别目录名)过滤,名字写错会得到空列表或数量远小于预期,可对照 extras/food101_class_names.txt 核对。
  • 只增不删:流程中shutil.copy2make_archive都是新增文件;notebook 末尾用于清理临时解压目录的os.remove/shutil.rmtree调用是注释掉的,需要清理时请自行判断后执行。

完整制作流程见 extras/04_custom_data_creation.ipynb,数据集在课程中的用法见 04_pytorch_custom_datasets.ipynb。

【免费下载链接】pytorch-deep-learningMaterials for the Learn PyTorch for Deep Learning: Zero to Mastery course.项目地址: https://gitcode.com/GitHub_Trending/py/pytorch-deep-learning

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询