Vladimir Shebuniayeu
Vladimir Shebuniayeu

Reputation: 344

Python Numpy: Random number in a loop

I have such code and use Jupyter-Notebook

for j in range(timesteps):    
    a_int = np.random.randint(largest_number/2) # int version

and i get random numbers, but when i try to move part of code to the functions, i start to receive same number in each iteration

def create_train_data():        
    np.random.seed(seed=int(time.time()))     
    a_int = np.random.randint(largest_number/2) # int version
    return a

for j in range(timesteps):    
    c = create_train_data()  

Why it's happend and how to fix it? i think maybe it because of processes in Jupyter-Notebook

Upvotes: 4

Views: 5972

Answers (3)

Joooeey
Joooeey

Reputation: 3876

Hans Musgrave's answer is great if you are happy with pseudo-random numbers. Pseudo-random numbers are good for most applications but they are problematic if used for cryptography.

The standard approach for getting one truly random number is seeding the random number generator with the system time before pulling the number, like you tried. However, as Hans Musgrave pointed out, if you cast the time to int, you get the time in seconds which will most likely be the same throughout the loop. The correct solution to seed the RNG with a time is:

def create_train_data():        
    np.random.seed()     
    a_int = np.random.randint(largest_number/2) # int version
    return a

This works because Numpy already uses the computer clock or another source of randomness for the seed if you pass no arguments (or None) to np.random.seed:

Parameters: seed : {None, int, array_like}, optional Random seed used to initialize the pseudo-random number generator. Can be any integer between 0 and 2**32 - 1 inclusive, an array (or other sequence) of such integers, or None (the default). If seed is None, then RandomState will try to read data from /dev/urandom (or the Windows analogue) if available or seed from the clock otherwise.

It all depends on your application though. Do note the warning in the docs:

Warning The pseudo-random generators of this module should not be used for security purposes. For security or cryptographic uses, see the secrets module.

Upvotes: 0

SRT HellKitty
SRT HellKitty

Reputation: 597

The other answers are correct in saying that it is because of the seed. If you look at the Documentation From SciPy you will see that seeds are used to create a predictable random sequence. However, I think the following answer from another question regarding seeds gives a better overview of what it does and why/where to use it. What does numpy.random.seed(0) do?

Upvotes: 0

Hans Musgrave
Hans Musgrave

Reputation: 7111

The offending line of code is

np.random.seed(seed=int(time.time()))

Since you're executing in a loop that completes fairly quickly, calling int() on the time reduces your random seed to the same number for the entire loop. If you really want to manually set the seed, the following is a more robust approach.

def create_train_data():   
    a_int = np.random.randint(largest_number/2) # int version
    return a

np.random.seed(seed=int(time.time()))
for j in range(timesteps):
    c = create_train_data()

Note how the seed is being created once and then used for the entire loop, so that every time a random integer is called the seed changes without being reset.

Note that numpy already takes care of a pseudo-random seed. You're not gaining more random results by using it. A common reason for manually setting the seed is to ensure reproducibility. You set the seed at the start of your program (top of your notebook) to some fixed integer (I see 42 in a lot of tutorials), and then all the calculations follow from that seed. If somebody wants to verify your results, the stochasticity of the algorithms can't be a confounding factor.

Upvotes: 5

Related Questions