创建图像数据集
有两种方法可以创建和共享图像数据集。本指南将向您展示如何
使用 Dataset.push_to_hub() 从 Python 中的本地文件创建音频数据集。这是一种简单的方法,只需在 Python 中执行几个步骤。
使用
ImageFolder
和一些元数据创建图像数据集。这是一种无需代码的解决方案,可以快速创建包含数千张图像的图像数据集。
您可以通过要求用户首先共享其联系信息来控制对数据集的访问。查看 受限数据集 指南,以获取有关如何在中心启用此功能的更多信息。
ImageFolder
ImageFolder
是一个数据集构建器,旨在快速加载包含数千张图像的图像数据集,无需编写任何代码。
💡 查看 分割模式层次结构,了解 ImageFolder
如何根据数据集存储库结构创建数据集分割。
ImageFolder
会根据目录名称自动推断数据集的类别标签。将您的数据集存储在如下所示的目录结构中:
folder/train/dog/golden_retriever.png
folder/train/dog/german_shepherd.png
folder/train/dog/chihuahua.png
folder/train/cat/maine_coon.png
folder/train/cat/bengal.png
folder/train/cat/birman.png
然后,用户可以通过在 load_dataset() 中指定 imagefolder
并在 data_dir
中指定目录来加载您的数据集。
>>> from datasets import load_dataset
>>> dataset = load_dataset("imagefolder", data_dir="/path/to/folder")
您还可以使用 imagefolder
加载涉及多个分割的数据集。为此,您的数据集目录应具有以下结构:
folder/train/dog/golden_retriever.png
folder/train/cat/maine_coon.png
folder/test/dog/german_shepherd.png
folder/test/cat/bengal.png
如果所有图像文件都包含在单个目录中,或者它们不在目录结构的同一级别,则不会自动添加 label
列。如果需要,请显式设置 drop_labels=False
。
如果您想包含有关数据集的其他信息,例如文本标题或边界框,请将其作为 metadata.csv
文件添加到您的文件夹中。这使您可以快速创建用于不同计算机视觉任务(如文本标题或目标检测)的数据集。您也可以使用 JSONL 文件 metadata.jsonl
。
folder/train/metadata.csv
folder/train/0001.png
folder/train/0002.png
folder/train/0003.png
您还可以压缩图像:
folder/metadata.csv folder/train.zip folder/test.zip folder/valid.zip
您的 metadata.csv
文件必须包含一个 file_name
列,该列将图像文件与其元数据关联。
file_name,additional_feature
0001.png,This is a first value of a text feature you added to your images
0002.png,This is a second value of a text feature you added to your images
0003.png,This is a third value of a text feature you added to your images
或使用 metadata.jsonl
:
{"file_name": "0001.png", "additional_feature": "This is a first value of a text feature you added to your images"}
{"file_name": "0002.png", "additional_feature": "This is a second value of a text feature you added to your images"}
{"file_name": "0003.png", "additional_feature": "This is a third value of a text feature you added to your images"}
如果存在元数据文件,则默认情况下会删除根据目录名称推断的标签。要包含这些标签,请在 load_dataset
中设置 drop_labels=False
。
图像字幕
图像字幕数据集包含描述图像的文本。一个示例 metadata.csv
可能如下所示:
file_name,text
0001.png,This is a golden retriever playing with a ball
0002.png,A german shepherd
0003.png,One chihuahua
使用 ImageFolder
加载数据集,它将为图像字幕创建一个 text
列。
>>> dataset = load_dataset("imagefolder", data_dir="/path/to/folder", split="train")
>>> dataset[0]["text"]
"This is a golden retriever playing with a ball"
目标检测
目标检测数据集包含边界框和类别,用于识别图像中的目标。一个示例 metadata.jsonl
可能如下所示:
{"file_name": "0001.png", "objects": {"bbox": [[302.0, 109.0, 73.0, 52.0]], "categories": [0]}}
{"file_name": "0002.png", "objects": {"bbox": [[810.0, 100.0, 57.0, 28.0]], "categories": [1]}}
{"file_name": "0003.png", "objects": {"bbox": [[160.0, 31.0, 248.0, 616.0], [741.0, 68.0, 202.0, 401.0]], "categories": [2, 2]}}
使用 ImageFolder
加载数据集,它将创建一个 objects
列,其中包含边界框和类别。
>>> dataset = load_dataset("imagefolder", data_dir="/path/to/folder", split="train")
>>> dataset[0]["objects"]
{"bbox": [[302.0, 109.0, 73.0, 52.0]], "categories": [0]}
将数据集上传到 Hub
创建数据集后,您可以使用 push_to_hub() 方法将其共享到 Hub。确保已安装 huggingface_hub 库并登录到您的 Hugging Face 帐户(有关更多详细信息,请参阅 使用 Python 上传教程)。
使用 push_to_hub() 上传您的数据集。
>>> from datasets import load_dataset
>>> dataset = load_dataset("imagefolder", data_dir="/path/to/folder", split="train")
>>> dataset.push_to_hub("stevhliu/my-image-captioning-dataset")
WebDataset
WebDataset 格式基于 TAR 档案,适用于大型图像数据集。实际上,您可以将图像分组到 TAR 档案中(例如,每个 TAR 档案 1GB 的图像),并拥有数千个 TAR 档案。
folder/train/00000.tar
folder/train/00001.tar
folder/train/00002.tar
...
在档案中,每个示例都由共享相同前缀的文件组成:
e39871fd9fd74f55.jpg
e39871fd9fd74f55.json
f18b91585c4d3f3e.jpg
f18b91585c4d3f3e.json
ede6e66b2fb59aab.jpg
ede6e66b2fb59aab.json
ed600d57fcee4f94.jpg
ed600d57fcee4f94.json
...
例如,您可以使用 JSON 或文本文件来放置图像标签/标题/边界框。
有关 WebDataset 格式和 Python 库的更多详细信息,请查看 WebDataset 文档。
加载您的 WebDataset,它将为每个文件后缀(此处为“jpg”和“json”)创建一个列:
>>> from datasets import load_dataset
>>> dataset = load_dataset("webdataset", data_dir="/path/to/folder", split="train")
>>> dataset[0]["json"]
{"bbox": [[302.0, 109.0, 73.0, 52.0]], "categories": [0]}
(旧版)加载脚本
编写数据集加载脚本以共享数据集。它定义数据集的分割和配置,并处理下载和生成数据集。该脚本位于与数据集相同的文件夹或存储库中,并且应具有相同的名称。
my_dataset/
├── README.md
├── my_dataset.py
└── data/ # optional, may contain your images or TAR archives
此结构允许您在一行中加载数据集:
>>> from datasets import load_dataset
>>> dataset = load_dataset("path/to/my_dataset")
本指南将向您展示如何为图像数据集创建数据集加载脚本,这与 为文本数据集创建加载脚本 略有不同。您将学习如何:
- 创建数据集构建器类。
- 创建数据集配置。
- 添加数据集元数据。
- 下载并定义数据集分割。
- 生成数据集。
- 生成数据集元数据(可选)。
- 将数据集上传到 Hub。
最好的学习方法是打开现有的图像数据集加载脚本,例如 Food-101,并跟随操作!
为了帮助您入门,我们创建了一个加载脚本 模板,您可以复制并用作起点!
创建数据集构建器类
GeneratorBasedBuilder 是从字典生成器生成数据集的基本类。在此类中,有三种方法可以帮助创建数据集:
info
存储有关数据集的信息,例如其描述、许可证和特征。split_generators
下载数据集并定义其分割。generate_examples
为每个分割生成图像和标签。
首先,将您的数据集类创建为 GeneratorBasedBuilder 的子类,并添加这三种方法。不必担心现在就填充每个方法,您将在接下来的几个部分中开发它们。
class Food101(datasets.GeneratorBasedBuilder):
"""Food-101 Images dataset"""
def _info(self):
def _split_generators(self, dl_manager):
def _generate_examples(self, images, metadata_path):
多个配置
在某些情况下,数据集可能有多个配置。例如,如果您查看Imagenette 数据集,您会注意到它有三个子集。
要创建不同的配置,请使用BuilderConfig 类为您的数据集创建子类。在data_url
和metadata_urls
中提供下载图像和标签的链接。
class Food101Config(datasets.BuilderConfig):
"""Builder Config for Food-101"""
def __init__(self, data_url, metadata_urls, **kwargs):
"""BuilderConfig for Food-101.
Args:
data_url: `string`, url to download the zip file from.
metadata_urls: dictionary with keys 'train' and 'validation' containing the archive metadata URLs
**kwargs: keyword arguments forwarded to super.
"""
super(Food101Config, self).__init__(version=datasets.Version("1.0.0"), **kwargs)
self.data_url = data_url
self.metadata_urls = metadata_urls
现在您可以在GeneratorBasedBuilder 的顶部定义您的子集。假设您想在 Food-101 数据集中根据食物是早餐还是晚餐创建两个子集。
- 在
BUILDER_CONFIGS
中的列表中使用Food101Config
定义您的子集。 - 对于每个配置,提供名称、描述以及从哪里下载图像和标签。
class Food101(datasets.GeneratorBasedBuilder):
"""Food-101 Images dataset"""
BUILDER_CONFIGS = [
Food101Config(
name="breakfast",
description="Food types commonly eaten during breakfast.",
data_url="https://link-to-breakfast-foods.zip",
metadata_urls={
"train": "https://link-to-breakfast-foods-train.txt",
"validation": "https://link-to-breakfast-foods-validation.txt"
},
,
Food101Config(
name="dinner",
description="Food types commonly eaten during dinner.",
data_url="https://link-to-dinner-foods.zip",
metadata_urls={
"train": "https://link-to-dinner-foods-train.txt",
"validation": "https://link-to-dinner-foods-validation.txt"
},
)...
]
现在,如果用户想要加载breakfast
配置,他们可以使用配置名称。
>>> from datasets import load_dataset
>>> ds = load_dataset("food101", "breakfast", split="train")
添加数据集元数据
添加有关数据集的信息对于用户了解数据集很有用。此信息存储在DatasetInfo 类中,该类由info
方法返回。用户可以通过以下方式访问此信息:
>>> from datasets import load_dataset_builder
>>> ds_builder = load_dataset_builder("food101")
>>> ds_builder.info
您可以指定许多有关数据集的信息,但一些重要的信息包括:
description
提供数据集的简洁描述。features
指定数据集列类型。由于您正在创建图像加载脚本,因此您需要包含Image 特性。supervised_keys
指定输入特征和标签。homepage
提供数据集主页的链接。citation
是数据集的 BibTeX 引用。license
说明数据集的许可证。
您会注意到许多数据集信息是在加载脚本的前面定义的,这使得它更容易阅读。您还可以输入其他~Datasets.Features
,因此请务必查看完整列表以获取更多详细信息。
def _info(self):
return datasets.DatasetInfo(
description=_DESCRIPTION,
features=datasets.Features(
{
"image": datasets.Image(),
"label": datasets.ClassLabel(names=_NAMES),
}
),
supervised_keys=("image", "label"),
homepage=_HOMEPAGE,
citation=_CITATION,
license=_LICENSE,
)
下载并定义数据集拆分
现在您已经添加了一些有关数据集的信息,下一步是下载数据集并生成拆分。
使用DownloadManager.download() 方法下载数据集以及您想与其关联的任何其他元数据。此方法接受:
- Hub 数据集存储库中文件的名称(换句话说,
data/
文件夹) - 托管在其他地方的文件的 URL
- 文件名或 URL 的列表或字典
在 Food-101 加载脚本中,您会再次注意到 URL 在脚本的前面定义。
- Hub 数据集存储库中文件的名称(换句话说,
下载数据集后,使用SplitGenerator 来组织每个拆分中的图像和标签。使用标准名称为每个拆分命名,例如:
Split.TRAIN
、Split.TEST
和SPLIT.Validation
。在
gen_kwargs
参数中,指定要迭代和加载的images
的文件路径。如有必要,您可以使用DownloadManager.iter_archive() 来迭代 TAR 存档中的图像。您还可以在metadata_path
中指定关联的标签。images
和metadata_path
实际上传递到下一步,您将在其中实际生成数据集。
要流式传输 TAR 存档文件,您需要使用DownloadManager.iter_archive()!DownloadManager.download_and_extract() 函数不支持流式模式下的 TAR 存档。
def _split_generators(self, dl_manager):
archive_path = dl_manager.download(_BASE_URL)
split_metadata_paths = dl_manager.download(_METADATA_URLS)
return [
datasets.SplitGenerator(
name=datasets.Split.TRAIN,
gen_kwargs={
"images": dl_manager.iter_archive(archive_path),
"metadata_path": split_metadata_paths["train"],
},
),
datasets.SplitGenerator(
name=datasets.Split.VALIDATION,
gen_kwargs={
"images": dl_manager.iter_archive(archive_path),
"metadata_path": split_metadata_paths["test"],
},
),
]
生成数据集
GeneratorBasedBuilder 类中的最后一个方法实际上生成数据集中图像和标签。它根据info
方法中features
中指定的结构生成数据集。如您所见,generate_examples
将上一个方法中的images
和metadata_path
作为参数。
要流式传输 TAR 存档文件,需要首先打开并读取metadata_path
。TAR 文件是按顺序访问和生成的。这意味着您需要先准备好元数据信息,以便您可以将其与相应的图像一起生成。
现在您可以编写一个函数来打开和加载数据集中的示例。
def _generate_examples(self, images, metadata_path):
"""Generate images and labels for splits."""
with open(metadata_path, encoding="utf-8") as f:
files_to_keep = set(f.read().split("\n"))
for file_path, file_obj in images:
if file_path.startswith(_IMAGES_DIR):
if file_path[len(_IMAGES_DIR) : -len(".jpg")] in files_to_keep:
label = file_path.split("/")[2]
yield file_path, {
"image": {"path": file_path, "bytes": file_obj.read()},
"label": label,
}
生成数据集元数据(可选)
数据集元数据可以在数据集卡片(README.md
文件)中生成和存储。
运行以下命令在README.md
中生成您的数据集元数据,并确保您的新加载脚本正常工作。
datasets-cli test path/to/<your-dataset-loading-script> --save_info --all_configs
如果您的加载脚本通过了测试,您现在应该在数据集文件夹中README.md
文件的标题中拥有dataset_info
YAML 字段。
将数据集上传到 Hub
恭喜,您现在可以从 Hub 加载您的数据集!🥳
>>> from datasets import load_dataset
>>> load_dataset("<username>/my_dataset")