После недавнего обновления до версии 1.4 Tensorflow включил tf.data
в ядро библиотеки. Одна «важная новая функция», описанная в примечаниях к выпуску версии 1.4 это tf.data.Dataset.apply()
, который является «методом применения пользовательских функций преобразования. ". Чем это отличается от уже существующего tf.data.Dataset.map()
?
Разница между tf.data.Dataset.map () и tf.data.Dataset.apply ()
Ответы (4)
Разница в том, что map
будет выполнять одну функцию для каждого элемента Dataset
отдельно, тогда как apply
будет выполнять одну функцию для всего Dataset
одновременно (например, _ 5_, приведенный в качестве примера в документации).
Аргумент apply
- это функция, которая принимает Dataset
и возвращает Dataset
, когда аргумент map
- это функция, которая принимает один элемент и возвращает один преобразованный элемент.
apply
. И теперь я вижу, что функции находятся в tf. ** contrib **. Data, а API набора данных был перемещен в tf.data, где я и искал.
- person GPhilo; 03.11.2017
map
используется для преобразования значений в наборе данных, а apply
работает с самим набором данных ... так что apply
также может заменить map
?
- person GPhilo; 03.11.2017
apply
используется, когда нужно рассмотреть сразу несколько элементов. Например, если вы хотите создать набор данных со средними значениями пяти последовательных элементов в вашем наборе данных, вы не сможете сделать это с map
- person Sunreef; 03.11.2017
apply
может полностью заменить map
(потому что, если у него есть доступ ко всем элементам, он также может иметь доступ к ним по одному, как map
), но писать функции для apply
не так просто, как писать функции которые работают с самими значениями, поэтому мы можем оставить map
по практическим соображениям. Имеет ли это смысл?
- person GPhilo; 03.11.2017
map
вызовом apply
, тогда ваша функция внутри apply
в любом случае должна будет выполнять эквивалент map
.
- person Sunreef; 03.11.2017
Ответ Sunreef абсолютно правильный. Возможно, вам все еще интересно, почему мы представили Dataset.apply()
< / a>, и я подумал, что могу предложить некоторую предысторию.
tf.data
API имеет набор основных преобразований, таких как Dataset.map()
и Dataset.filter()
, которые, как правило, полезны для широкого диапазона наборов данных, вряд ли изменятся и реализованы в виде методов для объекта tf.data.Dataset
. В частности, на них распространяются те же гарантии обратной совместимости, что и на другие основные API в TensorFlow.
Однако основной подход немного ограничен. Нам также нужна свобода экспериментировать с новыми преобразованиями перед добавлением их в ядро, а также позволить другим разработчикам библиотек создавать свои собственные преобразования, которые можно использовать повторно. Поэтому в TensorFlow 1.4 мы выделили набор настраиваемых преобразований, которые находятся в tf.contrib.data
. В число пользовательских преобразований входят некоторые, обладающие очень специфической функциональностью (например, tf.contrib.data.sloppy_interleave()
), и кое-где, где API все еще находится в разработке (например, _8 _). Первоначально мы реализовали эти пользовательские преобразования как функции от Dataset
до Dataset
, что отрицательно сказалось на синтаксическом потоке конвейера. Например:
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(...)
Поскольку это казалось обычным шаблоном, мы добавили Dataset.apply()
как способ связать основные и пользовательские преобразования в один конвейер:
dataset = (tf.data.TFRecordDataset(...)
.map(...)
.apply(custom_transformation(x, y, z))
.shuffle(...)
.repeat(...)
.batch(...))
Это второстепенная функция в общей схеме вещей, но, надеюсь, она помогает сделать tf.data
программы более легкими для чтения и библиотеку легче расширять.
tf.data
не имеют состояния и являются потоковыми, что означает, что они могут немедленно возвращать результаты и потреблять мало памяти при работе с большими наборами данных, которые могут не умещаться в памяти. Это означает, что если у вас есть Dataset.repeat()
после этих преобразований, они будут выполняться при каждом проходе через данные. Если вы хотите избежать этого, добавьте Dataset.cache()
после преобразований, которые вы хотите выполнить один раз.
- person mrry; 31.05.2018
custom_transformation
?
- person Marsellus Wallace; 30.11.2018
У меня недостаточно репутации для комментариев, но я просто хотел указать, что вы действительно можете использовать карту для применения к нескольким элементам в наборе данных, вопреки комментариям @sunreef к его собственному посту.
Согласно документации, карта принимает в качестве аргумента
map_func: функция, отображающая вложенную структуру тензоров (имеющую формы и типы, определенные в self.output_shapes и self.output_types) другой вложенной структуре тензоров.
output_shapes определяются набором данных и могут быть изменены с помощью функций API, таких как batch. Так, например, вы можете выполнить пакетную нормализацию, используя только dataset.batch и .map с:
dataset = dataset ...
dataset.batch(batch_size)
dataset.map(normalize_fn)
Похоже, что основная полезность apply()
- это когда вы действительно хотите выполнить преобразование всего набора данных.
Просто аргумент transformation_func
из apply()
Dataset
; аргумент map_func
из map()
element