tf.random.Normal() not generating different value

Viewed 444

I am trying to use tf.random.normal(mean, stddev) where both mean and stddev are like following

mean = np.array([0.5, 0.9, 0.5, 0.8])
stddev = np.array([0.1, 0.08, 0.1, 0.15])

but for same pair the generated values are always same

tf.random.normal([1],mean,stddev, tf.float32).numpy()

for example,

array([0.52523446, 0.92018753, 0.52523446, 0.83785176], dtype=float32)

every time i run the outputs are different but the generated value for same parameters are always same.

I want to avoid getting 0.52523446 twice. How can I ensure getting random results even if there are same mean, stddev pair mutiple times?

3 Answers

I would suggest to check this. Instead of using tf.random.normal, set a RNG and then use it to get reproducible results and handle the behaviour of it. You can do something like that:

TF_RNG1 = tf.random.Generator.from_seed(seed=1312)  # Set the RNG for example in global scope.


def random_samples(num_samples): # Call this func whenever you want new samples from each distr.
    mean_ar = np.array([0.5, 0.9, 0.5, 0.8])
    stddev_ar = np.array([0.1, 0.08, 0.1, 0.15])
    a = np.empty([0, num_samples])
    for mean, stddev in zip(mean_ar, stddev_ar):
        a = np.vstack([a, TF_RNG1.normal([num_samples], mean=mean, stddev=stddev).numpy()])
    return a

example_1 = random_samples(num_samples=2)
example_2 = random_samples(num_samples=2)


Which returns two samples from each random distribution define from means and stddvs:

[[0.64746159 0.28875741]
 [1.07901216 0.96285772]
 [0.68051326 0.48751786]
 [1.10349631 0.70149976]]
[[0.52678907 0.34632182]
 [1.1144588  0.97134733]
 [0.5085696  0.70959347]
 [0.78321898 0.57734704]]

This works for me:

tf.random.normal([4],mean,stddev, tf.float32).numpy()

Yields:

tf.random.normal([4],mean,stddev, tf.float32).numpy()
Out[20]: array([0.48897663, 0.94428   , 0.4471385 , 0.8360004 ], dtype=float32)

tf.random.normal([4],mean,stddev, tf.float32).numpy()
Out[21]: array([0.7033355 , 0.93688935, 0.43403187, 0.5589987 ], dtype=float32)

From https://www.tensorflow.org/guide/random_numbers and my own experience, tf.random.normal as well as any other APIs that used the old mechanism to generate random numbers are buggy and unreliable. tf.random.Generator is the new mechanism for generating random numbers. It internally used tf.Variable to make sure things work as expected.

You can vectorize the generation of random numbers from multiple normal distributions with different means and variances like this:

@tf.function
def vectorized_rand_gen(rand_gen,means,stds,n):
  return rand_gen.normal((n,)) * stds + means

rand_gen = tf.random.Generator.from_seed(8883)
means = tf.constant([5.0,10.0,5.0,1000.0])
stds =  tf.constant([1.0,2.0 ,1.0,4.0])

print(vectorized_rand_gen(rand_gen,means,stds,4))
print(vectorized_rand_gen(rand_gen,means,stds,4))
print(vectorized_rand_gen(rand_gen,means,stds,4))

Expected outputs:

tf.Tensor([   4.797662    11.434001     5.6649933 1000.5652   ], shape=(4,), dtype=float32)
tf.Tensor([   4.5091076    9.176998     4.685211  1005.33514  ], shape=(4,), dtype=float32)
tf.Tensor([   4.285514    8.202658    6.342854 1004.9558  ], shape=(4,), dtype=float32)
Related