Bu sayfa, Cloud Translation API ile çevrilmiştir.
Switch to English

Rastgele sayı oluşturma

TensorFlow.org üzerinde görüntüle Google Colab'da yayınla Kaynağı GitHub'da görüntüle Not defterini indir

TensorFlow olarak, rastlantısal-taklidi sayı üreteçleri (RNG) bir dizi sağlar tf.random modülü. Bu belgede rastgele sayı üreteçlerini nasıl kontrol edebileceğiniz ve bu üreteçlerin diğer tensorflow alt sistemleriyle nasıl etkileşime girdiği açıklanmaktadır.

TensorFlow rastgele sayı oluşturma sürecini kontrol etmek için iki yaklaşım sunmaktadır:

  1. tf.random.Generator nesnelerinin açık kullanımı sayesinde. Bu tür her nesne, her sayı üretiminden sonra değiştirilecek bir durumu ( tf.Variable ) korur.

  2. tf.random.stateless_uniform gibi tamamen işlevsel vatansız rasgele işlevler tf.random.stateless_uniform . Bu işlevlerin aynı argümanlarla (tohumu içeren) ve aynı cihazda çağrılması her zaman aynı sonuçları verecektir.

Kurmak

 import tensorflow as tf

# Creates 2 virtual devices cpu:0 and cpu:1 for using distribution strategy
physical_devices = tf.config.experimental.list_physical_devices("CPU")
tf.config.experimental.set_virtual_device_configuration(
    physical_devices[0], [
        tf.config.experimental.VirtualDeviceConfiguration(),
        tf.config.experimental.VirtualDeviceConfiguration()
    ])
 

tf.random.Generator sınıfı

tf.random.Generator sınıfı, her RNG çağrısının farklı sonuçlar üretmesini istediğiniz durumlarda kullanılır. Rastgele sayılar her oluşturulduğunda güncellenecek bir dahili durumu ( tf.Variable nesnesi tarafından yönetilir) tf.Variable . Devlet tf.Variable tarafından tf.Variable , kolay kontrol noktası, otomatik kontrol bağımlılığı ve iplik güvenliği gibi tf.Variable tarafından sağlanan tüm olanaklara sahiptir.

tf.random.Generator bir nesnesini el ile oluşturarak bir tf.random.get_global_generator() alabilirsiniz veya varsayılan global oluşturucuyu edinmek için tf.random.get_global_generator() çağırın:

 g1 = tf.random.Generator.from_seed(1)
print(g1.normal(shape=[2, 3]))
g2 = tf.random.get_global_generator()
print(g2.normal(shape=[2, 3]))
 
tf.Tensor(
[[ 0.43842274 -0.53439844 -0.07710262]
 [ 1.5658046  -0.1012345  -0.2744976 ]], shape=(2, 3), dtype=float32)
tf.Tensor(
[[-0.6078218  3.162639  -1.0558378]
 [ 1.2078347  0.6414574  0.4019502]], shape=(2, 3), dtype=float32)

Bir jeneratör nesnesi oluşturmanın birden çok yolu vardır. En kolayı, yukarıda gösterildiği gibi, bir tohumdan bir jeneratör oluşturan Generator.from_seed . Bir tohum negatif olmayan bir tamsayıdır. from_seed ayrıca bu jeneratör tarafından kullanılacak RNG algoritması olan isteğe bağlı bir alg alır:

 g1 = tf.random.Generator.from_seed(1, alg='philox')
print(g1.normal(shape=[2, 3]))
 
tf.Tensor(
[[ 0.43842274 -0.53439844 -0.07710262]
 [ 1.5658046  -0.1012345  -0.2744976 ]], shape=(2, 3), dtype=float32)

Bununla ilgili daha fazla bilgi için aşağıdaki Algoritmalar bölümüne bakın.

Bir jeneratör oluşturmanın başka bir yolu Generator.from_non_deterministic_state . Bu şekilde oluşturulan bir jeneratör, örneğin zaman ve işletim sistemine bağlı olarak deterministik olmayan bir durumdan başlayacaktır.

 g = tf.random.Generator.from_non_deterministic_state()
print(g.normal(shape=[2, 3]))
 
tf.Tensor(
[[ 1.1436943  1.729618   1.0391121]
 [-0.8502223 -1.8823647 -1.4051851]], shape=(2, 3), dtype=float32)

Bu kılavuzda yer almayan açık durumlar gibi jeneratörler oluşturmanın başka yolları da vardır.

Global jeneratörü elde etmek için tf.random.get_global_generator kullanırken, cihaz yerleşimi konusunda dikkatli olmanız gerekir. Genel jeneratör ilk kez (deterministik olmayan bir durumdan) oluşturulur ve tf.random.get_global_generator çağrılır ve bu çağrıda varsayılan cihaza yerleştirilir. Örneğin, tf.random.get_global_generator olarak adlandırdığınız ilk site bir tf.device("gpu") kapsamındaysa, global jeneratör GPU'ya yerleştirilecek ve daha sonra CPU'dan global jeneratörü kullanacak GPU'dan CPU'ya kopyalayın.

Global jeneratörü başka bir jeneratör nesnesiyle değiştirmek için bir tf.random.set_global_generator işlevi de vardır. Bu işlev dikkatle kullanılmalıdır, çünkü eski global jeneratör bir tf.function (zayıf bir referans olarak) tarafından yakalanmış olabilir ve değiştirilmesi, tf.function kırarak çöp toplanmasına neden olacaktır. Global jeneratörü sıfırlamanın daha iyi bir yolu, Generator.reset_from_seed gibi yeni jeneratör nesneleri oluşturmayacak "reset" fonksiyonlarından birini kullanmaktır.

 g = tf.random.Generator.from_seed(1)
print(g.normal([]))
print(g.normal([]))
g.reset_from_seed(1)
print(g.normal([]))
 
tf.Tensor(0.43842274, shape=(), dtype=float32)
tf.Tensor(1.6272374, shape=(), dtype=float32)
tf.Tensor(0.43842274, shape=(), dtype=float32)

Bağımsız rasgele sayı akışları oluşturma

Birçok uygulamada, üst üste binmeyecekleri ve istatistiksel olarak saptanabilir korelasyonları olmayacakları anlamında bağımsız olarak birden fazla bağımsız rasgele sayı akışına ihtiyaç vardır. Bu, birbirinden bağımsız olduğu garanti edilen birden fazla jeneratör oluşturmak için Generator.split kullanılarak elde edilir (yani bağımsız akışlar üretilir).

 g = tf.random.Generator.from_seed(1)
print(g.normal([]))
new_gs = g.split(3)
for new_g in new_gs:
  print(new_g.normal([]))
print(g.normal([]))
 
tf.Tensor(0.43842274, shape=(), dtype=float32)
tf.Tensor(2.536413, shape=(), dtype=float32)
tf.Tensor(0.33186463, shape=(), dtype=float32)
tf.Tensor(-0.07144657, shape=(), dtype=float32)
tf.Tensor(-0.79253083, shape=(), dtype=float32)

split , normal gibi bir RNG yöntemine benzer şekilde çağrıldığı jeneratörün durumunu değiştirir (yukarıdaki örnekte g ). Birbirinden bağımsız olmasının yanı sıra, yeni jeneratörlerin ( new_gs ) new_gs ( g ) bağımsız olması da garanti edilmektedir.

Cihazlar arası kopyanın ek yükünü önlemek için kullandığınız jeneratörün diğer hesaplamalarla aynı cihazda olduğundan emin olmak istediğinizde yeni jeneratörleri yumuşatmak da yararlıdır. Örneğin:

 with tf.device("cpu"):  # change "cpu" to the device you want
  g = tf.random.get_global_generator().split(1)[0]  
  print(g.normal([]))  # use of g won't cause cross-device copy, unlike the global generator
 
tf.Tensor(-1.7580209, shape=(), dtype=float32)

split jeneratörlerde split çağırarak özyinelemeli bölme yapabilirsiniz. Özyineleme derinliğinde sınır yoktur (tamsayı taşmasını engeller).

tf.function ile tf.function

tf.random.Generator , tf.Variable ile birlikte kullanıldığında tf.function ile aynı kurallara uyar. Bu üç yönü içerir.

tf.function dışında jeneratör oluşturma

tf.function dışında oluşturulmuş bir jeneratör kullanabilir.

 g = tf.random.Generator.from_seed(1)
@tf.function
def foo():
  return g.normal([])
print(foo())
 
tf.Tensor(0.43842274, shape=(), dtype=float32)

Kullanıcı, işlev çağrıldığında jeneratör nesnesinin hala canlı olduğundan (çöp toplanmamış değil) emin olmalıdır.

tf.function içinde jeneratör oluşturma

Bir tf.function içinde jeneratörlerin oluşturulması sadece fonksiyonun ilk çalışması sırasında gerçekleşebilir.

 g = None
@tf.function
def foo():
  global g
  if g is None:
    g = tf.random.Generator.from_seed(1)
  return g.normal([])
print(foo())
print(foo())
 
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/ops/resource_variable_ops.py:1817: calling BaseResourceVariable.__init__ (from tensorflow.python.ops.resource_variable_ops) with constraint is deprecated and will be removed in a future version.
Instructions for updating:
If using Keras pass *_constraint arguments to layers.
tf.Tensor(0.43842274, shape=(), dtype=float32)
tf.Tensor(1.6272374, shape=(), dtype=float32)

Jeneratörleri tf.function argüman olarak tf.function

Bir tf.function argüman olarak kullanıldığında, aynı durum büyüklüğüne sahip farklı jeneratör nesneleri (durum boyutu RNG algoritması tarafından belirlenir), tf.function geri tf.function neden tf.function , farklı durum boyutlarına sahip olanlar olacaktır.

 num_traces = 0
@tf.function
def foo(g):
  global num_traces
  num_traces += 1
  return g.normal([])
foo(tf.random.Generator.from_seed(1))
foo(tf.random.Generator.from_seed(2))
print(num_traces)
 
1

Dağıtım stratejileri ile etkileşim

Generator dağıtım stratejileri ile etkileşime girmesinin üç yolu vardır.

Dağıtım stratejileri dışında jeneratör oluşturma

Strateji kapsamlarının dışında bir jeneratör oluşturulursa, tüm kopyaların jeneratöre erişimi serileştirilir ve böylece kopyalar farklı rasgele sayılar alır.

 g = tf.random.Generator.from_seed(1)
strat = tf.distribute.MirroredStrategy(devices=["cpu:0", "cpu:1"])
with strat.scope():
  def f():
    print(g.normal([]))
  results = strat.run(f)
 
WARNING:tensorflow:There are non-GPU devices in `tf.distribute.Strategy`, not using nccl allreduce.
INFO:tensorflow:Using MirroredStrategy with devices ('/job:localhost/replica:0/task:0/device:CPU:0', '/job:localhost/replica:0/task:0/device:CPU:1')
WARNING:tensorflow:Using MirroredStrategy eagerly has significant overhead currently. We will be working on improving this in the future, but for now please wrap `call_for_each_replica` or `experimental_run` or `run` inside a tf.function to get the best performance.
tf.Tensor(0.43842274, shape=(), dtype=float32)
tf.Tensor(1.6272374, shape=(), dtype=float32)

Jeneratörün cihazı kopyalardan farklı olduğu için bu kullanımda performans sorunları olabilir.

Dağıtım stratejileri içinde jeneratörler oluşturma

Strateji kapsamlarının içinde jeneratörler oluşturmaya izin verilmez, çünkü bir jeneratörün nasıl kopyalanacağı konusunda belirsizlik vardır (örneğin, her bir kopya aynı rasgele sayıları alacak şekilde kopyalanmalı veya her bir kopya farklı rasgele sayılar elde edecek şekilde 'bölünmelidir).

 strat = tf.distribute.MirroredStrategy(devices=["cpu:0", "cpu:1"])
with strat.scope():
  try:
    tf.random.Generator.from_seed(1)
  except ValueError as e:
    print("ValueError:", e)
 
WARNING:tensorflow:There are non-GPU devices in `tf.distribute.Strategy`, not using nccl allreduce.
INFO:tensorflow:Using MirroredStrategy with devices ('/job:localhost/replica:0/task:0/device:CPU:0', '/job:localhost/replica:0/task:0/device:CPU:1')
ValueError: Creating a generator within a strategy scope is disallowed, because there is ambiguity on how to replicate a generator (e.g. should it be copied so that each replica gets the same random numbers, or 'split' so that each replica gets different random numbers).

Strategy.run argüman işlevini örtülü olarak bir strateji kapsamında çalıştıracağını unutmayın:

 strat = tf.distribute.MirroredStrategy(devices=["cpu:0", "cpu:1"])
def f():
  tf.random.Generator.from_seed(1)
try:
  strat.run(f)
except ValueError as e:
  print("ValueError:", e)
 
WARNING:tensorflow:There are non-GPU devices in `tf.distribute.Strategy`, not using nccl allreduce.
INFO:tensorflow:Using MirroredStrategy with devices ('/job:localhost/replica:0/task:0/device:CPU:0', '/job:localhost/replica:0/task:0/device:CPU:1')
WARNING:tensorflow:Using MirroredStrategy eagerly has significant overhead currently. We will be working on improving this in the future, but for now please wrap `call_for_each_replica` or `experimental_run` or `run` inside a tf.function to get the best performance.
INFO:tensorflow:Error reported to Coordinator: Creating a generator within a strategy scope is disallowed, because there is ambiguity on how to replicate a generator (e.g. should it be copied so that each replica gets the same random numbers, or 'split' so that each replica gets different random numbers).
Traceback (most recent call last):
  File "/tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/training/coordinator.py", line 297, in stop_on_exception
    yield
  File "/tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/distribute/mirrored_strategy.py", line 998, in run
    self.main_result = self.main_fn(*self.main_args, **self.main_kwargs)
  File "/tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/autograph/impl/api.py", line 282, in wrapper
    return func(*args, **kwargs)
  File "<ipython-input-14-2cd7806456bd>", line 3, in f
    tf.random.Generator.from_seed(1)
  File "/tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/ops/stateful_random_ops.py", line 444, in from_seed
    return cls(state=state, alg=alg)
  File "/tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/ops/stateful_random_ops.py", line 386, in __init__
    trainable=False)
  File "/tmpfs/src/tf_docs_env/lib/python3.6/site-packages/tensorflow/python/ops/stateful_random_ops.py", line 272, in _create_variable
    "Creating a generator within a strategy scope is disallowed, because "
ValueError: Creating a generator within a strategy scope is disallowed, because there is ambiguity on how to replicate a generator (e.g. should it be copied so that each replica gets the same random numbers, or 'split' so that each replica gets different random numbers).
ValueError: Creating a generator within a strategy scope is disallowed, because there is ambiguity on how to replicate a generator (e.g. should it be copied so that each replica gets the same random numbers, or 'split' so that each replica gets different random numbers).

Generator'ı Strategy.run argüman olarak Strategy.run

Her çoğaltmanın kendi oluşturucusunu kullanmasını istiyorsanız, n kopyasını (kopyalayarak veya bölerek) yapmanız gerekir; burada n , kopya sayısıdır ve bunları Strategy.run bağımsız değişken olarak Strategy.run .

 strat = tf.distribute.MirroredStrategy(devices=["cpu:0", "cpu:1"])
gs = tf.random.get_global_generator().split(2)
# to_args is a workaround for the absence of APIs to create arguments for 
# run. It will be replaced when such APIs are available.
def to_args(gs):  
  with strat.scope():
    def f():
      return [gs[tf.distribute.get_replica_context().replica_id_in_sync_group]]
    return strat.run(f)
args = to_args(gs)
def f(g):
  print(g.normal([]))
results = strat.run(f, args=args)
 
WARNING:tensorflow:There are non-GPU devices in `tf.distribute.Strategy`, not using nccl allreduce.
INFO:tensorflow:Using MirroredStrategy with devices ('/job:localhost/replica:0/task:0/device:CPU:0', '/job:localhost/replica:0/task:0/device:CPU:1')
WARNING:tensorflow:Using MirroredStrategy eagerly has significant overhead currently. We will be working on improving this in the future, but for now please wrap `call_for_each_replica` or `experimental_run` or `run` inside a tf.function to get the best performance.
WARNING:tensorflow:Using MirroredStrategy eagerly has significant overhead currently. We will be working on improving this in the future, but for now please wrap `call_for_each_replica` or `experimental_run` or `run` inside a tf.function to get the best performance.
tf.Tensor(-0.15682742, shape=(), dtype=float32)
tf.Tensor(-0.38042808, shape=(), dtype=float32)

Vatansız RNG'ler

Vatansız RNG'lerin kullanımı basittir. Sadece saf işlevler oldukları için, herhangi bir durum veya yan etki yoktur.

 print(tf.random.stateless_normal(shape=[2, 3], seed=[1, 2]))
print(tf.random.stateless_normal(shape=[2, 3], seed=[1, 2]))
 
tf.Tensor(
[[ 0.5441101   0.20738031  0.07356433]
 [ 0.04643455 -1.3015898  -0.95385665]], shape=(2, 3), dtype=float32)
tf.Tensor(
[[ 0.5441101   0.20738031  0.07356433]
 [ 0.04643455 -1.3015898  -0.95385665]], shape=(2, 3), dtype=float32)

Her vatansız RNG, tamsayı bir şekil Tensörü olması gereken bir seed argümanı gerektirir [2] . Operasyonun sonuçları bu tohum tarafından tamamen belirlenir.

Algoritmalar

Genel

Hem tf.random.Generator sınıfı hem de stateless işlevler, tüm cihazlarda Philox algoritmasını ( "philox" veya tf.random.Algorithm.PHILOX ) destekler.

Aynı algoritmayı kullanıyor ve aynı durumdan başlıyorsa, farklı cihazlar aynı tam sayıları üretecektir. Ayrıca, "neredeyse aynı" kayan nokta sayıları üreteceklerdir, ancak cihazların kayan nokta hesaplamasını gerçekleştirme yöntemlerinin farklı yollardan (örn. Azaltma sırası) kaynaklanan küçük sayısal tutarsızlıklar olabilir.

XLA cihazları

XLA ile çalışan cihazlarda (XLA etkinleştirildiğinde TPU ve ayrıca CPU / GPU gibi) ThreeFry algoritması ( "threefry" veya tf.random.Algorithm.THREEFRY ) da desteklenir. Bu algoritma TPU'da hızlı ancak Philox'a kıyasla CPU / GPU'da yavaştır.

Bu algoritmalar hakkında daha fazla ayrıntı için 'Paralel Rasgele Sayılar: 1, 2, 3 kadar Kolay' makalesine bakın.