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 устанавливает seed для Python, seed для NumPy и seed для 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/versions/r2.9/api_docs/python/tf/config/experimental/enable_op_determinism