Menulis kumpulan data khusus

Ikuti panduan ini untuk membuat kumpulan data baru (baik di TFDS atau di repositori Anda sendiri).

Periksa daftar kumpulan data kami untuk melihat apakah kumpulan data yang Anda inginkan sudah ada.

TL;DR

Cara termudah untuk menulis kumpulan data baru adalah dengan menggunakan 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/`

Untuk menggunakan kumpulan data baru dengan tfds.load('my_dataset') :

  • tfds.load akan secara otomatis mendeteksi dan memuat kumpulan data yang dihasilkan di ~/tensorflow_datasets/my_dataset/ (misalnya oleh tfds build ).
  • Alternatifnya, Anda dapat import my.project.datasets.my_dataset secara eksplisit untuk mendaftarkan kumpulan data Anda:
import my.project.datasets.my_dataset  # Register `my_dataset`

ds = tfds.load('my_dataset')  # `my_dataset` registered

Ringkasan

Kumpulan data didistribusikan dalam berbagai format dan tempat, dan tidak selalu disimpan dalam format yang siap dimasukkan ke dalam alur pembelajaran mesin. Masukkan TFDS.

TFDS memproses kumpulan data tersebut ke dalam format standar (data eksternal -> file serial), yang kemudian dapat dimuat sebagai pipeline pembelajaran mesin (file serial -> tf.data.Dataset ). Serialisasi hanya dilakukan satu kali. Akses selanjutnya akan membaca langsung dari file yang telah diproses sebelumnya.

Sebagian besar prapemrosesan dilakukan secara otomatis. Setiap kumpulan data mengimplementasikan subkelas tfds.core.DatasetBuilder , yang menentukan:

  • Dari mana data tersebut berasal (yaitu URL-nya);
  • Seperti apa kumpulan data tersebut (yaitu fitur-fiturnya);
  • Bagaimana data harus dipecah (misalnya TRAIN dan TEST );
  • dan contoh individual dalam kumpulan data.

Tulis kumpulan data Anda

Templat bawaan: tfds new

Gunakan TFDS CLI untuk menghasilkan file python template yang diperlukan.

cd path/to/project/datasets/  # Or use `--dir=path/to/project/datasets/` below
tfds new my_dataset

Perintah ini akan menghasilkan folder my_dataset/ baru dengan struktur berikut:

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

Telusuri TODO(my_dataset) di sini dan ubah sesuai kebutuhan.

Contoh kumpulan data

Semua kumpulan data diimplementasikan subkelas tfds.core.DatasetBuilder , yang menangani sebagian besar boilerplate. Ini mendukung:

  • Kumpulan data kecil/menengah yang dapat dihasilkan pada satu mesin (tutorial ini).
  • Kumpulan data yang sangat besar yang memerlukan pembuatan terdistribusi (menggunakan Apache Beam , lihat panduan kumpulan data besar kami)

Berikut adalah contoh minimal pembuat kumpulan data yang didasarkan pada 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',
      }

Perlu diperhatikan bahwa, untuk beberapa format data tertentu, kami menyediakan pembuat kumpulan data yang siap digunakan untuk menangani sebagian besar pemrosesan data.

Mari kita lihat secara detail 3 metode abstrak untuk ditimpa.

_info : metadata kumpulan data

_info mengembalikan tfds.core.DatasetInfo yang berisi metadata kumpulan data .

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

Sebagian besar bidang harus cukup jelas. Beberapa presisi:

Menulis file BibText CITATIONS.bib :

  • Telusuri situs web kumpulan data untuk instruksi kutipan (gunakan dalam format BibTex).
  • Untuk makalah arXiv : temukan makalahnya dan klik tautan BibText di sisi kanan.
  • Temukan makalah di Google Cendekia dan klik tanda kutip ganda di bawah judul dan pada popup, klik BibTeX .
  • Jika tidak ada makalah terkait (misalnya, hanya ada situs web), Anda dapat menggunakan BibTeX Online Editor untuk membuat entri BibTeX kustom (menu drop-down memiliki tipe entri Online ).

Memperbarui file TAGS.txt :

  • Semua tag yang diizinkan telah diisi sebelumnya dalam file yang dihasilkan.
  • Hapus semua tag yang tidak berlaku untuk kumpulan data.
  • Tag yang valid tercantum di tensorflow_datasets/core/valid_tags.txt .
  • Untuk menambahkan tag ke daftar itu, silakan kirimkan PR.

Pertahankan urutan kumpulan data

Secara default, rekaman kumpulan data diacak saat disimpan untuk membuat distribusi kelas lebih seragam di seluruh kumpulan data, karena sering kali rekaman milik kelas yang sama bersebelahan. Untuk menentukan bahwa kumpulan data harus diurutkan berdasarkan kunci yang dihasilkan yang disediakan oleh _generate_examples bidang disable_shuffling harus disetel ke True . Secara default diatur ke False .

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

Ingatlah bahwa menonaktifkan pengacakan memiliki dampak kinerja karena pecahan tidak dapat lagi dibaca secara paralel.

_split_generators : mengunduh dan membagi data

Mengunduh dan mengekstrak data sumber

Sebagian besar kumpulan data perlu mengunduh data dari web. Hal ini dilakukan dengan menggunakan argumen masukan tfds.download.DownloadManager dari _split_generators . dl_manager memiliki metode berikut:

  • download : mendukung http(s):// , ftp(s)://
  • extract : saat ini mendukung file .zip , .gz , dan .tar .
  • download_and_extract : Sama seperti dl_manager.extract(dl_manager.download(urls))

Semua metode tersebut mengembalikan tfds.core.Path (alias untuk epath.Path ), yang merupakan objek mirip pathlib.Path .

Metode-metode tersebut mendukung struktur bersarang sewenang-wenang ( list , dict ), seperti:

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/'),
}

Pengunduhan dan ekstraksi manual

Beberapa data tidak dapat diunduh secara otomatis (misalnya memerlukan login), dalam hal ini, pengguna akan mengunduh data sumber secara manual dan menempatkannya di manual_dir/ (defaultnya adalah ~/tensorflow_datasets/downloads/manual/ ).

File kemudian dapat diakses melalui 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)
    ...

Lokasi manual_dir dapat dikustomisasi dengan tfds build --manual_dir= atau menggunakan tfds.download.DownloadConfig .

Baca arsip secara langsung

dl_manager.iter_archive membaca arsip secara berurutan tanpa mengekstraknya. Hal ini dapat menghemat ruang penyimpanan dan meningkatkan kinerja pada beberapa sistem file.

for filename, fobj in dl_manager.iter_archive('path/to/archive.zip'):
  ...

fobj memiliki metode yang sama with open('rb') as fobj: (misalnya fobj.read() )

Menentukan pemisahan kumpulan data

Jika kumpulan data dilengkapi dengan pemisahan yang telah ditentukan sebelumnya (misalnya MNIST memiliki pemisahan train dan test ), simpanlah pemisahan tersebut. Jika tidak, hanya tentukan satu pemisahan all . Pengguna dapat secara dinamis membuat subsplit mereka sendiri dengan API subsplit (misalnya split='train[80%:]' ). Perhatikan bahwa string alfabet apa pun dapat digunakan sebagai nama terpisah, selain all yang disebutkan di atas.

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 : Contoh generator

_generate_examples menghasilkan contoh untuk setiap pemisahan dari data sumber.

Metode ini biasanya akan membaca artefak kumpulan data sumber (misalnya file CSV) dan menghasilkan tupel (key, feature_dict) :

  • key : Contoh pengenal. Digunakan untuk mengacak contoh secara deterministik menggunakan hash(key) atau mengurutkan berdasarkan kunci saat pengacakan dinonaktifkan (lihat bagian Menjaga urutan kumpulan data ). Seharusnya:
    • unik : Jika dua contoh menggunakan kunci yang sama, pengecualian akan dimunculkan.
    • deterministik : Tidak boleh bergantung pada download_dir , urutan os.path.listdir ,... Menghasilkan data dua kali akan menghasilkan kunci yang sama.
    • sebanding : Jika pengacakan dinonaktifkan, kunci akan digunakan untuk mengurutkan kumpulan data.
  • feature_dict : dict yang berisi nilai contoh.
    • Strukturnya harus sesuai dengan features= struktur yang ditentukan di tfds.core.DatasetInfo .
    • Tipe data kompleks (gambar, video, audio,...) akan dikodekan secara otomatis.
    • Setiap fitur sering kali menerima beberapa jenis input (misalnya video menerima /path/to/vid.mp4 , np.array(shape=(l, h, w, c)) , List[paths] , List[np.array(shape=(h, w, c)] , List[img_bytes] ,...)
    • Lihat panduan konektor fitur untuk informasi lebih lanjut.
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'],
      }

Akses file dan tf.io.gfile

Untuk mendukung sistem penyimpanan Cloud, hindari penggunaan operasi I/O bawaan Python.

Sebaliknya, dl_manager mengembalikan objek seperti pathlib yang kompatibel langsung dengan penyimpanan Google Cloud:

path = dl_manager.download_and_extract('http://some-website/my_data.zip')

json_path = path / 'data/file.json'

json.loads(json_path.read_text())

Alternatifnya, gunakan tf.io.gfile API alih-alih yang bawaan untuk operasi file:

Pathlib harus lebih disukai daripada tf.io.gfile (lihat rasional .

Ketergantungan ekstra

Beberapa kumpulan data memerlukan dependensi Python tambahan hanya selama pembuatan. Misalnya, kumpulan data SVHN menggunakan scipy untuk memuat beberapa data.

Jika Anda menambahkan kumpulan data ke dalam repositori TFDS, harap gunakan tfds.core.lazy_imports untuk menjaga paket tensorflow-datasets tetap kecil. Pengguna akan menginstal dependensi tambahan hanya jika diperlukan.

Untuk menggunakan lazy_imports :

  • Tambahkan entri untuk kumpulan data Anda ke DATASET_EXTRAS di setup.py . Hal ini memungkinkan pengguna melakukan, misalnya, pip install 'tensorflow-datasets[svhn]' untuk menginstal dependensi tambahan.
  • Tambahkan entri untuk impor Anda ke LazyImporter dan ke LazyImportsTest .
  • Gunakan tfds.core.lazy_imports untuk mengakses ketergantungan (misalnya, tfds.core.lazy_imports.scipy ) di DatasetBuilder Anda.

Data yang rusak

Beberapa kumpulan data tidak sepenuhnya bersih dan berisi beberapa data yang rusak (misalnya, gambar dalam file JPEG tetapi ada pula yang dalam format JPEG tidak valid). Contoh-contoh ini sebaiknya dilewati, namun tinggalkan catatan di deskripsi kumpulan data berapa banyak contoh yang dihilangkan dan alasannya.

Konfigurasi/varian kumpulan data (tfds.core.BuilderConfig)

Beberapa kumpulan data mungkin memiliki beberapa varian, atau opsi mengenai cara data diproses sebelumnya dan ditulis ke disk. Misalnya, cycle_gan memiliki satu konfigurasi per pasangan objek ( cycle_gan/horse2zebra , cycle_gan/monet2photo ,...).

Ini dilakukan melalui tfds.core.BuilderConfig s:

  1. Tentukan objek konfigurasi Anda sebagai subkelas dari tfds.core.BuilderConfig . Misalnya, MyDatasetConfig .

    @dataclasses.dataclass
    class MyDatasetConfig(tfds.core.BuilderConfig):
      img_size: Tuple[int, int] = (0, 0)
    
  2. Tentukan anggota kelas BUILDER_CONFIGS = [] di MyDataset yang mencantumkan MyDatasetConfig yang diekspos oleh kumpulan data.

    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. Gunakan self.builder_config di MyDataset untuk mengonfigurasi pembuatan data (misalnya shape=self.builder_config.img_size ). Ini mungkin termasuk menetapkan nilai yang berbeda di _info() atau mengubah akses data unduhan.

Catatan:

  • Setiap konfigurasi memiliki nama unik. Nama konfigurasi yang sepenuhnya memenuhi syarat adalah dataset_name/config_name (misalnya coco/2017 ).
  • Jika tidak ditentukan, konfigurasi pertama di BUILDER_CONFIGS akan digunakan (misalnya tfds.load('c4') default ke c4/en )

Lihat anli untuk contoh kumpulan data yang menggunakan BuilderConfig s.

Versi

Versi dapat merujuk pada dua arti yang berbeda:

  • Versi data asli "eksternal": misalnya COCO v2019, v2017,...
  • Versi kode TFDS "internal": misalnya mengganti nama fitur di tfds.features.FeaturesDict , memperbaiki bug di _generate_examples

Untuk memperbarui kumpulan data:

  • Untuk pembaruan data "eksternal": Beberapa pengguna mungkin ingin mengakses tahun/versi tertentu secara bersamaan. Hal ini dilakukan dengan menggunakan satu tfds.core.BuilderConfig per versi (misalnya coco/2017 , coco/2019 ) atau satu kelas per versi (misalnya Voc2007 , Voc2012 ).
  • Untuk pembaruan kode "internal": Pengguna hanya mengunduh versi terbaru. Pembaruan kode apa pun harus meningkatkan atribut kelas VERSION (misalnya dari 1.0.0 menjadi VERSION = tfds.core.Version('2.0.0') ) mengikuti versi semantik .

Tambahkan impor untuk pendaftaran

Jangan lupa untuk mengimpor modul dataset ke proyek Anda __init__ agar otomatis terdaftar di tfds.load , tfds.builder .

import my_project.datasets.my_dataset  # Register MyDataset

ds = tfds.load('my_dataset')  # MyDataset available

Misalnya, jika Anda berkontribusi pada tensorflow/datasets , tambahkan modul import ke __init__.py subdirektorinya (misalnya image/__init__.py .

Periksa gotcha implementasi umum

Silakan periksa implementasi umum gotchas .

Uji kumpulan data Anda

Unduh dan persiapkan: tfds build

Untuk menghasilkan kumpulan data, jalankan tfds build dari direktori my_dataset/ :

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

Beberapa tanda yang berguna untuk pengembangan:

  • --pdb : Masuk ke mode debugging jika pengecualian muncul.
  • --overwrite : Hapus file yang ada jika dataset sudah dibuat.
  • --max_examples_per_split : Hanya menghasilkan contoh X pertama (defaultnya adalah 1), bukan kumpulan data lengkap.
  • --register_checksums : Catat checksum url yang diunduh. Sebaiknya hanya digunakan saat dalam pengembangan.

Lihat dokumentasi CLI untuk daftar lengkap tandanya.

Checksum

Disarankan untuk mencatat checksum kumpulan data Anda untuk menjamin determinisme, bantuan dokumentasi,... Hal ini dilakukan dengan membuat kumpulan data dengan --register_checksums (lihat bagian sebelumnya).

Jika Anda merilis kumpulan data melalui PyPI, jangan lupa untuk mengekspor file checksums.tsv (misalnya di package_data setup.py Anda).

Uji unit kumpulan data Anda

tfds.testing.DatasetBuilderTestCase adalah TestCase dasar untuk menjalankan kumpulan data sepenuhnya. Ia menggunakan "data dummy" sebagai data uji yang meniru struktur kumpulan data sumber.

  • Data pengujian harus diletakkan di direktori my_dataset/dummy_data/ dan harus meniru artefak kumpulan data sumber seperti yang diunduh dan diekstraksi. Itu dapat dibuat secara manual atau otomatis dengan skrip ( contoh skrip ).
  • Pastikan untuk menggunakan data yang berbeda dalam pemisahan data pengujian Anda, karena pengujian akan gagal jika pemisahan kumpulan data Anda tumpang tindih.
  • Data pengujian tidak boleh mengandung materi berhak cipta apa pun . Jika ragu, jangan membuat data menggunakan bahan dari dataset asli.
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()

Jalankan perintah berikut untuk menguji kumpulan data.

python my_dataset_test.py

Kirimkan masukan kepada kami

Kami terus berupaya meningkatkan alur kerja pembuatan kumpulan data, namun hal ini hanya dapat dilakukan jika kami mengetahui masalahnya. Masalah atau kesalahan apa yang Anda temui saat membuat kumpulan data? Apakah ada bagian yang membingungkan, atau tidak berfungsi pada kali pertama?

Silakan bagikan tanggapan Anda di GitHub .