Trang này được dịch bởi Cloud Translation API.
Switch to English

hệ số ngẫu nhiên

Xem trên TensorFlow.org Chạy trong Google Colab Xem nguồn trên GitHub Tải về máy tính xách tay

TensorFlow cung cấp một bộ máy phát điện số giả ngẫu nhiên (RNG), trong tf.random module. Tài liệu này mô tả làm thế nào bạn có thể điều khiển máy phát điện số ngẫu nhiên, và làm thế nào những máy phát điện tương tác với hệ thống phụ tensorflow khác.

TensorFlow cung cấp hai cách tiếp cận để kiểm soát quá trình tạo số ngẫu nhiên:

  1. Thông qua việc sử dụng rõ ràng của tf.random.Generator đối tượng. Mỗi đối tượng như vậy duy trì một trạng thái (trong tf.Variable ) sẽ được thay đổi sau mỗi thế hệ số.

  2. Thông qua các chức năng ngẫu nhiên không quốc tịch hoàn toàn chức năng như tf.random.stateless_uniform . Kêu gọi các chức năng với các đối số tương tự (trong đó bao gồm các hạt giống) và trên cùng một thiết bị sẽ luôn tạo ra kết quả tương tự.

Thiết lập

 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()
    ])
 

Các tf.random.Generator lớp

Các tf.random.Generator lớp được sử dụng trong trường hợp bạn muốn mỗi cuộc gọi RNG để tạo ra kết quả khác nhau. Nó duy trì một trạng thái nội bộ (do một quản lý tf.Variable đối tượng) sẽ được cập nhật mỗi khi số ngẫu nhiên được tạo ra. Bởi vì nhà nước được quản lý bởi tf.Variable , nó rất thích tất cả các cơ sở cung cấp bởi tf.Variable như checkpointing dễ dàng, tự động điều khiển phụ thuộc và an toàn thread.

Bạn có thể có được một tf.random.Generator bằng cách thủ công tạo ra một đối tượng của lớp hoặc gọi tf.random.get_global_generator() để có được các máy phát điện toàn cầu mặc định:

 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)

Có nhiều cách để tạo ra một đối tượng máy phát điện. Các đơn giản nhất là Generator.from_seed , như trình bày ở trên, đó là tạo ra một máy phát điện từ một hạt giống. Một hạt giống là bất kỳ số nguyên không âm. from_seed cũng có một đối số tùy chọn alg đó là thuật toán RNG sẽ được sử dụng bởi máy phát điện này:

 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)

Xem phần Các thuật toán dưới đây để biết thêm thông tin về nó.

Một cách khác để tạo ra một máy phát điện là với Generator.from_non_deterministic_state . Một máy phát điện tạo ra theo cách này sẽ bắt đầu từ một trạng thái không xác định, ví dụ như phụ thuộc vào thời gian và hệ điều hành.

 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)

Có nhiều cách nhưng khác để tạo ra máy phát điện, chẳng hạn như từ các quốc gia rõ ràng, không được bao phủ bởi hướng dẫn này.

Khi sử dụng tf.random.get_global_generator để có được các máy phát điện toàn cầu, bạn cần phải cẩn thận về vị trí thiết bị. Máy phát điện toàn cầu được tạo ra (từ trạng thái không xác định) tại thời điểm đầu tiên tf.random.get_global_generator được gọi, và được đặt trên thiết bị mặc định khi có yêu cầu đó. Vì vậy, ví dụ, nếu trang web đầu tiên bạn gọi tf.random.get_global_generator là trong vòng một tf.device("gpu") phạm vi, máy phát điện toàn cầu sẽ được đặt trên GPU, và sử dụng các máy phát điện toàn cầu sau này từ CPU sẽ phải chịu một bản sao GPU-to-CPU.

Ngoài ra còn có một chức năng tf.random.set_global_generator để thay thế các máy phát điện toàn cầu với một đối tượng máy phát điện. Chức năng này nên được sử dụng một cách thận trọng suy nghĩ, bởi vì các máy phát điện toàn cầu cũ có thể đã được chụp bởi một tf.function (như là một tài liệu tham khảo yếu), và thay thế nó sẽ gây ra nó để được thu gom rác, phá vỡ tf.function . Một cách tốt hơn để thiết lập lại các máy phát điện toàn cầu là sử dụng một trong những chức năng "thiết lập lại" như Generator.reset_from_seed , mà sẽ không tạo các đối tượng phát mới.

 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)

Tạo dòng ngẫu nhiên số độc lập

Trong nhiều ứng dụng một nhu cầu nhiều độc lập suối ngẫu nhiên số lượng, độc lập theo nghĩa là họ sẽ không chồng chéo lên nhau và sẽ không có bất kỳ mối tương quan phát hiện về mặt thống kê. Điều này đạt được bằng cách sử dụng Generator.split để tạo ra nhiều máy phát điện được đảm bảo để được độc lập với nhau (suối độc lập tức tạo).

 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 sẽ thay đổi trạng thái của máy phát điện mà trên đó nó được gọi là ( g trong ví dụ trên), tương tự như một phương pháp RNG như normal . Ngoài việc là độc lập với nhau, các máy phát điện mới ( new_gs ) cũng được đảm bảo để được độc lập của một tuổi ( g ).

Đẻ trứng phát mới này cũng rất hữu ích khi bạn muốn chắc chắn rằng các máy phát điện bạn sử dụng là trên cùng một thiết bị như tính toán khác, để tránh việc sao chép trên nhiều thiết bị. Ví dụ:

 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)

Bạn có thể làm tách một cách đệ quy, kêu gọi split trên máy phát điện tách ra. Không có giới hạn (trừ đi số nguyên tràn) vào độ sâu của recursions.

Tương tác với tf.function

tf.random.Generator tuân theo các quy tắc tương tự như tf.Variable khi được sử dụng với tf.function . Điều này bao gồm ba khía cạnh.

Tạo máy phát điện bên ngoài tf.function

tf.function có thể sử dụng một máy phát điện tạo ra bên ngoài của nó.

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

Người sử dụng cần để đảm bảo rằng các đối tượng phát vẫn còn sống (không thu gom rác) khi hàm được gọi.

Tạo máy phát điện bên trong tf.function

Tạo ra các máy phát điện bên trong một tf.function chỉ có thể happend trong chạy đầu tiên của hàm.

 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)

Đi qua máy phát điện như các đối số để tf.function

Khi được sử dụng như một tham số để một tf.function , các đối tượng phát khác nhau với kích thước tương tự nhà nước (kích thước nhà nước được xác định bởi các thuật toán RNG) sẽ không gây ra retracing của tf.function , trong khi những người có kích thước khác nhau nhà nước sẽ.

 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

Tương tác với các chiến lược phân phối

Có ba cách thức mà Generator tương tác với các chiến lược phân phối.

Tạo máy phát điện bên ngoài chiến lược phân phối

Nếu một máy phát điện được tạo ra phạm vi chiến lược bên ngoài, truy cập tất cả các bản sao để các máy phát điện sẽ được tuần tự, và do đó các bản sao sẽ nhận được số ngẫu nhiên khác nhau.

 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)

Lưu ý rằng việc sử dụng này có thể có vấn đề hiệu suất vì thiết bị của máy phát điện là khác nhau từ các bản sao.

Tạo máy phát điện bên trong chiến lược phân phối

Tạo máy phát điện bên trong phạm vi chiến lược là không được phép, vì có sự mơ hồ về cách tái tạo một máy phát điện (ví dụ như nó nên được sao chép để mỗi bản sao được những con số ngẫu nhiên giống nhau, hoặc 'chia' để mỗi bản sao được số ngẫu nhiên khác nhau).

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

Lưu ý rằng Strategy.run sẽ chạy chức năng đối số của nó trong một phạm vi chiến lược ngầm:

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

Đi qua máy phát điện như các đối số để Strategy.run

Nếu bạn muốn mỗi bản sao để sử dụng máy phát điện riêng của mình, bạn cần phải thực hiện n máy phát điện (hoặc bằng cách sao chép hoặc tách), nơi n là số lượng bản sao, và sau đó vượt qua chúng như các đối số để 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 stateless

Sử dụng RNGs stateless là đơn giản. Kể từ khi họ chỉ là chức năng thuần túy, không có hiệu lực thi hành nhà nước hoặc bên liên quan.

 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)

Mỗi RNG stateless đòi hỏi một seed cãi nhau, mà cần phải là một số nguyên tensor hình dạng [2] . Các kết quả của op được xác định hoàn toàn bằng hạt này.

Các thuật toán

Chung

Cả tf.random.Generator lớp và stateless chức năng hỗ trợ các thuật toán Philox (viết như "philox" hoặc tf.random.Algorithm.PHILOX ) trên tất cả các thiết bị.

thiết bị khác nhau sẽ tạo ra những con số nguyên cùng, nếu sử dụng các thuật toán tương tự và bắt đầu từ tình trạng tương tự. Họ cũng sẽ tạo ra "gần như giống nhau" số float-point, mặc dù có thể có sự khác biệt nhỏ số gây ra bởi những cách khác nhau các thiết bị thực hiện việc tính toán float-điểm (ví dụ như để giảm).

thiết bị XLA

Trên các thiết bị XLA-driven (như TPU, và cũng CPU / GPU khi XLA được kích hoạt) thuật toán ThreeFry (viết như "threefry" hoặc tf.random.Algorithm.THREEFRY ) cũng được hỗ trợ. Thuật toán này là nhanh trên TPU nhưng chậm trên CPU / GPU so với Philox.

Xem giấy 'Parallel Số Ngẫu nhiên: dễ dàng như 1, 2, 3' để biết thêm chi tiết về các thuật toán.