0

I am trying to save the current random generator state of application to replicate a lot of random action taken during the process.

import random
import pickle
from Model import Resnet
def main():
    fileName = "09-08-2022T200803"
    with open("data/" + fileName + ".txt", "rb") as rb:
        data = pickle.load(rb)
        random.setstate(data[0][0])
#data[0][0] is some saved seed object, the file is only appended, it is always the same object

    myNetwork = Resnet.Network()
    model = myNetwork.getModel()

    playGame(model, 4, fileName)
Turn: 14, Action:251
Turn: 15, Action:33
Turn: 15, Action:186
Turn: 15, Action:16
GAME_FINISHED

However, when I close the program and run it again, the results differ:

Turn: 13, Action:251
Turn: 14, Action:29
Turn: 14, Action:251
Turn: 15, Action:33
GAME_FINISHED

Can it be done so I will keep the random generator state in file so I can debug the particular game that didn't work? (Game is 100% random as for now)

I have already tried to random.setstate() just before game and run it several times in the same application(in a loop) and it did play exactly the same games, however - when I rerun(stop->run) the program, it did not work, results differed between application runs (probably because it was after Resnet.Network() initialization)

The different approach which gave me exact the same results in one application run, but still different in between runs:

def main():
    myNetwork = Resnet.Network()
    model = myNetwork.getModel()

    fileName = "09-08-2022T200803"
    with open("data/"+fileName+".txt", "rb") as rb:
        while True:
            data = pickle.load(rb)
            playGame(model, 4, fileName, data[0][0])
#data[0][0] is same object each time I read the file(that's how its saved), therefore it works in single application run



def playGame(model, simulations, fileName, seedObject = None):
    if seedObject != None:
        random.setstate(seedObject)
    # ... game
Lidbey
  • 251
  • 1
  • 12
  • You don't show in your code where you are capturing the state of the `random` module. Is it possible that you are capturing it later, after it has been used and writing it then to your pickled file? In that case, it isn't going to be the same. You need to capture it right at the start – AirSquid Aug 09 '22 at 19:28
  • I am always using the same state (the file is not overwritten), so the first object I read is always the same object - therefore the state is the same in-between program runs. I think it would lead to higher complexity if I put code for saving the state – Lidbey Aug 09 '22 at 19:33
  • 1
    note that you might not get the same result across different machines. functions from different (implementations / versions) of the maths library can end up with slightly different numbers and this might affect your reproducibility. e.g. https://stackoverflow.com/a/72819537/1358308 – Sam Mason Aug 10 '22 at 09:21

2 Answers2

1

There are some elements of your code that are missing... specifically when you capture the state. If you are setting it the same before every execution, you should get the same result. Below is an example that will generate same results by capturing the state used in the first run (whether or not it is initially assigned).

import random

def game(rolls = 5, r_state=None):
    if r_state is not None:
        random.setstate(r_state)
    new_state = random.getstate()
    game_results = []
    for roll in range(rolls):
        game_results.append(random.randint(1,6)) # a roll of a die
    return game_results, new_state


def game_runner():
    r_state = None
    for trial in range(3):  # 3 games...
        results, new_state = game(r_state=r_state)
        r_state = new_state
        print(results)

if __name__=='__main__':
    game_runner()

Output:

[3, 2, 2, 3, 5]
[3, 2, 2, 3, 5]
[3, 2, 2, 3, 5]
AirSquid
  • 10,214
  • 2
  • 7
  • 31
  • Thank you for your help, it occurs that the problem occured in the part of code that used numpy arrays and tensorflow, as they did use different random module than 'random' therefore I needed to seed it with pseudo-random – Lidbey Aug 09 '22 at 19:45
  • I think it would be better practice to just capture their state and hold onto it, rather than assigning to both of them, but that is a small nit. – AirSquid Aug 09 '22 at 19:47
0

I have managed to find a solution, the deal was that both numpy and tensorflow used different seeding than random module:

import numpy as np
import tensorflow as tf
import random
import pickle
from Model import Resnet
def main():
    fileName = "09-08-2022T200803"
    with open("data/"+fileName+".txt", "rb") as rb:
        while True:
            data = pickle.load(rb)
            random.setstate(data[0][0])
            np.random.seed(random.randrange(999999999))
            tf.random.set_seed(random.randrange(999999999))
            myNetwork = Resnet.Network()
            model = myNetwork.getModel()
            playGame(model, 4, fileName, data[0][0])
Lidbey
  • 251
  • 1
  • 12