커스텀 데이터 세트 작성

이 가이드에 따라 새 데이터세트를 생성하세요(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 의 하위 클래스로 구현됩니다. 다음을 지원합니다:

다음은 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 파일 작성:

  • 데이터세트 웹사이트에서 인용 지침을 검색하세요(BibTex 형식 사용).
  • arXiv 논문의 경우: 논문을 찾아 오른쪽에 있는 BibText 링크를 클릭하세요.
  • Google Scholar 에서 논문을 찾아 제목 아래에 있는 큰따옴표를 클릭하고 팝업에서 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_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 의 별칭)를 반환합니다.

이러한 메서드는 다음과 같은 임의의 중첩 구조( 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 에는 traintest 분할이 있음) 이를 유지하세요. 그렇지 않으면 단일 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) 를 사용하여 예제를 결정적으로 섞거나 섞기가 비활성화된 경우 키별로 정렬하는 데 사용됩니다( 데이터 세트 순서 유지 섹션 참조). 해야한다:
    • Unique : 두 예제가 동일한 키를 사용하는 경우 예외가 발생합니다.
    • 결정적 : download_dir , os.path.listdir 순서 등에 의존해서는 안 됩니다. 데이터를 두 번 생성하면 동일한 키가 생성되어야 합니다.
    • Comparable : 셔플링이 비활성화된 경우 키는 데이터 세트를 정렬하는 데 사용됩니다.
  • feature_dict : 예시 값을 포함하는 dict 입니다.
    • 구조는 tfds.core.DatasetInfo 에 정의된 features= 구조와 일치해야 합니다.
    • 복잡한 데이터 유형(이미지, 비디오, 오디오 등)이 자동으로 인코딩됩니다.
    • 각 기능은 종종 여러 입력 유형을 허용합니다(예: video accept /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())

또는 파일 작업에 내장된 API 대신 tf.io.gfile API를 사용하세요.

tf.io.gfile 보다 Pathlib를 선호해야 합니다( rational .

추가 종속성

일부 데이터 세트에는 생성 중에만 추가 Python 종속성이 필요합니다. 예를 들어 SVHN 데이터 세트는 scipy 사용하여 일부 데이터를 로드합니다.

TFDS 저장소에 데이터세트를 추가하는 경우 tfds.core.lazy_imports 사용하여 tensorflow-datasets 패키지를 작게 유지하세요. 사용자는 필요한 경우에만 추가 종속성을 설치합니다.

lazy_imports 사용하려면 다음을 수행하십시오.

  • setup.pyDATASET_EXTRAS 에 데이터세트 항목을 추가합니다. 이를 통해 사용자는 예를 들어 pip install 'tensorflow-datasets[svhn]' 수행하여 추가 종속성을 설치할 수 있습니다.
  • LazyImporterLazyImportsTest 에 가져오기 항목을 추가합니다.
  • DatasetBuilder 의 종속성(예: tfds.core.lazy_imports.scipy )에 액세스하려면 tfds.core.lazy_imports 사용하세요.

손상된 데이터

일부 데이터 세트는 완벽하게 깨끗하지 않고 일부 손상된 데이터를 포함하고 있습니다(예: 이미지는 JPEG 파일이지만 일부는 유효하지 않은 JPEG임). 이러한 예시는 건너뛰어야 하지만, 삭제된 예시 수와 이유를 데이터 세트 설명에 메모로 남겨두세요.

데이터세트 구성/변형(tfds.core.BuilderConfig)

일부 데이터 세트에는 데이터가 전처리되어 디스크에 기록되는 방식에 대한 여러 변형 또는 옵션이 있을 수 있습니다. 예를 들어, Cycle_gan 에는 객체 쌍( cycle_gan/horse2zebra , cycle_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. 데이터세트가 노출하는 MyDatasetConfig 를 나열하는 MyDataset 에서 BUILDER_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. MyDataset 에서 self.builder_config 사용하여 데이터 생성을 구성합니다(예: shape=self.builder_config.img_size ). 여기에는 _info() 에서 다른 값을 설정하거나 다운로드 데이터 액세스를 변경하는 것이 포함될 수 있습니다.

노트:

  • 각 구성에는 고유한 이름이 있습니다. 구성의 정규화된 이름은 dataset_name/config_name (예: coco/2017 )입니다.
  • 지정하지 않으면 BUILDER_CONFIGS 의 첫 번째 구성이 사용됩니다(예: tfds.load('c4') 기본값은 c4/en )

BuilderConfig 를 사용하는 데이터 세트의 예는 anli 참조하세요.

버전

버전은 두 가지 다른 의미를 나타낼 수 있습니다.

  • "외부" 원본 데이터 버전: 예: 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') 으로)을 늘려야 합니다.

등록을 위해 가져오기 추가

tfds.load , tfds.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/ 디렉터리에 저장되어야 하며 다운로드 및 추출된 소스 데이터 세트 아티팩트를 모방해야 합니다. 수동으로 생성하거나 스크립트( 예제 스크립트 )를 사용하여 자동으로 생성할 수 있습니다.
  • 데이터 세트 분할이 겹치면 테스트가 실패하므로 테스트 데이터 분할에 다른 데이터를 사용해야 합니다.
  • 테스트 데이터에는 저작권이 있는 자료가 포함되어서는 안 됩니다 . 확실하지 않은 경우 원본 데이터세트의 자료를 사용하여 데이터를 생성하지 마세요.
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 에서 피드백을 공유해 주세요.