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