Результат отличается, когда я применяю torch.manual_seed перед загрузкой cuda () после загрузки модели - PullRequest
2 голосов
/ 14 февраля 2020

Я пытался убедиться, что мой код воспроизводим (всегда получаю одинаковые результаты)

Поэтому я применил следующие настройки перед моими кодами.

os.environ['PYTHONHASHSEED'] = str(args.seed)
random.seed(args.seed)
np.random.seed(args.seed)
torch.manual_seed(args.seed)
torch.cuda.manual_seed(args.seed)
torch.cuda.manual_seed_all(args.seed) # if you are using multi-GPU.
torch.backends.cudnn.benchmark = False
torch.backends.cudnn.deterministic = True

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

Howerver, когда я применил torch.manual_seed () после загрузки модели.

torch.manual_seed(args.seed)
model = Net()
Net.cuda()
torch.manual_seed(args.seed)
model = Net()
torch.manual_seed(args.seed)
Net.cuda()

Приведенные выше два результата были разными , Как мне понять эту ситуацию?

Реинициализируется ли seed после загрузки модели?

1 Ответ

0 голосов
/ 14 февраля 2020

Net.cuda() не влияет на генератор случайных чисел. Под капотом он просто вызывает cuda() для всех параметров модели. Так что в основном это несколько вызовов на Tensor.cuda().

https://github.com/pytorch/pytorch/blob/ecd3c252b4da3056797f8a505c9ebe8d68db55c4/torch/nn/modules/module.py#L293

Мы можем проверить это, выполнив следующее:

torch.random.manual_seed(42)
x = torch.rand(1)
x.cuda()
y = torch.rand(1)
y.cuda()
print(x, y)

# the above prints the same as below
torch.random.manual_seed(42)
print(torch.rand(1), torch.rand(1))

Итак это означает, что Net() использует генератор чисел для инициализации случайных весов в слоях.

torch.manual_seed(args.seed)
model = Net()
print(torch.rand(1))

# the below will print a different result
torch.manual_seed(args.seed)
model = Net()
torch.manual_seed(args.seed)
print(torch.rand(1))

Я бы рекомендовал сузить область управления случайными числами в исходном коде Python. Так что глобальный блок кода вне Модели не отвечает за то, как генерируются внутренние значения.

Проще говоря, передайте seed в качестве параметра __init__ модели.

model = Net(args.seed)
print(torch.rand(1))

Это заставит разработчиков всегда предоставлять начальное число для согласованности при использовании модели, и вы можете сделать параметр необязательным, если заполнение не выполняется ' т всегда необходимо.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...