• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2015 The TensorFlow Authors. All Rights Reserved.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14# ==============================================================================
15"""Operations for generating random numbers."""
16
17from __future__ import absolute_import
18from __future__ import division
19from __future__ import print_function
20
21import numpy as np
22
23from tensorflow.python.eager import context
24from tensorflow.python.framework import dtypes
25from tensorflow.python.framework import ops
26from tensorflow.python.framework import random_seed
27from tensorflow.python.framework import tensor_util
28from tensorflow.python.ops import array_ops
29from tensorflow.python.ops import control_flow_ops
30from tensorflow.python.ops import gen_random_ops
31from tensorflow.python.ops import math_ops
32from tensorflow.python.ops import stateless_random_ops
33
34# go/tf-wildcard-import
35# pylint: disable=wildcard-import
36from tensorflow.python.ops.gen_random_ops import *
37# pylint: enable=wildcard-import
38
39from tensorflow.python.util import deprecation
40from tensorflow.python.util import dispatch
41from tensorflow.python.util.tf_export import tf_export
42
43
44@tf_export("random.normal", v1=["random.normal", "random_normal"])
45@dispatch.add_dispatch_support
46@deprecation.deprecated_endpoints("random_normal")
47def random_normal(shape,
48                  mean=0.0,
49                  stddev=1.0,
50                  dtype=dtypes.float32,
51                  seed=None,
52                  name=None):
53  """Outputs random values from a normal distribution.
54
55  Example that generates a new set of random values every time:
56
57  >>> tf.random.set_seed(5);
58  >>> tf.random.normal([4], 0, 1, tf.float32)
59  <tf.Tensor: shape=(4,), dtype=float32, numpy=..., dtype=float32)>
60
61  Example that outputs a reproducible result:
62
63  >>> tf.random.set_seed(5);
64  >>> tf.random.normal([2,2], 0, 1, tf.float32, seed=1)
65  <tf.Tensor: shape=(2, 2), dtype=float32, numpy=
66  array([[-1.3768897 , -0.01258316],
67        [-0.169515   ,  1.0824056 ]], dtype=float32)>
68
69  In this case, we are setting both the global and operation-level seed to
70  ensure this result is reproducible.  See `tf.random.set_seed` for more
71  information.
72
73  Args:
74    shape: A 1-D integer Tensor or Python array. The shape of the output tensor.
75    mean: A Tensor or Python value of type `dtype`, broadcastable with `stddev`.
76      The mean of the normal distribution.
77    stddev: A Tensor or Python value of type `dtype`, broadcastable with `mean`.
78      The standard deviation of the normal distribution.
79    dtype: The type of the output.
80    seed: A Python integer. Used to create a random seed for the distribution.
81      See
82      `tf.random.set_seed`
83      for behavior.
84    name: A name for the operation (optional).
85
86  Returns:
87    A tensor of the specified shape filled with random normal values.
88  """
89  with ops.name_scope(name, "random_normal", [shape, mean, stddev]) as name:
90    shape_tensor = tensor_util.shape_tensor(shape)
91    mean_tensor = ops.convert_to_tensor(mean, dtype=dtype, name="mean")
92    stddev_tensor = ops.convert_to_tensor(stddev, dtype=dtype, name="stddev")
93    seed1, seed2 = random_seed.get_seed(seed)
94    rnd = gen_random_ops.random_standard_normal(
95        shape_tensor, dtype, seed=seed1, seed2=seed2)
96    mul = rnd * stddev_tensor
97    value = math_ops.add(mul, mean_tensor, name=name)
98    tensor_util.maybe_set_static_shape(value, shape)
99    return value
100
101
102ops.NotDifferentiable("RandomStandardNormal")
103
104
105def parameterized_truncated_normal(shape,
106                                   means=0.0,
107                                   stddevs=1.0,
108                                   minvals=-2.0,
109                                   maxvals=2.0,
110                                   dtype=dtypes.float32,
111                                   seed=None,
112                                   name=None):
113  """Outputs random values from a truncated normal distribution.
114
115  The generated values follow a normal distribution with specified mean and
116  standard deviation, except that values whose magnitude is more than 2 standard
117  deviations from the mean are dropped and re-picked.
118
119  Args:
120    shape: A 1-D integer Tensor or Python array. The shape of the output tensor.
121    means: A 0-D Tensor or Python value of type `dtype`. The mean of the
122      truncated normal distribution.
123    stddevs: A 0-D Tensor or Python value of type `dtype`. The standard
124      deviation of the truncated normal distribution.
125    minvals: A 0-D Tensor or Python value of type `dtype`. The minimum value of
126      the truncated normal distribution.
127    maxvals: A 0-D Tensor or Python value of type `dtype`. The maximum value of
128      the truncated normal distribution.
129    dtype: The type of the output.
130    seed: A Python integer. Used to create a random seed for the distribution.
131      See
132      `tf.random.set_seed`
133      for behavior.
134    name: A name for the operation (optional).
135
136  Returns:
137    A tensor of the specified shape filled with random truncated normal values.
138  """
139  with ops.name_scope(name, "parameterized_truncated_normal",
140                      [shape, means, stddevs, minvals, maxvals]) as name:
141    shape_tensor = tensor_util.shape_tensor(shape)
142    means_tensor = ops.convert_to_tensor(means, dtype=dtype, name="means")
143    stddevs_tensor = ops.convert_to_tensor(stddevs, dtype=dtype, name="stddevs")
144    minvals_tensor = ops.convert_to_tensor(minvals, dtype=dtype, name="minvals")
145    maxvals_tensor = ops.convert_to_tensor(maxvals, dtype=dtype, name="maxvals")
146    seed1, seed2 = random_seed.get_seed(seed)
147    rnd = gen_random_ops.parameterized_truncated_normal(
148        shape_tensor,
149        means_tensor,
150        stddevs_tensor,
151        minvals_tensor,
152        maxvals_tensor,
153        seed=seed1,
154        seed2=seed2)
155    tensor_util.maybe_set_static_shape(rnd, shape)
156    return rnd
157
158
159@tf_export("random.truncated_normal",
160           v1=["random.truncated_normal", "truncated_normal"])
161@dispatch.add_dispatch_support
162@deprecation.deprecated_endpoints("truncated_normal")
163def truncated_normal(shape,
164                     mean=0.0,
165                     stddev=1.0,
166                     dtype=dtypes.float32,
167                     seed=None,
168                     name=None):
169  """Outputs random values from a truncated normal distribution.
170
171  The values are drawn from a normal distribution with specified mean and
172  standard deviation, discarding and re-drawing any samples that are more than
173  two standard deviations from the mean.
174
175  Examples:
176
177  >>> tf.random.truncated_normal(shape=[2])
178  <tf.Tensor: shape=(2,), dtype=float32, numpy=array([..., ...], dtype=float32)>
179
180  >>> tf.random.truncated_normal(shape=[2], mean=3, stddev=1, dtype=tf.float32)
181  <tf.Tensor: shape=(2,), dtype=float32, numpy=array([..., ...], dtype=float32)>
182
183  Args:
184    shape: A 1-D integer Tensor or Python array. The shape of the output tensor.
185    mean: A 0-D Tensor or Python value of type `dtype`. The mean of the
186      truncated normal distribution.
187    stddev: A 0-D Tensor or Python value of type `dtype`. The standard deviation
188      of the normal distribution, before truncation.
189    dtype: The type of the output. Restricted to floating-point types:
190      `tf.half`, `tf.float`, `tf.double`, etc.
191    seed: A Python integer. Used to create a random seed for the distribution.
192      See `tf.random.set_seed` for more information.
193    name: A name for the operation (optional).
194
195  Returns:
196    A tensor of the specified shape filled with random truncated normal values.
197  """
198  with ops.name_scope(name, "truncated_normal", [shape, mean, stddev]) as name:
199    shape_tensor = tensor_util.shape_tensor(shape)
200    mean_tensor = ops.convert_to_tensor(mean, dtype=dtype, name="mean")
201    stddev_tensor = ops.convert_to_tensor(stddev, dtype=dtype, name="stddev")
202    seed1, seed2 = random_seed.get_seed(seed)
203    rnd = gen_random_ops.truncated_normal(
204        shape_tensor, dtype, seed=seed1, seed2=seed2)
205    mul = rnd * stddev_tensor
206    value = math_ops.add(mul, mean_tensor, name=name)
207    tensor_util.maybe_set_static_shape(value, shape)
208    return value
209
210
211ops.NotDifferentiable("ParameterizedTruncatedNormal")
212ops.NotDifferentiable("TruncatedNormal")
213
214
215@tf_export("random.uniform", v1=["random.uniform", "random_uniform"])
216@dispatch.add_dispatch_support
217@deprecation.deprecated_endpoints("random_uniform")
218def random_uniform(shape,
219                   minval=0,
220                   maxval=None,
221                   dtype=dtypes.float32,
222                   seed=None,
223                   name=None):
224  """Outputs random values from a uniform distribution.
225
226  The generated values follow a uniform distribution in the range
227  `[minval, maxval)`. The lower bound `minval` is included in the range, while
228  the upper bound `maxval` is excluded.
229
230  For floats, the default range is `[0, 1)`.  For ints, at least `maxval` must
231  be specified explicitly.
232
233  In the integer case, the random integers are slightly biased unless
234  `maxval - minval` is an exact power of two.  The bias is small for values of
235  `maxval - minval` significantly smaller than the range of the output (either
236  `2**32` or `2**64`).
237
238  Examples:
239
240  >>> tf.random.uniform(shape=[2])
241  <tf.Tensor: shape=(2,), dtype=float32, numpy=array([..., ...], dtype=float32)>
242  >>> tf.random.uniform(shape=[], minval=-1., maxval=0.)
243  <tf.Tensor: shape=(), dtype=float32, numpy=-...>
244  >>> tf.random.uniform(shape=[], minval=5, maxval=10, dtype=tf.int64)
245  <tf.Tensor: shape=(), dtype=int64, numpy=...>
246
247  The `seed` argument produces a deterministic sequence of tensors across
248  multiple calls. To repeat that sequence, use `tf.random.set_seed`:
249
250  >>> tf.random.set_seed(5)
251  >>> tf.random.uniform(shape=[], maxval=3, dtype=tf.int32, seed=10)
252  <tf.Tensor: shape=(), dtype=int32, numpy=2>
253  >>> tf.random.uniform(shape=[], maxval=3, dtype=tf.int32, seed=10)
254  <tf.Tensor: shape=(), dtype=int32, numpy=0>
255  >>> tf.random.set_seed(5)
256  >>> tf.random.uniform(shape=[], maxval=3, dtype=tf.int32, seed=10)
257  <tf.Tensor: shape=(), dtype=int32, numpy=2>
258  >>> tf.random.uniform(shape=[], maxval=3, dtype=tf.int32, seed=10)
259  <tf.Tensor: shape=(), dtype=int32, numpy=0>
260
261  Without `tf.random.set_seed` but with a `seed` argument is specified, small
262  changes to function graphs or previously executed operations will change the
263  returned value. See `tf.random.set_seed` for details.
264
265  Args:
266    shape: A 1-D integer Tensor or Python array. The shape of the output tensor.
267    minval: A Tensor or Python value of type `dtype`, broadcastable with
268      `shape` (for integer types, broadcasting is not supported, so it needs to
269      be a scalar). The lower bound on the range of random values to generate
270      (inclusive).  Defaults to 0.
271    maxval: A Tensor or Python value of type `dtype`, broadcastable with
272      `shape` (for integer types, broadcasting is not supported, so it needs to
273      be a scalar). The upper bound on the range of random values to generate
274      (exclusive). Defaults to 1 if `dtype` is floating point.
275    dtype: The type of the output: `float16`, `float32`, `float64`, `int32`,
276      or `int64`.
277    seed: A Python integer. Used in combination with `tf.random.set_seed` to
278      create a reproducible sequence of tensors across multiple calls.
279    name: A name for the operation (optional).
280
281  Returns:
282    A tensor of the specified shape filled with random uniform values.
283
284  Raises:
285    ValueError: If `dtype` is integral and `maxval` is not specified.
286  """
287  dtype = dtypes.as_dtype(dtype)
288  if dtype not in (dtypes.float16, dtypes.bfloat16, dtypes.float32,
289                   dtypes.float64, dtypes.int32, dtypes.int64):
290    raise ValueError("Invalid dtype %r" % dtype)
291  if maxval is None:
292    if dtype.is_integer:
293      raise ValueError("Must specify maxval for integer dtype %r" % dtype)
294    maxval = 1
295  with ops.name_scope(name, "random_uniform", [shape, minval, maxval]) as name:
296    shape = tensor_util.shape_tensor(shape)
297    # In case of [0,1) floating results, minval and maxval is unused. We do an
298    # `is` comparison here since this is cheaper than isinstance or  __eq__.
299    minval_is_zero = isinstance(minval, int) and minval == 0
300    maxval_is_one = isinstance(maxval, int) and maxval == 1
301    if not minval_is_zero or not maxval_is_one or dtype.is_integer:
302      minval = ops.convert_to_tensor(minval, dtype=dtype, name="min")
303      maxval = ops.convert_to_tensor(maxval, dtype=dtype, name="max")
304    seed1, seed2 = random_seed.get_seed(seed)
305    if dtype.is_integer:
306      result = gen_random_ops.random_uniform_int(
307          shape, minval, maxval, seed=seed1, seed2=seed2, name=name)
308    else:
309      result = gen_random_ops.random_uniform(
310          shape, dtype, seed=seed1, seed2=seed2)
311      if minval_is_zero:
312        if not maxval_is_one:
313          result = math_ops.multiply(result, maxval)
314      else:
315        result = math_ops.add(result * (maxval - minval), minval, name=name)
316    # TODO(b/132092188): C++ shape inference inside functional ops does not
317    # cross FuncGraph boundaries since that information is only available in
318    # python. So we manually get the static shape using
319    # `constant_value_as_shape` which *does* cross function boundaries.
320    tensor_util.maybe_set_static_shape(result, shape)
321    return result
322
323
324ops.NotDifferentiable("RandomUniform")
325
326
327@tf_export("random.shuffle", v1=["random.shuffle", "random_shuffle"])
328@dispatch.add_dispatch_support
329@deprecation.deprecated_endpoints("random_shuffle")
330def random_shuffle(value, seed=None, name=None):
331  """Randomly shuffles a tensor along its first dimension.
332
333  The tensor is shuffled along dimension 0, such that each `value[j]` is mapped
334  to one and only one `output[i]`. For example, a mapping that might occur for a
335  3x2 tensor is:
336
337  ```python
338  [[1, 2],       [[5, 6],
339   [3, 4],  ==>   [1, 2],
340   [5, 6]]        [3, 4]]
341  ```
342
343  Args:
344    value: A Tensor to be shuffled.
345    seed: A Python integer. Used to create a random seed for the distribution.
346      See
347      `tf.random.set_seed`
348      for behavior.
349    name: A name for the operation (optional).
350
351  Returns:
352    A tensor of same shape and type as `value`, shuffled along its first
353    dimension.
354  """
355  seed1, seed2 = random_seed.get_seed(seed)
356  return gen_random_ops.random_shuffle(
357      value, seed=seed1, seed2=seed2, name=name)
358
359
360@tf_export("image.random_crop", v1=["image.random_crop", "random_crop"])
361@dispatch.add_dispatch_support
362@deprecation.deprecated_endpoints("random_crop")
363def random_crop(value, size, seed=None, name=None):
364  """Randomly crops a tensor to a given size.
365
366  Slices a shape `size` portion out of `value` at a uniformly chosen offset.
367  Requires `value.shape >= size`.
368
369  If a dimension should not be cropped, pass the full size of that dimension.
370  For example, RGB images can be cropped with
371  `size = [crop_height, crop_width, 3]`.
372
373  Example usage:
374
375  >>> image = [[1, 2, 3], [4, 5, 6]]
376  >>> result = tf.image.random_crop(value=image, size=(1, 3))
377  >>> result.shape.as_list()
378  [1, 3]
379
380  For producing deterministic results given a `seed` value, use
381  `tf.image.stateless_random_crop`. Unlike using the `seed` param with
382  `tf.image.random_*` ops, `tf.image.stateless_random_*` ops guarantee the same
383  results given the same seed independent of how many times the function is
384  called, and independent of global seed settings (e.g. tf.random.set_seed).
385
386  Args:
387    value: Input tensor to crop.
388    size: 1-D tensor with size the rank of `value`.
389    seed: Python integer. Used to create a random seed. See
390      `tf.random.set_seed`
391      for behavior.
392    name: A name for this operation (optional).
393
394  Returns:
395    A cropped tensor of the same rank as `value` and shape `size`.
396  """
397  with ops.name_scope(name, "random_crop", [value, size]) as name:
398    value = ops.convert_to_tensor(value, name="value")
399    size = ops.convert_to_tensor(size, dtype=dtypes.int32, name="size")
400    shape = array_ops.shape(value)
401    check = control_flow_ops.Assert(
402        math_ops.reduce_all(shape >= size),
403        ["Need value.shape >= size, got ", shape, size],
404        summarize=1000)
405    shape = control_flow_ops.with_dependencies([check], shape)
406    limit = shape - size + 1
407    offset = random_uniform(
408        array_ops.shape(shape),
409        dtype=size.dtype,
410        maxval=size.dtype.max,
411        seed=seed) % limit
412    return array_ops.slice(value, offset, size, name=name)
413
414
415@tf_export("image.stateless_random_crop", v1=[])
416@dispatch.add_dispatch_support
417def stateless_random_crop(value, size, seed, name=None):
418  """Randomly crops a tensor to a given size in a deterministic manner.
419
420  Slices a shape `size` portion out of `value` at a uniformly chosen offset.
421  Requires `value.shape >= size`.
422
423  If a dimension should not be cropped, pass the full size of that dimension.
424  For example, RGB images can be cropped with
425  `size = [crop_height, crop_width, 3]`.
426
427  Guarantees the same results given the same `seed` independent of how many
428  times the function is called, and independent of global seed settings (e.g.
429  `tf.random.set_seed`).
430
431  Usage Example:
432
433  >>> image = [[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]]
434  >>> seed = (1, 2)
435  >>> tf.image.stateless_random_crop(value=image, size=(1, 2, 3), seed=seed)
436  <tf.Tensor: shape=(1, 2, 3), dtype=int32, numpy=
437  array([[[1, 2, 3],
438          [4, 5, 6]]], dtype=int32)>
439
440  Args:
441    value: Input tensor to crop.
442    size: 1-D tensor with size the rank of `value`.
443    seed: A shape [2] Tensor, the seed to the random number generator. Must have
444      dtype `int32` or `int64`. (When using XLA, only `int32` is allowed.)
445    name: A name for this operation (optional).
446
447  Returns:
448    A cropped tensor of the same rank as `value` and shape `size`.
449  """
450  with ops.name_scope(name, "random_crop", [value, size]) as name:
451    value = ops.convert_to_tensor(value, name="value")
452    size = ops.convert_to_tensor(size, dtype=dtypes.int32, name="size")
453    shape = array_ops.shape(value)
454    check = control_flow_ops.Assert(
455        math_ops.reduce_all(shape >= size),
456        ["Need value.shape >= size, got ", shape, size],
457        summarize=1000)
458    shape = control_flow_ops.with_dependencies([check], shape)
459    limit = shape - size + 1
460    offset = stateless_random_ops.stateless_random_uniform(
461        array_ops.shape(shape),
462        dtype=size.dtype,
463        maxval=size.dtype.max,
464        seed=seed) % limit
465    return array_ops.slice(value, offset, size, name=name)
466
467
468@tf_export(v1=["random.multinomial", "multinomial"])
469@dispatch.add_dispatch_support
470@deprecation.deprecated(
471    date=None, instructions="Use `tf.random.categorical` instead.")
472def multinomial(logits, num_samples, seed=None, name=None, output_dtype=None):
473  """Draws samples from a multinomial distribution.
474
475  Example:
476
477  ```python
478  # samples has shape [1, 5], where each value is either 0 or 1 with equal
479  # probability.
480  samples = tf.random.categorical(tf.math.log([[0.5, 0.5]]), 5)
481  ```
482
483  Args:
484    logits: 2-D Tensor with shape `[batch_size, num_classes]`.  Each slice
485      `[i, :]` represents the unnormalized log-probabilities for all classes.
486    num_samples: 0-D.  Number of independent samples to draw for each row slice.
487    seed: A Python integer. Used to create a random seed for the distribution.
488      See `tf.random.set_seed` for behavior.
489    name: Optional name for the operation.
490    output_dtype: integer type to use for the output. Defaults to int64.
491
492  Returns:
493    The drawn samples of shape `[batch_size, num_samples]`.
494  """
495  with ops.name_scope(name, "multinomial", [logits]):
496    return multinomial_categorical_impl(logits, num_samples, output_dtype, seed)
497
498
499@tf_export("random.categorical")
500@dispatch.add_dispatch_support
501def categorical(logits, num_samples, dtype=None, seed=None, name=None):
502  """Draws samples from a categorical distribution.
503
504  Example:
505
506  ```python
507  # samples has shape [1, 5], where each value is either 0 or 1 with equal
508  # probability.
509  samples = tf.random.categorical(tf.math.log([[0.5, 0.5]]), 5)
510  ```
511
512  Args:
513    logits: 2-D Tensor with shape `[batch_size, num_classes]`.  Each slice
514      `[i, :]` represents the unnormalized log-probabilities for all classes.
515    num_samples: 0-D.  Number of independent samples to draw for each row slice.
516    dtype: integer type to use for the output. Defaults to int64.
517    seed: A Python integer. Used to create a random seed for the distribution.
518      See `tf.random.set_seed` for behavior.
519    name: Optional name for the operation.
520
521  Returns:
522    The drawn samples of shape `[batch_size, num_samples]`.
523  """
524  with ops.name_scope(name, "categorical", [logits]):
525    return multinomial_categorical_impl(logits, num_samples, dtype, seed)
526
527
528def multinomial_categorical_impl(logits, num_samples, dtype, seed):
529  """Implementation for random.categorical (v1) and random.categorical (v2)."""
530  logits = ops.convert_to_tensor(logits, name="logits")
531  seed1, seed2 = random_seed.get_seed(seed)
532  return gen_random_ops.multinomial(
533      logits, num_samples, seed=seed1, seed2=seed2, output_dtype=dtype)
534
535
536ops.NotDifferentiable("Multinomial")
537
538
539def _maybe_set_static_shape_helper(tensor, shape, postfix_tensor):
540  if (not context.executing_eagerly() and
541      ops.get_default_graph().building_function and
542      not tensor.shape.is_fully_defined()):
543    shape = tensor_util.shape_tensor(shape)
544    const_shape = tensor_util.constant_value_as_shape(shape)
545    postfix_tensor = ops.convert_to_tensor(postfix_tensor)
546    tensor.set_shape(const_shape.concatenate(postfix_tensor.shape))
547
548
549@tf_export("random.gamma", v1=["random.gamma", "random_gamma"])
550@dispatch.add_dispatch_support
551@deprecation.deprecated_endpoints("random_gamma")
552def random_gamma(shape,
553                 alpha,
554                 beta=None,
555                 dtype=dtypes.float32,
556                 seed=None,
557                 name=None):
558  """Draws `shape` samples from each of the given Gamma distribution(s).
559
560  `alpha` is the shape parameter describing the distribution(s), and `beta` is
561  the inverse scale parameter(s).
562
563  Note: Because internal calculations are done using `float64` and casting has
564  `floor` semantics, we must manually map zero outcomes to the smallest
565  possible positive floating-point value, i.e., `np.finfo(dtype).tiny`.  This
566  means that `np.finfo(dtype).tiny` occurs more frequently than it otherwise
567  should.  This bias can only happen for small values of `alpha`, i.e.,
568  `alpha << 1` or large values of `beta`, i.e., `beta >> 1`.
569
570  The samples are differentiable w.r.t. alpha and beta.
571  The derivatives are computed using the approach described in
572  (Figurnov et al., 2018).
573
574  Example:
575
576  ```python
577  samples = tf.random.gamma([10], [0.5, 1.5])
578  # samples has shape [10, 2], where each slice [:, 0] and [:, 1] represents
579  # the samples drawn from each distribution
580
581  samples = tf.random.gamma([7, 5], [0.5, 1.5])
582  # samples has shape [7, 5, 2], where each slice [:, :, 0] and [:, :, 1]
583  # represents the 7x5 samples drawn from each of the two distributions
584
585  alpha = tf.constant([[1.],[3.],[5.]])
586  beta = tf.constant([[3., 4.]])
587  samples = tf.random.gamma([30], alpha=alpha, beta=beta)
588  # samples has shape [30, 3, 2], with 30 samples each of 3x2 distributions.
589
590  loss = tf.reduce_mean(tf.square(samples))
591  dloss_dalpha, dloss_dbeta = tf.gradients(loss, [alpha, beta])
592  # unbiased stochastic derivatives of the loss function
593  alpha.shape == dloss_dalpha.shape  # True
594  beta.shape == dloss_dbeta.shape  # True
595  ```
596
597  Args:
598    shape: A 1-D integer Tensor or Python array. The shape of the output samples
599      to be drawn per alpha/beta-parameterized distribution.
600    alpha: A Tensor or Python value or N-D array of type `dtype`. `alpha`
601      provides the shape parameter(s) describing the gamma distribution(s) to
602      sample. Must be broadcastable with `beta`.
603    beta: A Tensor or Python value or N-D array of type `dtype`. Defaults to 1.
604      `beta` provides the inverse scale parameter(s) of the gamma
605      distribution(s) to sample. Must be broadcastable with `alpha`.
606    dtype: The type of alpha, beta, and the output: `float16`, `float32`, or
607      `float64`.
608    seed: A Python integer. Used to create a random seed for the distributions.
609      See
610      `tf.random.set_seed`
611      for behavior.
612    name: Optional name for the operation.
613
614  Returns:
615    samples: a `Tensor` of shape
616      `tf.concat([shape, tf.shape(alpha + beta)], axis=0)` with values of type
617      `dtype`.
618
619  References:
620    Implicit Reparameterization Gradients:
621      [Figurnov et al., 2018]
622      (http://papers.nips.cc/paper/7326-implicit-reparameterization-gradients)
623      ([pdf]
624      (http://papers.nips.cc/paper/7326-implicit-reparameterization-gradients.pdf))
625  """
626  with ops.name_scope(name, "random_gamma", [shape, alpha, beta]):
627    shape = ops.convert_to_tensor(shape, name="shape", dtype=dtypes.int32)
628    alpha = ops.convert_to_tensor(alpha, name="alpha", dtype=dtype)
629    beta = ops.convert_to_tensor(
630        beta if beta is not None else 1, name="beta", dtype=dtype)
631    broadcast_shape = array_ops.broadcast_dynamic_shape(
632        array_ops.shape(alpha), array_ops.shape(beta))
633    alpha_broadcast = array_ops.broadcast_to(alpha, broadcast_shape)
634    seed1, seed2 = random_seed.get_seed(seed)
635    result = math_ops.maximum(
636        np.finfo(alpha.dtype.as_numpy_dtype).tiny,
637        gen_random_ops.random_gamma(
638            shape, alpha_broadcast, seed=seed1, seed2=seed2) / beta)
639    _maybe_set_static_shape_helper(result, shape, alpha_broadcast)
640    return result
641
642
643@tf_export(v1=["random.poisson", "random_poisson"])
644@dispatch.add_dispatch_support
645@deprecation.deprecated_endpoints("random_poisson")
646def random_poisson(lam, shape, dtype=dtypes.float32, seed=None, name=None):
647  """Draws `shape` samples from each of the given Poisson distribution(s).
648
649  `lam` is the rate parameter describing the distribution(s).
650
651  Example:
652
653  ```python
654  samples = tf.random.poisson([0.5, 1.5], [10])
655  # samples has shape [10, 2], where each slice [:, 0] and [:, 1] represents
656  # the samples drawn from each distribution
657
658  samples = tf.random.poisson([12.2, 3.3], [7, 5])
659  # samples has shape [7, 5, 2], where each slice [:, :, 0] and [:, :, 1]
660  # represents the 7x5 samples drawn from each of the two distributions
661  ```
662
663  Args:
664    lam: A Tensor or Python value or N-D array of type `dtype`.
665      `lam` provides the rate parameter(s) describing the poisson
666      distribution(s) to sample.
667    shape: A 1-D integer Tensor or Python array. The shape of the output samples
668      to be drawn per "rate"-parameterized distribution.
669    dtype: The type of the output: `float16`, `float32`, `float64`, `int32` or
670      `int64`.
671    seed: A Python integer. Used to create a random seed for the distributions.
672      See
673      `tf.random.set_seed`
674      for behavior.
675    name: Optional name for the operation.
676
677  Returns:
678    samples: a `Tensor` of shape `tf.concat([shape, tf.shape(lam)], axis=0)`
679      with values of type `dtype`.
680  """
681  return random_poisson_v2(shape, lam, dtype, seed, name)
682
683
684@tf_export("random.poisson", v1=[])
685@dispatch.add_dispatch_support
686def random_poisson_v2(shape, lam, dtype=dtypes.float32, seed=None, name=None):
687  """Draws `shape` samples from each of the given Poisson distribution(s).
688
689  `lam` is the rate parameter describing the distribution(s).
690
691  Example:
692
693  ```python
694  samples = tf.random.poisson([10], [0.5, 1.5])
695  # samples has shape [10, 2], where each slice [:, 0] and [:, 1] represents
696  # the samples drawn from each distribution
697
698  samples = tf.random.poisson([7, 5], [12.2, 3.3])
699  # samples has shape [7, 5, 2], where each slice [:, :, 0] and [:, :, 1]
700  # represents the 7x5 samples drawn from each of the two distributions
701  ```
702
703  Args:
704    shape: A 1-D integer Tensor or Python array. The shape of the output samples
705      to be drawn per "rate"-parameterized distribution.
706    lam: A Tensor or Python value or N-D array of type `dtype`.
707      `lam` provides the rate parameter(s) describing the poisson
708      distribution(s) to sample.
709    dtype: The type of the output: `float16`, `float32`, `float64`, `int32` or
710      `int64`.
711    seed: A Python integer. Used to create a random seed for the distributions.
712      See
713      `tf.random.set_seed`
714      for behavior.
715    name: Optional name for the operation.
716
717  Returns:
718    samples: a `Tensor` of shape `tf.concat([shape, tf.shape(lam)], axis=0)`
719      with values of type `dtype`.
720  """
721  with ops.name_scope(name, "random_poisson", [lam, shape]):
722    shape = ops.convert_to_tensor(shape, name="shape", dtype=dtypes.int32)
723    seed1, seed2 = random_seed.get_seed(seed)
724    result = gen_random_ops.random_poisson_v2(
725        shape, lam, dtype=dtype, seed=seed1, seed2=seed2)
726    _maybe_set_static_shape_helper(result, shape, lam)
727    return result
728