tf.data.TextLineDataset
Создает Dataset, состоящий из строк одного или нескольких текстовых файлов.
Наследует от: Dataset
tf.data.TextLineDataset(
filenames,
compression_type=None,
buffer_size=None,
num_parallel_reads=None,
name=None
)
Используется в блокнотах
| Используется в руководстве | Используется в учебных материалах |
|---|---|
tf.data.TextLineDataset загружает текст из текстовых файлов и создает набор данных, в котором каждая строка файла становится элементом набора данных.
Например, предположим, что у нас есть 2 файла «text_lines0.txt» и «text_lines1.txt» со следующими строками:
with open('/tmp/text_lines0.txt', 'w') as f:
f.write('the cow\n')
f.write('jumped over\n')
f.write('the moon\n')
with open('/tmp/text_lines1.txt', 'w') as f:
f.write('jack and jill\n')
f.write('went up\n')
f.write('the hill\n')Из них можно создать TextLineDataset следующим образом:
dataset = tf.data.TextLineDataset(['/tmp/text_lines0.txt',
'/tmp/text_lines1.txt'])Ожидается, что элементами набора данных будут:
for element in dataset.as_numpy_iterator(): print(element) b'the cow' b'jumped over' b'the moon' b'jack and jill' b'went up' b'the hill'
| Аргументы | |
|---|---|
filenames | tf.data.Dataset, элементы которого — скаляры tf.string, тензор tf.string или значение, которое можно преобразовать в тензор tf.string (например, список строк Python). |
compression_type | (Необязательно.) Скаляр tf.string, принимающий одно из значений "" (без сжатия), "ZLIB" или "GZIP". |
buffer_size | (Необязательно.) Скаляр tf.int64, задающий количество байтов для буферизации. Значение 0 приводит к использованию значений буферизации по умолчанию, выбранных в зависимости от типа сжатия. |
num_parallel_reads | (Необязательно.) Скаляр tf.int64, задающий количество файлов для параллельного чтения. Если значение больше единицы, записи из параллельно читаемых файлов выводятся в перемежающемся порядке. Если пропускная способность входного конвейера ограничена вводом-выводом, рассмотрите возможность задания для этого параметра значения больше единицы, чтобы распараллелить операции ввода-вывода. Если None, файлы будут читаться последовательно. |
name | (Необязательно.) Имя операции tf.data. |
| Атрибуты | |
|---|---|
element_spec | Спецификация типа элемента этого набора данных.
dataset = tf.data.Dataset.from_tensor_slices([1, 2, 3]) dataset.element_spec TensorSpec(shape=(), dtype=tf.int32, name=None) Подробнее см. в этом руководстве. |
Методы
apply
apply(
transformation_func
) -> 'DatasetV2'
Применяет функцию преобразования к этому набору данных.
apply позволяет объединять в цепочку пользовательские преобразования Dataset, представленные функциями, которые принимают один аргумент Dataset и возвращают преобразованный Dataset.
dataset = tf.data.Dataset.range(100) def dataset_fn(ds): return ds.filter(lambda x: x < 5) dataset = dataset.apply(dataset_fn) list(dataset.as_numpy_iterator()) [0, 1, 2, 3, 4]
| Аргументы | |
|---|---|
transformation_func | Функция, которая принимает один аргумент Dataset и возвращает Dataset. |
| Возвращает | |
|---|---|
Новый Dataset с примененным описанным выше преобразованием. |
as_numpy_iterator
as_numpy_iterator()
Возвращает итератор, преобразующий все элементы набора данных в массивы NumPy.
Используйте as_numpy_iterator для изучения содержимого набора данных. Чтобы увидеть формы и типы элементов, выводите элементы набора данных напрямую, а не используйте as_numpy_iterator.
dataset = tf.data.Dataset.from_tensor_slices([1, 2, 3]) for element in dataset: print(element) tf.Tensor(1, shape=(), dtype=int32) tf.Tensor(2, shape=(), dtype=int32) tf.Tensor(3, shape=(), dtype=int32)
Для работы этого метода необходимо использовать eager-режим, а element_spec набора данных должен содержать только компоненты TensorSpec.
dataset = tf.data.Dataset.from_tensor_slices([1, 2, 3]) for element in dataset.as_numpy_iterator(): print(element) 1 2 3
dataset = tf.data.Dataset.from_tensor_slices([1, 2, 3]) print(list(dataset.as_numpy_iterator())) [1, 2, 3]
as_numpy_iterator() сохраняет вложенную структуру элементов набора данных.
dataset = tf.data.Dataset.from_tensor_slices({'a': ([1, 2], [3, 4]),
'b': [5, 6]})
list(dataset.as_numpy_iterator()) == [{'a': (1, 3), 'b': 5},
{'a': (2, 4), 'b': 6}]
True| Возвращает | |
|---|---|
| Итерируемый объект с элементами набора данных, в котором тензоры преобразованы в массивы NumPy. |
| Вызывает исключение | |
|---|---|
TypeError | если элемент содержит значение, не являющееся Tensor. |
RuntimeError | если eager-выполнение не включено. |
batch
batch(
batch_size,
drop_remainder=False,
num_parallel_calls=None,
deterministic=None,
name=None
) -> 'DatasetV2'
Объединяет последовательные элементы этого набора данных в пакеты.
dataset = tf.data.Dataset.range(8) dataset = dataset.batch(3) list(dataset.as_numpy_iterator()) [array([0, 1, 2]), array([3, 4, 5]), array([6, 7])]
dataset = tf.data.Dataset.range(8) dataset = dataset.batch(3, drop_remainder=True) list(dataset.as_numpy_iterator()) [array([0, 1, 2]), array([3, 4, 5])]
Компоненты результирующего элемента будут иметь дополнительное внешнее измерение размером batch_size (или N % batch_size для последнего элемента, если batch_size не делит количество входных элементов N нацело и drop_remainder равно False). Если программа предполагает, что внешнее измерение пакетов имеет одинаковый размер, задайте для аргумента drop_remainder значение True, чтобы не создавать пакет меньшего размера.
Примечание: Если для программы требуются данные со статически известной формой (например, при использовании XLA), используйтеdrop_remainder=True. Безdrop_remainder=Trueформа выходного набора данных будет иметь неизвестное начальное измерение из-за возможности создания последнего пакета меньшего размера.
| Аргументы | |
|---|---|
batch_size | Скалярный tf.int64 tf.Tensor, задающий количество последовательных элементов этого набора данных для объединения в один пакет. |
drop_remainder | (Необязательно.) Скалярный tf.bool tf.Tensor, указывающий, нужно ли отбросить последний пакет, если в нем меньше batch_size элементов; по умолчанию пакет меньшего размера не отбрасывается. |
num_parallel_calls | (Необязательно.) Скалярный tf.int64 tf.Tensor, задающий количество пакетов, вычисляемых асинхронно параллельно. Если значение не указано, пакеты вычисляются последовательно. Если используется значение tf.data.AUTOTUNE, количество параллельных вызовов динамически определяется на основе доступных ресурсов. |
deterministic | (Необязательно.) Если задан параметр num_parallel_calls и указано это логическое значение (True или False), оно определяет порядок, в котором преобразование создает элементы. Если задано значение False, преобразование может выдавать элементы не по порядку, обменивая детерминированность на производительность. Если значение не указано, поведение определяется параметром tf.data.Options.deterministic (по умолчанию — True). |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Новый Dataset с примененным описанным выше преобразованием. |
bucket_by_sequence_length
bucket_by_sequence_length(
element_length_func,
bucket_boundaries,
bucket_batch_sizes,
padded_shapes=None,
padding_values=None,
pad_to_bucket_boundary=False,
no_padding=False,
drop_remainder=False,
name=None
) -> 'DatasetV2'
Преобразование, группирующее элементы Dataset по длине.
Элементы Dataset группируются по длине, после чего дополняются и объединяются в пакеты.
Это полезно для задач с последовательностями переменной длины. Группировка элементов схожей длины уменьшает общую долю дополнения в пакете, повышая эффективность шага обучения.
Ниже приведен пример распределения входных данных по 3 корзинам «[0, 3), [3, 5), [5, inf)» в зависимости от длины последовательности, с размером пакета 2.
elements = [
[0], [1, 2, 3, 4], [5, 6, 7],
[7, 8, 9, 10, 11], [13, 14, 15, 16, 19, 20], [21, 22]]
dataset = tf.data.Dataset.from_generator(
lambda: elements, tf.int64, output_shapes=[None])
dataset = dataset.bucket_by_sequence_length(
element_length_func=lambda elem: tf.shape(elem)[0],
bucket_boundaries=[3, 5],
bucket_batch_sizes=[2, 2, 2])
for elem in dataset.as_numpy_iterator():
print(elem)
[[1 2 3 4]
[5 6 7 0]]
[[ 7 8 9 10 11 0]
[13 14 15 16 19 20]]
[[ 0 0]
[21 22]]| Аргументы | |
|---|---|
element_length_func | Функция, преобразующая элемент Dataset в tf.int32; определяет длину элемента, по которой выбирается корзина. |
bucket_boundaries | list<int> — верхние границы длины корзин. |
bucket_batch_sizes | list<int> — размер пакета для каждой корзины. Длина должна быть len(bucket_boundaries) + 1. |
padded_shapes | Вложенная структура tf.TensorShape, передаваемая в tf.data.Dataset.padded_batch. Если не указана, используется dataset.output_shapes, в результате чего измерения переменной длины дополняются до максимальной длины в каждом пакете. |
padding_values | Значения для дополнения, передаваемые в tf.data.Dataset.padded_batch. По умолчанию дополнение выполняется нулями. |
pad_to_bucket_boundary | Логическое значение: если False, измерения неизвестного размера дополняются до максимальной длины в пакете. Если True, измерения неизвестного размера дополняются до границы корзины минус 1 (то есть до максимальной длины в каждой корзине), и вызывающий код должен гарантировать, что исходный Dataset не содержит элементов длиной больше max(bucket_boundaries). |
no_padding | bool — указывает, нужно ли дополнять признаки пакета (признаки должны иметь тип tf.sparse.SparseTensor или одинаковую форму). |
drop_remainder | (Необязательно.) Скалярный tf.bool tf.Tensor, указывающий, нужно ли отбросить последний пакет, если в нем меньше batch_size элементов; по умолчанию пакет меньшего размера не отбрасывается. |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Новый Dataset с примененным описанным выше преобразованием. |
| Вызывает исключение | |
|---|---|
ValueError | если len(bucket_batch_sizes) != len(bucket_boundaries) + 1. |
cache
cache(
filename='', name=None
) -> 'DatasetV2'
Кэширует элементы этого набора данных.
При первой итерации по набору данных его элементы кэшируются в указанном файле или в памяти. При последующих итерациях используются кэшированные данные.
Примечание: Чтобы гарантировать завершение создания кэша, необходимо полностью пройти входной набор данных, пока не будет вызвано исключение StopIteration. В противном случае при последующих итерациях кэшированные данные могут не использоваться.
dataset = tf.data.Dataset.range(5) dataset = dataset.map(lambda x: x**2) dataset = dataset.cache() # The first time reading through the data will generate the data using # `range` and `map`. list(dataset.as_numpy_iterator()) [0, 1, 4, 9, 16] # Subsequent iterations read from the cache. list(dataset.as_numpy_iterator()) [0, 1, 4, 9, 16]
При кэшировании в файл данные сохраняются между запусками. Даже первая итерация по данным будет считывать их из файла кэша. Изменение входного конвейера перед вызовом .cache() не даст эффекта, пока файл кэша не будет удален или не будет изменено его имя.
dataset = tf.data.Dataset.range(5)
dataset = dataset.cache("/path/to/file")
list(dataset.as_numpy_iterator())
# [0, 1, 2, 3, 4]
dataset = tf.data.Dataset.range(10)
dataset = dataset.cache("/path/to/file") # Same file!
list(dataset.as_numpy_iterator())
# [0, 1, 2, 3, 4]
Примечание:cacheбудет создавать в точности одни и те же элементы при каждой итерации по набору данных. Чтобы рандомизировать порядок итерации, вызывайтеshuffleпосле вызоваcache.
| Аргументы | |
|---|---|
filename | Скалярный tf.string tf.Tensor, задающий имя каталога в файловой системе, который будет использоваться для кэширования элементов этого набора данных. Если имя файла не указано, набор данных будет кэшироваться в памяти. |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Новый Dataset с примененным описанным выше преобразованием. |
cardinality
cardinality()
Возвращает мощность набора данных, если она известна.
cardinality может возвращать tf.data.INFINITE_CARDINALITY, если набор данных содержит бесконечное количество элементов, или tf.data.UNKNOWN_CARDINALITY, если анализу не удалось определить количество элементов в наборе данных (например, когда источником набора данных является файл).
dataset = tf.data.Dataset.range(42) print(dataset.cardinality().numpy()) 42 dataset = dataset.repeat() cardinality = dataset.cardinality() print((cardinality == tf.data.INFINITE_CARDINALITY).numpy()) True dataset = dataset.filter(lambda x: True) cardinality = dataset.cardinality() print((cardinality == tf.data.UNKNOWN_CARDINALITY).numpy()) True
| Возвращает | |
|---|---|
Скалярный tf.int64 Tensor, представляющий мощность набора данных. Если мощность бесконечна или неизвестна, cardinality возвращает именованные константы tf.data.INFINITE_CARDINALITY и tf.data.UNKNOWN_CARDINALITY соответственно. |
choose_from_datasets
@staticmethod
choose_from_datasets(
datasets, choice_dataset, stop_on_empty_dataset=True
) -> 'DatasetV2'
Создает набор данных, детерминированно выбирающий элементы из datasets.
Например, для следующих наборов данных:
datasets = [tf.data.Dataset.from_tensors("foo").repeat(),
tf.data.Dataset.from_tensors("bar").repeat(),
tf.data.Dataset.from_tensors("baz").repeat()]
# Define a dataset containing `[0, 1, 2, 0, 1, 2, 0, 1, 2]`.
choice_dataset = tf.data.Dataset.range(3).repeat(3)
result = tf.data.Dataset.choose_from_datasets(datasets, choice_dataset)
Элементами result будут:
"foo", "bar", "baz", "foo", "bar", "baz", "foo", "bar", "baz"
| Аргументы | |
|---|---|
datasets | Непустой список объектов tf.data.Dataset с совместимой структурой. |
choice_dataset | tf.data.Dataset из скалярных тензоров tf.int64 со значениями от 0 до len(datasets) - 1. |
stop_on_empty_dataset | Если True, выбор прекращается при обнаружении пустого набора данных. Если False, пустые наборы данных пропускаются. Рекомендуется задавать значение True. В противном случае сначала выбранные элементы будут соответствовать ожиданиям пользователя, но могут измениться, когда входные наборы данных опустеют. Это может быть трудно заметить, поскольку изначально набор данных выглядит правильно. По умолчанию — True. |
| Возвращает | |
|---|---|
Новый Dataset с примененным описанным выше преобразованием. |
| Вызывает исключение | |
|---|---|
TypeError | Если datasets или choice_dataset имеет неправильный тип. |
ValueError | Если datasets пуст. |
concatenate
concatenate(
dataset, name=None
) -> 'DatasetV2'
Создает Dataset, добавляя указанный набор данных к этому набору данных.
a = tf.data.Dataset.range(1, 4) # ==> [ 1, 2, 3 ] b = tf.data.Dataset.range(4, 8) # ==> [ 4, 5, 6, 7 ] ds = a.concatenate(b) list(ds.as_numpy_iterator()) [1, 2, 3, 4, 5, 6, 7] # The input dataset and dataset to be concatenated should have # compatible element specs. c = tf.data.Dataset.zip((a, b)) a.concatenate(c) Traceback (most recent call last): TypeError: Two datasets to concatenate have different types <dtype: 'int64'> and (tf.int64, tf.int64) d = tf.data.Dataset.from_tensor_slices(["a", "b", "c"]) a.concatenate(d) Traceback (most recent call last): TypeError: Two datasets to concatenate have different types <dtype: 'int64'> and <dtype: 'string'>
| Аргументы | |
|---|---|
dataset | Dataset для объединения. |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Новый Dataset с примененным описанным выше преобразованием. |
counter
@staticmethod
counter(
start=0,
step=1,
dtype=tf.dtypes.int64,
name=None
) -> 'DatasetV2'
Создает Dataset, который считает от start с шагом step.
В отличие от tf.data.Dataset.range, который останавливается на заданном конечном значении, tf.data.Dataset.counter бесконечно выдает элементы.
dataset = tf.data.experimental.Counter().take(5) list(dataset.as_numpy_iterator()) [0, 1, 2, 3, 4] dataset.element_spec TensorSpec(shape=(), dtype=tf.int64, name=None) dataset = tf.data.experimental.Counter(dtype=tf.int32) dataset.element_spec TensorSpec(shape=(), dtype=tf.int32, name=None) dataset = tf.data.experimental.Counter(start=2).take(5) list(dataset.as_numpy_iterator()) [2, 3, 4, 5, 6] dataset = tf.data.experimental.Counter(start=2, step=5).take(5) list(dataset.as_numpy_iterator()) [2, 7, 12, 17, 22] dataset = tf.data.experimental.Counter(start=10, step=-1).take(5) list(dataset.as_numpy_iterator()) [10, 9, 8, 7, 6]
| Аргументы | |
|---|---|
start | (Необязательно.) Начальное значение счетчика. По умолчанию — 0. |
step | (Необязательно.) Шаг счетчика. По умолчанию — 1. |
dtype | (Необязательно.) Тип данных элементов счетчика. По умолчанию — tf.int64. |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Dataset из скалярных элементов dtype. |
enumerate
enumerate(
start=0, name=None
) -> 'DatasetV2'
Добавляет нумерацию к элементам этого набора данных.
Этот метод похож на enumerate в Python.
dataset = tf.data.Dataset.from_tensor_slices([1, 2, 3]) dataset = dataset.enumerate(start=5) for element in dataset.as_numpy_iterator(): print(element) (5, 1) (6, 2) (7, 3)
# The (nested) structure of the input dataset determines the # structure of elements in the resulting dataset. dataset = tf.data.Dataset.from_tensor_slices([(7, 8), (9, 10)]) dataset = dataset.enumerate() for element in dataset.as_numpy_iterator(): print(element) (0, array([7, 8], dtype=int32)) (1, array([ 9, 10], dtype=int32))
| Аргументы | |
|---|---|
start | Скалярный tf.int64 tf.Tensor, задающий начальное значение нумерации. |
name | Необязательно. Имя операций tf.data, используемых enumerate. |
| Возвращает | |
|---|---|
Новый Dataset с примененным описанным выше преобразованием. |
filter
filter(
predicate, name=None
) -> 'DatasetV2'
Фильтрует этот набор данных согласно predicate.
dataset = tf.data.Dataset.from_tensor_slices([1, 2, 3]) dataset = dataset.filter(lambda x: x < 3) list(dataset.as_numpy_iterator()) [1, 2] # `tf.math.equal(x, y)` is required for equality comparison def filter_fn(x): return tf.math.equal(x, 1) dataset = dataset.filter(filter_fn) list(dataset.as_numpy_iterator()) [1]
| Аргументы | |
|---|---|
predicate | Функция, сопоставляющая элемент набора данных логическому значению. |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Новый Dataset с примененным описанным выше преобразованием. |
fingerprint
fingerprint()
Вычисляет отпечаток этого Dataset.
Если два набора данных имеют одинаковый отпечаток, гарантируется, что они будут создавать идентичные элементы, пока содержимое исходных входных файлов не меняется и данные создаются детерминированно.
Однако одинаковые значения, создаваемые двумя наборами данных, не всегда означают, что у них будет одинаковый отпечаток из-за различий в структуре графа.
Иными словами, два набора данных с разными отпечатками все еще могут создавать одинаковые значения.
| Возвращает | |
|---|---|
Скалярный tf.Tensor типа tf.uint64. |
flat_map
flat_map(
map_func, name=None
) -> 'DatasetV2'
Применяет map_func к этому набору данных и уплощает результат.
Сигнатура типа:
def flat_map( self: Dataset[T], map_func: Callable[[T], Dataset[S]] ) -> Dataset[S]
Используйте flat_map, если необходимо сохранить порядок элементов набора данных. Например, чтобы преобразовать набор пакетов в набор отдельных элементов:
dataset = tf.data.Dataset.from_tensor_slices(
[[1, 2, 3], [4, 5, 6], [7, 8, 9]])
dataset = dataset.flat_map(tf.data.Dataset.from_tensor_slices)
list(dataset.as_numpy_iterator())
[1, 2, 3, 4, 5, 6, 7, 8, 9]tf.data.Dataset.interleave() — обобщение flat_map, поскольку flat_map создает тот же результат, что и tf.data.Dataset.interleave(cycle_length=1)
| Аргументы | |
|---|---|
map_func | Функция, преобразующая элемент набора данных в набор данных. |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Новый Dataset с примененным описанным выше преобразованием. |
from_generator
@staticmethod
from_generator(
generator,
output_types=None,
output_shapes=None,
args=None,
output_signature=None,
name=None
) -> 'DatasetV2'
Создает Dataset, элементы которого генерируются с помощью generator. (устаревшие аргументы)
Примечание: Текущая реализацияDataset.from_generator()используетtf.numpy_functionи имеет те же ограничения. В частности, операции, связанные с набором данных и итератором, должны выполняться на устройстве в том же процессе, что и программа Python, вызвавшаяDataset.from_generator(). В частности, использованиеfrom_generatorисключает возможность применения tf.data service для масштабирования обработки наборов данных. Телоgeneratorне будет сериализовано вGraphDef, поэтому не следует использовать этот метод, если необходимо сериализовать модель и восстановить ее в другой среде.
Аргумент generator должен быть вызываемым объектом, который возвращает объект, поддерживающий протокол iter() (например, функцию-генератор).
Элементы, генерируемые generator, должны быть совместимы с заданным аргументом output_signature либо с заданными аргументами output_types и (необязательно) output_shapes — в зависимости от того, какие из них были указаны.
Рекомендуемый способ вызова from_generator — использовать аргумент output_signature. В этом случае предполагается, что выходные данные состоят из объектов с классами, формами и типами, заданными объектами tf.TypeSpec из аргумента output_signature:
def gen():
ragged_tensor = tf.ragged.constant([[1, 2], [3]])
yield 42, ragged_tensor
dataset = tf.data.Dataset.from_generator(
gen,
output_signature=(
tf.TensorSpec(shape=(), dtype=tf.int32),
tf.RaggedTensorSpec(shape=(2, None), dtype=tf.int32)))
list(dataset.take(1))
[(<tf.Tensor: shape=(), dtype=int32, numpy=42>,
<tf.RaggedTensor [[1, 2], [3]]>)]Также существует устаревший способ вызова from_generator: только с аргументом output_types либо вместе с аргументом output_shapes. В этом случае предполагается, что выходные данные функции состоят из объектов tf.Tensor с типами, заданными output_types, и формами, которые либо не заданы, либо определены output_shapes.
Примечание: Еслиgeneratorзависит от изменяемых глобальных переменных или другого внешнего состояния, имейте в виду, что среда выполнения может вызыватьgeneratorнесколько раз (для поддержки повторного выполненияDataset) и в любой момент между вызовомDataset.from_generator()и получением первого элемента из генератора. Изменение глобальных переменных или внешнего состояния может привести к неопределенному поведению. Рекомендуем явно кэшировать любое внешнее состояние вgeneratorдо вызоваDataset.from_generator().
Примечание: Хотя параметрoutput_signatureпозволяет выдавать элементыDataset, область примененияDataset.from_generator()следует ограничить логикой, которую нельзя выразить с помощью операций tf.data. Использование операций tf.data внутри функции-генератора считается антипаттерном и может привести к постепенному увеличению потребления памяти.
| Аргументы | |
|---|---|
generator | Вызываемый объект, возвращающий объект, который поддерживает протокол iter(). Если args не указан, generator не должен принимать аргументов; в противном случае он должен принимать столько аргументов, сколько значений содержится в args. |
output_types | (Необязательно.) (Вложенная) структура объектов tf.DType, соответствующих каждому компоненту элемента, выдаваемого generator. |
output_shapes | (Необязательно.) (Вложенная) структура объектов tf.TensorShape, соответствующих каждому компоненту элемента, выдаваемого generator. |
args | (Необязательно.) Кортеж объектов tf.Tensor, которые будут вычислены и переданы в generator в качестве аргументов-массивов NumPy. |
output_signature | (Необязательно.) (Вложенная) структура объектов tf.TypeSpec, соответствующих каждому компоненту элемента, выдаваемого generator. |
name | (Необязательно.) Имя операций tf.data, используемых from_generator. |
| Возвращает | |
|---|---|
Dataset | Dataset. |
from_tensor_slices
@staticmethod
from_tensor_slices(
tensors, name=None
) -> 'DatasetV2'
Создает Dataset, элементы которого являются срезами заданных тензоров.
Заданные тензоры разбиваются вдоль первого измерения. Эта операция сохраняет структуру входных тензоров, удаляя первое измерение каждого тензора и используя его в качестве измерения набора данных. Все входные тензоры должны иметь одинаковый размер по первому измерению.
# Slicing a 1D tensor produces scalar tensor elements. dataset = tf.data.Dataset.from_tensor_slices([1, 2, 3]) list(dataset.as_numpy_iterator()) [1, 2, 3]
# Slicing a 2D tensor produces 1D tensor elements. dataset = tf.data.Dataset.from_tensor_slices([[1, 2], [3, 4]]) list(dataset.as_numpy_iterator()) [array([1, 2], dtype=int32), array([3, 4], dtype=int32)]
# Slicing a tuple of 1D tensors produces tuple elements containing # scalar tensors. dataset = tf.data.Dataset.from_tensor_slices(([1, 2], [3, 4], [5, 6])) list(dataset.as_numpy_iterator()) [(1, 3, 5), (2, 4, 6)]
# Dictionary structure is also preserved.
dataset = tf.data.Dataset.from_tensor_slices({"a": [1, 2], "b": [3, 4]})
list(dataset.as_numpy_iterator()) == [{'a': 1, 'b': 3},
{'a': 2, 'b': 4}]
True# Two tensors can be combined into one Dataset object.
features = tf.constant([[1, 3], [2, 1], [3, 3]]) # ==> 3x2 tensor
labels = tf.constant(['A', 'B', 'A']) # ==> 3x1 tensor
dataset = Dataset.from_tensor_slices((features, labels))
# Both the features and the labels tensors can be converted
# to a Dataset object separately and combined after.
features_dataset = Dataset.from_tensor_slices(features)
labels_dataset = Dataset.from_tensor_slices(labels)
dataset = Dataset.zip((features_dataset, labels_dataset))
# A batched feature and label set can be converted to a Dataset
# in similar fashion.
batched_features = tf.constant([[[1, 3], [2, 3]],
[[2, 1], [1, 2]],
[[3, 3], [3, 2]]], shape=(3, 2, 2))
batched_labels = tf.constant([['A', 'A'],
['B', 'B'],
['A', 'B']], shape=(3, 2, 1))
dataset = Dataset.from_tensor_slices((batched_features, batched_labels))
for element in dataset.as_numpy_iterator():
print(element)
(array([[1, 3],
[2, 3]], dtype=int32), array([[b'A'],
[b'A']], dtype=object))
(array([[2, 1],
[1, 2]], dtype=int32), array([[b'B'],
[b'B']], dtype=object))
(array([[3, 3],
[3, 2]], dtype=int32), array([[b'A'],
[b'B']], dtype=object))Обратите внимание: если tensors содержит массив NumPy и eager execution не включен, значения будут встроены в граф в виде одной или нескольких операций tf.constant. Для больших наборов данных (> 1 GB) это может приводить к неэффективному расходу памяти и превышению ограничений на размер сериализуемого графа в байтах. Если tensors содержит один или несколько больших массивов NumPy, рассмотрите альтернативу, описанную в этом руководстве.
| Аргументы | |
|---|---|
tensors | Элемент набора данных, компоненты которого имеют одинаковое первое измерение. Поддерживаемые значения описаны здесь. |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Dataset | Dataset. |
from_tensors
@staticmethod
from_tensors(
tensors, name=None
) -> 'DatasetV2'
Создает Dataset с одним элементом, состоящим из заданных тензоров.
from_tensors создает набор данных, содержащий только один элемент. Чтобы разбить входной тензор на несколько элементов, используйте вместо этого from_tensor_slices.
dataset = tf.data.Dataset.from_tensors([1, 2, 3]) list(dataset.as_numpy_iterator()) [array([1, 2, 3], dtype=int32)] dataset = tf.data.Dataset.from_tensors(([1, 2, 3], 'A')) list(dataset.as_numpy_iterator()) [(array([1, 2, 3], dtype=int32), b'A')]
# You can use `from_tensors` to produce a dataset which repeats # the same example many times. example = tf.constant([1,2,3]) dataset = tf.data.Dataset.from_tensors(example).repeat(2) list(dataset.as_numpy_iterator()) [array([1, 2, 3], dtype=int32), array([1, 2, 3], dtype=int32)]
Обратите внимание: если tensors содержит массив NumPy и eager execution не включен, значения будут встроены в граф в виде одной или нескольких операций tf.constant. Для больших наборов данных (> 1 GB) это может приводить к неэффективному расходу памяти и превышению ограничений на размер сериализуемого графа в байтах. Если tensors содержит один или несколько больших массивов NumPy, рассмотрите альтернативу, описанную в этом руководстве.
| Аргументы | |
|---|---|
tensors | «Элемент» набора данных. Поддерживаемые значения описаны здесь. |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Dataset | Dataset. |
get_single_element
get_single_element(
name=None
)
Возвращает единственный элемент dataset.
Эта функция позволяет использовать tf.data.Dataset в выражении без состояния «тензор на входе — тензор на выходе», не создавая итератор. Это упрощает преобразование данных в тензорах с помощью оптимизированной абстракции tf.data.Dataset, построенной поверх них.
Например, рассмотрим preprocessing_fn, который принимает необработанные признаки и возвращает обработанный признак вместе с его меткой.
def preprocessing_fn(raw_feature):
# ... the raw_feature is preprocessed as per the use-case
return feature
raw_features = ... # input batch of BATCH_SIZE elements.
dataset = (tf.data.Dataset.from_tensor_slices(raw_features)
.map(preprocessing_fn, num_parallel_calls=BATCH_SIZE)
.batch(BATCH_SIZE))
processed_features = dataset.get_single_element()
В приведенном выше примере тензор raw_features длины BATCH_SIZE преобразуется в tf.data.Dataset. Затем каждый из raw_feature обрабатывается с помощью preprocessing_fn, а обработанные признаки группируются в один пакет. Итоговый dataset содержит только один элемент — пакет со всеми обработанными признаками.
Примечание: dataset должен содержать только один элемент.
Теперь вместо создания итератора для dataset и получения пакета признаков используется функция tf.data.get_single_element(), которая позволяет пропустить создание итератора и напрямую вывести пакет признаков.
Это может быть особенно полезно, если преобразования тензоров выражены в виде операций tf.data.Dataset и вы хотите использовать их при обслуживании модели.
Keras
model = ... # A pre-built or custom model
class PreprocessingModel(tf.keras.Model):
def __init__(self, model):
super().__init__(self)
self.model = model
@tf.function(input_signature=[...])
def serving_fn(self, data):
ds = tf.data.Dataset.from_tensor_slices(data)
ds = ds.map(preprocessing_fn, num_parallel_calls=BATCH_SIZE)
ds = ds.batch(batch_size=BATCH_SIZE)
return tf.argmax(self.model(ds.get_single_element()), axis=-1)
preprocessing_model = PreprocessingModel(model)
your_exported_model_dir = ... # save the model to this path.
tf.saved_model.save(preprocessing_model, your_exported_model_dir,
signatures={'serving_default': preprocessing_model.serving_fn}
)
| Аргументы | |
|---|---|
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Вложенная структура объектов tf.Tensor, соответствующая единственному элементу dataset. |
| Вызывает исключение | |
|---|---|
InvalidArgumentError | (во время выполнения), если dataset содержит не ровно один элемент. |
group_by_window
group_by_window(
key_func, reduce_func, window_size=None, window_size_func=None, name=None
) -> 'DatasetV2'
Группирует окна элементов по ключу и сокращает их.
Это преобразование сопоставляет каждому элементу набора данных ключ с помощью key_func и группирует элементы по ключу. Затем оно применяет reduce_func не более чем к window_size_func(key) элементам, соответствующим одному ключу. Все окна, кроме последнего для каждого ключа, содержат window_size_func(key) элементов; последнее окно может быть меньше.
Можно указать постоянное значение window_size или размер окна, определяемый ключом с помощью window_size_func.
dataset = tf.data.Dataset.range(10)
window_size = 5
key_func = lambda x: x%2
reduce_func = lambda key, dataset: dataset.batch(window_size)
dataset = dataset.group_by_window(
key_func=key_func,
reduce_func=reduce_func,
window_size=window_size)
for elem in dataset.as_numpy_iterator():
print(elem)
[0 2 4 6 8]
[1 3 5 7 9]| Аргументы | |
|---|---|
key_func | Функция, преобразующая вложенную структуру тензоров (с формами и типами, заданными self.output_shapes и self.output_types) в скалярный тензор tf.int64. |
reduce_func | Функция, преобразующая ключ и набор данных, содержащий до window_size последовательных элементов с этим ключом, в другой набор данных. |
window_size | Скалярный тензор tf.Tensor типа tf.int64, задающий число последовательных элементов с одним и тем же ключом, объединяемых в один пакет, который будет передан в reduce_func. Не может использоваться одновременно с window_size_func. |
window_size_func | Функция, преобразующая ключ в скалярный тензор tf.Tensor типа tf.int64, задающий число последовательных элементов с одним и тем же ключом, объединяемых в один пакет, который будет передан в reduce_func. Не может использоваться одновременно с window_size. |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Новый Dataset с преобразованием, примененным, как описано выше. |
| Вызывает исключение | |
|---|---|
ValueError | если передан ни один или оба аргумента из {window_size, window_size_func}. |
ignore_errors
ignore_errors(
log_warning=False, name=None
) -> 'DatasetV2'
Отбрасывает элементы, вызывающие ошибки.
dataset = tf.data.Dataset.from_tensor_slices([1., 2., 0., 4.]) dataset = dataset.map(lambda x: tf.debugging.check_numerics(1. / x, "")) list(dataset.as_numpy_iterator()) Traceback (most recent call last): InvalidArgumentError: ... Tensor had Inf values dataset = dataset.ignore_errors() list(dataset.as_numpy_iterator()) [1.0, 0.5, 0.25]
| Аргументы | |
|---|---|
log_warning | (Необязательно.) Логическое значение, указывающее, следует ли записывать сведения об игнорируемых ошибках в stderr. По умолчанию — False. |
name | (Необязательно.) Строка с именем операции tf.data. |
| Возвращает | |
|---|---|
Новый Dataset с преобразованием, примененным, как описано выше. |
interleave
interleave(
map_func,
cycle_length=None,
block_length=None,
num_parallel_calls=None,
deterministic=None,
name=None
) -> 'DatasetV2'
Применяет map_func к этому набору данных и чередует полученные результаты.
Сигнатура типа:
def interleave( self: Dataset[T], map_func: Callable[[T], Dataset[S]] ) -> Dataset[S]
Например, можно использовать Dataset.interleave() для параллельной обработки множества входных файлов:
# Preprocess 4 files concurrently, and interleave blocks of 16 records
# from each file.
filenames = ["/var/data/file1.txt", "/var/data/file2.txt",
"/var/data/file3.txt", "/var/data/file4.txt"]
dataset = tf.data.Dataset.from_tensor_slices(filenames)
def parse_fn(filename):
return tf.data.Dataset.range(10)
dataset = dataset.interleave(lambda x:
tf.data.TextLineDataset(x).map(parse_fn, num_parallel_calls=1),
cycle_length=4, block_length=16)Аргументы cycle_length и block_length определяют порядок выдачи элементов. cycle_length управляет количеством входных элементов, обрабатываемых одновременно. Если задать для cycle_length значение 1, это преобразование будет обрабатывать по одному входному элементу за раз и выдаст результаты, идентичные результатам tf.data.Dataset.flat_map. В общем случае это преобразование применяет map_func к cycle_length входным элементам, открывает итераторы для возвращенных объектов Dataset и циклически проходит по ним, выдавая block_length последовательных элементов из каждого итератора и обрабатывая следующий входной элемент при каждом достижении конца итератора.
Например:
dataset = Dataset.range(1, 6) # ==> [ 1, 2, 3, 4, 5 ]
# NOTE: New lines indicate "block" boundaries.
dataset = dataset.interleave(
lambda x: Dataset.from_tensors(x).repeat(6),
cycle_length=2, block_length=4)
list(dataset.as_numpy_iterator())
[1, 1, 1, 1,
2, 2, 2, 2,
1, 1,
2, 2,
3, 3, 3, 3,
4, 4, 4, 4,
3, 3,
4, 4,
5, 5, 5, 5,
5, 5]Примечание: Порядок элементов, выдаваемых этим преобразованием, детерминирован, еслиmap_funcявляется чистой функцией иdeterministic=True. Еслиmap_funcсодержит операции с состоянием, порядок доступа к этому состоянию не определен.
Производительность часто можно повысить, задав num_parallel_calls, чтобы interleave использовал несколько потоков для получения элементов. Если детерминированность не требуется, производительность также можно повысить, задав deterministic=False.
filenames = ["/var/data/file1.txt", "/var/data/file2.txt",
"/var/data/file3.txt", "/var/data/file4.txt"]
dataset = tf.data.Dataset.from_tensor_slices(filenames)
dataset = dataset.interleave(lambda x: tf.data.TFRecordDataset(x),
cycle_length=4, num_parallel_calls=tf.data.AUTOTUNE,
deterministic=False)| Аргументы | |
|---|---|
map_func | Функция, принимающая элемент набора данных и возвращающая tf.data.Dataset. |
cycle_length | (Необязательно.) Количество входных элементов, обрабатываемых одновременно. Если не задано, среда выполнения tf.data определяет его на основе доступных ресурсов ЦП. Если для num_parallel_calls задано значение tf.data.AUTOTUNE, аргумент cycle_length задает максимальный уровень параллелизма. |
block_length | (Необязательно.) Количество последовательных элементов, выдаваемых для каждого входного элемента до перехода к другому входному элементу. Если не задано, по умолчанию равно 1. |
num_parallel_calls | (Необязательно.) Если задано, реализация создает пул потоков, используемый для асинхронного и параллельного получения входных данных из элементов цикла. По умолчанию входные данные из элементов цикла получаются синхронно, без параллелизма. Если используется значение tf.data.AUTOTUNE, количество параллельных вызовов динамически определяется на основе доступных ресурсов ЦП. |
deterministic | (Необязательно.) Если задан num_parallel_calls, это логическое значение (True или False) управляет порядком выдачи элементов преобразованием. Если задано значение False, преобразованию разрешено выдавать элементы не по порядку, жертвуя детерминированностью ради производительности. Если значение не задано, поведение определяется параметром tf.data.Options.deterministic (по умолчанию — True). |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Новый Dataset с преобразованием, примененным, как описано выше. |
list_files
@staticmethod
list_files(
file_pattern, shuffle=None, seed=None, name=None
) -> 'DatasetV2'
Набор данных, состоящий из всех файлов, соответствующих одному или нескольким шаблонам glob.
Аргумент file_pattern должен содержать небольшое количество шаблонов glob. Если для имен файлов уже были применены шаблоны glob, используйте вместо этого Dataset.from_tensor_slices(filenames), поскольку повторное сопоставление каждого имени файла с шаблоном в list_files может привести к снижению производительности при работе с удаленными системами хранения.
Примечание: По умолчанию этот метод возвращает имена файлов в случайном порядке, который не является детерминированным. Передайтеseedилиshuffle=False, чтобы получить результат в детерминированном порядке.
| Пример | |
|---|---|
Допустим, в нашей файловой системе есть следующие файлы:
Если передать "/path/to/dir/*.py" в качестве каталога, набор данных выдаст:
|
| Аргументы | |
|---|---|
file_pattern | Строка, список строк или tf.Tensor строкового типа (скаляр или вектор), задающие шаблоны glob для имен файлов (то есть шаблоны подстановки оболочки), которым должны соответствовать файлы. |
shuffle | (Необязательно.) Если True, имена файлов будут перемешаны в случайном порядке. По умолчанию — True. |
seed | (Необязательно.) Скалярный тензор tf.Tensor типа tf.int64, задающий начальное значение генератора случайных чисел, используемое для создания распределения. Описание поведения см. в разделе tf.random.set_seed. |
name | Необязательно. Имя операций tf.data, используемых list_files. |
| Возвращает | |
|---|---|
Dataset | Dataset строк с именами файлов. |
load
@staticmethod
load(
path, element_spec=None, compression=None, reader_func=None
) -> 'DatasetV2'
Загружает ранее сохраненный набор данных.
Пример использования:
import tempfile path = os.path.join(tempfile.gettempdir(), "saved_data") # Save a dataset dataset = tf.data.Dataset.range(2) tf.data.Dataset.save(dataset, path) new_dataset = tf.data.Dataset.load(path) for elem in new_dataset: print(elem) tf.Tensor(0, shape=(), dtype=int64) tf.Tensor(1, shape=(), dtype=int64)
Если при сохранении набора данных использовалось стандартное разбиение на шарды, порядок элементов сохраненного набора данных будет сохранен при его загрузке.
Аргумент reader_func можно использовать, чтобы задать пользовательский порядок загрузки элементов из отдельных шардов. Предполагается, что reader_func принимает один аргумент — набор наборов данных, каждый из которых содержит элементы одного из шардов, — и возвращает набор элементов. Например, при загрузке порядок шардов можно перемешать следующим образом:
def custom_reader_func(datasets):
datasets = datasets.shuffle(NUM_SHARDS)
return datasets.interleave(lambda x: x, num_parallel_calls=AUTOTUNE)
dataset = tf.data.Dataset.load(
path="/path/to/data", ..., reader_func=custom_reader_func)
| Аргументы | |
|---|---|
path | Обязательный. Путь к ранее сохраненному набору данных. |
element_spec | Необязательный. Вложенная структура объектов tf.TypeSpec, соответствующая структуре элемента сохраненного набора данных и задающая тип отдельных компонентов элемента. Если не указана, используется вложенная структура tf.TypeSpec, сохраненная вместе с набором данных. Обратите внимание, что этот аргумент обязателен в режиме графа. |
compression | Необязательный. Алгоритм распаковки данных при чтении. Поддерживаемые варианты: GZIP и NONE. По умолчанию — NONE. |
reader_func | Необязательная. Функция, управляющая чтением данных из шардов. Если указана, функция будет трассирована и выполнена как вычисление графа. |
| Возвращает | |
|---|---|
Экземпляр tf.data.Dataset. |
| Вызывает исключение | |
|---|---|
FileNotFoundError | Если element_spec не указан и сохраненную вложенную структуру tf.TypeSpec невозможно найти вместе с сохраненным набором данных. |
ValueError | Если element_spec не указан, а метод выполняется в режиме графа. |
map
map(
map_func, num_parallel_calls=None, deterministic=None, name=None
)
Применяет map_func к элементам этого набора данных.
Это преобразование применяет map_func к каждому элементу набора данных и возвращает новый набор данных с преобразованными элементами в том же порядке, в котором они встречались во входных данных. map_func можно использовать для изменения значений и структуры элементов набора данных. Поддерживаемые конструкции структуры описаны здесь.
Например, map можно использовать, чтобы прибавить 1 к каждому элементу или выбрать подмножество компонентов элемента.
dataset = Dataset.range(1, 6) # ==> [ 1, 2, 3, 4, 5 ] dataset = dataset.map(lambda x: x + 1) list(dataset.as_numpy_iterator()) [2, 3, 4, 5, 6]
Сигнатура входных данных map_func определяется структурой каждого элемента этого набора данных.
dataset = Dataset.range(5) # `map_func` takes a single argument of type `tf.Tensor` with the same # shape and dtype. result = dataset.map(lambda x: x + 1)
# Each element is a tuple containing two `tf.Tensor` objects.
elements = [(1, "foo"), (2, "bar"), (3, "baz")]
dataset = tf.data.Dataset.from_generator(
lambda: elements, (tf.int32, tf.string))
# `map_func` takes two arguments of type `tf.Tensor`. This function
# projects out just the first component.
result = dataset.map(lambda x_int, y_str: x_int)
list(result.as_numpy_iterator())
[1, 2, 3]# Each element is a dictionary mapping strings to `tf.Tensor` objects.
elements = ([{"a": 1, "b": "foo"},
{"a": 2, "b": "bar"},
{"a": 3, "b": "baz"}])
dataset = tf.data.Dataset.from_generator(
lambda: elements, {"a": tf.int32, "b": tf.string})
# `map_func` takes a single argument of type `dict` with the same keys
# as the elements.
result = dataset.map(lambda d: str(d["a"]) + d["b"])Значение или значения, возвращаемые map_func, определяют структуру каждого элемента возвращаемого набора данных.
dataset = tf.data.Dataset.range(3) # `map_func` returns two `tf.Tensor` objects. def g(x): return tf.constant(37.0), tf.constant(["Foo", "Bar", "Baz"]) result = dataset.map(g) result.element_spec (TensorSpec(shape=(), dtype=tf.float32, name=None), TensorSpec(shape=(3,), dtype=tf.string, name=None)) # Python primitives, lists, and NumPy arrays are implicitly converted to # `tf.Tensor`. def h(x): return 37.0, ["Foo", "Bar"], np.array([1.0, 2.0], dtype=np.float64) result = dataset.map(h) result.element_spec (TensorSpec(shape=(), dtype=tf.float32, name=None), TensorSpec(shape=(2,), dtype=tf.string, name=None), TensorSpec(shape=(2,), dtype=tf.float64, name=None)) # `map_func` can return nested structures. def i(x): return (37.0, [42, 16]), "foo" result = dataset.map(i) result.element_spec ((TensorSpec(shape=(), dtype=tf.float32, name=None), TensorSpec(shape=(2,), dtype=tf.int32, name=None)), TensorSpec(shape=(), dtype=tf.string, name=None))
map_func может принимать в качестве аргументов и возвращать любой тип элемента набора данных.
Обратите внимание: независимо от контекста, в котором определена map_func (eager execution или граф), tf.data трассирует функцию и выполняет ее как граф. Для использования кода Python внутри функции есть несколько вариантов:
1) Положиться на AutoGraph, чтобы преобразовать код Python в эквивалентное вычисление графа. Недостаток этого подхода в том, что AutoGraph может преобразовать не весь код Python.
2) Использовать tf.py_function, позволяющую писать произвольный код Python, но обычно обеспечивающую более низкую производительность, чем вариант 1). Например:
d = tf.data.Dataset.from_tensor_slices(['hello', 'world'])
# transform a string tensor to upper case string using a Python function
def upper_case_fn(t: tf.Tensor):
return t.numpy().decode('utf-8').upper()
d = d.map(lambda x: tf.py_function(func=upper_case_fn,
inp=[x], Tout=tf.string))
list(d.as_numpy_iterator())
[b'HELLO', b'WORLD']3) Использовать tf.numpy_function, которая также позволяет писать произвольный код Python. Обратите внимание: tf.py_function принимает объекты tf.Tensor, тогда как tf.numpy_function принимает массивы NumPy и возвращает только массивы NumPy. Например:
d = tf.data.Dataset.from_tensor_slices(['hello', 'world'])
def upper_case_fn(t: np.ndarray):
return t.decode('utf-8').upper()
d = d.map(lambda x: tf.numpy_function(func=upper_case_fn,
inp=[x], Tout=tf.string))
list(d.as_numpy_iterator())
[b'HELLO', b'WORLD']Обратите внимание: использование tf.numpy_function и tf.py_function в целом исключает возможность выполнения пользовательских преобразований параллельно (из-за GIL Python).
Производительность часто можно повысить, задав num_parallel_calls, чтобы map использовал несколько потоков для обработки элементов. Если детерминированный порядок не требуется, производительность также можно повысить, задав deterministic=False.
dataset = Dataset.range(1, 6) # ==> [ 1, 2, 3, 4, 5 ]
dataset = dataset.map(lambda x: x + 1,
num_parallel_calls=tf.data.AUTOTUNE,
deterministic=False)Порядок элементов, выдаваемых этим преобразованием, детерминирован, если deterministic=True. Если map_func содержит операции с состоянием и num_parallel_calls > 1, порядок доступа к этому состоянию не определен, поэтому значения выходных элементов могут быть недетерминированными независимо от значения флага deterministic.
| Аргументы | |
|---|---|
map_func | Функция, преобразующая элемент набора данных в другой элемент набора данных. |
num_parallel_calls | (Необязательно.) Скалярный tf.int64 tf.Tensor, задающий количество элементов, которые нужно обрабатывать асинхронно параллельно. Если не указано, элементы обрабатываются последовательно. Если используется значение tf.data.AUTOTUNE, количество параллельных вызовов динамически задаётся с учётом доступных ресурсов ЦП. |
deterministic | (Необязательно.) Если задан параметр num_parallel_calls, этот логический параметр (True или False) определяет порядок, в котором преобразование выдаёт элементы. Если задано значение False, преобразование может выдавать элементы не по порядку, обменивая детерминированность на производительность. Если параметр не указан, поведение определяется параметром tf.data.Options.deterministic (по умолчанию — True). |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Новый Dataset с преобразованием, применённым, как описано выше. |
options
options()
Возвращает параметры этого набора данных и его входных данных.
| Возвращает | |
|---|---|
Объект tf.data.Options, представляющий параметры набора данных. |
padded_batch
padded_batch(
batch_size,
padded_shapes=None,
padding_values=None,
drop_remainder=False,
name=None
) -> 'DatasetV2'
Объединяет последовательные элементы этого набора данных в дополненные пакеты.
Это преобразование объединяет несколько последовательных элементов входного набора данных в один элемент.
Как и в случае с tf.data.Dataset.batch, компоненты результирующего элемента получают дополнительное внешнее измерение, размер которого будет равен batch_size (или N % batch_size для последнего элемента, если batch_size не делит количество входных элементов N нацело и drop_remainder имеет значение False). Если программа предполагает, что внешнее измерение пакетов всегда имеет одинаковый размер, задайте аргумент drop_remainder равным True, чтобы не создавать пакет меньшего размера.
В отличие от tf.data.Dataset.batch, входные элементы, объединяемые в пакет, могут иметь разные формы, и это преобразование дополнит каждый компонент до соответствующей формы, заданной в padded_shapes. Аргумент padded_shapes определяет результирующую форму каждого измерения каждого компонента выходного элемента:
- Если размер измерения постоянен, компонент дополняется до этой длины в данном измерении.
- Если размер измерения неизвестен, компонент дополняется до максимальной длины этого измерения среди всех элементов.
A = (tf.data.Dataset
.range(1, 5, output_type=tf.int32)
.map(lambda x: tf.fill([x], x)))
# Pad to the smallest per-batch size that fits all elements.
B = A.padded_batch(2)
for element in B.as_numpy_iterator():
print(element)
[[1 0]
[2 2]]
[[3 3 3 0]
[4 4 4 4]]
# Pad to a fixed size.
C = A.padded_batch(2, padded_shapes=5)
for element in C.as_numpy_iterator():
print(element)
[[1 0 0 0 0]
[2 2 0 0 0]]
[[3 3 3 0 0]
[4 4 4 4 0]]
# Pad with a custom value.
D = A.padded_batch(2, padded_shapes=5, padding_values=-1)
for element in D.as_numpy_iterator():
print(element)
[[ 1 -1 -1 -1 -1]
[ 2 2 -1 -1 -1]]
[[ 3 3 3 -1 -1]
[ 4 4 4 4 -1]]
# Components of nested elements can be padded independently.
elements = [([1, 2, 3], [10]),
([4, 5], [11, 12])]
dataset = tf.data.Dataset.from_generator(
lambda: iter(elements), (tf.int32, tf.int32))
# Pad the first component of the tuple to length 4, and the second
# component to the smallest size that fits.
dataset = dataset.padded_batch(2,
padded_shapes=([4], [None]),
padding_values=(-1, 100))
list(dataset.as_numpy_iterator())
[(array([[ 1, 2, 3, -1], [ 4, 5, -1, -1]], dtype=int32),
array([[ 10, 100], [ 11, 12]], dtype=int32))]
# Pad with a single value and multiple components.
E = tf.data.Dataset.zip((A, A)).padded_batch(2, padding_values=-1)
for element in E.as_numpy_iterator():
print(element)
(array([[ 1, -1],
[ 2, 2]], dtype=int32), array([[ 1, -1],
[ 2, 2]], dtype=int32))
(array([[ 3, 3, 3, -1],
[ 4, 4, 4, 4]], dtype=int32), array([[ 3, 3, 3, -1],
[ 4, 4, 4, 4]], dtype=int32))См. также tf.data.experimental.dense_to_sparse_batch, которое объединяет элементы с различными формами в tf.sparse.SparseTensor.
| Аргументы | |
|---|---|
batch_size | Скалярный tf.int64 tf.Tensor, задающий количество последовательных элементов этого набора данных, объединяемых в один пакет. |
padded_shapes | (Необязательно.) (Вложенная) структура объектов, подобных векторным тензорам tf.TensorShape или tf.int64, задающая форму, до которой следует дополнить соответствующий компонент каждого входного элемента перед объединением в пакет. Все измерения неизвестного размера дополняются до максимального размера этого измерения в каждом пакете. Если не задано, все измерения всех компонентов дополняются до максимального размера в пакете. Параметр padded_shapes необходимо задать, если у какого-либо компонента неизвестный ранг. |
padding_values | (Необязательно.) (Вложенная) структура tf.Tensor скалярной формы, задающая значения дополнения для соответствующих компонентов. Значение None означает, что для дополнения (вложенной) структуры следует использовать значения по умолчанию. Для числовых типов по умолчанию используется 0, а для строковых — пустая строка. Параметр padding_values должен иметь ту же (вложенную) структуру, что и входной набор данных. Если padding_values содержит один элемент, а входной набор данных — несколько компонентов, для дополнения каждого компонента набора данных будет использоваться одно и то же значение padding_values. Если padding_values — скаляр, его значение будет транслировано до формы каждого компонента. |
drop_remainder | (Необязательно.) Скалярный tf.bool tf.Tensor, указывающий, следует ли отбрасывать последний пакет, если в нём меньше batch_size элементов; по умолчанию пакет меньшего размера не отбрасывается. |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Новый Dataset с преобразованием, применённым, как описано выше. |
| Вызывает исключение | |
|---|---|
ValueError | Если у компонента неизвестный ранг, а аргумент padded_shapes не задан. |
TypeError | Если компонент имеет неподдерживаемый тип. Список поддерживаемых типов приведён в документации по адресу https://www.tensorflow.org/guide/data#dataset_structure |
prefetch
prefetch(
buffer_size, name=None
) -> 'DatasetV2'
Создаёт Dataset, предварительно загружающий элементы из этого набора данных.
Большинство конвейеров ввода данных должны завершаться вызовом prefetch. Это позволяет подготавливать следующие элементы, пока обрабатывается текущий. Часто это повышает производительность и пропускную способность за счёт использования дополнительной памяти для хранения предварительно загруженных элементов.
Примечание: Как и другие методыDataset, prefetch работает с элементами входного набора данных. Он не различает отдельные примеры и пакеты.examples.prefetch(2)предварительно загрузит два элемента (2 примера), аexamples.batch(20).prefetch(2)— 2 элемента (2 пакета по 20 примеров в каждом).
dataset = tf.data.Dataset.range(3) dataset = dataset.prefetch(2) list(dataset.as_numpy_iterator()) [0, 1, 2]
| Аргументы | |
|---|---|
buffer_size | Скалярный tf.int64 tf.Tensor, задающий максимальное количество элементов, буферизуемых при предварительной загрузке. Если используется значение tf.data.AUTOTUNE, размер буфера настраивается динамически. |
name | Необязательно. Имя преобразования tf.data. |
| Возвращает | |
|---|---|
Новый Dataset с преобразованием, применённым, как описано выше. |
ragged_batch
ragged_batch(
batch_size,
drop_remainder=False,
row_splits_dtype=tf.dtypes.int64,
name=None
) -> 'DatasetV2'
Объединяет последовательные элементы этого набора данных в tf.RaggedTensor.
Как и в случае с tf.data.Dataset.batch, компоненты результирующего элемента получают дополнительное внешнее измерение, размер которого будет равен batch_size (или N % batch_size для последнего элемента, если batch_size не делит количество входных элементов N нацело и drop_remainder имеет значение False). Если программа предполагает, что внешнее измерение пакетов всегда имеет одинаковый размер, задайте аргумент drop_remainder равным True, чтобы не создавать пакет меньшего размера.
В отличие от tf.data.Dataset.batch, входные элементы, объединяемые в пакет, могут иметь разные формы:
- Если входной элемент — это
tf.Tensor, статическая формаtf.TensorShapeкоторого полностью определена, он обрабатывается как обычно. - Если входной элемент — это
tf.Tensor, статическая формаtf.TensorShapeкоторого содержит одну или несколько осей неизвестного размера (то естьshape[i]=None), выходные данные содержатtf.RaggedTensorс переменной длиной по таким измерениям. - Если входной элемент — это
tf.RaggedTensorили объект любого другого типа, он обрабатывается как обычно.
Пример:
dataset = tf.data.Dataset.range(6) dataset = dataset.map(lambda x: tf.range(x)) dataset.element_spec.shape TensorShape([None]) dataset = dataset.ragged_batch(2) for batch in dataset: print(batch) <tf.RaggedTensor [[], [0]]> <tf.RaggedTensor [[0, 1], [0, 1, 2]]> <tf.RaggedTensor [[0, 1, 2, 3], [0, 1, 2, 3, 4]]>
| Аргументы | |
|---|---|
batch_size | Скалярный tf.int64 tf.Tensor, задающий количество последовательных элементов этого набора данных, объединяемых в один пакет. |
drop_remainder | (Необязательно.) Скалярный tf.bool tf.Tensor, указывающий, следует ли отбрасывать последний пакет, если в нём меньше batch_size элементов; по умолчанию пакет меньшего размера не отбрасывается. |
row_splits_dtype | Тип данных, используемый для row_splits любых новых тензоров с переменной длиной. Тип данных row_splits существующих элементов tf.RaggedTensor не изменяется. |
name | (Необязательно.) Строка с именем операции tf.data. |
| Возвращает | |
|---|---|
Новый Dataset с преобразованием, применённым, как описано выше. |
random
@staticmethod
random(
seed=None, rerandomize_each_iteration=None, name=None
) -> 'DatasetV2'
Создаёт Dataset псевдослучайных значений.
Набор данных генерирует последовательность равномерно распределённых целочисленных значений.
Параметр rerandomize_each_iteration определяет, нужно ли генерировать новую случайную последовательность для каждой эпохи. По умолчанию используется значение False, поэтому набор данных генерирует одну и ту же последовательность случайных чисел для каждой эпохи.
ds1 = tf.data.Dataset.random(seed=4).take(10) ds2 = tf.data.Dataset.random(seed=4).take(10) print(list(ds1.as_numpy_iterator())==list(ds2.as_numpy_iterator())) True
ds3 = tf.data.Dataset.random(seed=4).take(10) ds3_first_epoch = list(ds3.as_numpy_iterator()) ds3_second_epoch = list(ds3.as_numpy_iterator()) print(ds3_first_epoch == ds3_second_epoch) True
ds4 = tf.data.Dataset.random(
seed=4, rerandomize_each_iteration=True).take(10)
ds4_first_epoch = list(ds4.as_numpy_iterator())
ds4_second_epoch = list(ds4.as_numpy_iterator())
print(ds4_first_epoch == ds4_second_epoch)
False| Аргументы | |
|---|---|
seed | (Необязательно.) Если задан, набор данных выдаёт детерминированную последовательность значений. |
rerandomize_each_iteration | (Необязательно.) Если задано значение False, набор данных генерирует одну и ту же последовательность случайных чисел для каждой эпохи. Если задано значение True, для каждой эпохи генерируется отдельная детерминированная последовательность случайных чисел. Если параметр не указан, по умолчанию используется значение False. |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Dataset | Dataset. |
range
@staticmethod
range(
*args, **kwargs
) -> 'DatasetV2'
Создаёт Dataset значений диапазона с заданным шагом.
list(Dataset.range(5).as_numpy_iterator()) [0, 1, 2, 3, 4] list(Dataset.range(2, 5).as_numpy_iterator()) [2, 3, 4] list(Dataset.range(1, 5, 2).as_numpy_iterator()) [1, 3] list(Dataset.range(1, 5, -2).as_numpy_iterator()) [] list(Dataset.range(5, 1).as_numpy_iterator()) [] list(Dataset.range(5, 1, -2).as_numpy_iterator()) [5, 3] list(Dataset.range(2, 5, output_type=tf.int32).as_numpy_iterator()) [2, 3, 4] list(Dataset.range(1, 5, 2, output_type=tf.float32).as_numpy_iterator()) [1.0, 3.0]
| Аргументы | |
|---|---|
*args | Семантика та же, что и у функции range в Python. len(args) == 1 -> start = 0, stop = args[0], step = 1. len(args) == 2 -> start = args[0], stop = args[1], step = 1. len(args) == 3 -> start = args[0], stop = args[1], step = args[2]. |
**kwargs |
|
| Возвращает | |
|---|---|
Dataset | RangeDataset. |
| Вызывает исключение | |
|---|---|
ValueError | если len(args) == 0. |
rebatch
rebatch(
batch_size, drop_remainder=False, name=None
) -> 'DatasetV2'
Создаёт Dataset, заново формирующий пакеты из элементов этого набора данных.
Функционально rebatch(N) эквивалентен unbatch().batch(N), но работает эффективнее, выполняя одно копирование вместо двух.
ds = tf.data.Dataset.range(6) ds = ds.batch(2) ds = ds.rebatch(3) list(ds.as_numpy_iterator()) [array([0, 1, 2]), array([3, 4, 5])]
ds = tf.data.Dataset.range(7) ds = ds.batch(4) ds = ds.rebatch(3) list(ds.as_numpy_iterator()) [array([0, 1, 2]), array([3, 4, 5]), array([6])]
ds = tf.data.Dataset.range(7) ds = ds.batch(2) ds = ds.rebatch(3, drop_remainder=True) list(ds.as_numpy_iterator()) [array([0, 1, 2]), array([3, 4, 5])]
Если аргумент batch_size является списком, rebatch циклически перебирает список, определяя размер каждого пакета.
ds = tf.data.Dataset.range(8) ds = ds.batch(4) ds = ds.rebatch([2, 1, 1]) list(ds.as_numpy_iterator()) [array([0, 1]), array([2]), array([3]), array([4, 5]), array([6]), array([7])]
| Аргументы | |
|---|---|
batch_size | Скалярное или векторное значение tf.int64, задающее размер создаваемых пакетов. Если этот аргумент является вектором, значения перебираются по кругу. |
drop_remainder | (Необязательно.) Скалярный tf.bool tf.Tensor, указывающий, следует ли отбрасывать последний пакет, если в нём меньше batch_size[cycle_index] элементов; по умолчанию пакет меньшего размера не отбрасывается. |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Dataset из скалярных элементов dtype. |
reduce
reduce(
initial_state, reduce_func, name=None
)
Сводит входной набор данных к одному элементу.
Преобразование последовательно вызывает reduce_func для каждого элемента входного набора данных до тех пор, пока набор не будет исчерпан, накапливая информацию во внутреннем состоянии. Аргумент initial_state используется как начальное состояние, а итоговое состояние возвращается в качестве результата.
tf.data.Dataset.range(5).reduce(np.int64(0), lambda x, _: x + 1).numpy() 5 tf.data.Dataset.range(5).reduce(np.int64(0), lambda x, y: x + y).numpy() 10
| Аргументы | |
|---|---|
initial_state | Элемент, представляющий начальное состояние преобразования. |
reduce_func | Функция, преобразующая (old_state, input_element) в new_state. Она должна принимать два аргумента и возвращать новый элемент. Структура new_state должна соответствовать структуре initial_state. |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
| Элемент набора данных, соответствующий итоговому состоянию преобразования. |
rejection_resample
rejection_resample(
class_func, target_dist, initial_dist=None, seed=None, name=None
) -> 'DatasetV2'
Повторно выбирает элементы, чтобы достичь целевого распределения.
Примечание: Чтобы достичьtarget_dist, эта реализация может отклонять или повторять элементы. Поэтому в некоторых случаях выходнойDatasetможет быть больше входногоDataset.
initial_dist = [0.6, 0.4] n = 1000 elems = np.random.choice(len(initial_dist), size=n, p=initial_dist) dataset = tf.data.Dataset.from_tensor_slices(elems) zero, one = np.bincount(list(dataset.as_numpy_iterator())) / n
В результате initial_dist значение zero составляет ~0.6, а one — ~0.4.
target_dist = [0.5, 0.5] dataset = dataset.rejection_resample( class_func=lambda x: x, target_dist=target_dist, initial_dist=initial_dist) dataset = dataset.map(lambda class_func_result, data: data) zero, one = np.bincount(list(dataset.as_numpy_iterator())) / n
В результате target_dist значение zero составляет ~0.5, а one — ~0.5.
| Аргументы | |
|---|---|
class_func | Функция, преобразующая элемент входного набора данных в скалярный тензор tf.int32. Значения должны находиться в диапазоне [0, num_classes). |
target_dist | Тензор с плавающей точкой формы [num_classes]. |
initial_dist | (Необязательно.) Тензор с плавающей точкой формы [num_classes]. Если не задан, фактическое распределение классов оценивается в реальном времени в потоковом режиме. |
seed | (Необязательно.) Целочисленное значение Python, используемое как начальное значение для повторной выборки. |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Новый Dataset с преобразованием, применённым, как описано выше. |
repeat
repeat(
count=None, name=None
) -> 'DatasetV2'
Повторяет этот набор данных, чтобы каждое исходное значение встречалось count раз.
dataset = tf.data.Dataset.from_tensor_slices([1, 2, 3]) dataset = dataset.repeat(3) list(dataset.as_numpy_iterator()) [1, 2, 3, 1, 2, 3, 1, 2, 3]
Примечание: Если входной набор данных зависит от глобального состояния (например, генератора случайных чисел) или его выходные данные недетерминированы (например, из-за расположенного выше по конвейеру shuffle), при разных повторах могут появляться разные элементы.
| Аргументы | |
|---|---|
count | (Необязательно.) Скалярный tf.int64 tf.Tensor, задающий количество повторений набора данных. По умолчанию (если count имеет значение None или -1) набор данных повторяется бесконечно. |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Новый Dataset с преобразованием, применённым, как описано выше. |
sample_from_datasets
@staticmethod
sample_from_datasets(
datasets,
weights=None,
seed=None,
stop_on_empty_dataset=False,
rerandomize_each_iteration=None
) -> 'DatasetV2'
Случайным образом выбирает элементы из наборов данных в datasets.
Создаёт набор данных, чередуя элементы из datasets и выбирая элемент из набора данных i с вероятностью weight[i]. Выборка выполняется без возвращения. Например, предположим, что у нас есть 2 набора данных:
dataset1 = tf.data.Dataset.range(0, 3) dataset2 = tf.data.Dataset.range(100, 103)
Предположим, что выборка из этих 2 наборов данных выполняется со следующими весами:
sample_dataset = tf.data.Dataset.sample_from_datasets(
[dataset1, dataset2], weights=[0.5, 0.5])
Один из возможных результатов элементов в sample_dataset:
print(list(sample_dataset.as_numpy_iterator())) # [100, 0, 1, 101, 2, 102]
| Аргументы | |
|---|---|
datasets | Непустой список объектов tf.data.Dataset с совместимой структурой. |
weights | (Необязательно.) Список или тензор из len(datasets) значений с плавающей точкой, где weights[i] задаёт вероятность выборки из datasets[i], либо объект tf.data.Dataset, каждый элемент которого является таким списком. По умолчанию используется равномерное распределение между datasets. |
seed | (Необязательно.) Скалярный tf.int64 tf.Tensor, задающий начальное значение для генерации распределения. Описание поведения см. в разделе tf.random.set_seed. |
stop_on_empty_dataset | Если задано значение True, выборка прекращается при обнаружении пустого набора данных. Если задано значение False, выборка продолжается, а пустые наборы данных пропускаются. Рекомендуется задать значение True. В противном случае распределение выборки сначала соответствует заданному пользователем, но может измениться, если входные наборы данных опустеют. Это может быть сложно заметить, поскольку вначале набор данных выглядит корректно. Для обратной совместимости по умолчанию используется значение False. |
rerandomize_each_iteration | Необязательный bool. Логический аргумент определяет, будет ли последовательность случайных чисел, используемая для выбора набора данных, генерироваться заново для каждой эпохи. То есть он определяет, будут ли наборы данных выбираться в одном и том же порядке в разных эпохах (поведение по умолчанию). |
| Возвращает | |
|---|---|
Набор данных, случайным образом чередующий элементы из datasets согласно weights, если оно задано, или с равномерной вероятностью в противном случае. |
| Вызывает исключение | |
|---|---|
TypeError | Если аргументы datasets или weights имеют неверный тип. |
ValueError |
|
save
save(
path, compression=None, shard_func=None, checkpoint_args=None
)
Сохраняет содержимое указанного набора данных.
Пример использования:
import tempfile path = os.path.join(tempfile.gettempdir(), "saved_data") # Save a dataset dataset = tf.data.Dataset.range(2) dataset.save(path) new_dataset = tf.data.Dataset.load(path) for elem in new_dataset: print(elem) tf.Tensor(0, shape=(), dtype=int64) tf.Tensor(1, shape=(), dtype=int64)
Сохранённый набор данных записывается в несколько файловых «шардов». По умолчанию выходные данные набора данных распределяются по шардам по кругу, но можно задать собственное распределение с помощью функции shard_func. Например, набор данных можно сохранить в одном шарде следующим образом:
dataset = make_dataset()
def custom_shard_func(element):
return np.int64(0)
dataset.save(
path="/path/to/data", ..., shard_func=custom_shard_func)
Чтобы включить создание контрольных точек, передайте checkpoint_args методу save следующим образом:
dataset = tf.data.Dataset.range(100)
save_dir = "..."
checkpoint_prefix = "..."
step_counter = tf.Variable(0, trainable=False)
checkpoint_args = {
"checkpoint_interval": 50,
"step_counter": step_counter,
"directory": checkpoint_prefix,
"max_to_keep": 20,
}
dataset.save(dataset, save_dir, checkpoint_args=checkpoint_args)
Примечание: Структура каталогов и формат файлов, используемые для сохранения набора данных, считаются деталями реализации и могут измениться. Поэтому наборы данных, сохранённые с помощьюtf.data.Dataset.save, следует загружать только с помощьюtf.data.Dataset.load, для которого гарантирована обратная совместимость.
| Аргументы | |
|---|---|
path | Обязательный параметр. Каталог для сохранения набора данных. |
compression | Необязательный параметр. Алгоритм сжатия данных при записи. Поддерживаются варианты GZIP и NONE. По умолчанию используется NONE. |
shard_func | Необязательный параметр. Функция, определяющая распределение элементов набора данных по файловым шардам. Ожидается, что функция будет преобразовывать элементы входного набора данных в идентификаторы шардов типа int64. Если функция задана, она будет трассирована и выполнена как вычисление графа. |
checkpoint_args | Необязательные аргументы для создания контрольных точек, передаваемые в tf.train.CheckpointManager. Если checkpoint_args не заданы, контрольные точки создаваться не будут. Реализация save() самостоятельно создаёт объект tf.train.Checkpoint, поэтому пользователям не следует задавать аргумент checkpoint в checkpoint_args. |
| Возвращает | |
|---|---|
| Операцию, выполнение которой сохраняет данные. При записи контрольных точек возвращает None. Возвращаемое значение полезно в модульных тестах. |
| Вызывает исключение | |
|---|---|
ValueError, если в checkpoint_args передан checkpoint. |
scan
scan(
initial_state, scan_func, name=None
) -> 'DatasetV2'
Преобразование, применяющее функцию поэлементно к входному набору данных с накоплением состояния.
Это преобразование является версией tf.data.Dataset.map с сохранением состояния. Помимо применения функции scan_func к элементам входного набора данных, scan() накапливает один или несколько тензоров состояния, начальные значения которых заданы в initial_state.
dataset = tf.data.Dataset.range(10) initial_state = tf.constant(0, dtype=tf.int64) scan_func = lambda state, i: (state + i, state + i) dataset = dataset.scan(initial_state=initial_state, scan_func=scan_func) list(dataset.as_numpy_iterator()) [0, 1, 3, 6, 10, 15, 21, 28, 36, 45]
| Аргументы | |
|---|---|
initial_state | Вложенная структура тензоров, представляющая начальное состояние аккумулятора. |
scan_func | Функция, преобразующая (old_state, input_element) в (new_state, output_element). Она должна принимать два аргумента и возвращать пару вложенных структур тензоров. new_state должна соответствовать структуре initial_state. |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Новый объект Dataset с преобразованием, примененным, как описано выше. |
shard
shard(
num_shards, index, name=None
) -> 'DatasetV2'
Создает объект Dataset, содержащий только 1/num_shards этого набора данных.
shard является детерминированной. Набор данных, созданный с помощью A.shard(n, i), будет содержать все элементы A, для которых индекс mod n = i.
A = tf.data.Dataset.range(10) B = A.shard(num_shards=3, index=0) list(B.as_numpy_iterator()) [0, 3, 6, 9] C = A.shard(num_shards=3, index=1) list(C.as_numpy_iterator()) [1, 4, 7] D = A.shard(num_shards=3, index=2) list(D.as_numpy_iterator()) [2, 5, 8]
Этот оператор набора данных очень полезен при распределенном обучении, поскольку позволяет каждому рабочему узлу считывать уникальное подмножество данных.
При чтении одного входного файла можно разделить элементы на сегменты следующим образом:
d = tf.data.TFRecordDataset(input_file) d = d.shard(num_workers, worker_index) d = d.repeat(num_epochs) d = d.shuffle(shuffle_buffer_size) d = d.map(parser_fn, num_parallel_calls=num_map_threads)
Важные замечания:
- Обязательно выполняйте разбиение на сегменты до применения любых операторов рандомизации (например, перемешивания).
- Как правило, оператор разбиения на сегменты лучше использовать в начале конвейера обработки набора данных. Например, при чтении набора файлов TFRecord выполняйте разбиение на сегменты до преобразования набора данных во входные образцы. Это позволяет избежать чтения каждого файла на каждом рабочем узле. Ниже приведен пример эффективной стратегии разбиения на сегменты в рамках полного конвейера:
d = Dataset.list_files(pattern, shuffle=False)
d = d.shard(num_workers, worker_index)
d = d.repeat(num_epochs)
d = d.shuffle(shuffle_buffer_size)
d = d.interleave(tf.data.TFRecordDataset,
cycle_length=num_readers, block_length=1)
d = d.map(parser_fn, num_parallel_calls=num_map_threads)
| Аргументы | |
|---|---|
num_shards | Скалярный объект tf.int64 типа tf.Tensor, представляющий количество сегментов, обрабатываемых параллельно. |
index | Скалярный объект tf.int64 типа tf.Tensor, представляющий индекс рабочего узла. |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Новый объект Dataset с преобразованием, примененным, как описано выше. |
| Вызывает исключение | |
|---|---|
InvalidArgumentError | если num_shards или index имеют недопустимые значения. Примечание: проверка ошибок выполняется по возможности, и гарантировать их обнаружение при создании набора данных нельзя. (Например, передача тензора-заполнителя обходит раннюю проверку и вместо этого приводит к ошибке при вызове session.run.) |
shuffle
shuffle(
buffer_size, seed=None, reshuffle_each_iteration=None, name=None
) -> 'DatasetV2'
Случайным образом перемешивает элементы этого набора данных.
Этот оператор заполняет буфер элементами buffer_size, а затем случайным образом выбирает элементы из этого буфера, заменяя выбранные элементы новыми. Для идеального перемешивания размер буфера должен быть не меньше полного размера набора данных.
Например, если набор данных содержит 10 000 элементов, а buffer_size равно 1 000, то shuffle сначала выберет случайный элемент только из первых 1 000 элементов буфера. После выбора элемента его место в буфере займет следующий элемент (то есть элемент 1 001), благодаря чему размер буфера останется равным 1 000 элементам.
reshuffle_each_iteration определяет, должен ли порядок перемешивания изменяться при каждой эпохе. В TF 1.X идиоматичным способом создания эпох было преобразование repeat:
dataset = tf.data.Dataset.range(3) dataset = dataset.shuffle(3, reshuffle_each_iteration=True) dataset = dataset.repeat(2) # [1, 0, 2, 1, 2, 0] dataset = tf.data.Dataset.range(3) dataset = dataset.shuffle(3, reshuffle_each_iteration=False) dataset = dataset.repeat(2) # [1, 0, 2, 1, 0, 2]
В TF 2.0 объекты tf.data.Dataset являются итерируемыми объектами Python, поэтому эпохи можно создавать также с помощью итерации Python:
dataset = tf.data.Dataset.range(3) dataset = dataset.shuffle(3, reshuffle_each_iteration=True) list(dataset.as_numpy_iterator()) # [1, 0, 2] list(dataset.as_numpy_iterator()) # [1, 2, 0]
dataset = tf.data.Dataset.range(3) dataset = dataset.shuffle(3, reshuffle_each_iteration=False) list(dataset.as_numpy_iterator()) # [1, 0, 2] list(dataset.as_numpy_iterator()) # [1, 0, 2]
Полное перемешивание всех данных
Чтобы перемешать весь набор данных, задайте buffer_size=dataset.cardinality(). Это эквивалентно установке значения buffer_size, равного количеству элементов в наборе данных, что обеспечивает равномерное перемешивание.
Примечание: shuffle(dataset.cardinality()) загружает весь набор данных в память для перемешивания. Если набор данных слишком велик, это приведет к ошибке переполнения памяти (OOM), поэтому полное перемешивание следует использовать только для наборов данных, которые заведомо помещаются в память, например для наборов имен файлов или других небольших наборов данных.
dataset = tf.data.Dataset.range(20) dataset = dataset.shuffle(dataset.cardinality()) # [18, 4, 9, 2, 17, 8, 5, 10, 0, 6, 16, 3, 19, 7, 14, 11, 15, 13, 12, 1]
| Аргументы | |
|---|---|
buffer_size | Скалярный объект tf.int64 типа tf.Tensor, представляющий количество элементов этого набора данных, из которых новый набор данных будет выбирать элементы. Чтобы равномерно перемешать весь набор данных, используйте buffer_size=dataset.cardinality(). |
seed | (Необязательно.) Скалярный объект tf.int64 типа tf.Tensor, представляющий начальное значение генератора случайных чисел, используемое для создания распределения. Описание поведения см. в разделе tf.random.set_seed. |
reshuffle_each_iteration | (Необязательно.) Логическое значение, которое при значении true указывает, что набор данных следует псевдослучайно перемешивать заново при каждой итерации. (По умолчанию — True.) |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Новый объект Dataset с преобразованием, примененным, как описано выше. |
skip
skip(
count, name=None
) -> 'DatasetV2'
Создает объект Dataset, пропускающий count элементов этого набора данных.
dataset = tf.data.Dataset.range(10) dataset = dataset.skip(7) list(dataset.as_numpy_iterator()) [7, 8, 9]
| Аргументы | |
|---|---|
count | Скалярный объект tf.int64 типа tf.Tensor, представляющий количество элементов этого набора данных, которые нужно пропустить, чтобы сформировать новый набор данных. Если count больше размера этого набора данных, новый набор данных не будет содержать элементов. Если count равно -1, пропускается весь набор данных. |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Новый объект Dataset с преобразованием, примененным, как описано выше. |
snapshot
snapshot(
path,
compression='AUTO',
reader_func=None,
shard_func=None,
name=None
) -> 'DatasetV2'
API для сохранения результатов входного набора данных.
API snapshot позволяет прозрачно сохранять результаты конвейера предварительной обработки на диск и использовать предварительно обработанные данные при другом запуске обучения.
Этот API позволяет объединять повторяющиеся этапы предварительной обработки и повторно использовать уже обработанные данные, обменивая дисковое пространство и пропускную способность сети на высвобождение более ценных ресурсов ЦП и времени вычислений ускорителя.
Подробная документация по проектированию этой функции доступна по адресу https://github.com/tensorflow/community/blob/master/rfcs/20200107-tf-data-snapshot.md.
Пользователи могут задавать различные параметры, управляющие поведением snapshot, в том числе способы чтения и записи снимков, передавая пользовательские функции в параметры reader_func и shard_func.
shard_func — это заданная пользователем функция, которая сопоставляет входные элементы с сегментами снимка.
Пользователи могут задать эту функцию, чтобы управлять способом записи файлов снимка на диск. Ниже приведен пример возможной реализации shard_func.
dataset = ...
dataset = dataset.enumerate()
dataset = dataset.snapshot("/path/to/snapshot/dir",
shard_func=lambda x, y: x % NUM_SHARDS, ...)
dataset = dataset.map(lambda x, y: y)
reader_func — это заданная пользователем функция, принимающая один аргумент: (1) набор данных, состоящий из наборов данных, каждый из которых представляет собой «раздел» элементов исходного набора данных. Кардинальность входного набора данных соответствует количеству сегментов, заданному в параметре shard_func (см. выше). Функция должна возвращать набор данных, содержащий элементы исходного набора данных.
Пользователи могут задать эту функцию, чтобы управлять способом чтения файлов снимка с диска, включая степень перемешивания и параллелизма.
Ниже приведен пример стандартной функции чтения, которую может определить пользователь. Эта функция обеспечивает перемешивание набора данных и параллельное чтение наборов данных:
def user_reader_func(datasets):
# shuffle the datasets splits
datasets = datasets.shuffle(NUM_CORES)
# read datasets in parallel and interleave their elements
return datasets.interleave(lambda x: x, num_parallel_calls=AUTOTUNE)
dataset = dataset.snapshot("/path/to/snapshot/dir",
reader_func=user_reader_func)
По умолчанию snapshot распараллеливает чтение в соответствии с количеством доступных ядер системы, но не пытается перемешивать данные.
| Аргументы | |
|---|---|
path | Обязательный параметр. Каталог для хранения и загрузки снимка. |
compression | Необязательный параметр. Тип сжатия, применяемый к снимку, записываемому на диск. Поддерживаются варианты GZIP, SNAPPY, AUTO или None. По умолчанию используется AUTO, который пытается подобрать подходящий алгоритм сжатия для набора данных. |
reader_func | Необязательный параметр. Функция, управляющая чтением данных из сегментов снимка. |
shard_func | Необязательный параметр. Функция, управляющая разбиением данных на сегменты при записи снимка. |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Новый объект Dataset с преобразованием, примененным, как описано выше. |
sparse_batch
sparse_batch(
batch_size, row_shape, name=None
) -> 'DatasetV2'
Объединяет последовательные элементы в объекты tf.sparse.SparseTensor.
Как и Dataset.padded_batch(), это преобразование объединяет несколько последовательных элементов набора данных, которые могут иметь разные формы, в один элемент. Полученный элемент содержит три компонента (indices, values и dense_shape), образующих объект tf.sparse.SparseTensor, представляющий те же данные. row_shape задает плотную форму каждой строки полученного объекта tf.sparse.SparseTensor, к которой добавляется эффективный размер пакета. Например:
# NOTE: The following examples use `{ ... }` to represent the
# contents of a dataset.
a = { ['a', 'b', 'c'], ['a', 'b'], ['a', 'b', 'c', 'd'] }
a.apply(tf.data.experimental.dense_to_sparse_batch(
batch_size=2, row_shape=[6])) ==
{
([[0, 0], [0, 1], [0, 2], [1, 0], [1, 1]], # indices
['a', 'b', 'c', 'a', 'b'], # values
[2, 6]), # dense_shape
([[0, 0], [0, 1], [0, 2], [0, 3]],
['a', 'b', 'c', 'd'],
[1, 6])
}
| Аргументы | |
|---|---|
batch_size | Скалярный объект tf.int64 типа tf.Tensor, представляющий количество последовательных элементов этого набора данных, которые нужно объединить в один пакет. |
row_shape | Объект tf.TensorShape или векторный объект, подобный тензору, типа tf.int64, представляющий эквивалентную плотную форму строки в результирующем объекте tf.sparse.SparseTensor. Все элементы этого набора данных должны иметь тот же ранг, что и row_shape, и размер не больше row_shape по каждому измерению. |
name | (Необязательно.) Строка, задающая имя операции tf.data. |
| Возвращает | |
|---|---|
Новый объект Dataset с преобразованием, примененным, как описано выше. |
take
take(
count, name=None
) -> 'DatasetV2'
Создает объект Dataset, содержащий не более count элементов этого набора данных.
dataset = tf.data.Dataset.range(10) dataset = dataset.take(3) list(dataset.as_numpy_iterator()) [0, 1, 2]
| Аргументы | |
|---|---|
count | Скалярный объект tf.int64 типа tf.Tensor, представляющий количество элементов этого набора данных, которые нужно взять для формирования нового набора данных. Если count равно -1 или count превышает размер этого набора данных, новый набор данных будет содержать все его элементы. |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Новый объект Dataset с преобразованием, примененным, как описано выше. |
take_while
take_while(
predicate, name=None
) -> 'DatasetV2'
Преобразование, останавливающее итерацию по набору данных на основании predicate.
dataset = tf.data.Dataset.range(10) dataset = dataset.take_while(lambda x: x < 5) list(dataset.as_numpy_iterator()) [0, 1, 2, 3, 4]
| Аргументы | |
|---|---|
predicate | Функция, преобразующая вложенную структуру тензоров (формы и типы которых определяются self.output_shapes и self.output_types) в скалярный тензор типа tf.bool. |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Новый объект Dataset с преобразованием, примененным, как описано выше. |
unbatch
unbatch(
name=None
) -> 'DatasetV2'
Разбивает элементы набора данных на несколько элементов.
Например, если форма элементов набора данных — [B, a0, a1, ...], где B может различаться для каждого входного элемента, то для каждого элемента набора данных разбитый набор данных будет содержать B последовательных элементов формы [a0, a1, ...].
elements = [ [1, 2, 3], [1, 2], [1, 2, 3, 4] ] dataset = tf.data.Dataset.from_generator(lambda: elements, tf.int64) dataset = dataset.unbatch() list(dataset.as_numpy_iterator()) [1, 2, 3, 1, 2, 1, 2, 3, 4]
Примечание: Дляunbatchтребуется копирование данных, чтобы разделить пакетный тензор на меньшие тензоры без пакетов. При оптимизации производительности старайтесь не использоватьunbatchбез необходимости.
| Аргументы | |
|---|---|
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Новый объект Dataset с преобразованием, примененным, как описано выше. |
unique
unique(
name=None
) -> 'DatasetV2'
Преобразование, удаляющее повторяющиеся элементы из объекта Dataset.
Используйте это преобразование, чтобы создать набор данных, содержащий по одному экземпляру каждого уникального элемента входных данных. Например:
dataset = tf.data.Dataset.from_tensor_slices([1, 37, 2, 37, 2, 1]) dataset = dataset.unique() sorted(list(dataset.as_numpy_iterator())) [1, 2, 37]
Примечание: Это преобразование поддерживает только наборы данных, которые помещаются в память и содержат элементы типаtf.int32,tf.int64илиtf.string.
| Аргументы | |
|---|---|
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Новый объект Dataset с преобразованием, примененным, как описано выше. |
window
window(
size, shift=None, stride=1, drop_remainder=False, name=None
) -> 'DatasetV2'
Возвращает набор данных из «окон».
Каждое «окно» — это набор данных, содержащий подмножество элементов входного набора данных. Это конечные наборы данных размером size (или меньше, если входных элементов недостаточно для заполнения окна и drop_remainder принимает значение False).
Например:
dataset = tf.data.Dataset.range(7).window(3) for window in dataset: print(window) <...Dataset element_spec=TensorSpec(shape=(), dtype=tf.int64, name=None)> <...Dataset element_spec=TensorSpec(shape=(), dtype=tf.int64, name=None)> <...Dataset element_spec=TensorSpec(shape=(), dtype=tf.int64, name=None)>
Поскольку окна являются наборами данных, по ним можно выполнять итерацию:
for window in dataset: print(list(window.as_numpy_iterator())) [0, 1, 2] [3, 4, 5] [6]
Смещение
Аргумент shift определяет количество входных элементов, на которое сдвигается начало каждого окна. Если окна и элементы нумеруются с 0, то первым элементом окна k будет элемент k * shift входного набора данных. В частности, первым элементом первого окна всегда будет первый элемент входного набора данных.
dataset = tf.data.Dataset.range(7).window(3, shift=1,
drop_remainder=True)
for window in dataset:
print(list(window.as_numpy_iterator()))
[0, 1, 2]
[1, 2, 3]
[2, 3, 4]
[3, 4, 5]
[4, 5, 6]Шаг
Аргумент stride определяет шаг между входными элементами внутри окна.
dataset = tf.data.Dataset.range(7).window(3, shift=1, stride=2,
drop_remainder=True)
for window in dataset:
print(list(window.as_numpy_iterator()))
[0, 2, 4]
[1, 3, 5]
[2, 4, 6]Вложенные элементы
Когда преобразование window применяется к набору данных, элементы которого являются вложенными структурами, оно создает набор данных с такой же вложенной структурой, но каждый лист заменяется окном. Иными словами, вложенность применяется вне окон, а не внутри них.
Сигнатура типа:
def window(
self: Dataset[Nest[T]], ...
) -> Dataset[Nest[Dataset[T]]]
Применение window к Dataset кортежей дает кортеж окон:
dataset = tf.data.Dataset.from_tensor_slices(([1, 2, 3, 4, 5],
[6, 7, 8, 9, 10]))
dataset = dataset.window(2)
windows = next(iter(dataset))
windows
(<...Dataset element_spec=TensorSpec(shape=(), dtype=tf.int32, name=None)>,
<...Dataset element_spec=TensorSpec(shape=(), dtype=tf.int32, name=None)>)def to_numpy(ds): return list(ds.as_numpy_iterator()) for windows in dataset: print(to_numpy(windows[0]), to_numpy(windows[1])) [1, 2] [6, 7] [3, 4] [8, 9] [5] [10]
Применение window к Dataset словарей дает словарь Datasets:
dataset = tf.data.Dataset.from_tensor_slices({'a': [1, 2, 3],
'b': [4, 5, 6],
'c': [7, 8, 9]})
dataset = dataset.window(2)
def to_numpy(ds):
return list(ds.as_numpy_iterator())
for windows in dataset:
print(tf.nest.map_structure(to_numpy, windows))
{'a': [1, 2], 'b': [4, 5], 'c': [7, 8]}
{'a': [3], 'b': [6], 'c': [9]}Преобразование набора окон в плоский набор данных
Методы Dataset.flat_map и Dataset.interleave можно использовать для преобразования набора окон в один набор данных.
Аргумент flat_map — это функция, которая принимает элемент набора данных и возвращает Dataset. flat_map последовательно объединяет полученные наборы данных.
Например, чтобы преобразовать каждое окно в плотный тензор:
dataset = tf.data.Dataset.range(7).window(3, shift=1,
drop_remainder=True)
batched = dataset.flat_map(lambda x:x.batch(3))
for batch in batched:
print(batch.numpy())
[0 1 2]
[1 2 3]
[2 3 4]
[3 4 5]
[4 5 6]| Аргументы | |
|---|---|
size | Скалярный объект tf.int64 типа tf.Tensor, представляющий количество элементов входного набора данных, объединяемых в окно. Должен быть положительным. |
shift | (Необязательно.) Скалярный объект tf.int64 типа tf.Tensor, представляющий количество входных элементов, на которое сдвигается окно при каждой итерации. По умолчанию — size. Должен быть положительным. |
stride | (Необязательно.) Скалярный объект tf.int64 типа tf.Tensor, представляющий шаг входных элементов в скользящем окне. Должен быть положительным. Значение по умолчанию 1 означает «сохранять каждый входной элемент». |
drop_remainder | (Необязательно.) Скалярный объект tf.bool типа tf.Tensor, указывающий, следует ли отбрасывать последние окна, если их размер меньше size. |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Новый объект Dataset с преобразованием, примененным, как описано выше. |
with_options
with_options(
options, name=None
) -> 'DatasetV2'
Возвращает новый объект tf.data.Dataset с заданными параметрами.
Параметры являются «глобальными» в том смысле, что применяются ко всему набору данных. Если параметры задаются несколько раз, они объединяются, при условии что для разных параметров не указаны различные значения, отличные от значений по умолчанию.
ds = tf.data.Dataset.range(5)
ds = ds.interleave(lambda x: tf.data.Dataset.range(5),
cycle_length=3,
num_parallel_calls=3)
options = tf.data.Options()
# This will make the interleave order non-deterministic.
options.deterministic = False
ds = ds.with_options(options)| Аргументы | |
|---|---|
options | Объект tf.data.Options, задающий используемые параметры. |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Новый объект Dataset с преобразованием, примененным, как описано выше. |
| Вызывает исключение | |
|---|---|
ValueError | если для параметра более одного раза задано значение, отличное от значения по умолчанию |
zip
@staticmethod
zip(
*args, datasets=None, name=None
) -> 'DatasetV2'
Создает объект Dataset, объединяя заданные наборы данных с помощью zip.
Этот метод имеет семантику, похожую на семантику встроенной функции zip() в Python, но с тем отличием, что аргумент datasets может представлять собой (вложенную) структуру объектов Dataset. Поддерживаемые способы вложения описаны здесь.
# The datasets or nested structure of datasets `*args` argument
# determines the structure of elements in the resulting dataset.
a = tf.data.Dataset.range(1, 4) # ==> [ 1, 2, 3 ]
b = tf.data.Dataset.range(4, 7) # ==> [ 4, 5, 6 ]
ds = tf.data.Dataset.zip(a, b)
list(ds.as_numpy_iterator())
[(1, 4), (2, 5), (3, 6)]
ds = tf.data.Dataset.zip(b, a)
list(ds.as_numpy_iterator())
[(4, 1), (5, 2), (6, 3)]
# The `datasets` argument may contain an arbitrary number of datasets.
c = tf.data.Dataset.range(7, 13).batch(2) # ==> [ [7, 8],
# [9, 10],
# [11, 12] ]
ds = tf.data.Dataset.zip(a, b, c)
for element in ds.as_numpy_iterator():
print(element)
(1, 4, array([7, 8]))
(2, 5, array([ 9, 10]))
(3, 6, array([11, 12]))
# The number of elements in the resulting dataset is the same as
# the size of the smallest dataset in `datasets`.
d = tf.data.Dataset.range(13, 15) # ==> [ 13, 14 ]
ds = tf.data.Dataset.zip(a, d)
list(ds.as_numpy_iterator())
[(1, 13), (2, 14)]| Аргументы | |
|---|---|
*args | Наборы данных или вложенные структуры наборов данных, которые нужно объединить с помощью zip. Нельзя задавать, если задан datasets. |
datasets | (Вложенная) структура наборов данных. Нельзя задавать, если задан *args. Обратите внимание: этот параметр существует только для обратной совместимости; предпочтительно использовать *args. |
name | (Необязательно.) Имя операции tf.data. |
| Возвращает | |
|---|---|
Новый объект Dataset с преобразованием, примененным, как описано выше. |
__bool__
__bool__()
__iter__
__iter__() -> iterator_ops.OwnedIterator
Создает итератор для элементов этого набора данных.
Возвращаемый итератор реализует протокол Iterator языка Python.
| Возвращает | |
|---|---|
Объект tf.data.Iterator для элементов этого набора данных. |
| Вызывает исключение | |
|---|---|
RuntimeError | Если выполнение происходит не внутри tf.function и не в режиме eager. |
__len__
__len__()
Возвращает длину набора данных, если она известна и конечна.
Для вызова этого метода необходимо выполнять код в режиме eager, а длина набора данных должна быть известна и конечна. Если длина может быть неизвестной или бесконечной либо код выполняется в режиме графа, используйте вместо этого tf.data.Dataset.cardinality.
| Возвращает | |
|---|---|
| Целое число, представляющее длину набора данных. |
| Вызывает исключение | |
|---|---|
RuntimeError | Если длина набора данных неизвестна или бесконечна либо выполнение в режиме eager не включено. |
__nonzero__
__nonzero__()
© 2022 The TensorFlow Authors. All rights reserved.
Licensed under the Creative Commons Attribution License 4.0.
Code samples licensed under the Apache 2.0 License.
https://www.tensorflow.org/api_docs/python/tf/data/TextLineDataset