Мы не гарантируем идеально воспроизводимых результатов для всех версий или платформ PyTorch. Кроме того, результаты могут не совпадать между запусками ЦП и ГП, даже с идентичными начальными значениями.

Вы можете предпринять некоторые шаги, чтобы ограничить количество источников недетерминированного поведения для данной платформы, устройства и версии PyTorch. Вы можете контролировать источники случайности, которые могут вызывать различное поведение при нескольких запусках приложения. Затем вы можете настроить PyTorch так, чтобы он не использовал недетерминированные алгоритмы для некоторых операций, поэтому несколько вызовов этих операций с одним и тем же входом возвращали один и тот же результат.

Вот несколько протоколов, которым нужно следовать, чтобы воспроизвести результаты, учитывая пункты, указанные выше:

  • Вызовите эти строки кода перед запуском любой части вашего кода:
import random, os
import numpy as np                                                              import torch
                                                                  random.seed(seed)                                 os.environ['PYTHONHASHSEED'] = str(seed)                                 np.random.seed(seed)
torch.manual_seed(seed)
torch.cuda.manual_seed(seed)
torch.cuda.manual_seed_all(seed)  # if you are using multi-GPU.
torch.backends.cudnn.benchmark = False
torch.backends.cudnn.deterministic = True
  • вы можете создать функцию, используя приведенную выше строку кодов, и вызвать эту функцию с учетом конкретного начального значения в начале вашего основного кода.
  • Давайте определим, что будут делать приведенные выше строки кода:
random.seed(seed) 

случайное число генерируется в результате некоторой операции с предыдущим значением. Если предыдущего значения нет, то текущее время автоматически принимается за предыдущее значение. Мы можем предоставить это предыдущее значение самостоятельно, используя random.seed(x), где x может быть любым числом или строкой и т. д.

os.environ['PYTHONHASHSEED'] = str(seed)

Если эта переменная не установлена ​​или имеет значение random, для заполнения хэшей объектов str, bytes и datetime используется случайное значение. Если для параметра PYTHONHASHSEED задано целочисленное значение, оно используется в качестве фиксированного начального значения для генерации hash() типов, охваченных рандомизацией хэшей. Его цель — разрешить повторяющееся хеширование, например, для самотестирования самого интерпретатора или кластера процессов Python для совместного использования хэш-значений. Целое число должно быть десятичным числом в диапазоне [0,4294967295]. Указание значения 0 отключит рандомизацию хэша.

np.random.seed(seed)

Подобна random.seed(seed), но библиотека numpy.random содержит несколько дополнительных вероятностных распределений, обычно используемых в научных исследованиях, а также пару удобных функций для создания массивов случайных данных. Библиотека random.random немного легче и подойдет, если вы не занимаетесь научными исследованиями или другими видами деятельности в области статистики.

torch.manual_seed(seed)

manual_seed устанавливает случайное начальное число от генераторов случайных чисел pytorch

torch.cuda.manual_seed(seed)

Устанавливает начальное число для генерации случайных чисел для текущего графического процессора. Эту функцию безопасно вызывать, если CUDA недоступен; в этом случае он молча игнорируется.

torch.cuda.manual_seed_all(seed)  # if you are using multi-GPU.
torch.backends.cudnn.benchmark = False

Он отключает тестовый режим в cudnn.
Режим эталонного тестирования удобен, когда размеры входных данных для вашей сети не изменяются. Таким образом, cudnn будет искать оптимальный набор алгоритмов для данной конкретной конфигурации (что занимает некоторое время). Обычно это приводит к более быстрому времени выполнения. Но если ваши входные размеры меняются на каждой итерации, то cudnn будет проводить бенчмаркинг каждый раз, когда появляется новый размер, что может привести к ухудшению производительности во время выполнения.
Если установить для этого параметра значение False, каждый раз будут получаться одни и те же результаты.

torch.backends.cudnn.deterministic = True 
#A bool that, if True, causes cuDNN to only use deterministic convolution algorithms.

Вам нужно установить функцию инициализации воркеров, которые будут переданы в DataLoader:

def _init_fn(worker_id):
    np.random.seed(int(seed))

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

Выполнение описанных выше шагов приводит к тем же результатам. Если это не так, вы можете использовать внешнюю библиотеку, которая генерирует случайность, или недетерминированный модуль Pytorch. Если для вас важна воспроизводимость, вы можете отследить источник случайности, постепенно запуская свой код и проверяя результаты на каждом этапе. Убедитесь, что детерминированная часть вашего кода действительно детерминирована.

ИСПОЛЬЗОВАННАЯ ЛИТЕРАТУРА:

https://pytorch.org/docs/stable/notes/randomness.htm