按照本指南建立新的資料集 (無論是在 TFDS 中或您自己的存放庫中)。
查看我們的資料集清單,看看您想要的資料集是否已存在。
TL;DR
撰寫新資料集最簡單的方式是使用 TFDS CLI
cd path/to/my/project/datasets/
tfds new my_dataset # Create `my_dataset/my_dataset.py` template files
# [...] Manually modify `my_dataset/my_dataset_dataset_builder.py` to implement your dataset.
cd my_dataset/
tfds build # Download and prepare the dataset to `~/tensorflow_datasets/`
若要搭配 tfds.load('my_dataset')
使用新的資料集
tfds.load
將自動偵測並載入在~/tensorflow_datasets/my_dataset/
中產生的資料集 (例如,透過tfds build
)。- 或者,您可以明確
import my.project.datasets.my_dataset
來註冊您的資料集
import my.project.datasets.my_dataset # Register `my_dataset`
ds = tfds.load('my_dataset') # `my_dataset` registered
總覽
資料集以各種格式和各種位置分發,而且它們不一定以可直接饋送到機器學習管線的格式儲存。進入 TFDS 的世界。
TFDS 將這些資料集處理成標準格式 (外部資料 -> 序列化檔案),然後可以將其載入為機器學習管線 (序列化檔案 -> tf.data.Dataset
)。序列化只執行一次。後續存取將直接從這些預先處理的檔案讀取。
大部分的預先處理都是自動完成的。每個資料集都會實作 tfds.core.DatasetBuilder
的子類別,該子類別指定
- 資料的來源 (即其 URL);
- 資料集的樣貌 (即其功能);
- 資料應如何分割 (例如,
TRAIN
和TEST
); - 以及資料集中的個別範例。
撰寫您的資料集
預設範本:tfds new
使用 TFDS CLI 產生所需的範本 Python 檔案。
cd path/to/project/datasets/ # Or use `--dir=path/to/project/datasets/` below
tfds new my_dataset
此命令將產生新的 my_dataset/
資料夾,其中包含以下結構
my_dataset/
__init__.py
README.md # Markdown description of the dataset.
CITATIONS.bib # Bibtex citation for the dataset.
TAGS.txt # List of tags describing the dataset.
my_dataset_dataset_builder.py # Dataset definition
my_dataset_dataset_builder_test.py # Test
dummy_data/ # (optional) Fake data (used for testing)
checksum.tsv # (optional) URL checksums (see `checksums` section).
在此處搜尋 TODO(my_dataset)
並相應地修改。
資料集範例
所有資料集都是 tfds.core.DatasetBuilder
的實作子類別,其負責處理大部分的重複程式碼。它支援
- 可在單一機器上產生的小型/中型資料集 (本教學課程)。
- 需要分散式產生的超大型資料集 (使用 Apache Beam,請參閱我們的巨量資料集指南)
以下是基於 tfds.core.GeneratorBasedBuilder
的資料集建立工具的最小範例
class Builder(tfds.core.GeneratorBasedBuilder):
"""DatasetBuilder for my_dataset dataset."""
VERSION = tfds.core.Version('1.0.0')
RELEASE_NOTES = {
'1.0.0': 'Initial release.',
}
def _info(self) -> tfds.core.DatasetInfo:
"""Dataset metadata (homepage, citation,...)."""
return self.dataset_info_from_configs(
features=tfds.features.FeaturesDict({
'image': tfds.features.Image(shape=(256, 256, 3)),
'label': tfds.features.ClassLabel(
names=['no', 'yes'],
doc='Whether this is a picture of a cat'),
}),
)
def _split_generators(self, dl_manager: tfds.download.DownloadManager):
"""Download the data and define splits."""
extracted_path = dl_manager.download_and_extract('http://data.org/data.zip')
# dl_manager returns pathlib-like objects with `path.read_text()`,
# `path.iterdir()`,...
return {
'train': self._generate_examples(path=extracted_path / 'train_images'),
'test': self._generate_examples(path=extracted_path / 'test_images'),
}
def _generate_examples(self, path) -> Iterator[Tuple[Key, Example]]:
"""Generator of examples for each split."""
for img_path in path.glob('*.jpeg'):
# Yields (key, example)
yield img_path.name, {
'image': img_path,
'label': 'yes' if img_path.name.startswith('yes_') else 'no',
}
請注意,對於某些特定的資料格式,我們提供現成的資料集建立工具來處理大部分的資料處理。
讓我們詳細瞭解要覆寫的 3 個抽象方法。
_info
:資料集metadata
_info
傳回 tfds.core.DatasetInfo
,其中包含資料集metadata。
def _info(self):
# The `dataset_info_from_configs` base method will construct the
# `tfds.core.DatasetInfo` object using the passed-in parameters and
# adding: builder (self), description/citations/tags from the config
# files located in the same package.
return self.dataset_info_from_configs(
homepage='https://dataset-homepage.org',
features=tfds.features.FeaturesDict({
'image_description': tfds.features.Text(),
'image': tfds.features.Image(),
# Here, 'label' can be 0-4.
'label': tfds.features.ClassLabel(num_classes=5),
}),
# If there's a common `(input, target)` tuple from the features,
# specify them here. They'll be used if as_supervised=True in
# builder.as_dataset.
supervised_keys=('image', 'label'),
# Specify whether to disable shuffling on the examples. Set to False by default.
disable_shuffling=False,
)
大多數欄位都應是不言自明的。一些精確度
features
:這指定資料集結構、形狀等等。支援複雜的資料類型 (音訊、影片、巢狀序列等等)。請參閱可用的功能或功能連接器指南以取得更多資訊。disable_shuffling
:請參閱維護資料集順序章節。
撰寫 BibText
CITATIONS.bib
檔案
- 在資料集網站上搜尋引用指示 (以 BibTex 格式使用)。
- 對於 arXiv 論文:找到論文並按一下右側的
BibText
連結。 - 在 Google 學術搜尋上找到論文,然後按一下標題下方的雙引號,並在彈出視窗中按一下
BibTeX
。 - 如果沒有相關論文 (例如,只有一個網站),您可以使用 BibTeX 線上編輯器建立自訂 BibTeX 項目 (下拉式選單中有
Online
項目類型)。
更新 TAGS.txt
檔案
- 所有允許的標籤都預先填寫在產生的檔案中。
- 移除所有不適用於資料集的標籤。
- 有效標籤列在 tensorflow_datasets/core/valid_tags.txt 中。
- 若要將標籤新增至該清單,請傳送 PR。
維護資料集順序
預設情況下,當資料集儲存時,記錄會被打亂,以便使整個資料集中的類別分佈更均勻,因為通常屬於同一類別的記錄是連續的。為了指定資料集應依據 _generate_examples
提供的金鑰產生排序,應將欄位 disable_shuffling
設定為 True
。預設情況下,它會設定為 False
。
def _info(self):
return self.dataset_info_from_configs(
# [...]
disable_shuffling=True,
# [...]
)
請記住,停用洗牌會對效能產生影響,因為分片無法再並行讀取。
_split_generators
:下載並分割資料
下載並解壓縮來源資料
大多數資料集都需要從網路下載資料。這是透過 _split_generators
的 tfds.download.DownloadManager
輸入引數完成的。dl_manager
具有以下方法
download
:支援http(s)://
、ftp(s)://
extract
:目前支援.zip
、.gz
和.tar
檔案。download_and_extract
:與dl_manager.extract(dl_manager.download(urls))
相同
所有這些方法都會傳回 tfds.core.Path
(別名為 epath.Path
),它們是類似 pathlib.Path 的物件。
這些方法支援任意巢狀結構 (list
、dict
),例如
extracted_paths = dl_manager.download_and_extract({
'foo': 'https://example.com/foo.zip',
'bar': 'https://example.com/bar.zip',
})
# This returns:
assert extracted_paths == {
'foo': Path('/path/to/extracted_foo/'),
'bar': Path('/path/extracted_bar/'),
}
手動下載和解壓縮
有些資料無法自動下載 (例如,需要登入),在這種情況下,使用者將手動下載來源資料並將其放置在 manual_dir/
中 (預設為 ~/tensorflow_datasets/downloads/manual/
)。
然後可以透過 dl_manager.manual_dir
存取檔案
class MyDataset(tfds.core.GeneratorBasedBuilder):
MANUAL_DOWNLOAD_INSTRUCTIONS = """
Register into https://example.org/login to get the data. Place the `data.zip`
file in the `manual_dir/`.
"""
def _split_generators(self, dl_manager):
# data_path is a pathlib-like `Path('<manual_dir>/data.zip')`
archive_path = dl_manager.manual_dir / 'data.zip'
# Extract the manually downloaded `data.zip`
extracted_path = dl_manager.extract(archive_path)
...
manual_dir
位置可以使用 tfds build --manual_dir=
或使用 tfds.download.DownloadConfig
自訂。
直接讀取封存檔
dl_manager.iter_archive
循序讀取封存檔,而無需解壓縮。這可以節省儲存空間並改善某些檔案系統的效能。
for filename, fobj in dl_manager.iter_archive('path/to/archive.zip'):
...
fobj
具有與 with open('rb') as fobj:
相同的方法 (例如,fobj.read()
)
指定資料集分割
如果資料集隨附預先定義的分割 (例如,MNIST
具有 train
和 test
分割),請保留這些分割。否則,僅指定單一 all
分割。使用者可以使用子分割 API 動態建立自己的子分割 (例如,split='train[80%:]'
)。請注意,除了上述 all
之外,任何字母字串都可以用作分割名稱。
def _split_generators(self, dl_manager):
# Download source data
extracted_path = dl_manager.download_and_extract(...)
# Specify the splits
return {
'train': self._generate_examples(
images_path=extracted_path / 'train_imgs',
label_path=extracted_path / 'train_labels.csv',
),
'test': self._generate_examples(
images_path=extracted_path / 'test_imgs',
label_path=extracted_path / 'test_labels.csv',
),
}
_generate_examples
:範例產生器
_generate_examples
從來源資料產生每個分割的範例。
此方法通常會讀取來源資料集成品 (例如 CSV 檔案) 並產生 (key, feature_dict)
元組
key
:範例識別碼。用於使用hash(key)
確定性地打亂範例,或在停用洗牌時依金鑰排序 (請參閱維護資料集順序章節)。應為- 唯一:如果兩個範例使用相同的金鑰,則會引發例外狀況。
- 決定性:不應依賴
download_dir
、os.path.listdir
順序等等。產生資料兩次應產生相同的金鑰。 - 可比較:如果停用洗牌,則金鑰將用於排序資料集。
feature_dict
:包含範例值的dict
。- 結構應符合在
tfds.core.DatasetInfo
中定義的features=
結構。 - 複雜的資料類型 (影像、影片、音訊等等) 將自動編碼。
- 每個功能通常接受多種輸入類型 (例如,影片接受
/path/to/vid.mp4
、np.array(shape=(l, h, w, c))
、List[paths]
、List[np.array(shape=(h, w, c)]
、List[img_bytes]
等等。) - 請參閱功能連接器指南以取得更多資訊。
- 結構應符合在
def _generate_examples(self, images_path, label_path):
# Read the input data out of the source files
with label_path.open() as f:
for row in csv.DictReader(f):
image_id = row['image_id']
# And yield (key, feature_dict)
yield image_id, {
'image_description': row['description'],
'image': images_path / f'{image_id}.jpeg',
'label': row['label'],
}
檔案存取和 tf.io.gfile
為了支援雲端儲存系統,請避免使用 Python 內建的 I/O 運算。
相反地,dl_manager
會傳回直接與 Google Cloud Storage 相容的類似 pathlib 的物件
path = dl_manager.download_and_extract('http://some-website/my_data.zip')
json_path = path / 'data/file.json'
json.loads(json_path.read_text())
或者,使用 tf.io.gfile
API 而不是內建 API 進行檔案作業
open
->tf.io.gfile.GFile
os.rename
->tf.io.gfile.rename
- ...
Pathlib 應優先於 tf.io.gfile
(請參閱理由。
額外的依附元件
有些資料集僅在產生期間需要額外的 Python 依附元件。例如,SVHN 資料集使用 scipy
載入某些資料。
如果您要將資料集新增至 TFDS 存放庫,請使用 tfds.core.lazy_imports
以保持 tensorflow-datasets
套件小巧。使用者只會在需要時安裝額外的依附元件。
若要使用 lazy_imports
- 在
setup.py
中的DATASET_EXTRAS
中為您的資料集新增一個項目。這樣做是為了讓使用者可以執行例如pip install 'tensorflow-datasets[svhn]'
來安裝額外的依附元件。 - 在
LazyImporter
和LazyImportsTest
中為您的匯入新增一個項目。 - 在您的
DatasetBuilder
中使用tfds.core.lazy_imports
存取依附元件 (例如,tfds.core.lazy_imports.scipy
)。
損毀的資料
有些資料集並非完全乾淨,且包含一些損毀的資料 (例如,影像在 JPEG 檔案中,但有些是無效的 JPEG)。這些範例應略過,但在資料集說明中註明已捨棄多少範例以及原因。
資料集組態/變體 (tfds.core.BuilderConfig)
有些資料集可能有多個變體,或關於資料如何預先處理和寫入磁碟的選項。例如,cycle_gan 每個物件配對都有一個組態 (cycle_gan/horse2zebra
、cycle_gan/monet2photo
等等。)。
這是透過 tfds.core.BuilderConfig
完成的
將您的組態物件定義為
tfds.core.BuilderConfig
的子類別。例如,MyDatasetConfig
。@dataclasses.dataclass class MyDatasetConfig(tfds.core.BuilderConfig): img_size: Tuple[int, int] = (0, 0)
在
MyDataset
中定義BUILDER_CONFIGS = []
類別成員,列出資料集公開的MyDatasetConfig
。class MyDataset(tfds.core.GeneratorBasedBuilder): VERSION = tfds.core.Version('1.0.0') # pytype: disable=wrong-keyword-args BUILDER_CONFIGS = [ # `name` (and optionally `description`) are required for each config MyDatasetConfig(name='small', description='Small ...', img_size=(8, 8)), MyDatasetConfig(name='big', description='Big ...', img_size=(32, 32)), ] # pytype: enable=wrong-keyword-args
在
MyDataset
中使用self.builder_config
來設定資料產生 (例如,shape=self.builder_config.img_size
)。這可能包括在_info()
中設定不同的值或變更下載資料存取。
注意事項
- 每個組態都有一個唯一的名稱。組態的完整名稱是
dataset_name/config_name
(例如,coco/2017
)。 - 如果未指定,將使用
BUILDER_CONFIGS
中的第一個組態 (例如,tfds.load('c4')
預設為c4/en
)
請參閱 anli
,以取得使用 BuilderConfig
的資料集範例。
版本
版本可以指兩種不同的含義
- 「外部」原始資料版本:例如 COCO v2019、v2017 等等。
- 「內部」TFDS 程式碼版本:例如,在
tfds.features.FeaturesDict
中重新命名功能,修正_generate_examples
中的錯誤
若要更新資料集
- 對於「外部」資料更新:多個使用者可能想要同時存取特定的年份/版本。這是透過每個版本使用一個
tfds.core.BuilderConfig
(例如,coco/2017
、coco/2019
) 或每個版本一個類別 (例如,Voc2007
、Voc2012
) 來完成的。 - 對於「內部」程式碼更新:使用者只會下載最新版本。任何程式碼更新都應依照語意版本控制,增加
VERSION
類別屬性 (例如,從1.0.0
到VERSION = tfds.core.Version('2.0.0')
)。
新增匯入以進行註冊
別忘了將資料集模組匯入您的專案 __init__
,以便在 tfds.load
、tfds.builder
中自動註冊。
import my_project.datasets.my_dataset # Register MyDataset
ds = tfds.load('my_dataset') # MyDataset available
例如,如果您要為 tensorflow/datasets
貢獻,請將模組匯入新增至其子目錄的 __init__.py
(例如,image/__init__.py
。
檢查常見的實作陷阱
請檢查常見的實作陷阱。
測試您的資料集
下載並準備:tfds build
若要產生資料集,請從 my_dataset/
目錄執行 tfds build
cd path/to/datasets/my_dataset/
tfds build --register_checksums
一些用於開發的實用標記
--pdb
:如果引發例外狀況,則進入偵錯模式。--overwrite
:如果已產生資料集,則刪除現有檔案。--max_examples_per_split
:僅產生前 X 個範例 (預設為 1),而不是完整資料集。--register_checksums
:記錄下載網址的總和檢查碼。僅應在開發期間使用。
請參閱 CLI 文件以取得完整標記清單。
總和檢查碼
建議記錄資料集的總和檢查碼,以保證決定性、協助文件等等。這可以透過使用 --register_checksums
產生資料集來完成 (請參閱上一節)。
如果您要透過 PyPI 發布您的資料集,請別忘了匯出 checksums.tsv
檔案 (例如,在您的 setup.py
的 package_data
中)。
單元測試您的資料集
tfds.testing.DatasetBuilderTestCase
是完全練習資料集的基本 TestCase
。它使用「虛擬資料」作為測試資料,以模仿來源資料集的結構。
- 測試資料應放置在
my_dataset/dummy_data/
目錄中,並應模仿下載和解壓縮的來源資料集成品。它可以手動建立或使用指令碼自動建立 (範例指令碼)。 - 請務必在您的測試資料分割中使用不同的資料,因為如果您的資料集分割重疊,測試將會失敗。
- 測試資料不應包含任何受著作權保護的資料。如有疑問,請勿使用原始資料集的資料來建立資料。
import tensorflow_datasets as tfds
from . import my_dataset_dataset_builder
class MyDatasetTest(tfds.testing.DatasetBuilderTestCase):
"""Tests for my_dataset dataset."""
DATASET_CLASS = my_dataset_dataset_builder.Builder
SPLITS = {
'train': 3, # Number of fake train example
'test': 1, # Number of fake test example
}
# If you are calling `download/download_and_extract` with a dict, like:
# dl_manager.download({'some_key': 'http://a.org/out.txt', ...})
# then the tests needs to provide the fake output paths relative to the
# fake data directory
DL_EXTRACT_RESULT = {
'name1': 'path/to/file1', # Relative to my_dataset/dummy_data dir.
'name2': 'file2',
}
if __name__ == '__main__':
tfds.testing.test_main()
執行以下命令來測試資料集。
python my_dataset_test.py
傳送意見回饋給我們
我們不斷嘗試改進資料集建立工作流程,但只有在我們知道問題時才能做到。您在建立資料集時遇到哪些問題或錯誤?是否有任何部分令人困惑,或第一次無法運作?
請在 GitHub 上分享您的意見回饋。