カスタムデータセットの作成

このガイドに従って、新しいデータセットを作成します(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.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 )。シリアル化は1回だけ行われます。その後のアクセスでは、これらの前処理されたファイルから直接読み取られます。

ほとんどの前処理は自動的に行われます。各データセットの実装のサブクラスtfds.core.DatasetBuilder 、指定:

  • データの出所(つまり、そのURL)。
  • データセットがどのように見えるか(つまり、その機能)。
  • どのようにデータ(例えば、分割する必要がありますTRAINTEST )。
  • データセット内の個々の例。

データセットを書く

デフォルトのテンプレートは: 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
    my_dataset.py # Dataset definition
    my_dataset_test.py # (optional) Test
    dummy_data/ # (optional) Fake data (used for testing)
    checksum.tsv # (optional) URL checksums (see `checksums` section).

検索TODO(my_dataset)ここでは、それに応じて変更します。

データセットの例

すべてのデータセットは、次のように実装されているtfds.core.GeneratorBasedBuilder 、のサブクラスtfds.core.DatasetBuilder最も定型の世話をします。それはサポートします:

データセットクラスの最小限の例を次に示します。

class MyDataset(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 tfds.core.DatasetInfo(
        builder=self,
        features=tfds.features.FeaturesDict({
            'image': tfds.features.Image(shape=(256, 256, 3)),
            'label': tfds.features.ClassLabel(names=['no', 'yes']),
        }),
    )

  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 :データセットのメタデータ

_info戻りtfds.core.DatasetInfo含むデータセットのメタデータを

def _info(self):
  return tfds.core.DatasetInfo(
      builder=self,
      # Description and homepage used for documentation
      description="""
      Markdown description of the dataset. The text will be automatically
      stripped and dedent.
      """,
      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,
      # Bibtex citation for the dataset
      citation=r"""
      @article{my-awesome-dataset-2020,
               author = {Smith, John},}
      """,
  )

ほとんどのフィールドは自明である必要があります。いくつかの精度:

  • features :これは、...データセットの構造、形状を指定し、複雑なデータタイプ(オーディオ、ビデオ、ネストされたシーケンスを、...)サポートしています。参照してください。利用可能な機能フィーチャーコネクタガイド詳細はを。
  • disable_shuffling :参照セクションには、データセットの順序を維持します
  • citation :検索するにBibText引用を:
    • データセットのWebサイトで引用命令を検索します(BibTex形式で使用します)。
    • arXivののペーパー:紙を見つけてクリックしBibText右側にリンクを。
    • 上の論文検索Googleニュースを、タイトルの下に、ポップアップ上でダブルクォーテーションマークをクリックし、クリックBibTeX
    • 何の紙が関連付けられている場合は、使用することができます(たとえば、単にウェブサイトありません) BibTeXのオンラインエディタをカスタムのBibTeXエントリを(ドロップダウンメニューを持って作成するためにOnlineエントリータイプ)。

データセットの順序を維持する

同じクラスに属するレコードは連続していることが多いため、デフォルトでは、データセット全体でクラスの分布をより均一にするために、データセットのレコードは保存時にシャッフルされます。データセットがで提供生成キーでソートされるように指定するために_generate_examplesフィールドdisable_shufflingに設定する必要がありますTrue 。デフォルトではに設定されているFalse

def _info(self):
  return tfds.core.DatasetInfo(
    # [...]
    disable_shuffling=True,
    # [...]
  )

シャードを並行して読み取ることができなくなったため、シャッフルを無効にするとパフォーマンスに影響することに注意してください。

_split_generators :ダウンロードおよび分割データ

ソースデータのダウンロードと抽出

ほとんどのデータセットは、Webからデータをダウンロードする必要があります。これは、使用して行われtfds.download.DownloadManagerの入力引数_split_generatorsdl_manager次のメソッドがあります。

  • download :サポートhttp(s)://ftp(s)://
  • extract :現在サポートしているが、 .zip.gz 、と.tarファイル。
  • download_and_extract :同じdl_manager.extract(dl_manager.download(urls))

すべてのこれらのメソッドは返しtfds.core.ReadOnlyPathあり、 pathlib.Pathのようなオブジェクトを。

これらの方法のサポートは、入れ子構造(任意のlistdictなど)、:

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ありtraintest分割を)、それらを保ちます。それ以外の場合は、一つだけ指定tfds.Split.TRAIN分割を。ユーザーが動的に自分のsubsplitsを作成することができますsubsplit API (例えばsplit='train[80%:]'

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ソースデータから各分割の例を生成します。

この方法は、典型的には、ソースデータセットの成果物(例えばA CSVファイル)と歩留まり読み込みます(key, feature_dict)タプルを:

  • key :例識別子。決定論的にするために使用使用例をシャッフルhash(key)シャッフルが無効になっている場合(セクションでは、参照するか、キーによるソートするデータセットの順序を維持)。する必要があります:
    • ユニーク:二つの例は同じキーを使用している場合は、例外が発生します。
    • 決定論:万一は依存しませdownload_diros.path.listdirため、... 2倍のデータを生成すると、同じキーを生成する必要があります。
    • 比較可能:シャッフルが無効になっている場合、キーはデータセットをソートするために使用されます。
  • feature_dictdictの例値を含みます。
    • 構造が一致している必要がありfeatures=で定義された構造tfds.core.DatasetInfo
    • 複雑なデータタイプ(画像、ビデオ、オーディオなど)は自動的にエンコードされます。
    • 各機能しばしば複数の入力タイプを受け入れる(例えば、ビデオ受け入れる/path/to/vid.mp4np.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返しpathlibのようなオブジェクトGoogleクラウドストレージとの直接の互換性を:

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:

Pathlibはに好まれるべきtf.io.gfile参照(合理的

追加の依存関係

一部のデータセットは、生成中にのみ追加のPython依存関係を必要とします。例えば、SVHNデータセットの用途は、 scipy 、いくつかのデータをロードします。

あなたはTFDSリポジトリにデータセットを追加する場合は、使用してくださいtfds.core.lazy_imports保つためにtensorflow-datasets小型パッケージ。ユーザーは、必要な場合にのみ追加の依存関係をインストールします。

使用するにはlazy_imports

  • あなたのデータセットのエントリの追加DATASET_EXTRASsetup.py 。これにより、ユーザーは、例えば、行うことができますので、それを作るpip install 'tensorflow-datasets[svhn]'余分な依存関係をインストールします。
  • インポート用のエントリを追加しLazyImporterとにLazyImportsTest
  • 使用はtfds.core.lazy_imports依存関係(例えば、アクセスするためにtfds.core.lazy_imports.scipyあなたに) DatasetBuilder

破損したデータ

一部のデータセットは完全にクリーンではなく、破損したデータが含まれています(たとえば、画像はJPEGファイルにありますが、一部は無効なJPEGです)。これらの例はスキップする必要がありますが、データセットの説明に、削除された例の数とその理由をメモしてください。

データセット構成/バリアント(tfds.core.BuilderConfig)

一部のデータセットには、複数のバリアント、またはデータを前処理してディスクに書き込む方法のオプションが含まれている場合があります。例えば、 cycle_ganはオブジェクトのペアごとに設定(持つcycle_gan/horse2zebracycle_gan/monet2photo 、...)。

これは、を介して行われtfds.core.BuilderConfig秒:

  1. サブクラスとして、コンフィギュレーション・オブジェクトを定義しますtfds.core.BuilderConfig 。例えば、 MyDatasetConfig

    @dataclasses.dataclass
    class MyDatasetConfig(tfds.core.BuilderConfig):
      img_size: Tuple[int, int] = (0, 0)
    
  2. 定義BUILDER_CONFIGS = []内のクラスメンバMyDatasetリストすることを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
    
  3. 使用self.builder_configMyDatasetのconfigureデータ生成(例えばshape=self.builder_config.img_size )。これは、異なる値を設定することを含んでもよい_info()またはダウンロードデータへのアクセスを変更します。

ノート:

  • 各構成には一意の名前があります。設定の完全修飾名ですdataset_name/config_name (例えばcoco/2017 )。
  • 指定されていない場合は、最初の設定BUILDER_CONFIGS使用されます(例えばtfds.load('c4')へのデフォルトのc4/en

参照anli使用するデータセットの例については、 BuilderConfig秒。

バージョン

バージョンは、2つの異なる意味を参照できます。

  • 「外部」の元のデータバージョン:例:COCO v2019、v2017、...
  • 「内部」TFDSコードバージョン:例えば、リネームで機能tfds.features.FeaturesDict 、中にバグを修正_generate_examples

データセットを更新するには:

  • 「外部」データ更新の場合:複数のユーザーが特定の年/バージョンに同時にアクセスしたい場合があります。これは、1使用して行われtfds.core.BuilderConfigバージョンごとに(例えばcoco/2017coco/2019 )またはバージョンごとに一つのクラス(例えばVoc2007Voc2012 )。
  • 「内部」コード更新の場合:ユーザーは最新バージョンのみをダウンロードします。任意のコードの更新は増加するはずVERSION (例えばからクラス属性1.0.0VERSION = tfds.core.Version('2.0.0')以下)セマンティックバージョニングを

登録用のインポートを追加します

プロジェクトにデータセットモジュールをインポートすることを忘れないでください__init__自動的に登録するtfds.loadtfds.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

データセットを生成するには、実行しtfds buildからmy_dataset/ディレクトリ:

cd path/to/datasets/my_dataset/
tfds build --register_checksums

開発に役立ついくつかのフラグ:

  • --pdb :例外が発生した場合にデバッグモードを入力します。
  • --overwrite :削除既存のファイルをデータセットがすでに生成された場合。
  • --max_examples_per_split :のみ最初のX例(1デフォルト)ではなく、完全なデータセットを生成します。
  • --register_checksums :ダウンロードされたURLのレコードのチェックサム。開発中のみ使用する必要があります。

参照してください。 CLIドキュメンテーションフラグの完全なリストについては、を。

チェックサム

これは、保証決定論、ドキュメンテーションを支援するために、あなたのデータセットのチェックサムを記録することが推奨され、...これは、とのデータセットを生成することによって行われ--register_checksums (前のセクションを参照してください)。

あなたはは、PyPIを通して、あなたのデータセットをリリースしている場合は、エクスポートすることを忘れないでくださいchecksums.tsv (例えば内のファイルをpackage_dataあなたのsetup.py )。

データセットの単体テスト

tfds.testing.DatasetBuilderTestCaseベースとなるTestCase完全データセットを行使する。ソースデータセットの構造を模倣するテストデータとして「ダミーデータ」を使用します。

  • テストデータは、中に配置する必要がありますmy_dataset/dummy_data/ディレクトリに、ダウンロードし、抽出されたとして、ソースデータセットの成果物を模倣する必要があります。これは、スクリプト(で手動または自動で作成することができますスクリプトの例)。
  • データセットの分割が重複するとテストが失敗するため、テストデータの分割には必ず異なるデータを使用してください。
  • テストデータは、任意の著作物を含むべきではありません。疑わしい場合は、元のデータセットの資料を使用してデータを作成しないでください。
import tensorflow_datasets as tfds
from . import my_dataset


class MyDatasetTest(tfds.testing.DatasetBuilderTestCase):
  """Tests for my_dataset dataset."""
  DATASET_CLASS = my_dataset.MyDataset
  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 dummy_data/my_dataset dir.
      'name2': 'file2',
  }


if __name__ == '__main__':
  tfds.testing.test_main()

次のコマンドを実行して、データセットをテストします。

python my_dataset_test.py

フィードバックを送ってください

データセット作成ワークフローの改善に継続的に取り組んでいますが、問題を認識している場合にのみ改善できます。データセットの作成中に発生した問題、エラーはどれですか?紛らわしい部分、定型的な部分、または最初に機能しなかった部分はありましたか?あなたの共有してくださいgithubの上のフィードバックを