Hi all,
I would like to write an object that generates a deterministic output given a seed. Without the given seed, I’d like it to return the seed that would generate the same output. Furthermore, it should be aware of any manual seed set before its creation. I think I’m close, but I’m not quite there yet. Context: reproducibility of random transforms in TorchIO.
I’ve read the docs on reproducibility, torch.Generator
, fork_rng
, etc., but I might have missed something.
This is some code I’m playing with, called script.py
:
import sys
import torch
if len(sys.argv) > 1:
seed = int(sys.argv[1])
torch.manual_seed(seed)
print('Initial seed:', seed)
else:
print('No initial seed')
def random_stuff(seed=None):
with torch.random.fork_rng():
if seed is None:
seed = torch.seed()
else:
torch.manual_seed(seed & (2**63 - 1))
number = int(1000 * torch.rand(1).item())
return number, seed
print('random_stuff(seed=None):', random_stuff(seed=None))
nice_number, nice_seed = random_stuff(seed=None)
print('random_stuff(seed=None) to reproduce:', nice_number, nice_seed)
print('random_stuff(seed=42):', random_stuff(seed=42))
print('random_stuff(seed=42):', random_stuff(seed=42))
print('1000 * int(torch.rand(1).item()):', int(1000 * torch.rand(1).item()))
print('Reproduced result:', random_stuff(seed=nice_seed)[0])
print('1000 * int(torch.rand(1).item()):', int(1000 * torch.rand(1).item()))
print()
I call this command:
$ for i in {,,99,99}; do python script.py $i; done
And get this output, that I have commented:
No initial seed
random_stuff(seed=None): (233, 1238635228448488131)
random_stuff(seed=None) to reproduce: 270 16876508215961374208
random_stuff(seed=42): (882, 42)
random_stuff(seed=42): (882, 42)
1000 * int(torch.rand(1).item()): 154
Reproduced result: 270
1000 * int(torch.rand(1).item()): 771
No initial seed
random_stuff(seed=None): (873, 6207067658288732991)
random_stuff(seed=None) to reproduce: 83 9352679628244516342
random_stuff(seed=42): (882, 42)
random_stuff(seed=42): (882, 42)
1000 * int(torch.rand(1).item()): 591
Reproduced result: 83
1000 * int(torch.rand(1).item()): 20
Initial seed: 99
random_stuff(seed=None): (442, 4463515504174338291)
random_stuff(seed=None) to reproduce: 919 5178903995377210757
random_stuff(seed=42): (882, 42)
random_stuff(seed=42): (882, 42)
1000 * int(torch.rand(1).item()): 103
Reproduced result: 919
1000 * int(torch.rand(1).item()): 970
Initial seed: 99
random_stuff(seed=None): (95, 3538104565691272705)
random_stuff(seed=None) to reproduce: 24 12991252712705207801
random_stuff(seed=42): (882, 42)
random_stuff(seed=42): (882, 42)
1000 * int(torch.rand(1).item()): 103
Reproduced result: 24
1000 * int(torch.rand(1).item()): 970
I would like the first two (and second to last) lines of the 4th block to be the same as the ones in the 3rd block.
Do you know which direction I should follow here? I feel like I should somehow get the “current seed” instead of calling torch.seed()
. I’ve tried different things involving e.g. torch.default_generator
, with no luck.