Spec-Zone.ru › TensorFlow 2.3

tf.distribute.Strategy

Просмотреть исходный код на GitHub

Политика распределения состояния и вычислений по списку устройств.

tf.distribute.Strategy(
    extended
)

См. руководство для обзора и примеров. См. tf.distribute.StrategyExtended и tf.distribute для глоссария понятий, упомянутых на этой странице, таких как «на реплику», реплика и reduce.

Вкратце:

  • Для использования с Keras compile/fit, пожалуйста, ознакомьтесь.
  • Вы можете передать потомка tf.distribute.Strategy в tf.estimator.RunConfig, чтобы указать, как tf.estimator.Estimator должен распределить свои вычисления. См. руководство.
  • В противном случае используйте tf.distribute.Strategy.scope, чтобы указать, что стратегия должна использоваться при построении и выполнении вашей модели. (Это помещает вас в «межрепликативный контекст» для этой стратегии, что означает, что стратегия управляет такими вещами, как размещение переменных.)
  • Если вы пишете пользовательский цикл обучения, вам потребуется вызвать несколько дополнительных методов, см. руководство:

    • Начните с создания tf.data.Dataset обычным способом или с использованием tf.distribute.experimental_make_numpy_dataset для создания набора данных из массива numpy.

    • Используйте tf.distribute.Strategy.experimental_distribute_dataset для преобразования tf.data.Dataset в нечто, что генерирует значения «на реплику». Если вы хотите вручную указать, как набор данных должен быть разделен между репликами, используйте tf.distribute.Strategy.experimental_distribute_datasets_from_function вместо этого.

    • Используйте tf.distribute.Strategy.run для выполнения функции один раз на каждой реплике, принимая значения, которые могут быть «на реплику» (например, из объекта tf.distribute.DistributedDataset) и возвращая значения «на реплику». Эта функция выполняется в «контексте реплики», что означает, что каждая операция выполняется отдельно на каждой реплике.

    • Наконец, используйте метод (такой как tf.distribute.Strategy.reduce) для преобразования полученных значений «на реплику» в обычные Tensor.

Пользовательский цикл обучения может быть таким простым:

with my_strategy.scope():
  @tf.function
  def distribute_train_epoch(dataset):
    def replica_fn(input):
      # process input and return result
      return result

    total_result = 0
    for x in dataset:
      per_replica_result = my_strategy.run(replica_fn, args=(x,))
      total_result += my_strategy.reduce(tf.distribute.ReduceOp.SUM,
                                         per_replica_result, axis=None)
    return total_result

  dist_dataset = my_strategy.experimental_distribute_dataset(dataset)
  for _ in range(EPOCHS):
    train_result = distribute_train_epoch(dist_dataset)

Это принимает обычный dataset и replica_fn и запускает его в распределённом режиме с использованием конкретной стратегии tf.distribute.Strategy под названием my_strategy выше. Любые переменные, созданные в replica_fn, создаются с политикой my_strategy, а библиотечные функции, вызываемые replica_fn, могут использовать API get_replica_context() для реализации специфичного для распределенного режима поведения.

Вы можете использовать API reduce для агрегирования результатов по репликам и использовать это в качестве возвращаемого значения одной итерации над tf.distribute.DistributedDataset. Или вы можете использовать tf.keras.metrics (такие как потеря, точность и т. д.) для накопления метрик на шагах в данном эпохе.

См. руководство по пользовательскому циклу обучения для более подробного примера.

Примечание: tf.distribute.Strategy в настоящее время не поддерживает разделяемые переменные TensorFlow (где одна переменная разделена между несколькими устройствами) на данный момент.
Атрибуты
cluster_resolver Возвращает решатель кластера, связанный с этой стратегией.

В общем случае, при использовании многоузловой tf.distribute стратегии, такой как tf.distribute.experimental.MultiWorkerMirroredStrategy или tf.distribute.experimental.TPUStrategy(), существует tf.distribute.cluster_resolver.ClusterResolver, связанный с используемой стратегией, и такой экземпляр возвращается этим свойством.

Стратегии, которые намерены иметь связанный tf.distribute.cluster_resolver.ClusterResolver, должны установить соответствующий атрибут или переопределить это свойство; в противном случае None возвращается по умолчанию. Эти стратегии также должны предоставить информацию о том, что возвращается этим свойством.

Стратегии для одного узла обычно не имеют tf.distribute.cluster_resolver.ClusterResolver, и в этих случаях это свойство вернёт None.

tf.distribute.cluster_resolver.ClusterResolver может быть полезен, когда пользователю требуется получить доступ к информации, такой как спецификация кластера, тип задачи или идентификатор задачи. Например,

os.environ['TF_CONFIG'] = json.dumps({
'cluster': {
'worker': ["localhost:12345", "localhost:23456"],
'ps': ["localhost:34567"]
},
'task': {'type': 'worker', 'index': 0}
})

# This implicitly uses TF_CONFIG for the cluster and current task info.
strategy = tf.distribute.experimental.MultiWorkerMirroredStrategy()

...

if strategy.cluster_resolver.task_type == 'worker':
# Perform something that's only applicable on workers. Since we set this
# as a worker above, this block will run on this particular instance.
elif strategy.cluster_resolver.task_type == 'ps':
# Perform something that's only applicable on parameter servers. Since we
# set this as a worker above, this block will not run on this particular
# instance.

Для получения дополнительной информации, см. документацию API tf.distribute.cluster_resolver.ClusterResolver.

extended tf.distribute.StrategyExtended с дополнительными методами.
num_replicas_in_sync Возвращает количество реплик, по которым агрегируются градиенты.

Методы

experimental_assign_to_logical_device

Просмотреть исходный код

experimental_assign_to_logical_device(
    tensor, logical_device_id
)

Добавляет аннотацию, что tensor будет назначено логическому устройству.

Примечание: Этот API поддерживается только в TPUStrategy на данный момент. Это добавляет аннотацию к tensor, указывающую, что операции над tensor будут вызваны на логическом устройстве с идентификатором ядра logical_device_id. При использовании параллелизма моделей по умолчанию все операции размещаются на логическом устройстве с номером ноль.
# Initializing TPU system with 2 logical devices and 4 replicas.
resolver = tf.distribute.cluster_resolver.TPUClusterResolver(tpu='')
tf.config.experimental_connect_to_cluster(resolver)
topology = tf.tpu.experimental.initialize_tpu_system(resolver)
device_assignment = tf.tpu.experimental.DeviceAssignment.build(
    topology,
    computation_shape=[1, 1, 1, 2],
    num_replicas=4)
strategy = tf.distribute.TPUStrategy(
    resolver, experimental_device_assignment=device_assignment)
iterator = iter(inputs)

@tf.function()
def step_fn(inputs):
  output = tf.add(inputs, inputs)

  # Add operation will be executed on logical device 0.
  output = strategy.experimental_assign_to_logical_device(output, 0)
  return output

strategy.run(step_fn, args=(next(iterator),))
Аргументы
tensor Входной тензор для аннотации.
logical_device_id Идентификатор логического ядра, которому будет назначен тензор.
Исключения
ValueError Идентификатор логического устройства не соответствует общему количеству разделений, указанных назначением устройства.
Возвращает
Аннотированный тензор с идентичным значением, как у tensor.

experimental_distribute_dataset

Просмотреть исходный код

experimental_distribute_dataset(
    dataset, options=None
)

Создаёт tf.distribute.DistributedDataset из tf.data.Dataset.

Возвращаемый tf.distribute.DistributedDataset можно перебирать аналогично тому, как можно перебирать обычные наборы данных. ПРИМЕЧАНИЕ: пользователь не может добавить больше преобразований к tf.distribute.DistributedDataset.

Вот пример:

strategy = tf.distribute.MirroredStrategy()

# Create a dataset
dataset = dataset_ops.Dataset.TFRecordDataset([
  "/a/1.tfr", "/a/2.tfr", "/a/3.tfr", "/a/4.tfr"])

# Distribute that dataset
dist_dataset = strategy.experimental_distribute_dataset(dataset)

# Iterate over the `tf.distribute.DistributedDataset`
for x in dist_dataset:
  # process dataset elements
  strategy.run(replica_fn, args=(x,))

В приведённом фрагменте кода tf.distribute.DistributedDataset dist_dataset сгруппирован по GLOBAL_BATCH_SIZE, и мы перебираем его с помощью for x in dist_dataset. x содержит данные для всех реплик, которые агрегируются в пакет GLOBAL_BATCH_SIZE. tf.distribute.Strategy.run позаботится о подаче правильных данных на реплику в x правильной replica_fn, выполняемой на каждой реплике.

Что происходит за кулисами этого метода, когда мы говорим, что экземпляр tf.data.Dataset - dataset - распределяется? Это зависит от того, как вы установили tf.data.experimental.AutoShardPolicy через tf.data.experimental.DistributeOptions. По умолчанию он установлен на tf.data.experimental.AutoShardPolicy.AUTO. В многоузловой среде мы сначала попытаемся распределить dataset, определив, создаётся ли dataset из наборов данных ридеров (например, tf.data.TFRecordDataset, tf.data.TextLineDataset и т. д.) и, если да, попытаемся разбить входные файлы. Обратите внимание, что должно быть по крайней мере один входной файл на узел. Если у вас меньше одного входного файла на узел, мы рекомендуем отключить фрагментацию наборов данных по узлам, установив tf.data.experimental.DistributeOptions.auto_shard_policy на tf.data.experimental.AutoShardPolicy.OFF.

Если попытка разбить по файлам не удалась (т. е. набор данных не читается из файлов), мы разделим набор данных равномерно в конце, добавив операцию .shard в конец потока обработки. Это заставит весь поток предобработки для всех данных выполняться на каждом узле, и каждый узел выполнит избыточную работу. Мы выведем предупреждение, если этот путь будет выбран.

Как уже упоминалось, внутри каждого узла мы также разделим данные между всеми устройствами узла (если их несколько). Это произойдёт даже если фрагментация по нескольким узлам отключена.

Если описанный выше метод разделения пакетов и фрагментации наборов данных нежелателен, используйте tf.distribute.Strategy.experimental_distribute_datasets_from_function вместо него, который не выполняет автоматического разделения или фрагментации.

Также можно использовать свойство element_spec экземпляра tf.distribute.DistributedDataset, возвращаемого этим API, для запроса tf.TypeSpec элементов, возвращаемых итератором. Это можно использовать для установки свойства input_signature объекта tf.function.

strategy = tf.distribute.MirroredStrategy()

# Create a dataset
dataset = dataset_ops.Dataset.TFRecordDataset([
  "/a/1.tfr", "/a/2.tfr", "/a/3.tfr", "/a/4.tfr"])

# Distribute that dataset
dist_dataset = strategy.experimental_distribute_dataset(dataset)

@tf.function(input_signature=[dist_dataset.element_spec])
def train_step(inputs):
  # train model with inputs
  return

# Iterate over the `tf.distribute.DistributedDataset`
for x in dist_dataset:
  # process dataset elements
  strategy.run(train_step, args=(x,))
Примечание: Порядок обработки данных рабочими процессами при использовании tf.distribute.Strategy.experimental_distribute_dataset или tf.distribute.Strategy.experimental_distribute_datasets_from_function не гарантируется. Это обычно требуется, если вы используете tf.distribute для масштабирования предсказаний. Однако вы можете вставить индекс для каждого элемента в пакете и упорядочить результаты соответственно. Обратитесь к этому фрагменту для примера упорядочения результатов.
Аргументы
dataset tf.data.Dataset, который будет фрагментирован по всем репликам в соответствии с правилами, указанными выше.
options tf.distribute.InputOptions, используемые для управления параметрами распределения этого набора данных.
Возвращаемое значение
Объект tf.distribute.DistributedDataset.

experimental_distribute_datasets_from_function

Просмотреть исходный код

experimental_distribute_datasets_from_function(
    dataset_fn, options=None
)

Распределяет экземпляры tf.data.Dataset, созданные вызовами dataset_fn.

dataset_fn будет вызываться один раз для каждого рабочего процесса в стратегии. Каждая реплика на этом рабочем процессе будет извлекать один пакет входов из локального Dataset (т.е. если у рабочего процесса две реплики, то на каждом шаге будут извлекаться два пакета из Dataset).

Этот метод может быть использован для различных целей. Например, в тех случаях, когда experimental_distribute_dataset не может фрагментировать входные файлы, этот метод можно использовать для ручного фрагментирования набора данных (избегая медленного поведения по умолчанию в experimental_distribute_dataset). В случае бесконечных наборов данных это фрагментирование можно выполнить, создав копии наборов данных, отличающиеся только случайным начальным значением. experimental_distribute_dataset также иногда может не удаваться разделить пакет между репликами на рабочем процессе. В этом случае этот метод может быть использован, так как в нем нет этого ограничения.

dataset_fn должен принимать экземпляр tf.distribute.InputContext, где можно получить информацию о пакетировании и репликации входов.

Также можно использовать свойство element_spec экземпляра tf.distribute.DistributedDataset, возвращаемого этим API, для запроса tf.TypeSpec элементов, возвращаемых итератором. Это можно использовать для установки свойства input_signature объекта tf.function.

global_batch_size = 8
def dataset_fn(input_context):
  batch_size = input_context.get_per_replica_batch_size(
                   global_batch_size)
  d = tf.data.Dataset.from_tensors([[1.]]).repeat().batch(batch_size)
  return d.shard(
      input_context.num_input_pipelines,
      input_context.input_pipeline_id)
strategy = tf.distribute.MirroredStrategy()
ds = strategy.experimental_distribute_datasets_from_function(dataset_fn)
def train(ds):
  @tf.function(input_signature=[ds.element_spec])
  def step_fn(inputs):
    # train the model with inputs
    return inputs

... for batch in ds: ... replica_results = strategy.run(replica_fn, args=(batch,))

train(ds)

Ключевой момент: Набор данных tf.data.Dataset, возвращаемый dataset_fn должен иметь размер пакета для каждой реплики, в отличие от experimental_distribute_dataset, который использует общий размер пакета. Это можно вычислить с помощью input_context.get_per_replica_batch_size.
Примечание: Порядок обработки данных рабочими процессами при использовании tf.distribute.Strategy.experimental_distribute_dataset или tf.distribute.Strategy.experimental_distribute_datasets_from_function не гарантируется. Это обычно требуется, если вы используете tf.distribute для масштабирования предсказаний. Однако вы можете вставить индекс для каждого элемента в пакете и упорядочить результаты соответственно. Обратитесь к этому фрагменту для примера упорядочения результатов.
Аргументы
dataset_fn Функция, принимающая экземпляр tf.distribute.InputContext и возвращающая tf.data.Dataset.
options tf.distribute.InputOptions, используемые для управления параметрами распределения этого набора данных.
Возвращаемое значение
Объект tf.distribute.DistributedDataset.

experimental_distribute_values_from_function

Просмотреть исходный код

experimental_distribute_values_from_function(
    value_fn
)

Генерирует tf.distribute.DistributedValues из value_fn.

Эта функция предназначена для генерации tf.distribute.DistributedValues для передачи в run, reduce, или другие методы, принимающие распределённые значения, когда не используются наборы данных.

Аргументы
value_fn Функция, выполняемая для генерации значений. Она вызывается для каждой реплики с tf.distribute.ValueContext в качестве единственного аргумента. Она должна возвращать тензор или тип, который может быть преобразован в тензор.
Возвращаемое значение
tf.distribute.DistributedValues, содержащий значение для каждой реплики.

Пример использования:

  1. Возвращение константного значения для каждой реплики:
strategy = tf.distribute.MirroredStrategy()
def value_fn(ctx):
  return tf.constant(1.)
distributed_values = (
     strategy.experimental_distribute_values_from_function(
       value_fn))
local_result = strategy.experimental_local_results(distributed_values)
local_result
(<tf.Tensor: shape=(), dtype=float32, numpy=1.0>,)
  1. Распределение значений в массиве на основе идентификатора реплики:
strategy = tf.distribute.MirroredStrategy()
array_value = np.array([3., 2., 1.])
def value_fn(ctx):
  return array_value[ctx.replica_id_in_sync_group]
distributed_values = (
     strategy.experimental_distribute_values_from_function(
       value_fn))
local_result = strategy.experimental_local_results(distributed_values)
local_result
(3.0,)
  1. Указание значений с помощью num_replicas_in_sync:
strategy = tf.distribute.MirroredStrategy()
def value_fn(ctx):
  return ctx.num_replicas_in_sync
distributed_values = (
     strategy.experimental_distribute_values_from_function(
       value_fn))
local_result = strategy.experimental_local_results(distributed_values)
local_result
(1,)
  1. Размещение значений на устройствах и распределение:
strategy = tf.distribute.TPUStrategy()
worker_devices = strategy.extended.worker_devices
multiple_values = []
for i in range(strategy.num_replicas_in_sync):
  with tf.device(worker_devices[i]):
    multiple_values.append(tf.constant(1.0))

def value_fn(ctx):
  return multiple_values[ctx.replica_id_in_sync_group]

distributed_values = strategy.
  experimental_distribute_values_from_function(
  value_fn)

experimental_local_results

Просмотреть исходный код

experimental_local_results(
    value
)

Возвращает список всех локальных значений для каждой реплики, содержащихся в value.

Примечание: Это возвращает только значения на рабочем процессе, инициированном этим клиентом. При использовании tf.distribute.Strategy, например tf.distribute.experimental.MultiWorkerMirroredStrategy, каждый рабочий процесс будет собственным клиентом, и эта функция вернёт только значения, вычисленные на этом рабочем процессе.
Аргументы
value Значение, возвращённое experimental_run(), run(), extended.call_for_each_replica(), или переменной, созданной в scope.
Возвращаемое значение
Кортеж значений, содержащихся в value. Если value представляет единственное значение, возвращается (value,).

experimental_make_numpy_dataset

Просмотреть исходный код

experimental_make_numpy_dataset(
    numpy_input
)

Создаёт tf.data.Dataset из массива NumPy. (устарело)

Предупреждение: ЭТА ФУНКЦИЯ УСТАРЕЛА. Она будет удалена после 2020-09-30. Инструкции по обновлению: Используйте tf.data.Dataset.from_tensor_slices вместо неё

Это позволяет избежать добавления numpy_input как большого константы в граф и копирует данные на машину или машины, которые будут обрабатывать ввод.

Обратите внимание, что вам, вероятно, потребуется использовать experimental_distribute_dataset с возвращаемым набором данных для дальнейшего распределения его с помощью стратегии.

Пример:

strategy = tf.distribute.MirroredStrategy()
numpy_input = np.ones([10], dtype=np.float32)
dataset = strategy.experimental_make_numpy_dataset(numpy_input)
dataset
<TensorSliceDataset shapes: (), types: tf.float32>
dataset = dataset.batch(2)
dist_dataset = strategy.experimental_distribute_dataset(dataset)
Аргументы
numpy_input вложенный массив NumPy входных массивов, который будет преобразован в набор данных. Обратите внимание, что массивы NumPy склеиваются, так как это стандартное поведение tf.data.Dataset.
Возвращаемое значение
tf.data.Dataset, представляющий numpy_input.

experimental_replicate_to_logical_devices

Просмотреть исходный код

experimental_replicate_to_logical_devices(
    tensor
)

Добавляет аннотацию, что tensor будет дублирован на все логические устройства.

Примечание: Этот API поддерживается только в TPUStrategy на данный момент. Это добавляет аннотацию к тензору tensor, указывая, что операции с tensor будут вызваны на всех логических устройствах.
# Initializing TPU system with 2 logical devices and 4 replicas.
resolver = tf.distribute.cluster_resolver.TPUClusterResolver(tpu='')
tf.config.experimental_connect_to_cluster(resolver)
topology = tf.tpu.experimental.initialize_tpu_system(resolver)
device_assignment = tf.tpu.experimental.DeviceAssignment.build(
    topology,
    computation_shape=[1, 1, 1, 2],
    num_replicas=4)
strategy = tf.distribute.TPUStrategy(
    resolver, experimental_device_assignment=device_assignment)

iterator = iter(inputs)

@tf.function()
def step_fn(inputs):
  images, labels = inputs
  images = strategy.experimental_split_to_logical_devices(
    inputs, [1, 2, 4, 1])

  # model() function will be executed on 8 logical devices with `inputs`
  # split 2 * 4  ways.
  output = model(inputs)

  # For loss calculation, all logical devices share the same logits
  # and labels.
  labels = strategy.experimental_replicate_to_logical_devices(labels)
  output = strategy.experimental_replicate_to_logical_devices(output)
  loss = loss_fn(labels, output)

  return loss

strategy.run(step_fn, args=(next(iterator),))

Args: tensor: Входной тензор для аннотации.

Возвращаемое значение
Аннотированный тензор с идентичным значением, как у tensor.

experimental_split_to_logical_devices

Просмотреть исходный код

experimental_split_to_logical_devices(
    tensor, partition_dimensions
)

Добавляет аннотацию, что tensor будет разделен на логические устройства.

Примечание: Этот API поддерживается только в TPUStrategy на данный момент. Это добавляет аннотацию к тензору tensor , указывающую, что операции над tensor будут распределены между несколькими логическими устройствами. Тензор tensor будет разделен по измерениям, указанным в partition_dimensions. Размеры tensor должны быть кратны соответствующим значениям в partition_dimensions.

Например, для системы с 8 логическими устройствами, если tensor — это тензор изображения с формой (размер_пакета, ширина, высота, канал) и partition_dimensions — это [1, 2, 4, 1], то tensor будет разделен на 2 по ширине и на 4 по высоте, а значения разбиений тензора будут переданы на 8 логических устройств.

# Initializing TPU system with 8 logical devices and 1 replica.
resolver = tf.distribute.cluster_resolver.TPUClusterResolver(tpu='')
tf.config.experimental_connect_to_cluster(resolver)
topology = tf.tpu.experimental.initialize_tpu_system(resolver)
device_assignment = tf.tpu.experimental.DeviceAssignment.build(
    topology,
    computation_shape=[1, 2, 2, 2],
    num_replicas=1)
strategy = tf.distribute.TPUStrategy(
    resolver, experimental_device_assignment=device_assignment)

iterator = iter(inputs)

@tf.function()
def step_fn(inputs):
  inputs = strategy.experimental_split_to_logical_devices(
    inputs, [1, 2, 4, 1])

  # model() function will be executed on 8 logical devices with `inputs`
  # split 2 * 4  ways.
  output = model(inputs)
  return output

strategy.run(step_fn, args=(next(iterator),))

Аргументы: tensor: Входной тензор для аннотации. partition_dimensions: Не вложенный список целых чисел с размером, равным рангу tensor , определяющий, как tensor будет разделен. Произведение всех элементов в partition_dimensions должно быть равно общему числу логических устройств на реплику.

Возбуждает
ValueError

1) Если размер partition_dimensions не равен рангу tensor , или 2) если произведение элементов partition_dimensions не соответствует числу логических устройств на реплику, определенному в спецификации устройства реализующей DistributionStrategy, или 3) если известный размер tensor не кратен соответствующему значению в partition_dimensions.

Возвращает
Анотированный тензор с идентичным значением, как у tensor.

reduce

Просмотреть исходный код

reduce(
    reduce_op, value, axis
)

Сведение value по репликам.

Учитывая значение на реплику, возвращенное run, например, потерю на пример, пакет будет разделен между всеми репликами. Эта функция позволяет агрегировать по репликам и необязательно по элементам пакета. Например, если у вас есть глобальный размер пакета 8 и 2 реплики, значения для примеров [0, 1, 2, 3] будут на реплике 0, а [4, 5, 6, 7] — на реплике 1. По умолчанию reduce просто агрегирует по репликам, возвращая [0+4, 1+5, 2+6, 3+7]. Это полезно, когда каждая реплика вычисляет скаляр или какое-то другое значение без измерения «пакет» (например, градиент). Чаще всего вам нужно будет агрегировать по глобальному пакету, что можно сделать, указав измерение пакета в качестве axis, обычно axis=0. В этом случае он вернет скаляр 0+1+2+3+4+5+6+7.

Если есть последний частичный пакет, вам нужно будет указать ось, чтобы результат имел согласованную форму по репликам. Итак, если последний пакет имеет размер 6 и разделен на [0, 1, 2, 3] и [4, 5], у вас возникнет несоответствие формы, если вы не укажете axis=0. Если вы укажете tf.distribute.ReduceOp.MEAN, используя axis=0 будет использоваться правильный знаменатель 6. Противопоставьте это вычислению reduce_mean для получения скалярного значения на каждой реплике и этой функции для усреднения этих средних значений, что даст разным значениям 1/8 и другим 1/4 разный вес.

Аргументы
reduce_op Значение tf.distribute.ReduceOp, определяющее, как следует комбинировать значения.
value «значение на реплику», например, возвращенное run, для объединения в один тензор.
axis Указывает измерение, по которому следует выполнять сокращение внутри тензора каждой реплики. Обычно следует устанавливать в измерение пакета или None для сокращения только по репликам (например, если тензор не имеет измерения пакета).
Возвращает
Tensor.

run

Просмотреть исходный код

run(
    fn, args=(), kwargs=None, options=None
)

Запуск fn на каждой реплике с заданными аргументами.

Выполняет операции, указанные в fn, на каждой реплике. Если args или kwargs содержат tf.distribute.DistributedValues, такие как те, которые создаются с помощью tf.distribute.DistributedDataset из tf.distribute.Strategy.experimental_distribute_dataset или tf.distribute.Strategy.experimental_distribute_datasets_from_function, при выполнении fn на определенной реплике, она будет выполнена с компонентом tf.distribute.DistributedValues, соответствующим этой реплике.

fn может вызвать tf.distribute.get_replica_context(), чтобы получить доступ к элементам, таким как all_reduce.

Все аргументы в args или kwargs должны быть либо вложенными тензорами, либо tf.distribute.DistributedValues, содержащими тензоры или составные тензоры.

Ключевая информация: В зависимости от реализации tf.distribute.Strategy и от того, включена ли жадная обработка, fn может вызываться один или несколько раз. Если fn анотировано с tf.function или tf.distribute.Strategy.run вызывается внутри tf.function, жадная обработка отключена и fn вызывается один раз (или один раз на реплику, если вы используете MirroredStrategy) для создания графа TensorFlow, который затем будет повторно использоваться для выполнения с новыми входными данными. В противном случае, если жадная обработка включена, fn будет вызываться каждый шаг, как обычный код Python.

Пример использования:

  1. Входной тензор-константа.
strategy = tf.distribute.MirroredStrategy()
tensor_input = tf.constant(3.0)
@tf.function
def replica_fn(input):
  return input*2.0
result = strategy.run(replica_fn, args=(tensor_input,))
result
<tf.Tensor: shape=(), dtype=float32, numpy=6.0>
  1. Входные значения DistributedValues.
strategy = tf.distribute.MirroredStrategy()
@tf.function
def run():
  def value_fn(value_context):
    return value_context.num_replicas_in_sync
  distributed_values = (
    strategy.experimental_distribute_values_from_function(
      value_fn))
  def replica_fn2(input):
    return input*2
  return strategy.run(replica_fn2, args=(distributed_values,))
result = run()
result
<tf.Tensor: shape=(), dtype=int32, numpy=2>
Аргументы
fn Функция для выполнения. Выходные данные должны быть tf.nest Tensors.
args (Необязательно) Позиционные аргументы для fn.
kwargs (Необязательно) Именованные аргументы для fn.
options (Необязательно) Экземпляр tf.distribute.RunOptions, определяющий параметры выполнения fn.
Возвращает
Объединенный результат fn по репликам. Структура возвращаемого значения такая же, как и возвращаемого значением fn. Каждый элемент структуры может быть tf.distribute.DistributedValues, объектами Tensor или Tensor (например, при запуске на одной реплике).

scope

Просмотреть исходный код

scope()

Менеджер контекста для установки текущей стратегии и распределения переменных.

Этот метод возвращает менеджер контекста и используется следующим образом:

strategy = tf.distribute.MirroredStrategy()
# Variable created inside scope:
with strategy.scope():
  mirrored_variable = tf.Variable(1.)
mirrored_variable
MirroredVariable:{
  0: <tf.Variable 'Variable:0' shape=() dtype=float32, numpy=1.0>
}
# Variable created outside scope:
regular_variable = tf.Variable(1.)
regular_variable
<tf.Variable 'Variable:0' shape=() dtype=float32, numpy=1.0>

Что происходит при входе в область Strategy.scope?

  • strategy устанавливается в глобальном контексте в качестве текущей стратегии. Внутри этой области tf.distribute.get_strategy() теперь вернет эту стратегию. За пределами этой области она возвращает стратегию по умолчанию без действий.
  • Вход в область также влечет за собой вход в «межрепликовый контекст». См. tf.distribute.StrategyExtended для объяснения межрепликовых и реплико-контекстов.
  • Создание переменной внутри scope перехватывается стратегией. Каждая стратегия определяет, как она хочет повлиять на создание переменных. Синхронные стратегии, такие как MirroredStrategy, TPUStrategy и MultiWorkerMiroredStrategy создают переменные, дублированные на каждой реплике, в то время как ParameterServerStrategy создает переменные на серверах параметров. Это делается с помощью пользовательского tf.variable_creator_scope.
  • В некоторых стратегиях может быть также введена область по умолчанию для устройства: в MultiWorkerMiroredStrategy, область устройства по умолчанию "/CPU:0" вводится на каждом работнике.
Примечание: Вход в область не автоматически распределяет вычисление, за исключением случаев использования высокоуровневого фреймворка обучения, такого как keras model.fit. Если вы не используете model.fit, вам необходимо использовать API strategy.run для явного распределения этого вычисления. См. пример в руководстве по пользовательской цикле обучения custom training loop tutorial.

Что должно быть в области и что должно быть вне ее?

Существует ряд требований к тому, что должно происходить внутри области. Однако в тех местах, где у нас есть информация о используемой стратегии, мы часто входим в область для пользователя, чтобы они не должны были делать это явно (т.е. вызов внутри или вне области допустим).

END_OF_DOCUMENT_MARKER
  • Всё, что создаёт переменные, которые должны быть распределёнными, должно находиться в strategy.scope. Это можно сделать, поместив их напрямую в область действия или используя другой API, например strategy.run или model.fit, для их ввода. Любые переменные, созданные вне области действия, не будут распределены и могут повлиять на производительность. Общие вещи, создающие переменные в TF: модели, оптимизаторы, метрики. Они всегда должны создаваться внутри области действия. Другим источником создания переменных может быть восстановление контрольной точки — когда переменные создаются лениво. Обратите внимание, что любая переменная, созданная внутри стратегии, содержит информацию о стратегии. Поэтому чтение и запись в эти переменные вне strategy.scope также могут работать без проблем, без необходимости ввода пользователем области действия.
  • Некоторые API стратегии (например, strategy.run и strategy.reduce), которые требуют нахождения в области действия стратегии, автоматически входят в эту область, что означает, что при использовании этих API вам не нужно входить в область действия самостоятельно.
  • Когда tf.keras.Model создаётся внутри strategy.scope, эта информация сохраняется. При вызове методов высокоуровневых фреймворков обучения, таких как model.compile, model.fit и т. д., на этой модели мы автоматически входим в область действия и используем эту стратегию для распределения обучения и т. д. Подробный пример см. в учебнике по распределённому Keras. Обратите внимание, что вызов просто model(..) не затрагивается — только высокоуровневые API фреймворков обучения. model.compile, model.fit, model.evaluate, model.predict и model.save можно вызывать как внутри, так и вне области действия.
  • Следующее может находиться как внутри, так и вне области действия: ** Создание наборов данных для входных данных ** Определение tf.function для представления шага обучения ** API сохранения, такие как tf.saved_model.save. Загрузка создаёт переменные, поэтому, если вы хотите обучить модель распределённым способом, это должно находиться внутри области действия. ** Сохранение контрольных точек. Как упоминалось выше, checkpoint.restore иногда может потребоваться находиться внутри области действия, если оно создаёт переменные.
Возвращает
Менеджер контекста.

© 2020 The TensorFlow Authors. All rights reserved.
Licensed under the Creative Commons Attribution License 3.0.
Code samples licensed under the Apache 2.0 License.
https://www.tensorflow.org/versions/r2.3/api_docs/python/tf/distribute/Strategy

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API