Home > Back-end >  Difference Between np.random.uniform() and uniform() using built-in python packages
Difference Between np.random.uniform() and uniform() using built-in python packages

Time:04-17

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!

  • Related