Générateurs d'ensembles de données spécifiques au format

Ce guide documente tous les générateurs d'ensembles de données spécifiques au format actuellement disponibles dans TFDS.

Les générateurs d'ensembles de données spécifiques au format sont des sous-classes de tfds.core.GeneratorBasedBuilder qui prennent en charge la plupart du traitement des données pour un format de données spécifique.

Ensembles de données basés sur tf.data.Dataset

Si vous souhaitez créer un ensemble de données TFDS à partir d'un ensemble de données au format tf.data.Dataset ( référence ), vous pouvez utiliser tfds.dataset_builders.TfDataBuilder (voir la documentation de l'API ).

Nous envisageons deux utilisations typiques de cette classe :

  • Création d'ensembles de données expérimentaux dans un environnement de type notebook
  • Définir un générateur de jeu de données dans le code

Créer un nouvel ensemble de données à partir d'un notebook

Supposons que vous travailliez dans un bloc-notes, que vous chargiez des données en tant que tf.data.Dataset , que vous appliquiez diverses transformations (carte, filtre, etc.) et que vous souhaitiez maintenant stocker ces données et les partager facilement avec vos coéquipiers ou les charger dans d'autres blocs-notes. Au lieu d'avoir à définir une nouvelle classe de générateur d'ensemble de données, vous pouvez également instancier un tfds.dataset_builders.TfDataBuilder et appeler download_and_prepare pour stocker votre ensemble de données en tant qu'ensemble de données TFDS.

Puisqu'il s'agit d'un ensemble de données TFDS, vous pouvez le versionner, utiliser des configurations, avoir différentes divisions et le documenter pour une utilisation plus facile ultérieure. Cela signifie que vous devez également indiquer à TFDS quelles sont les fonctionnalités de votre ensemble de données.

Voici un exemple factice de la façon dont vous pouvez l'utiliser.

import tensorflow as tf
import tensorflow_datasets as tfds

my_ds_train = tf.data.Dataset.from_tensor_slices({"number": [1, 2, 3]})
my_ds_test = tf.data.Dataset.from_tensor_slices({"number": [4, 5]})

# Optionally define a custom `data_dir`.
# If None, then the default data dir is used.
custom_data_dir = "/my/folder"

# Define the builder.
single_number_builder = tfds.dataset_builders.TfDataBuilder(
    name="my_dataset",
    config="single_number",
    version="1.0.0",
    data_dir=custom_data_dir,
    split_datasets={
        "train": my_ds_train,
        "test": my_ds_test,
    },
    features=tfds.features.FeaturesDict({
        "number": tfds.features.Scalar(dtype=tf.int64),
    }),
    description="My dataset with a single number.",
    release_notes={
        "1.0.0": "Initial release with numbers up to 5!",
    }
)

# Make the builder store the data as a TFDS dataset.
single_number_builder.download_and_prepare()

La méthode download_and_prepare parcourra les tf.data.Dataset d'entrée et stockera l'ensemble de données TFDS correspondant dans /my/folder/my_dataset/single_number/1.0.0 , qui contiendra à la fois les fractionnements d'entraînement et de test.

L'argument config est facultatif et peut être utile si vous souhaitez stocker différentes configurations sous le même ensemble de données.

L'argument data_dir peut être utilisé pour stocker l'ensemble de données TFDS généré dans un dossier différent, par exemple dans votre propre bac à sable si vous ne souhaitez pas (encore) le partager avec d'autres. Notez que ce faisant, vous devez également transmettre le data_dir à tfds.load . Si l'argument data_dir n'est pas spécifié, alors le répertoire de données TFDS par défaut sera utilisé.

Chargement de votre ensemble de données

Une fois l'ensemble de données TFDS stocké, il peut être chargé à partir d'autres scripts ou par des coéquipiers s'ils ont accès aux données :

# If no custom data dir was specified:
ds_test = tfds.load("my_dataset/single_number", split="test")

# When there are multiple versions, you can also specify the version.
ds_test = tfds.load("my_dataset/single_number:1.0.0", split="test")

# If the TFDS was stored in a custom folder, then it can be loaded as follows:
custom_data_dir = "/my/folder"
ds_test = tfds.load("my_dataset/single_number:1.0.0", split="test", data_dir=custom_data_dir)

Ajout d'une nouvelle version ou configuration

Après avoir parcouru davantage votre ensemble de données, vous avez peut-être ajouté ou modifié certaines des transformations des données sources. Pour stocker et partager cet ensemble de données, vous pouvez facilement le stocker en tant que nouvelle version.

def add_one(example):
  example["number"] = example["number"] + 1
  return example

my_ds_train_v2 = my_ds_train.map(add_one)
my_ds_test_v2 = my_ds_test.map(add_one)

single_number_builder_v2 = tfds.dataset_builders.TfDataBuilder(
    name="my_dataset",
    config="single_number",
    version="1.1.0",
    data_dir=custom_data_dir,
    split_datasets={
        "train": my_ds_train_v2,
        "test": my_ds_test_v2,
    },
    features=tfds.features.FeaturesDict({
        "number": tfds.features.Scalar(dtype=tf.int64, doc="Some number"),
    }),
    description="My dataset with a single number.",
    release_notes={
        "1.1.0": "Initial release with numbers up to 6!",
        "1.0.0": "Initial release with numbers up to 5!",
    }
)

# Make the builder store the data as a TFDS dataset.
single_number_builder_v2.download_and_prepare()

Définir une nouvelle classe de générateur de jeux de données

Vous pouvez également définir un nouveau DatasetBuilder basé sur cette classe.

import tensorflow as tf
import tensorflow_datasets as tfds

class MyDatasetBuilder(tfds.dataset_builders.TfDataBuilder):
  def __init__(self):
    ds_train = tf.data.Dataset.from_tensor_slices([1, 2, 3])
    ds_test = tf.data.Dataset.from_tensor_slices([4, 5])
    super().__init__(
        name="my_dataset",
        version="1.0.0",
        split_datasets={
            "train": ds_train,
            "test": ds_test,
        },
        features=tfds.features.FeaturesDict({
            "number": tfds.features.Scalar(dtype=tf.int64),
        }),
        config="single_number",
        description="My dataset with a single number.",
        release_notes={
            "1.0.0": "Initial release with numbers up to 5!",
        })

CroissantBuilder

Le format

Croissant 🥐 est un format de haut niveau pour les ensembles de données d'apprentissage automatique qui combine les métadonnées, les descriptions de fichiers de ressources, la structure des données et la sémantique ML par défaut dans un seul fichier ; il fonctionne avec les ensembles de données existants pour les rendre plus faciles à trouver, à utiliser et à prendre en charge avec des outils.

Croissant s'appuie sur schema.org et son vocabulaire sc:Dataset , un format largement utilisé pour représenter des ensembles de données sur le Web et les rendre consultables.

CroissantBuilder

Un CroissantBuilder définit un ensemble de données TFDS basé sur un fichier de métadonnées Croissant 🥐 ; chacun des record_set_names spécifiés donnera lieu à un ConfigBuilder distinct.

Par exemple, pour initialiser un CroissantBuilder pour le jeu de données MNIST en utilisant sa définition Croissant 🥐 :

import tensorflow_datasets as tfds
builder = tfds.dataset_builders.CroissantBuilder(
    jsonld="https://raw.githubusercontent.com/mlcommons/croissant/main/datasets/0.8/huggingface-mnist/metadata.json",
    file_format='array_record',
)
builder.download_and_prepare()
ds = builder.as_data_source()
print(ds['default'][0])

CoNLL

Le format

CoNLL est un format populaire utilisé pour représenter des données textuelles annotées.

Les données au format CoNLL contiennent généralement un jeton avec ses annotations linguistiques par ligne ; au sein d'une même ligne, les annotations sont généralement séparées par des espaces ou des tabulations. Les lignes vides représentent les limites des phrases.

Considérons à titre d'exemple la phrase suivante de l'ensemble de données conll2003 , qui suit le format d'annotation CoNLL :

U.N. NNP I-NP I-ORG official
NN I-NP O
Ekeus NNP I-NP I-PER
heads VBZ I-VP O
for IN I-PP O
Baghdad NNP I-NP
I-LOC . . O O

ConllDatasetBuilder

Pour ajouter un nouvel ensemble de données basé sur CoNLL à TFDS, vous pouvez baser votre classe de générateur d'ensemble de données sur tfds.dataset_builders.ConllDatasetBuilder . Cette classe de base contient du code commun pour gérer les spécificités des jeux de données CoNLL (itération sur le format basé sur les colonnes, listes précompilées de fonctionnalités et de balises, ...).

tfds.dataset_builders.ConllDatasetBuilder implémente un GeneratorBasedBuilder spécifique à CoNLL. Reportez-vous à la classe suivante comme exemple minimal de générateur d'ensemble de données CoNLL :

from tensorflow_datasets.core.dataset_builders.conll import conll_dataset_builder_utils as conll_lib
import tensorflow_datasets.public_api as tfds

class MyCoNNLDataset(tfds.dataset_builders.ConllDatasetBuilder):
  VERSION = tfds.core.Version('1.0.0')
  RELEASE_NOTES = {'1.0.0': 'Initial release.'}

  # conllu_lib contains a set of ready-to-use CONLL-specific configs.
  BUILDER_CONFIGS = [conll_lib.CONLL_2003_CONFIG]

  def _info(self) -> tfds.core.DatasetInfo:
    return self.create_dataset_info(
        # ...
    )

  def _split_generators(self, dl_manager):
    path = dl_manager.download_and_extract('https://data-url')

    return {'train': self._generate_examples(path=path / 'train.txt'),
            'test': self._generate_examples(path=path / 'train.txt'),
    }

Quant aux constructeurs de jeux de données standards, cela nécessite d'écraser les méthodes de classe _info et _split_generators . En fonction de l'ensemble de données, vous devrez peut-être également mettre à jour conll_dataset_builder_utils.py pour inclure les fonctionnalités et la liste des balises spécifiques à votre ensemble de données.

La méthode _generate_examples ne devrait pas nécessiter d'écrasement supplémentaire, sauf si votre ensemble de données nécessite une implémentation spécifique.

Exemples

Considérez conll2003 comme exemple d'ensemble de données implémenté à l'aide du générateur d'ensemble de données spécifique à CoNLL.

CLI

Le moyen le plus simple d'écrire un nouvel ensemble de données basé sur CoNLL consiste à utiliser la CLI TFDS :

cd path/to/my/project/datasets/
tfds new my_dataset --format=conll   # Create `my_dataset/my_dataset.py` CoNLL-specific template files

CoNLL-U

Le format

CoNLL-U est un format populaire utilisé pour représenter des données textuelles annotées.

CoNLL-U améliore le format CoNLL en ajoutant un certain nombre de fonctionnalités, telles que la prise en charge des mots multi-jetons . Les données au format CoNLL-U contiennent généralement un jeton avec ses annotations linguistiques par ligne ; au sein d'une même ligne, les annotations sont généralement séparées par des caractères de tabulation simples. Les lignes vides représentent les limites des phrases.

Généralement, chaque ligne de mot annotée CoNLL-U contient les champs suivants, comme indiqué dans la documentation officielle :

  • ID : Index des mots, entier commençant à 1 pour chaque nouvelle phrase ; peut être une plage pour les jetons multi-mots ; peut être un nombre décimal pour les nœuds vides (les nombres décimaux peuvent être inférieurs à 1 mais doivent être supérieurs à 0).
  • FORME : Forme de mot ou symbole de ponctuation.
  • LEMME : Lemme ou radical de la forme d'un mot.
  • UPOS : Balise de partie grammaticale universelle.
  • XPOS : balise de partie du discours spécifique à la langue ; souligner s’il n’est pas disponible.
  • FEATS : Liste de caractéristiques morphologiques issues de l'inventaire universel de caractéristiques ou d'une extension spécifique à une langue définie ; souligner s’il n’est pas disponible.
  • HEAD : en-tête du mot actuel, qui est soit une valeur ID, soit zéro (0).
  • DEPREL : relation de dépendance universelle avec le HEAD (racine ssi HEAD = 0) ou un sous-type spécifique au langage défini de celui-ci.
  • DEPS : graphe de dépendance amélioré sous la forme d'une liste de paires tête-deprel.
  • DIVERS : Toute autre annotation.

Considérons à titre d'exemple la phrase annotée CoNLL-U suivante tirée de la documentation officielle :

1-2    vámonos   _
1      vamos     ir
2      nos       nosotros
3-4    al        _
3      a         a
4      el        el
5      mar       mar

ConllUDatasetBuilder

Pour ajouter un nouvel ensemble de données basé sur CoNLL-U à TFDS, vous pouvez baser votre classe de générateur d'ensemble de données sur tfds.dataset_builders.ConllUDatasetBuilder . Cette classe de base contient du code commun pour gérer les spécificités des jeux de données CoNLL-U (itération sur le format basé sur les colonnes, listes précompilées de fonctionnalités et de balises, ...).

tfds.dataset_builders.ConllUDatasetBuilder implémente un GeneratorBasedBuilder spécifique à CoNLL-U. Reportez-vous à la classe suivante comme exemple minimal de générateur d'ensemble de données CoNLL-U :

from tensorflow_datasets.core.dataset_builders.conll import conllu_dataset_builder_utils as conllu_lib
import tensorflow_datasets.public_api as tfds

class MyCoNNLUDataset(tfds.dataset_builders.ConllUDatasetBuilder):
  VERSION = tfds.core.Version('1.0.0')
  RELEASE_NOTES = {'1.0.0': 'Initial release.'}

  # conllu_lib contains a set of ready-to-use features.
  BUILDER_CONFIGS = [
      conllu_lib.get_universal_morphology_config(
          language='en',
          features=conllu_lib.UNIVERSAL_DEPENDENCIES_FEATURES,
      )
  ]

  def _info(self) -> tfds.core.DatasetInfo:
    return self.create_dataset_info(
        # ...
    )

  def _split_generators(self, dl_manager):
    path = dl_manager.download_and_extract('https://data-url')

    return {
        'train':
            self._generate_examples(
                path=path / 'train.txt',
                # If necessary, add optional custom processing (see conllu_lib
                # for examples).
                # process_example_fn=...,
            )
    }

Quant aux constructeurs de jeux de données standards, ils nécessitent d'écraser les méthodes de classe _info et _split_generators . En fonction de l'ensemble de données, vous devrez peut-être également mettre à jour conllu_dataset_builder_utils.py pour inclure les fonctionnalités et la liste des balises spécifiques à votre ensemble de données.

La méthode _generate_examples ne devrait pas nécessiter d'écrasement supplémentaire, sauf si votre ensemble de données nécessite une implémentation spécifique. Notez que, si votre ensemble de données nécessite un prétraitement spécifique - par exemple s'il prend en compte des fonctionnalités de dépendance universelles non classiques - vous devrez peut-être mettre à jour l'attribut process_example_fn de votre fonction generate_examples (voir l'ensemble de données xtreme_pos à titre d'exemple).

Exemples

Considérez les ensembles de données suivants, qui utilisent le générateur d'ensembles de données spécifique CoNNL-U, à titre d'exemple :

CLI

Le moyen le plus simple d'écrire un nouvel ensemble de données basé sur CoNLL-U consiste à utiliser la CLI TFDS :

cd path/to/my/project/datasets/
tfds new my_dataset --format=conllu   # Create `my_dataset/my_dataset.py` CoNLL-U specific template files