it-swarm.com.de

Reproduzierbare Ergebnisse im Tensorflow mit tf.set_random_seed

Ich versuche, N Sätze unabhängiger Zufallszahlen zu erzeugen. Ich habe einen einfachen Code, der das Problem für 3 Sätze von 10 Zufallszahlen zeigt. Ich stelle fest, dass die Ergebnisse verschiedener Läufe nicht gleich aussehen, obwohl ich den tf.set_random_seed zum Einstellen des Startwerts verwende. Jede Hilfe oder Kommentare werden sehr geschätzt.

(py3p6) bash-3.2$ cat test.py 
import tensorflow as tf
for i in range(3):
  tf.set_random_seed(1234)
  generate = tf.random_uniform((10,), 0, 10)
  with tf.Session() as sess:
    b = sess.run(generate)
    print(b)

Dies ist die Ausgabe des Codes:

# output :
[9.604688  5.811516  6.4159    9.621765  0.5434954 4.1893444 5.8865128
 7.9785547 8.296125  8.388672 ]
[8.559105  3.2390785 6.447526  8.316823  1.6297233 1.4103293 2.647568
 2.954973  6.5975866 7.494894 ]
[2.0277488 6.6134906 0.7579422 4.6359386 6.97507   3.3192968 2.866236
 2.2205782 6.7940736 7.2391043]

Ich möchte etwas wie

[9.604688  5.811516  6.4159    9.621765  0.5434954 4.1893444 5.8865128
 7.9785547 8.296125  8.388672 ]
[9.604688  5.811516  6.4159    9.621765  0.5434954 4.1893444 5.8865128
 7.9785547 8.296125  8.388672 ]
[9.604688  5.811516  6.4159    9.621765  0.5434954 4.1893444 5.8865128
 7.9785547 8.296125  8.388672 ]

Update 1: Der Grund, aus dem ich den Seed-Initialisierer in die for-Schleife gestellt hatte, war, dass ich sie anders einstellen möchte (zB verschiedene MCMC-Läufe). Dies ist mein Code, der die Arbeit erledigt, aber ich bin nicht sicher, ob er effizient ist. Grundsätzlich generiere ich ein paar zufällige Samen zwischen 0 und 2 ^ 32-1 und ändere den Samen in jedem Lauf. Jede Hilfe oder Kommentare, um den Arbeitsspeicher und den Arbeitsspeicher effizienter zu gestalten, werden sehr geschätzt.

import numpy as np
import tensorflow as tf
global_seed = 42
N_chains = 5
np.random.seed(global_seed)
seeds = np.random.randint(0, 4294967295, size=N_chains)

for i in range(N_chains):
    tf.set_random_seed(seeds[i])
    .... some stuff ....
    kernel_initializer = tf.random_normal_initializer(seed=seeds[i])
    .... some stuff
    with tf.Session() as sess:
         .... some stuff .....
 .
 .
 .
4
Mehdi Rezaie

Für Tensorflow 2.0 tf.random.set_random_seed(seed) geändert in tf.random.set_seed(seed).

siehe TF docs:

5
mx_muc

Beim Tensorflow beruht eine zufällige Operation auf zwei verschiedenen Startwerten: einem globalen Startwert, der durch tf.set_random_seed festgelegt wird, und einem Operationsstartwert, der der Operation als Argument zur Verfügung gestellt wird. Weitere Einzelheiten zu ihrer Beziehung finden Sie in den Dokumenten .

Sie haben für jede Zufallsoperation einen anderen Startzeitpunkt, da jede Zufallsoperation ihren eigenen internen Status für die Pseudozufallszahlengenerierung beibehält. Der Grund dafür, dass jeder Zufallsgenerator seinen eigenen Status beibehält, besteht darin, robust zu sein, wenn er geändert wird: Wenn er den gleichen Status verwendet, wird das Hinzufügen eines neuen Zufallsgenerators irgendwo in Ihrem Graphen die Werte ändern, die von allen anderen Generatoren erzeugt werden mit einem Samen.

Warum haben wir dieses duale System von globalen und per-op-Samen? Nun, eigentlich ist das globale Saatgut nicht notwendig. Es ist aus Bequemlichkeitsgründen da: Es erlaubt, alle zufälligen Op-Seeds gleichzeitig auf einen anderen und deterministischen (wenn auch unbekannten) Wert zu setzen, ohne sie alle ausführlich durchgehen zu müssen.

Wenn nun ein globaler Startwert gesetzt wird, nicht jedoch der op-Startwert,

Das System wählt deterministisch einen Operationsstartwert in Verbindung mit dem Startwert auf Diagrammebene aus, sodass er eine eindeutige zufällige Sequenz erhält.

Genauer gesagt ist der bereitgestellte Startwert die ID der letzten im aktuellen Diagramm erstellten Operation. Demzufolge sind global ausgesetzte Zufallsoperationen extrem anfällig für Änderungen in der Grafik, insbesondere für diejenigen, die vor sich selbst erstellt wurden.

Zum Beispiel,

import tensorflow as tf
tf.set_random_seed(1234)
generate = tf.random_uniform(())
with tf.Session() as sess:
  print(generate.eval())
  # 0.96046877

Wenn wir jetzt einen Knoten erstellen, ändert sich das Ergebnis:

import tensorflow as tf
tf.set_random_seed(1234)
tf.zeros(()) # new op added before 
generate = tf.random_uniform(())
with tf.Session() as sess:
  print(generate.eval())
  # 0.29252338

Wenn ein Knoten nach dem Erstellen erstellt wird, hat dies jedoch keinen Einfluss auf den Op-Seed:

import tensorflow as tf
tf.set_random_seed(1234)
generate = tf.random_uniform(())
tf.zeros(()) # new op added after
with tf.Session() as sess:
  print(generate.eval())
  # 0.96046877

Wenn Sie wie in Ihrem Fall mehrere Operationen generieren, haben diese offensichtlich unterschiedliche Samen:

import tensorflow as tf
tf.set_random_seed(1234)
gen1 = tf.random_uniform(())
gen2 = tf.random_uniform(())
with tf.Session() as sess:
  print(gen1.eval())
  print(gen2.eval())
  # 0.96046877
  # 0.85591054

Als Kuriosität und zur Bestätigung der Tatsache, dass Seeds einfach die zuletzt verwendete ID im Diagramm sind, können Sie den Seed von gen2 an gen1 mit ausrichten

import tensorflow as tf
tf.set_random_seed(1234)
gen1 = tf.random_uniform(())
# 4 operations seems to be created after seed has been picked
seed = tf.get_default_graph()._last_id - 4
gen2 = tf.random_uniform((), seed=seed)
with tf.Session() as sess:
  print(gen1.eval())
  print(gen2.eval())
  # 0.96046877
  # 0.96046877

Natürlich sollte dies keine Code-Überprüfung durchlaufen.

4
P-Gn

Es gibt eine verwandte Ausgabe von GitHub . . In Ihrem Fall lesen Sie bitte die Dokumentation von tf.set_random_seed :

Legt den zufälligen Startwert auf Diagrammebene fest.

Sie möchten wahrscheinlich die gleiche - Grafik und gleiche - Operation verwenden, um die gleiche Zufallszahlen in verschiedenen Sitzungen zu erhalten.

import tensorflow as tf

tf.set_random_seed(1234)
generate = tf.random_uniform((10,), 0, 10)
tf.get_default_graph().finalize() # something everybody tends to forget

for i in range(3):
    with tf.Session() as sess:
        b = sess.run(generate)
        print(b)

gibt

[9.604688  5.811516  6.4159    9.621765  0.5434954 4.1893444 5.8865128
 7.9785547 8.296125  8.388672 ]
[9.604688  5.811516  6.4159    9.621765  0.5434954 4.1893444 5.8865128
 7.9785547 8.296125  8.388672 ]
[9.604688  5.811516  6.4159    9.621765  0.5434954 4.1893444 5.8865128
 7.9785547 8.296125  8.388672 ]

In Ihrem Fall haben Sie verschiedene Operationen innerhalb desselben Diagramms erstellt.

3
Patwie

Spät zur Party, jedoch wurde der Zufallsgenerator überarbeitet (siehe https://github.com/tensorflow/community/pull/38 für eine Zusammenfassung des Prozesses) und das tf.random.experimental.Generator class bietet jetzt die gewünschte Funktionalität.

Ab TF 1.14 (inkl. TF 2.0) können Sie den Generator setzen und unabhängig von Sitzung, Plattform oder sogar Architektur genau dieselbe Zufallszahl erhalten.

import tensorflow as tf

rng = tf.random.experimental.Generator.from_seed(1234)
rng.uniform((), 5, 10, tf.int64)  # draw a random scalar (0-D tensor) between 5 and 10

Einzelheiten finden Sie in der Dokumentation:

Um Ihre spezielle Frage zu beantworten (ich verwende TF 2.0):

for i in range(3):
  b = tf.random.uniform((10,), 0, 10, seed=1234)
  print(b)

gibt

tf.Tensor(
[2.7339518  9.339194   5.2865124  8.912003   8.402512   0.53086996
 4.385383   4.8005686  2.2077608  2.1795273 ], shape=(10,), dtype=float32)
tf.Tensor(
[9.668942   3.4503186  7.4577675  2.9200733  1.8064988  6.1576104
 3.9958012  1.889689   3.8289428  0.36031008], shape=(10,), dtype=float32)
tf.Tensor(
[8.019657  4.895439  5.90925   2.418766  4.524292  7.901089  9.702316
 5.1606855 9.744821  2.4418736], shape=(10,), dtype=float32)

während dieser

for i in range(3):
  rng = tf.random.experimental.Generator.from_seed(1234)
  b = rng.uniform((10,), 0, 10)
  print(b)

gibt was du willst:

tf.Tensor(
[3.581475  1.132276  5.6670904 6.712369  3.2565057 1.7095459 8.468903
 6.2697005 1.0973608 2.7732193], shape=(10,), dtype=float32)
tf.Tensor(
[3.581475  1.132276  5.6670904 6.712369  3.2565057 1.7095459 8.468903
 6.2697005 1.0973608 2.7732193], shape=(10,), dtype=float32)
tf.Tensor(
[3.581475  1.132276  5.6670904 6.712369  3.2565057 1.7095459 8.468903
 6.2697005 1.0973608 2.7732193], shape=(10,), dtype=float32)
2
John Doe

Sie erhalten unterschiedliche Ergebnisse bei verschiedenen Läufen, da in der Grafik drei generate-Variablen (Operationen) definiert sind und nicht eine. Dies liegt daran, dass Sie die Generierungsoperation innerhalb der for-Schleife haben, die zu drei Operationen führt .(Tensor("random_uniform:0"), Tensor("random_uniform_1:0"), Tensor("random_uniform_2:0")). Machen Sie einfach print(generate) in der for-Schleife. Sie sehen drei verschiedene Operationen wie oben angegeben.

tf.set_random_seed legt den Startwert auf Diagrammebene fest. Daher wählt es deterministisch den Samen für jede Operation in der Grafik aus. Den drei generate-Vorgängen werden also bei jedem Lauf die gleichen drei Startwerte zugewiesen. Aus diesem Grund würden Sie für jeden Lauf die gleichen Ergebnisse für alle drei Variablen sehen. Weitere Informationen zum Setzen von Zufalls-Startwerten finden Sie in this .

Wenn Sie also jedes Mal die gleichen Ergebnisse erzielen möchten, wenn Sie eine Sitzung ausführen, können Sie Folgendes tun:

tf.set_random_seed(1234)
generate = tf.random_uniform((10,), 0, 10)
for i in range(3):
    with tf.Session() as sess:
        b = sess.run(generate)
        print(b)

Aber warum möchten Sie n-Sitzungen erstellen? Sie sollten im Idealfall eine Sitzung erstellen und dann die Sitzung n ausführen. Das Erstellen einer neuen Sitzung für jeden Lauf ist nicht erforderlich. Jedes Mal, wenn versucht wird, die Variablen und Operationen im Diagramm auf dem Gerät (GPU oder CPU) zu platzieren.

0