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