एमएल समुदाय दिवस 9 नवंबर है! TensorFlow, JAX से नई जानकारी के लिए हमसे जुड़ें, और अधिक जानें

यादृच्छिक संख्या पीढ़ी

TensorFlow.org पर देखें Google Colab में चलाएं GitHub पर स्रोत देखें नोटबुक डाउनलोड करें

TensorFlow में, छद्म यादृच्छिक संख्या जनरेटर (RNG) का एक सेट प्रदान tf.random मॉड्यूल। यह दस्तावेज़ बताता है कि आप यादृच्छिक संख्या जनरेटर को कैसे नियंत्रित कर सकते हैं, और ये जनरेटर अन्य टेंसरफ़्लो उप-प्रणालियों के साथ कैसे इंटरैक्ट करते हैं।

TensorFlow यादृच्छिक संख्या पीढ़ी प्रक्रिया को नियंत्रित करने के लिए दो दृष्टिकोण प्रदान करता है:

  1. का स्पष्ट उपयोग के माध्यम से tf.random.Generator वस्तुओं। ऐसी प्रत्येक वस्तु एक राज्य (में रखता है tf.Variable ) कि प्रत्येक संख्या पीढ़ी के बाद बदल जाएगा।

  2. जैसे विशुद्ध रूप से कार्यात्मक राज्यविहीन यादृच्छिक कार्यों के माध्यम से tf.random.stateless_uniform । इन फ़ंक्शंस को समान तर्कों (जिसमें बीज शामिल है) और एक ही डिवाइस पर कॉल करना हमेशा समान परिणाम देगा।

सेट अप

import tensorflow as tf

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

tf.random.Generator वर्ग

tf.random.Generator वर्ग मामलों में जहां आप प्रत्येक RNG कॉल से भिन्न परिणाम करना चाहते हैं प्रयोग किया जाता है। यह एक आंतरिक स्थिति (एक द्वारा प्रबंधित का कहना है tf.Variable वस्तु) जो हर बार यादृच्छिक संख्या उत्पन्न कर रहे हैं अद्यतन किया जाएगा। क्योंकि राज्य द्वारा किया जाता है tf.Variable , यह द्वारा प्रदान की सभी सुविधाएं प्राप्त है tf.Variable ऐसे आसान checkpointing, स्वत: नियंत्रण-निर्भरता और धागा सुरक्षा के रूप में।

आप एक प्राप्त कर सकते हैं 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.43842277 -0.53439844 -0.07710262]
 [ 1.5658046  -0.1012345  -0.2744976 ]], shape=(2, 3), dtype=float32)
tf.Tensor(
[[-0.5496427   0.24263908 -1.1436267 ]
 [ 1.861458   -0.6756685  -0.9900103 ]], 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.43842277 -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(
[[-0.9078738   0.11009752  1.037219  ]
 [ 0.661036    0.4169741   1.4539026 ]], 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-to-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.43842277, shape=(), dtype=float32)
tf.Tensor(1.6272374, shape=(), dtype=float32)
tf.Tensor(0.43842277, 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.43842277, 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(0.4142675, shape=(), dtype=float32)

आपके पास कॉल रिकर्सिवली बंटवारे कर सकते हैं, split splitted जनरेटर पर। रिकर्सन की गहराई पर कोई सीमा नहीं है (पूर्णांक अतिप्रवाह को छोड़कर)।

के साथ बातचीत 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.43842277, shape=(), dtype=float32)

उपयोगकर्ता को यह सुनिश्चित करने की ज़रूरत है कि फ़ंक्शन को कॉल करते समय जेनरेटर ऑब्जेक्ट अभी भी जीवित है (कचरा-एकत्र नहीं)।

अंदर जनरेटर बनाना tf.function

एक के अंदर जनरेटर का निर्माण tf.function केवल समारोह के पहले चलाने के दौरान happend कर सकते हैं।

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())
tf.Tensor(0.43842277, shape=(), dtype=float32)
tf.Tensor(1.6272374, shape=(), dtype=float32)

करने के लिए तर्क के रूप में जनरेटर पासिंग tf.function

जब एक के लिए एक तर्क के रूप में इस्तेमाल किया tf.function , विभिन्न जनरेटर वस्तुओं की 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)
2

ध्यान दें कि यह retracing व्यवहार के साथ संगत है tf.Variable :

num_traces = 0
@tf.function
def foo(v):
  global num_traces
  num_traces += 1
  return v.read_value()
foo(tf.Variable(1))
foo(tf.Variable(2))
print(num_traces)
2

वितरण रणनीतियों के साथ सहभागिता

दो तरह से कर रहे हैं 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():
  g = tf.random.Generator.from_seed(1)
  print(strat.run(lambda: g.normal([])))
  print(strat.run(lambda: g.normal([])))
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.
PerReplica:{
  0: tf.Tensor(-0.87930447, shape=(), dtype=float32),
  1: tf.Tensor(0.020661574, shape=(), dtype=float32)
}
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.
PerReplica:{
  0: tf.Tensor(-1.5822568, shape=(), dtype=float32),
  1: tf.Tensor(0.77539235, shape=(), dtype=float32)
}

जनरेटर वरीयता प्राप्त है, तो (उदाहरण के द्वारा बनाई गई Generator.from_seed ), यादृच्छिक संख्या बीज द्वारा निर्धारित किया जाता है, हालांकि विभिन्न प्रतिकृतियां अलग और असहसंबद्ध नंबर प्राप्त करें। कोई एक प्रतिकृति पर उत्पन्न एक यादृच्छिक संख्या को प्रतिकृति आईडी के हैश के रूप में और एक "प्राथमिक" यादृच्छिक संख्या के रूप में सोच सकता है जो सभी प्रतिकृतियों के लिए सामान्य है। इसलिए, पूरी प्रणाली अभी भी नियतात्मक है।

tf.random.Generator भी अंदर बनाया जा सकता है Strategy.run :

strat = tf.distribute.MirroredStrategy(devices=["cpu:0", "cpu:1"])
with strat.scope():
  def f():
    g = tf.random.Generator.from_seed(1)
    a = g.normal([])
    b = g.normal([])
    return tf.stack([a, b])
  print(strat.run(f))
  print(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.
PerReplica:{
  0: tf.Tensor([-0.87930447 -1.5822568 ], shape=(2,), dtype=float32),
  1: tf.Tensor([0.02066157 0.77539235], shape=(2,), dtype=float32)
}
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.
PerReplica:{
  0: tf.Tensor([-0.87930447 -1.5822568 ], shape=(2,), dtype=float32),
  1: tf.Tensor([0.02066157 0.77539235], shape=(2,), dtype=float32)
}

हम अब गुजर की सिफारिश tf.random.Generator के तर्कों के रूप Strategy.run , क्योंकि Strategy.run आम तौर पर उम्मीद तर्क tensors, नहीं जनरेटर होने के लिए।

जनरेटर की बचत

आम तौर पर बचत या serializing आप एक संभाल कर सकते हैं के लिए tf.random.Generator उसी तरह आप एक संभाल होगा tf.Variable या एक tf.Module (या इसके उपवर्ग)। : TF में क्रमांकन के लिए दो प्रणालियों देखते हैं चेकप्वाइंट और SavedModel

जांच की चौकी

जेनरेटर स्वतंत्र रूप से बचाया जा सकता है और उसे पुन: उपयोग करते हुए tf.train.Checkpoint । रिस्टोरिंग पॉइंट से रैंडम-नंबर स्ट्रीम वही होगी जो सेविंग पॉइंट से होती है।

filename = "./checkpoint"
g = tf.random.Generator.from_seed(1)
cp = tf.train.Checkpoint(generator=g)
print(g.normal([]))
tf.Tensor(0.43842277, shape=(), dtype=float32)
cp.write(filename)
print("RNG stream from saving point:")
print(g.normal([]))
print(g.normal([]))
RNG stream from saving point:
tf.Tensor(1.6272374, shape=(), dtype=float32)
tf.Tensor(1.6307176, shape=(), dtype=float32)
cp.restore(filename)
print("RNG stream from restoring point:")
print(g.normal([]))
print(g.normal([]))
RNG stream from restoring point:
tf.Tensor(1.6272374, shape=(), dtype=float32)
tf.Tensor(1.6307176, shape=(), dtype=float32)

आप वितरण कार्यनीति के अंतर्गत सहेज भी सकते हैं और पुनर्स्थापित भी कर सकते हैं:

filename = "./checkpoint"
strat = tf.distribute.MirroredStrategy(devices=["cpu:0", "cpu:1"])
with strat.scope():
  g = tf.random.Generator.from_seed(1)
  cp = tf.train.Checkpoint(my_generator=g)
  print(strat.run(lambda: g.normal([])))
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')
PerReplica:{
  0: tf.Tensor(-0.87930447, shape=(), dtype=float32),
  1: tf.Tensor(0.020661574, shape=(), dtype=float32)
}
with strat.scope():
  cp.write(filename)
  print("RNG stream from saving point:")
  print(strat.run(lambda: g.normal([])))
  print(strat.run(lambda: g.normal([])))
RNG stream from saving point:
PerReplica:{
  0: tf.Tensor(-1.5822568, shape=(), dtype=float32),
  1: tf.Tensor(0.77539235, shape=(), dtype=float32)
}
PerReplica:{
  0: tf.Tensor(-0.5039703, shape=(), dtype=float32),
  1: tf.Tensor(0.1251838, shape=(), dtype=float32)
}
with strat.scope():
  cp.restore(filename)
  print("RNG stream from restoring point:")
  print(strat.run(lambda: g.normal([])))
  print(strat.run(lambda: g.normal([])))
RNG stream from restoring point:
PerReplica:{
  0: tf.Tensor(-1.5822568, shape=(), dtype=float32),
  1: tf.Tensor(0.77539235, shape=(), dtype=float32)
}
PerReplica:{
  0: tf.Tensor(-0.5039703, shape=(), dtype=float32),
  1: tf.Tensor(0.1251838, shape=(), dtype=float32)
}

आपको यह सुनिश्चित करना चाहिए कि सेव करने से पहले रेप्लिका अपने RNG कॉल इतिहास में अलग-अलग न हों (उदाहरण के लिए एक रेप्लिका एक RNG कॉल करती है जबकि दूसरी दो RNG कॉल करती है)। अन्यथा, उनकी आंतरिक RNG राज्यों वितरित हो जाएगा और tf.train.Checkpoint (जो केवल पहले प्रतिकृति के राज्य बचाता है) ठीक से सभी प्रतिकृतियां नहीं हो जाएगी।

आप किसी सहेजे गए चेकपॉइंट को किसी भिन्न वितरण कार्यनीति में भिन्न संख्या में प्रतिकृतियों के साथ पुनर्स्थापित भी कर सकते हैं। क्योंकि एक tf.random.Generator एक रणनीति में बनाया वस्तु केवल एक ही रणनीति में इस्तेमाल किया जा सकता है, एक अलग रणनीति के लिए बहाल करने के लिए, आप एक नया बनाने के लिए tf.random.Generator लक्ष्य रणनीति और एक नया में tf.train.Checkpoint इसके लिए, के रूप में इस उदाहरण में दिखाया गया है:

filename = "./checkpoint"
strat1 = tf.distribute.MirroredStrategy(devices=["cpu:0", "cpu:1"])
with strat1.scope():
  g1 = tf.random.Generator.from_seed(1)
  cp1 = tf.train.Checkpoint(my_generator=g1)
  print(strat1.run(lambda: g1.normal([])))
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')
PerReplica:{
  0: tf.Tensor(-0.87930447, shape=(), dtype=float32),
  1: tf.Tensor(0.020661574, shape=(), dtype=float32)
}
with strat1.scope():
  cp1.write(filename)
  print("RNG stream from saving point:")
  print(strat1.run(lambda: g1.normal([])))
  print(strat1.run(lambda: g1.normal([])))
RNG stream from saving point:
PerReplica:{
  0: tf.Tensor(-1.5822568, shape=(), dtype=float32),
  1: tf.Tensor(0.77539235, shape=(), dtype=float32)
}
PerReplica:{
  0: tf.Tensor(-0.5039703, shape=(), dtype=float32),
  1: tf.Tensor(0.1251838, shape=(), dtype=float32)
}
strat2 = tf.distribute.MirroredStrategy(devices=["cpu:0", "cpu:1", "cpu:2"])
with strat2.scope():
  g2 = tf.random.Generator.from_seed(1)
  cp2 = tf.train.Checkpoint(my_generator=g2)
  cp2.restore(filename)
  print("RNG stream from restoring point:")
  print(strat2.run(lambda: g2.normal([])))
  print(strat2.run(lambda: g2.normal([])))
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', '/job:localhost/replica:0/task:0/device:CPU:2')
RNG stream from restoring point:
PerReplica:{
  0: tf.Tensor(-1.5822568, shape=(), dtype=float32),
  1: tf.Tensor(0.77539235, shape=(), dtype=float32),
  2: tf.Tensor(0.6851049, shape=(), dtype=float32)
}
PerReplica:{
  0: tf.Tensor(-0.5039703, shape=(), dtype=float32),
  1: tf.Tensor(0.1251838, shape=(), dtype=float32),
  2: tf.Tensor(-0.58519536, shape=(), dtype=float32)
}

हालांकि g1 और cp1 से अलग वस्तुओं रहे हैं g2 और cp2 , वे आम चौकी फ़ाइल के माध्यम से जुड़े हुए हैं filename और ऑब्जेक्ट नाम my_generator । ओवरलैपिंग रणनीतियों के बीच प्रतिकृतियां (जैसे cpu:0 और cpu:1 ऊपर) अपने RNG ठीक से पूर्व उदाहरणों में की तरह बहाल स्ट्रीम होगा। यह गारंटी उस मामले को कवर नहीं करती है जब एक जनरेटर को एक रणनीति के दायरे में सहेजा जाता है और किसी भी रणनीति के दायरे से बाहर बहाल किया जाता है या इसके विपरीत, क्योंकि रणनीति के बाहर एक उपकरण को रणनीति में किसी भी प्रतिकृति से अलग माना जाता है।

सहेजा गया मॉडल

tf.random.Generator एक SavedModel को बचाया जा सकता। जनरेटर को एक रणनीति के दायरे में बनाया जा सकता है। बचत एक रणनीति के दायरे में भी हो सकती है।

filename = "./saved_model"

class MyModule(tf.Module):

  def __init__(self):
    super(MyModule, self).__init__()
    self.g = tf.random.Generator.from_seed(0)

  @tf.function
  def __call__(self):
    return self.g.normal([])

  @tf.function
  def state(self):
    return self.g.state

strat = tf.distribute.MirroredStrategy(devices=["cpu:0", "cpu:1"])
with strat.scope():
  m = MyModule()
  print(strat.run(m))
  print("state:", m.state())
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')
PerReplica:{
  0: tf.Tensor(-1.4154755, shape=(), dtype=float32),
  1: tf.Tensor(-0.113884404, shape=(), dtype=float32)
}
state: tf.Tensor([256   0   0], shape=(3,), dtype=int64)
with strat.scope():
  tf.saved_model.save(m, filename)
  print("RNG stream from saving point:")
  print(strat.run(m))
  print("state:", m.state())
  print(strat.run(m))
  print("state:", m.state())
INFO:tensorflow:Assets written to: ./saved_model/assets
RNG stream from saving point:
PerReplica:{
  0: tf.Tensor(-0.68758255, shape=(), dtype=float32),
  1: tf.Tensor(0.8084062, shape=(), dtype=float32)
}
state: tf.Tensor([512   0   0], shape=(3,), dtype=int64)
PerReplica:{
  0: tf.Tensor(-0.27342677, shape=(), dtype=float32),
  1: tf.Tensor(-0.53093255, shape=(), dtype=float32)
}
state: tf.Tensor([768   0   0], shape=(3,), dtype=int64)
2021-09-22 20:45:46.222281: W tensorflow/python/util/util.cc:348] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
imported = tf.saved_model.load(filename)
print("RNG stream from loading point:")
print("state:", imported.state())
print(imported())
print("state:", imported.state())
print(imported())
print("state:", imported.state())
RNG stream from loading point:
state: tf.Tensor([256   0   0], shape=(3,), dtype=int64)
tf.Tensor(-1.0359411, shape=(), dtype=float32)
state: tf.Tensor([512   0   0], shape=(3,), dtype=int64)
tf.Tensor(-0.06425078, shape=(), dtype=float32)
state: tf.Tensor([768   0   0], shape=(3,), dtype=int64)

एक SavedModel युक्त लोड हो रहा है tf.random.Generator एक वितरण रणनीति में अनुशंसित नहीं है क्योंकि प्रतिकृतियां सभी एक ही यादृच्छिक संख्या धारा (जो क्योंकि प्रतिकृति आईडी SavedModel के ग्राफ में जमे हुए है) उत्पन्न होगा।

एक वितरित लोड हो रहा है tf.random.Generator एक गैर रणनीति वातावरण में (एक जनरेटर एक वितरण रणनीति के भीतर बनाई गई), ऊपर के उदाहरण की तरह, यह भी एक चेतावनी है। आरएनजी राज्य को ठीक से बहाल किया जाएगा, लेकिन उत्पन्न यादृच्छिक संख्या अपनी रणनीति में मूल जनरेटर से अलग होगी (फिर से क्योंकि रणनीति के बाहर एक उपकरण को रणनीति में किसी भी प्रतिकृति से अलग माना जाता है)।

स्टेटलेस आरएनजी

स्टेटलेस आरएनजी का उपयोग सरल है। चूंकि वे सिर्फ शुद्ध कार्य हैं, इसमें कोई राज्य या साइड इफेक्ट शामिल नहीं है।

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.30159    -0.95385665]], shape=(2, 3), dtype=float32)
tf.Tensor(
[[ 0.5441101   0.20738031  0.07356433]
 [ 0.04643455 -1.30159    -0.95385665]], shape=(2, 3), dtype=float32)

हर राज्यविहीन RNG एक आवश्यकता seed तर्क है, जो आकार के एक पूर्णांक टेन्सर होने की जरूरत है [2] । ऑप के परिणाम पूरी तरह से इसी बीज से निर्धारित होते हैं।

स्टेटलेस आरएनजी द्वारा उपयोग किया जाने वाला आरएनजी एल्गोरिदम डिवाइस-निर्भर है, जिसका अर्थ है कि एक अलग डिवाइस पर चलने वाला एक ही ऑप अलग-अलग आउटपुट उत्पन्न कर सकता है।

एल्गोरिदम

आम

दोनों tf.random.Generator वर्ग और stateless कार्यों Philox एल्गोरिथ्म (के रूप में लिखा समर्थन "philox" या tf.random.Algorithm.PHILOX सभी उपकरणों पर)।

यदि एक ही एल्गोरिदम का उपयोग करते हुए और एक ही राज्य से शुरू करते हैं, तो विभिन्न डिवाइस एक ही पूर्णांक संख्या उत्पन्न करेंगे। वे "लगभग समान" फ्लोट-पॉइंट नंबर भी उत्पन्न करेंगे, हालांकि विभिन्न तरीकों के कारण छोटी संख्यात्मक विसंगतियां हो सकती हैं जो डिवाइस फ्लोट-पॉइंट गणना (उदाहरण के लिए कमी क्रम) को पूरा करते हैं।

एक्सएलए डिवाइस

(जैसे TPU के रूप में, और यह भी CPU / GPU जब XLA सक्षम है) XLA चालित उपकरणों ThreeFry एल्गोरिथ्म (के रूप में लिखा पर "threefry" या tf.random.Algorithm.THREEFRY ) भी समर्थित है। यह एल्गोरिथम टीपीयू पर तेज है लेकिन फिलॉक्स की तुलना में सीपीयू/जीपीयू पर धीमा है।

कागज देखें : 'के रूप में 1, 2, 3 के रूप में आराम से समानांतर रैंडम नंबर' इन एल्गोरिदम के बारे में अधिक जानकारी के लिए।