I'm using np.random.uniform()
to generate a number in a class. Surprisingly, when I run the code, I can't see any expected changes in my results. On the other hand, when I use uniform()
from python built-in packages, I see the changes in my results and that's obviously normal.
Are they really the same or is there anything tricky in their implementation?
Thank you in advance!
CodePudding user response:
Create one module, say, blankpaper.py
, with only two lines of code
import numpy as np
np.random.seed(420)
Then, in your main script, execute
import numpy as np
import blankpaper
print(np.random.uniform())
You should be getting exactly the same numbers.
When a module or library sets np.random.seed(some_number)
, it is global. Behind the numpy.random.*
functions is an instance of the global RandomState
generator, emphasis on the global
.
It is very likely that something that you are importing is doing the aforementioned.
Change the main script to
import numpy as np
import blankpaper
rng = np.random.default_rng()
print(rng.uniform())
and you should be getting new numbers each time.
default_rng
is a constructor for the random number class, Generator
. As stated in the documentation,
This function does not manage a default global instance.
In reply to the question, "[a]re you setting a seed first?", you said
Yes, I'm using it but it doesn't matter if I don't use a seed or change the seed number. I checked it several times.
Imagine we redefine blankpaper.py
to contain the lines
import numpy as np
def foo():
np.random.seed(420)
print("I exist to always give you the same number.")
and suppose your main script is
import numpy as np
import blankpaper
np.random.seed(840)
blankpaper.foo()
print(np.random.uniform())
then you should be getting the same numbers as were obtained from executing the first main script (top of the answer).
In this case, the setting of the seed is hidden in one of the functions in the blankpaper
module, but the same thing would happen if blankpaper.foo
were a class and blankpaper.foo
's __init__()
method set the seed.
So this setting of the global seed can be quite "hidden".
Note also that the above also applies for the functions in the random module
The functions supplied by this module are actually bound methods of a hidden instance of the random.Random class. You can instantiate your own instances of Random to get generators that don’t share state.
So when uniform()
from the random
module was generating different numbers each time for you, it was very likely because you nor some other module set the seed shared by functions from the random
module.
In both numpy
and random
, if your class or application wants to have it's own state, create an instance of Generator
from numpy
or Random
from random
(or SystemRandom
for cryptographically-secure randomness). This will be something you can pass around within your application. It's methods will be the functions in the numpy.random
or random
module, only they will have their own state (unless you explicitly set them to be equal).
Finally, I am not claiming that this is exactly what is causing your problem (I had to make a few inferences since I cannot see your code), but this is a very likely reason.
Any questions/concerns please let me know!