tf.config.experimental.enable_op_determinism
Настраивает операции TensorFlow для выполнения в детерминированном режиме.
tf.config.experimental.enable_op_determinism()
При включенном режиме детерминированности операций TensorFlow операции будут детерминированными. Это означает, что если операция выполняется несколько раз с одними и теми же входными данными на одном и том же оборудовании, она будет выдавать точно такие же результаты каждый раз. Это полезно для отладки моделей. Обратите внимание, что детерминированность, как правило, достигается за счёт снижения производительности, поэтому ваша модель может работать медленнее, когда режим детерминированности операций включен.
Если вы хотите, чтобы ваша программа TensorFlow работала в детерминированном режиме, поместите следующий код в начале своей программы.
tf.keras.utils.set_random_seed(1) tf.config.experimental.enable_op_determinism()
Вызов tf.keras.utils.set_random_seed устанавливает семена для Python, NumPy и TensorFlow. Установка этих семян необходима, чтобы гарантировать, что все случайные числа, генерируемые вашей программой, также будут детерминированными.
По умолчанию режим детерминированности операций не включен, поэтому операции могут возвращать разные результаты при выполнении с одними и теми же входными данными. Эти различия часто вызваны использованием асинхронных потоков внутри операции, которые непредсказуемо изменяют порядок добавления чисел с плавающей запятой. Большинство случаев недетерминированности возникают на графических процессорах (GPU), которые используют тысячи аппаратных потоков для выполнения операций. Включение детерминированности направляет такие операции на использование другого алгоритма, не использующего потоки непредсказуемым образом.
Ещё одним потенциальным источником недетерминированности является обработка данных на основе tf.data. Обычно это может вносить непредсказуемость из-за использования параллелизма в методах, таких как Dataset.map, генерирующих входные данные или выполняющих состоятельные операции в непредсказуемом порядке. Включение режима детерминированности устранит такие источники непредсказуемости.
Включение детерминированности, скорее всего, замедлит работу вашей модели или обработки данных tf.data. Например, Dataset.map может замедлиться на несколько порядков величины, если функция map содержит случайные операции или другие состоятельные операции. Подробности см. в разделе «Детерминированность и tf.data» ниже. В будущих версиях TensorFlow мы планируем улучшить производительность детерминированности, особенно для распространённых сценариев, таких как Dataset.map.
Некоторые операции могут вызвать UnimplementedError, так как у них ещё нет детерминированного реализации. Кроме того, из-за ошибок некоторые операции могут быть недетерминированными и не вызывать UnimplementedError. Если вы столкнетесь с такими операциями, пожалуйста, отправьте сообщение в сообщество разработчиков.
Пример включения детерминированности. Операция tf.nn.softmax_cross_entropy_with_logits выполняется несколько раз, и вывод показан одинаковым каждый раз. Этот пример, скорее всего, не пройдёт при выполнении на GPU, если детерминированность не включена, потому что tf.nn.softmax_cross_entropy_with_logits по умолчанию использует недетерминированный алгоритм на GPU.
labels = tf.random.normal((1, 10000))
logits = tf.random.normal((1, 10000))
output = tf.nn.softmax_cross_entropy_with_logits(labels=labels,
logits=logits)
for _ in range(5):
output2 = tf.nn.softmax_cross_entropy_with_logits(labels=labels,
logits=logits)
tf.debugging.assert_equal(output, output2)
Создание детерминированных моделей
Вы можете сделать свои модели детерминированными, включив режим детерминированности операций. Это означает, что вы можете обучить модель и завершить каждое выполнение с точно такими же обучаемыми переменными. Это также означает, что выводы вашей предварительно обученной модели будут точно такими же при каждом запуске. Как правило, модели можно сделать детерминированными, просто установив семена и включив режим детерминированности операций, как в примере выше. Однако, чтобы гарантировать, что ваша модель работает в детерминированном режиме, необходимо выполнить все следующие требования:
- Вызовите
tf.config.experimental.enable_op_determinism(), как указано выше. - Восстановите любые псевдослучайные генераторы чисел (PRNG), которые вы используете, например, установив семена для стандартных PRNG в TensorFlow, Python и NumPy, как указано выше. Обратите внимание, что некоторые новые классы NumPy, такие как
numpy.random.default_rng, игнорируют глобальное семя NumPy, поэтому семя необходимо явно передавать таким классам, если они используются. - Используйте одинаковую конфигурацию оборудования при каждом запуске.
- Используйте одинаковую программную среду при каждом запуске (ОС, контрольные точки, версия CUDA и TensorFlow, переменные среды и т. д.). Обратите внимание, что детерминированность не гарантируется в разных версиях TensorFlow.
- Не используйте конструкции вне TensorFlow, которые являются не детерминированными, такие как чтение из
/dev/randomили использование нескольких потоков/процессов таким образом, что это влияет на поведение TensorFlow. - Убедитесь, что ваша цепочка входных данных детерминирована. Если вы используете
tf.data, это делается автоматически (за счёт производительности). См. «Детерминированность и tf.data» ниже для получения дополнительной информации. - Не используйте
tf.compat.v1.Sessionиtf.distribute.experimental.ParameterServerStrategy, которые могут вносить непредсказуемость. Помимо операций (включаяtf.dataоперации), это единственные известные потенциальные источники непредсказуемости в TensorFlow (если вы найдёте больше, пожалуйста, отправьте сообщение в сообщество разработчиков). Обратите внимание, чтоtf.compat.v1.Sessionтребуется для использования API TF1, поэтому детерминированность не гарантируется при использовании API TF1. - Не используйте пользовательские операции, которые не являются детерминированными.
Дополнительные сведения о детерминированности
Для того, чтобы состоятельные операции были детерминированными, состояние системы должно быть одинаковым при каждом выполнении операции. Например, результат tf.Variable.sparse_read (очевидно) зависит как от значения переменной, так и от параметра функции indices. При включении режима детерминированности побочные эффекты состоятельных операций являются детерминированными.
Случайные операции TensorFlow, такие как tf.random.normal, вызовут RuntimeError, если режим детерминированности включен, а семя не установлено. Однако попытка сгенерировать недетерминированные случайные числа с помощью Python или NumPy не вызовет таких ошибок. Убедитесь, что вы помните о настройке семян Python и NumPy. Вызов tf.keras.utils.set_random_seed — простой способ установить все три семени.
Обратите внимание, что задержка, потребление памяти, пропускная способность и другие характеристики производительности не делаются детерминированными путём включения детерминированности операций. Детерминированы только результаты операций и побочные эффекты. Кроме того, модель может непредсказуемо вызвать tf.errors.ResourceExhaustedError из-за нехватки памяти, поскольку потребление памяти не детерминировано.
Детерминированность и tf.data
Включение детерминированных операций делает tf.data детерминированным несколькими способами:
- Для методов набора данных с аргументом
deterministic, например,Dataset.mapиDataset.batch, аргументdeterministicпереопределяется наTrueнезависимо от его настройки. - Параметр
tf.data.Option.experimental_deterministicпереопределяется наTrueнезависимо от его настройки. - В
Dataset.mapиDataset.interleave, если функция map или interleave содержит состоятельные случайные операции или другие состоятельные операции, функция будет выполняться последовательно, а не параллельно. Это означает, что аргументnum_parallel_callsкmapиinterleaveфактически игнорируется. - Кэширование с помощью
Dataset.prefetchбудет отключено, если любая функция, выполняемая в рамках цепочки входных данных, имеет определённые состоятельные операции. Аналогично, любой метод набора данных с аргументомnum_parallel_callsбудет запущен последовательно, если любая функция в цепочке входных данных имеет такие состоятельные операции. Старые случайные операции, такие какtf.random.normal, не вызовут изменения таких наборов данных, но большинство других состоятельных операций — да.
К сожалению, из-за (3), производительность может значительно снизиться, когда состоятельные операции используются в Dataset.map, поскольку функция map больше не выполняется параллельно. Распространённым примером состоятельных операций, используемых в Dataset.map, являются случайные операции, такие как tf.random.normal, которые обычно используются для искажений. Одним из способов решения этой проблемы является использование бессостоятельных случайных операций вместо них. В качестве альтернативы, вы можете перенести все случайные операции в свой отдельный вызов Dataset.map, сделав исходный вызов Dataset.map бессостоятельным и, таким образом, избежав необходимости сериализации его выполнения.
(4) также может снизить производительность, но происходит реже, чем (3), поскольку старые случайные операции не заставляют (4) вступать в силу. Однако, в отличие от (3), когда в пользовательской функции есть неслучайные состоятельные операции, все наборы данных map и interleave затронуты, а не только map или interleave наборы данных с функцией, имеющей состоятельные операции. Кроме того, prefetch наборы данных и любой набор данных с аргументом num_parallel_calls также затронуты.
© 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/config/experimental/enable_op_determinism