Детерминизм в обновлениях тензорного градиента?

Итак, у меня есть очень простой NN-скрипт, написанный на Tensorflow, и я с трудом пытаюсь отследить, откуда взялась некоторая "случайность".

Я записал

  • Массы,
  • Градиенты,
  • логит

из моей сети, когда я тренируюсь, и для первой итерации ясно, что все начинается одинаково. У меня есть значение SEED как для считывания данных, так и значение SEED для инициализации весов сети. Те, которые я никогда не меняю.

Моя проблема в том, что, скажем, на второй итерации каждого повторного запуска я начинаю видеть, как градиенты расходятся (на небольшое количество, например, 1e-6 или около того). Однако со временем это, конечно, приводит к неповторяющемуся поведению.

Что может быть причиной этого? Я не знаю, откуда взялся любой возможный источник случайности...

Спасибо

3 ответа

Решение

Существует большая вероятность того, что вы можете получить детерминированные результаты, если ваша сеть работает на CPU (export CUDA_VISIBLE_DEVICES=), с одним потоком в пуле собственных потоков (tf.Session(config=tf.ConfigProto(intra_op_parallelism_threads=1)), один поток Python (нет многопоточных обработчиков очередей, которые вы получаете от ops, как tf.batch), и один четко определенный порядок работы. Также используя inter_op_parallelism_threads=1 может помочь в некоторых сценариях.

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

За исключением этого, вы можете выделить, какая операция недетерминированная, и попытаться избежать использования этой операции. Например, есть tf.add_n op, который ничего не говорит о порядке, в котором он суммирует значения, но разные порядки дают разные результаты.

Получение детерминированных результатов - трудная битва, потому что детерминизм находится в конфликте с производительностью, а производительность обычно является целью, которая привлекает больше внимания. Альтернативой попыткам иметь одинаковые числа при повторных запусках является фокусировка на числовой стабильности - если ваш алгоритм стабилен, вы получите воспроизводимые результаты (т. Е. Такое же количество ошибочных классификаций), даже если точные значения параметров могут немного отличаться

Как известно, тензор потока redu_sum определен как недетерминированный. Кроме того, lower_sum используется для вычисления градиентов смещения.

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

Я столкнулся с той же проблемой.. Рабочим решением для меня было:

1- использование tf.set_random_seed(1) для того, чтобы все функции TF имели одинаковое начальное число при каждом новом запуске

2- Обучение модели с использованием CPU, а не GPU, чтобы избежать недетерминированных операций GPU из-за точности.

Другие вопросы по тегам