12 月 7 日の Women in ML シンポジウムに参加する今すぐ登録する

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

コレクションでコンテンツを整理 必要に応じて、コンテンツの保存と分類を行います。

このガイドに従って、新しいデータセットを (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);
  • データセットがどのように見えるか (つまり、その機能);
  • データの分割方法 (例: 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
    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のサブクラスとして実装されています。以下をサポートします。

  • 1 台のマシンで生成できる小規模/中規模のデータセット (このチュートリアル)。
  • 分散生成が必要な非常に大規模なデータセット ( 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 : データセットのメタデータ

_infoは、データセット メタデータを含むtfds.core.DatasetInfoを返します。

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,
  )

ほとんどのフィールドは一目瞭然です。いくつかの精度:

BibText CITATIONS.bibファイルの書き込み:

  • データセットの Web サイトで引用の説明を検索します (BibTex 形式のものを使用してください)。
  • arXiv論文の場合: 論文を見つけて、右側のBibTextリンクをクリックします。
  • Google Scholarで論文を見つけて、タイトルの下にある二重引用符をクリックし、ポップアップで [ BibTeX ] をクリックします。
  • 関連する論文がない場合 (たとえば、Web サイトだけがある場合)、 BibTeX オンライン エディターを使用してカスタムの BibTeX エントリを作成できます (ドロップダウン メニューにはOnlineエントリ タイプがあります)。

TAGS.txtファイルの更新:

  • 許可されたすべてのタグは、生成されたファイルに事前に入力されています。
  • データセットに適用されないすべてのタグを削除します。
  • 有効なタグはtensorflow_datasets/core/valid_tags.txtにリストされています。
  • そのリストにタグを追加するには、PR を送信してください。

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

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

def _info(self):
  return self.dataset_info_from_configs(
    # [...]
    disable_shuffling=True,
    # [...]
  )

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

_split_generators : データのダウンロードと分割

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

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

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

これらのメソッドはすべて、 pathlib.Path のようなオブジェクトであるtfds.core.Path ( epath.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には、fobj と同じwith open('rb') as fobj: (例fobj.read() )

データセット分割の指定

データセットに事前定義された分割が付属している場合 (たとえば、 MNISTにはtraintestの分割がある)、それらを保持します。それ以外の場合は、単一のtfds.Split.TRAIN分割のみを指定してください。ユーザーは、 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は、ソース データから各分割の例を生成します。

このメソッドは通常、ソース データセット アーティファクト (CSV ファイルなど) を読み取り(key, feature_dict)タプルを生成します。

  • key : 識別子の例。 hash(key)を使用して例を決定論的にシャッフルするために、またはシャッフルが無効になっているときにキーでソートするために使用されます (セクションデータセットの順序を維持する を参照してください)。次のようにする必要があります。
    • unique : 2 つの例で同じキーを使用すると、例外が発生します。
    • deterministic : download_diros.path.listdirの順序などに依存すべきではありません... データを 2 回生成すると、同じキーが生成されます。
    • 比較可能: シャッフルが無効になっている場合、キーはデータセットの並べ替えに使用されます。
  • 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 ops を使用しないでください。

代わりに、 dl_managerは、Google Cloud ストレージと直接互換性のある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 を使用します。

tf.io.gfile よりもPathlibを優先する必要があります ( tf.io.gfile .

追加の依存関係

一部のデータセットでは、生成時にのみ追加の Python 依存関係が必要になります。たとえば、SVHN データセットはscipyを使用して一部のデータを読み込みます。

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

lazy_importsを使用するには:

  • データセットのエントリをsetup.pyDATASET_EXTRASに追加します。これにより、ユーザーは、たとえばpip install 'tensorflow-datasets[svhn]'を実行して追加の依存関係をインストールできるようになります。
  • インポートのエントリをLazyImporterLazyImportsTestに追加します。
  • tfds.core.lazy_importsを使用して、 DatasetBuilderの依存関係 (たとえば、 tfds.core.lazy_imports.scipy ) にアクセスします。

破損したデータ

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

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

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

これはtfds.core.BuilderConfigを通して行われます:

  1. 構成オブジェクトをtfds.core.BuilderConfigのサブクラスとして定義します。たとえば、 MyDatasetConfigです。

    @dataclasses.dataclass
    class MyDatasetConfig(tfds.core.BuilderConfig):
      img_size: Tuple[int, int] = (0, 0)
    
  2. データセットが公開するMyDatasetをリストするMyDatasetConfigBUILDER_CONFIGS = []クラス メンバーを定義します。

    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を使用して、データ生成を構成します (例: 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 )、またはバージョンごとに 1 つのクラス (例: Voc2007Voc2012 ) を使用して行われます。
  • 「内部」コード更新の場合: ユーザーは最新バージョンのみをダウンロードします。セマンティック バージョニングに従って、コードを更新すると、 VERSIONクラス属性が増加します (たとえば、 1.0.0からVERSION = tfds.core.Version('2.0.0')に)。

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

tfds.loadtfds.builderに自動的に登録されるように、データセット モジュールをプロジェクト__init__にインポートすることを忘れないでください。

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 : ダウンロードした URL のチェックサムを記録します。開発中のみ使用してください。

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

チェックサム

データセットのチェックサムを記録して、決定性を保証し、ドキュメントを支援することをお勧めします...これは、 --register_checksumsを使用してデータセットを生成することによって行われます (前のセクションを参照)。

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

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

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

  • テスト データはmy_dataset/dummy_data/ディレクトリに配置する必要があり、ダウンロードおよび抽出されたソース データセット アーティファクトを模倣する必要があります。これは、スクリプト ( example script ) を使用して手動または自動で作成できます。
  • データセットの分割が重複するとテストが失敗するため、テスト データの分割では必ず異なるデータを使用してください。
  • テスト データには、著作権で保護された素材を含めないでください。疑わしい場合は、元のデータセットの素材を使用してデータを作成しないでください。
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でフィードバックを共有してください。