1

I am trying to generate a function which generate random numbers from a uniform distribution Number_Rand() and another one which generates a random number given a certain seed Number_Rand_Seed() - so that it will always be the same for a fixed seed. However, I call the function Number_Rand_Seed() inside Number_Rand(), and for some reason the seed is also used to generate random numbers in Number_Rand(), so that its output is always the same. Shouldn't the seed be a local variable inside Number_Rand_Seed()? And shouldn't the seed be "renewed" everytime I call a np.random function (see, e.g., this answer)? What should I do then to "renew" the seed inside Number_Rand() and ignore the seed of Number_Rand_Seed()?

Here is an example:

def Number_Rand_Seed():
    np.random.seed(300121)
    a = np.random.uniform(0, 10)
    return a

def Number_Rand():
    a = Number_Rand_Seed()
    b = np.random.uniform(0, 10)
    return a, b

for i in range(3):
    print(Number_Rand()) 

The output is

(9.354120260352017, 2.552916103146633)
(9.354120260352017, 2.552916103146633)
(9.354120260352017, 2.552916103146633)

but I wanted something like

(9.354120260352017, 8.823425849537022)
(9.354120260352017, 5.950595370176398)
(9.354120260352017, 9.992406389398592)
Tucci
  • 13
  • 3
  • `np.random.seed` sets the seed for any calls to np.random. Its not scoped to functions – Chris Doyle Oct 28 '21 at 10:35
  • @ChrisDoyle ok I see it. Do you know why this is the case? – Tucci Oct 28 '21 at 10:40
  • Well `seed` is an attribute of the `np.random` module. so when you set the value your setting it in the np.random package. All the other random functions will be refering to this attribute. So your not setting seed at a function level. your setting at the scope of the np.random package level and all methods of np.random will refer to that vaule – Chris Doyle Oct 28 '21 at 10:45
  • with newer versions you can set up several random generators. Use one for `a` with the seed, and another 'normal' one for `b` – hpaulj Oct 28 '21 at 11:04

2 Answers2

1

If you want to reset the seed after setting it, you can use the function:

numpy.random.seed()

Which changes the seed to a random value, something like this:

def Number_Rand_Seed():
    np.random.seed(300121)
    a = np.random.uniform(0, 10)
    return a

def Number_Rand():
    a = Number_Rand_Seed()
    np.random.seed()
    b = np.random.uniform(0, 10)
    return a, b

for i in range(3):
    print(Number_Rand()) 
Zaid Al Shattle
  • 1,454
  • 1
  • 12
  • 21
0

In recent numpy versions, you can create separate random number generators using np.random.default_rng.

In the following I use that for a, while retaining the default for b:

In [35]: def Number_Rand_Seed():
    ...:     rng = np.random.default_rng(300121)
    ...:     a = rng.uniform(0, 10)
    ...:     return a
    ...: 
    ...: def Number_Rand():
    ...:     a = Number_Rand_Seed()
    ...:     b = np.random.uniform(0, 10)
    ...:     return a, b
    ...: 
    ...: for i in range(3):
    ...:     print(Number_Rand())
    ...: 
(9.98668624527619, 2.7036401003521817)
(9.98668624527619, 9.154952983315784)
(9.98668624527619, 1.413705001678095)
In [36]: Number_Rand()
Out[36]: (9.98668624527619, 5.274283695955279)

Or define a "default" rng outside the function. The rng in Number_Rand_Seed is local, and doesn't interfere with the rng defined outside it. Of course the code would be clearer to humans if I used different names.

...: rng = np.random.default_rng()
...: def Number_Rand():
...:     a = Number_Rand_Seed()
...:     b = rng.uniform(0, 10)
...:     return a, b
hpaulj
  • 221,503
  • 14
  • 230
  • 353