web-dev-qa-db-fra.com

Différence entre tf.data.Dataset.map () et tf.data.Dataset.apply ()

Avec la récente mise à niveau vers la version 1.4, Tensorflow incluait tf.data Dans le noyau de la bibliothèque. Une "nouvelle fonctionnalité majeure" décrite dans les notes de publication de la version 1.4 est tf.data.Dataset.apply() , qui est une "méthode pour appliquer des fonctions de transformation personnalisées". En quoi est-ce différent de celui qui existe déjà tf.data.Dataset.map() ?

17
GPhilo

La différence est que map exécutera une fonction sur chaque élément de Dataset séparément, tandis que apply exécutera une fonction sur l'ensemble Dataset à la fois ( tel que group_by_window donné comme exemple dans la documentation).

L'argument de apply est une fonction qui prend un Dataset et renvoie un Dataset lorsque l'argument de map est une fonction qui prend un élément et retourne un élément transformé.

22
Sunreef

réponse de Sunreef est absolument correct. Vous vous demandez peut-être encore pourquoi nous avons introduit Dataset.apply() , et j'ai pensé offrir un peu de contexte.

L'API tf.data Possède un ensemble de transformations de base , comme Dataset.map() et Dataset.filter()— qui sont généralement utiles dans un large éventail d'ensembles de données, peu susceptibles de changer et implémentées en tant que méthodes sur l'objet tf.data.Dataset. En particulier, ils sont soumis aux mêmes garanties de compatibilité descendante que les autres API principales de TensorFlow.

Cependant, l'approche de base est un peu restrictive. Nous voulons également avoir la liberté d'expérimenter de nouvelles transformations avant de les ajouter au cœur et de permettre aux autres développeurs de bibliothèque de créer leurs propres transformations réutilisables. Par conséquent, dans TensorFlow 1.4, nous avons divisé un ensemble de transformations personnalisées qui vivent dans tf.contrib.data. Les transformations personnalisées incluent certaines qui ont des fonctionnalités très spécifiques (comme tf.contrib.data.sloppy_interleave() ), et certaines où l'API est toujours en cours de transformation (comme tf.contrib.data.group_by_window() ). À l'origine, nous avons implémenté ces transformations personnalisées en tant que fonctions de Dataset à Dataset, ce qui a eu un effet malheureux sur le flux syntaxique d'un pipeline. Par exemple:

dataset = tf.data.TFRecordDataset(...).map(...)

# Method chaining breaks when we apply a custom transformation.
dataset = custom_transformation(dataset, x, y, z)

dataset = dataset.shuffle(...).repeat(...).batch(...)

Comme cela semblait être un modèle courant, nous avons ajouté Dataset.apply() comme moyen de chaîner les transformations de base et personnalisées dans un seul pipeline:

dataset = (tf.data.TFRecordDataset(...)
           .map(...)
           .apply(custom_transformation(x, y, z))
           .shuffle(...)
           .repeat(...)
           .batch(...))

C'est une fonctionnalité mineure dans le grand schéma des choses, mais j'espère que cela aidera à rendre les programmes tf.data Plus faciles à lire et la bibliothèque plus facile à étendre.

15
mrry

Je n'ai pas assez de réputation pour commenter, mais je voulais juste souligner que vous pouvez réellement utiliser map pour appliquer à plusieurs éléments dans un ensemble de données contrairement aux commentaires de @ sunreef sur son propre post.

Selon la documentation, la carte prend comme argument

map_func: fonction mappant une structure imbriquée de tenseurs (dont les formes et les types sont définis par self.output_shapes et self.output_types) à une autre structure imbriquée de tenseurs.

les formes_sortie sont définies par l'ensemble de données et peuvent être modifiées à l'aide de fonctions api comme batch. Ainsi, par exemple, vous pouvez effectuer une normalisation par lots en utilisant uniquement dataset.batch et .map avec:

dataset = dataset ...
dataset.batch(batch_size)
dataset.map(normalize_fn)

Il semble que l'utilitaire principal de apply() est lorsque vous voulez vraiment faire une transformation sur l'ensemble de données entier.

3
zephyrus