Blog

Tensorflow: Op level seeding
Tensorflow allows specifying seeds (a process of specifying initial state to a random process) to an op. By using seeding, we can improve the randomness of the number generation process. However there is one issue. The op level seed only takes integer. If we supply an integer, it is not helpful in producing randomness as can be seen in the example below.
Here, we are using Tensorflow to create a series of 5 uniformly distributed random numbers in the range 1 to 59. We supply an op level seed (an initial state) of 30. We then begin a session and evaluate the graph. This produces a set of 5 random numbers. If we run the code multiple times in the same Python session, we will get exactly the same 5 values. So instead of increasing randomness, we produced the opposite.
import tensorflow as tf
# Op level seeding with value of 30
randno= tf.random_uniform(shape=(5, ), minval=1,
                           maxval=59, dtype=tf.int32, seed=30)
# Start a session, so that all these variables can be evaluated.
with tf.Session() as sess1:
randval = sess1.run(randno)
   print(randval)

[49 11  8 55 50]

Python's random module allows seeding with any Python object. However Tensorflow only accepts integers. So how can we produce better seeds that will increase randomness? To do just that, we will use the current date and time. The current date and especically the time changes frequently. By supplying an integer that changes rapidly, we can ensure randomness.
In the function below, we will supply a datetime object (dt) and convert it in to the number of seconds. If the datetime is not specified, we will assume the current time. The mktime function in time module takes a tuple of date time and converts it in to a float. We will use the int() to convert the float in to an integer and return it.
Finally we will test the function with two inputs. The first function call takes a datetime object that is 4 seconds before the current time and the second function call takes no input. If you notice the output of the first call is lower than the second call by 4 seconds as expected.
import time
from datetime import datetime, timedelta

def getinttime(dt=None):
'''
   If the timeval is None, we will assume that the seconds needs to
   be calculated based on current date and time. Else the provided time
   will be used.
   '''
   if not dt:
       return int(time.mktime(datetime.now().timetuple()))
   else:
       return int(time.mktime(dt.timetuple()))

# TESTING TIME 
# Provide a time 4 seconds before the current time as input
print(getinttime(datetime.now()-timedelta(seconds=4)))
# Provide no input
print(getinttime())

1499119087
1499119091

We will now use this function getinttime() as seed to the random_uniform function. If you run the code below multiples times, a different set of 5 numbers will be generated each time as the time changes and hence the initial state (seed) as well. So we made our random generation more random.
import tensorflow as tf
# Op level seeding with value of 30
randno= tf.random_uniform(shape=(5, ), minval=1,
                    maxval=59, dtype=tf.int32, seed=getinttime())
# Start a session, so that all these variables can be evaluated.
with tf.Session() as sess1:
    randval = sess1.run(randno)
    print(randval)

[41 30 19  6 38]

 

 

Tag: Tensorflow

Comments