私は独立した乱数のNセットを生成しようとしています。 10個の乱数の3セットの問題を示す簡単なコードがあります。 tf.set_random_seed
を使用してシードを設定しても、異なる実行の結果は似ていないことがわかります。どんな助けやコメントも大歓迎です。
(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)
これはコードの出力です:
# 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]
私は何かが欲しい
[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 ]
更新1:実際にforループ内にシード初期化子を配置した理由は、それらを異なるように設定したいためです(たとえば、MCMCの実行が異なる場合など)。これは仕事をする私のコードですが、それが効率的かどうかはわかりません。基本的に、0〜2 ^ 32-1のランダムなシードをいくつか生成し、実行するたびにシードを変更します。メモリ/ RAMの効率を高めるためのヘルプやコメントを歓迎します。
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 .....
.
.
.
テンソルフローでは、ランダム操作は2つの異なるシードに依存します:tf.set_random_seed
で設定されるグローバルシードと、操作の引数として提供される操作シードです。それらがどのように関連するかについての詳細を見つけるでしょう ドキュメントで 。
各ランダムopは、擬似乱数生成のために独自の内部状態を維持するため、各ランダムopに異なるシードがあります。各ランダムジェネレーターが独自の状態を維持する理由は、変化に強いことです:同じ状態を共有している場合、グラフのどこかに新しいランダムジェネレーターを追加すると、他のすべてのジェネレーターによって生成される値が変更され、目的が無効になりますシードを使用します。
さて、なぜグローバルandのper-opシードの二重システムがあるのでしょうか?実際、グローバルシードは必要ありません。利便性のためにあります:すべてのランダムopシードを、すべてを徹底的に調べることなく、一度に異なる確定的な値(不明な場合)に設定できます。
ドキュメントによると、グローバルシードは設定されているがopシードは設定されていない場合、
システムは、一意のランダムシーケンスを取得するように、グラフレベルのシードと連動して操作シードを決定論的に選択します。
より正確には、提供されるシードは、現在のグラフで作成された最後の操作のIDです。したがって、グローバルにシードされたランダム操作は、グラフの変更、特にそれ自体の前に作成された変更に非常に敏感です。
例えば、
import tensorflow as tf
tf.set_random_seed(1234)
generate = tf.random_uniform(())
with tf.Session() as sess:
print(generate.eval())
# 0.96046877
前にノードを作成すると、結果が変わります:
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
ただし、ノードが後に作成される場合、opシードには影響しません。
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
明らかに、あなたの場合のように、いくつかの操作を生成する場合、それらは異なるシードを持ちます:
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
好奇心として、そしてシードが単にグラフで最後に使用されたIDであるという事実を検証するために、gen2
のシードをgen1
に揃えることができます。
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
ただし、明らかに、これはコードレビューに合格するべきではありません。
Tensorflow 2.0tf.random.set_random_seed(seed)
をtf.random.set_seed(seed)
に変更しました。
tFドキュメントを参照してください:
関連する GitHubの問題 があります。しかし、あなたの場合は、 tf.set_random_seed
:
グラフレベルのランダムシードを設定します。
おそらくsameグラフとsame操作を使用して、 samedifferentセッションの乱数。
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)
与える
[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 ]
あなたの場合、同じグラフ内に異なる操作を作成しました。
パーティーに遅れて、しかし、乱数ジェネレーターがオーバーホールされました(プロセスの要約については https://github.com/tensorflow/community/pull/38 を参照)およびtf.random.experimental.Generator
クラスが必要な機能を提供するようになりました。
TF 1.14以降(TF 2.0を含む)から、ジェネレーターをシードして、セッション、プラットフォーム、またはアーキテクチャに関係なく、まったく同じ乱数を取得できます。
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
詳細については、ドキュメントを参照してください。
特定の質問に対処するには(TF 2.0を使用しています):
for i in range(3):
b = tf.random.uniform((10,), 0, 10, seed=1234)
print(b)
与える
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)
これながら
for i in range(3):
rng = tf.random.experimental.Generator.from_seed(1234)
b = rng.uniform((10,), 0, 10)
print(b)
あなたが欲しいものを与えます:
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)
グラフには1つではなく3つのgenerate
変数(操作)が定義されているため、実行ごとに異なる結果が得られます。これは、forループ内に3つの操作につながる生成操作があるためです。_(Tensor("random_uniform:0"), Tensor("random_uniform_1:0"), Tensor("random_uniform_2:0"))
_。 forループ内でprint(generate)
するだけです。上記の3つの異なる操作が表示されます。
_tf.set_random_seed
_は、グラフレベルでシードを設定します。そのため、グラフ内の各操作のシードを決定論的に選択します。そのため、3つのgenerate
操作には、実行ごとに同じ3つのシードが割り当てられます。これが、実行ごとに、3つの変数すべてに対応して同じ結果が表示される理由です。ランダムシードの設定の詳細については、 this をご覧ください。
そのため、セッションを実行するたびに同じ結果が得られるようにするには、次のようにします。
_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)
_
しかし、なぜn
セッションを作成したいのですか。 1つのセッションを作成してから、セッションをn
回実行するのが理想的です。実行ごとに新しいセッションを作成する必要はなく、変数と操作をグラフ内のデバイス(GPUまたはCPU)に配置しようとするたびに必要です。