این صفحه به‌وسیله ‏Cloud Translation API‏ ترجمه شده است.
Switch to English

تولید اعداد تصادفی

نمایش بر روی TensorFlow.org اجرا در گوگل COLAB مشاهده منبع در گیتهاب دانلود نوت بوک

TensorFlow فراهم می کند مجموعه ای از ژنراتور عدد شبه تصادفی (RNG)، در tf.random ماژول. این سند چگونه شما می توانید مولد عدد تصادفی را کنترل کنند، و چگونه این ژنراتور با دیگر زیر سیستم tensorflow ارتباط برقرار.

TensorFlow فراهم می کند دو روش برای کنترل فرآیند تولید عدد تصادفی:

  1. از طریق استفاده صریح از tf.random.Generator اشیاء. هر یک از این شی یک دولت (در حفظ tf.Variable ) خواهد شد که بعد از هر نسل تعداد تغییر کرده است.

  2. از طریق توابع تصادفی بدون تابعیت صرفا کارکردی مانند tf.random.stateless_uniform . فراخوانی این توابع با استدلال مشابه (که شامل دانه) و در همان دستگاه همیشه تولید نتایج مشابه.

برپایی

 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 کلاس

tf.random.Generator کلاس در مواردی که شما می خواهید هر تماس RNG به تولید نتایج مختلف استفاده می شود. آن را حفظ دولت های داخلی (مدیریت توسط tf.Variable شی) که به روز خواهد شد هر بار اعداد تصادفی تولید شده است. از آنجا که دولت را مدیریت tf.Variable ، آن برخوردار تمام امکانات ارائه شده توسط tf.Variable مانند حالتبرداری آسان، کنترل اتوماتیک وابستگی و ایمنی موضوع.

شما می توانید یک از tf.random.Generator به صورت دستی ایجاد یک شی از کلاس و یا پاسخ tf.random.get_global_generator() برای دریافت ژنراتور جهانی به طور پیش فرض:

 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)

راه های متعددی برای ایجاد یک شیء ژنراتور وجود دارد. ساده ترین است Generator.from_seed ، به عنوان بالا نشان داده شده، که باعث ایجاد یک ژنراتور از دانه. دانه هر عدد صحیح غیر منفی است. from_seed نیز طول می کشد یک آرگومان اختیاری alg است که الگوریتم RNG را که باید توسط این ژنراتور استفاده می شود:

 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)

بخش الگوریتم زیر برای اطلاعات بیشتر در مورد آن را ببینید.

راه دیگر برای ایجاد یک ژنراتور است با Generator.from_non_deterministic_state . ژنراتور ایجاد این راه از یک حالت غیر قطعی شروع خواهد شد، بسته به زمان مانند و سیستم عامل.

 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)

راه دیگر برای ایجاد و در عین حال ژنراتور، از جمله از کشورهای صریح و روشن، که توسط این راهنما پوشش داده نمی شود.

هنگام استفاده از tf.random.get_global_generator برای دریافت ژنراتور جهانی، شما باید مراقب باشید در مورد قرار دادن دستگاه. ژنراتور جهانی ایجاد می شود (از یک حالت غیر قطعی) در اولین بار tf.random.get_global_generator نامیده می شود، و در دستگاه به طور پیش فرض در آن پاسخ قرار داده است. بنابراین، برای مثال، اگر اولین سایت شما پاسخ tf.random.get_global_generator در یک tf.device("gpu") دامنه، ژنراتور جهانی خواهد شد بر روی GPU با استفاده از ژنراتور جهانی بعد از آن از پردازنده قرار داده شده، و متحمل یک کپی GPU به CPU.

همچنین یک تابع وجود دارد tf.random.set_global_generator برای جایگزینی ژنراتور جهانی با یکی دیگر از جسم ژنراتور. این تابع باید با فکر احتیاط مورد استفاده قرار است، چرا که ژنراتور، جهانی ممکن است توسط یک دستگیر شده اند tf.function (به عنوان یک مرجع ضعف)، و جایگزین کردن آن باعث می شود آن را به جمع آوری زباله، شکستن tf.function . یک راه بهتر برای تنظیم مجدد ژنراتور جهانی است به استفاده از یکی از "تنظیم مجدد" از توابع مانند Generator.reset_from_seed ، که اشیاء ژنراتور جدید ایجاد کنید.

 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)

ساخت جریان اعداد تصادفی مستقل

در بسیاری از برنامه های کاربردی یکی نیازهای چندگانه مستقل جریان اعداد تصادفی، مستقل به این معنا که آنها نمی خواهند به همپوشانی و هر گونه ارتباط آماری قابل تشخیص نیست. این است که با استفاده از دست Generator.split به ایجاد ژنراتور های متعدد است که تضمین می کند مستقل از یکدیگر (یعنی تولید جریان مستقل).

 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 دولت از ژنراتور است که در آن آن را به نام (تغییر خواهد کرد g در مثال بالا)، شبیه به یک روش RNG مانند normal . علاوه بر مستقل از یکدیگر بودن، ژنراتورهای جدید ( new_gs ) نیز تضمین می شود مستقل از یکی از قدیمی ( g ).

تخم ریزی ژنراتورهای جدید نیز مفید است زمانی که می خواهید مطمئن شوید ژنراتور استفاده می کنید بر روی دستگاه هم مانند دیگر محاسبات، برای جلوگیری از سربار از کپی متقابل دستگاه. مثلا:

 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 در ژنراتور پذیری. هیچ محدودیتی وجود ندارد (محرومیت سرریز عدد صحیح) به عمق بازگشتی وجود ندارد.

تعامل با tf.function

tf.random.Generator اطاعت از قوانین همان tf.Variable زمانی که با استفاده tf.function . این شامل سه جنبه.

ایجاد ژنراتور خارج tf.function

tf.function می توانید یک ژنراتور ایجاد در خارج از آن استفاده کنید.

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

کاربر نیاز به مطمئن شوید که شی ژنراتور هنوز زنده است (جمع آوری زباله نیست) هنگامی که از عملکرد نامیده می شود.

ایجاد ژنراتور در داخل tf.function

ایجاد ژنراتور در داخل یک tf.function فقط می توانید در طول اولین اجرا از تابع اتفاق.

 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)

عبور ژنراتور به عنوان آرگومان به tf.function

هنگامی که به عنوان یک استدلال به استفاده tf.function ، اشیاء ژنراتور های مختلف با اندازه همان حالت (اندازه دولت است که توسط الگوریتم RNG تعیین) نه علت retracing از tf.function ، در حالی که کسانی که با اندازه های مختلف دولت است.

 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

تعامل با استراتژی توزیع

سه راه وجود دارد که در آن Generator تعامل با استراتژی توزیع.

ایجاد ژنراتور خارج استراتژی توزیع

اگر یک ژنراتور حوزه استراتژی خارج ایجاد شده است، دسترسی به تمام کپی به ژنراتور می شود مرتب خواهد، و از این رو کپی خواهد شماره های مختلف طور تصادفی دریافت.

 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)

توجه داشته باشید که این استفاده ممکن است مسائل مربوط به عملکرد داشته باشد چرا که دستگاه ژنراتور متفاوت از کپی است.

ایجاد ژنراتور در داخل استراتژی توزیع

ژنراتور ایجاد در داخل حوزه استراتژی مجاز است، زیرا ابهام در مورد نحوه تکرار یک ژنراتور وجود دارد (به عنوان مثال باید آن را کپی می شود به طوری که هر ماکت می شود اعداد تصادفی همان، و یا "تقسیم به طوری که هر ماکت می شود شماره های مختلف تصادفی).

 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 تابع استدلال خود را در یک دامنه استراتژی به طور ضمنی اجرا خواهد شد:

 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).

عبور ژنراتور به عنوان آرگومان به Strategy.run

اگر می خواهید هر ماکت به استفاده از ژنراتور خود را، شما نیاز به ایجاد n ژنراتور (یا با کپی کردن یا تقسیم)، که در آن n تعداد کپی است، و سپس آنها را به عنوان آرگومان به تصویب 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)

RNGs بی وطن

استفاده از RNGs بدون تابعیت ساده است. از آنجا که آنها فقط توابع خالص هستند، هیچ اثر دولت و یا سمت درگیر وجود دارد.

 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)

هر RNG بدون تابعیت نیاز به یک seed استدلال، که نیاز به یک عدد صحیح تانسور شکل [2] . نتایج حاصل از این عملیات به طور کامل توسط این دانه تعیین می شود.

الگوریتم

عمومی

هر دو tf.random.Generator کلاس و stateless توابع پشتیبانی از الگوریتم Philox (نوشته شده به عنوان "philox" یا tf.random.Algorithm.PHILOX ) در تمام دستگاه.

دستگاه های مختلف را به اعداد صحیح همان تولید، اگر با استفاده از همان الگوریتم و با شروع از همان حالت. آنها همچنین تولید خواهد شد "تقریبا همان" اعداد شناور نقطه، هر چند ممکن است تفاوت های عددی کوچک ناشی از روش های مختلف دستگاه انجام محاسبات شناور نقطه (به عنوان مثال کاهش سفارش) وجود دارد.

دستگاه های وابسته به جنس مورد

در دستگاه های وابسته به جنس محور (مانند TPU، و همچنین CPU / GPU که XLA فعال باشد) الگوریتم ThreeFry (به عنوان نوشته شده است "threefry" یا tf.random.Algorithm.THREEFRY ) نیز پشتیبانی می کند. این الگوریتم این است سریع در TPU اما آهسته در CPU / GPU نسبت به Philox.

مقاله مشاهده : آسانی به عنوان 1، 2، 3 موازی اعداد تصادفی: برای اطلاعات بیشتر در مورد این الگوریتم ها.