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