generates variable seeds upon each call to a rngusing function in keras all rngusing methods such as keras random normal are stateless meaning that if you pass an integer seed to them such as seed42 they will return the same values at each call in order to get different values at each call you must use a seedgenerator instead as the seed argument the seedgenerator object is stateful example python seedgen keras random seedgeneratorseed42 values keras random normalshape2 3 seedseedgen newvalues keras random normalshape2 3 seedseedgen usage in a layer python class dropoutkeras layer def initself kwargs super initkwargs self seedgenerator keras random seedgenerator1337 def callself x trainingfalse if training return keras random dropout x rate0 5 seedself seedgenerator return x use 1 to create a copy this produces a sequence of nearunique numbers between 0 and 1m generates variable seeds upon each call to a rng using function in keras all rng using methods such as keras random normal are stateless meaning that if you pass an integer seed to them such as seed 42 they will return the same values at each call in order to get different values at each call you must use a seedgenerator instead as the seed argument the seedgenerator object is stateful example python seed_gen keras random seedgenerator seed 42 values keras random normal shape 2 3 seed seed_gen new_values keras random normal shape 2 3 seed seed_gen usage in a layer python class dropout keras layer def __init__ self kwargs super __init__ kwargs self seed_generator keras random seedgenerator 1337 def call self x training false if training return keras random dropout x rate 0 5 seed self seed_generator return x use 1 to create a copy this produces a sequence of near unique numbers between 0 and 1m
import random as python_random

import numpy as np

from keras import backend
from keras.api_export import keras_export
from keras.backend.common import global_state
from keras.utils import jax_utils


@keras_export("keras.random.SeedGenerator")
class SeedGenerator:
    

    def __init__(self, seed=None, **kwargs):
        custom_backend = kwargs.pop("backend", None)
        if kwargs:
            raise ValueError(f"Unrecognized keyword arguments: {kwargs}")
        if custom_backend is not None:
            self.backend = custom_backend
        else:
            self.backend = backend

        self._initial_seed = seed
        if seed is None:
            seed = make_default_seed()

        if not isinstance(seed, int):
            raise ValueError(
                "Argument `seed` must be an integer. " f"Received: seed={seed}"
            )

        def seed_initializer(*args, **kwargs):
            dtype = kwargs.get("dtype", None)
            return self.backend.convert_to_tensor([seed, 0], dtype=dtype)

        self.state = self.backend.Variable(
            seed_initializer,
            shape=(2,),
            dtype="uint32",
            trainable=False,
            name="seed_generator_state",
        )

    def next(self, ordered=True):
        seed_state = self.state
        
        new_seed_value = seed_state.value * 1
        if ordered:
            increment = self.backend.convert_to_tensor(
                np.array([0, 1]), dtype="uint32"
            )
            self.state.assign(seed_state + increment)
        else:
            
            
            self.state.assign((seed_state + 1) * 5387 % 933199)
        return new_seed_value


def global_seed_generator():
    if jax_utils.is_in_jax_tracing_scope():
        raise ValueError(
            "When tracing a JAX function, "
            "you should only use seeded random ops, e.g. "
            "you should create a `SeedGenerator` instance, attach it "
            "to your layer/model, and pass the instance as the `seed` "
            "argument when calling random ops. Unseeded random ops "
            "would get incorrectly traced by JAX and would become constant "
            "after tracing."
        )
    gen = global_state.get_global_attribute("global_seed_generator")
    if gen is None:
        gen = SeedGenerator()
        global_state.set_global_attribute("global_seed_generator", gen)
    return gen


def make_default_seed():
    return python_random.randint(1, int(1e9))


def draw_seed(seed):
    from keras.backend import convert_to_tensor

    if isinstance(seed, SeedGenerator):
        return seed.next()
    elif isinstance(seed, int):
        return convert_to_tensor([seed, 0], dtype="uint32")
    elif seed is None:
        return global_seed_generator().next(ordered=False)
    raise ValueError(
        "Argument `seed` must be either an integer "
        "or an instance of `SeedGenerator`. "
        f"Received: seed={seed} (of type {type(seed)})"
    )