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( 291 ("Invalid dtype. Dtype should be one of float16, float32, " 292 f"float64, int32 and int64, but is {dtype}. ")) 293 if maxval is None: 294 if dtype.is_integer: 295 raise ValueError("Must specify maxval for integer dtype %r" % dtype) 296 maxval = 1 297 with ops.name_scope(name, "random_uniform", [shape, minval, maxval]) as name: 298 shape = tensor_util.shape_tensor(shape) 299 # In case of [0,1) floating results, minval and maxval is unused. We do an 300 # `is` comparison here since this is cheaper than isinstance or __eq__. 301 minval_is_zero = isinstance(minval, int) and minval == 0 302 maxval_is_one = isinstance(maxval, int) and maxval == 1 303 if not minval_is_zero or not maxval_is_one or dtype.is_integer: 304 minval = ops.convert_to_tensor(minval, dtype=dtype, name="min") 305 maxval = ops.convert_to_tensor(maxval, dtype=dtype, name="max") 306 seed1, seed2 = random_seed.get_seed(seed) 307 if dtype.is_integer: 308 result = gen_random_ops.random_uniform_int( 309 shape, minval, maxval, seed=seed1, seed2=seed2, name=name) 310 else: 311 result = gen_random_ops.random_uniform( 312 shape, dtype, seed=seed1, seed2=seed2) 313 if minval_is_zero: 314 if not maxval_is_one: 315 result = math_ops.multiply(result, maxval) 316 else: 317 result = math_ops.add(result * (maxval - minval), minval, name=name) 318 # TODO(b/132092188): C++ shape inference inside functional ops does not 319 # cross FuncGraph boundaries since that information is only available in 320 # python. So we manually get the static shape using 321 # `constant_value_as_shape` which *does* cross function boundaries. 322 tensor_util.maybe_set_static_shape(result, shape) 323 return result 324 325 326ops.NotDifferentiable("RandomUniform") 327 328 329@tf_export("random.shuffle", v1=["random.shuffle", "random_shuffle"]) 330@dispatch.add_dispatch_support 331@deprecation.deprecated_endpoints("random_shuffle") 332def random_shuffle(value, seed=None, name=None): 333 """Randomly shuffles a tensor along its first dimension. 334 335 The tensor is shuffled along dimension 0, such that each `value[j]` is mapped 336 to one and only one `output[i]`. For example, a mapping that might occur for a 337 3x2 tensor is: 338 339 ```python 340 [[1, 2], [[5, 6], 341 [3, 4], ==> [1, 2], 342 [5, 6]] [3, 4]] 343 ``` 344 345 Args: 346 value: A Tensor to be shuffled. 347 seed: A Python integer. Used to create a random seed for the distribution. 348 See 349 `tf.random.set_seed` 350 for behavior. 351 name: A name for the operation (optional). 352 353 Returns: 354 A tensor of same shape and type as `value`, shuffled along its first 355 dimension. 356 """ 357 seed1, seed2 = random_seed.get_seed(seed) 358 return gen_random_ops.random_shuffle( 359 value, seed=seed1, seed2=seed2, name=name) 360 361 362@tf_export("image.random_crop", v1=["image.random_crop", "random_crop"]) 363@dispatch.add_dispatch_support 364@deprecation.deprecated_endpoints("random_crop") 365def random_crop(value, size, seed=None, name=None): 366 """Randomly crops a tensor to a given size. 367 368 Slices a shape `size` portion out of `value` at a uniformly chosen offset. 369 Requires `value.shape >= size`. 370 371 If a dimension should not be cropped, pass the full size of that dimension. 372 For example, RGB images can be cropped with 373 `size = [crop_height, crop_width, 3]`. 374 375 Example usage: 376 377 >>> image = [[1, 2, 3], [4, 5, 6]] 378 >>> result = tf.image.random_crop(value=image, size=(1, 3)) 379 >>> result.shape.as_list() 380 [1, 3] 381 382 For producing deterministic results given a `seed` value, use 383 `tf.image.stateless_random_crop`. Unlike using the `seed` param with 384 `tf.image.random_*` ops, `tf.image.stateless_random_*` ops guarantee the same 385 results given the same seed independent of how many times the function is 386 called, and independent of global seed settings (e.g. tf.random.set_seed). 387 388 Args: 389 value: Input tensor to crop. 390 size: 1-D tensor with size the rank of `value`. 391 seed: Python integer. Used to create a random seed. See 392 `tf.random.set_seed` 393 for behavior. 394 name: A name for this operation (optional). 395 396 Returns: 397 A cropped tensor of the same rank as `value` and shape `size`. 398 """ 399 with ops.name_scope(name, "random_crop", [value, size]) as name: 400 value = ops.convert_to_tensor(value, name="value") 401 size = ops.convert_to_tensor(size, dtype=dtypes.int32, name="size") 402 shape = array_ops.shape(value) 403 check = control_flow_ops.Assert( 404 math_ops.reduce_all(shape >= size), 405 ["Need value.shape >= size, got ", shape, size], 406 summarize=1000) 407 shape = control_flow_ops.with_dependencies([check], shape) 408 limit = shape - size + 1 409 offset = random_uniform( 410 array_ops.shape(shape), 411 dtype=size.dtype, 412 maxval=size.dtype.max, 413 seed=seed) % limit 414 return array_ops.slice(value, offset, size, name=name) 415 416 417@tf_export("image.stateless_random_crop", v1=[]) 418@dispatch.add_dispatch_support 419def stateless_random_crop(value, size, seed, name=None): 420 """Randomly crops a tensor to a given size in a deterministic manner. 421 422 Slices a shape `size` portion out of `value` at a uniformly chosen offset. 423 Requires `value.shape >= size`. 424 425 If a dimension should not be cropped, pass the full size of that dimension. 426 For example, RGB images can be cropped with 427 `size = [crop_height, crop_width, 3]`. 428 429 Guarantees the same results given the same `seed` independent of how many 430 times the function is called, and independent of global seed settings (e.g. 431 `tf.random.set_seed`). 432 433 Usage Example: 434 435 >>> image = [[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]] 436 >>> seed = (1, 2) 437 >>> tf.image.stateless_random_crop(value=image, size=(1, 2, 3), seed=seed) 438 <tf.Tensor: shape=(1, 2, 3), dtype=int32, numpy= 439 array([[[1, 2, 3], 440 [4, 5, 6]]], dtype=int32)> 441 442 Args: 443 value: Input tensor to crop. 444 size: 1-D tensor with size the rank of `value`. 445 seed: A shape [2] Tensor, the seed to the random number generator. Must have 446 dtype `int32` or `int64`. (When using XLA, only `int32` is allowed.) 447 name: A name for this operation (optional). 448 449 Returns: 450 A cropped tensor of the same rank as `value` and shape `size`. 451 """ 452 with ops.name_scope(name, "random_crop", [value, size]) as name: 453 value = ops.convert_to_tensor(value, name="value") 454 size = ops.convert_to_tensor(size, dtype=dtypes.int32, name="size") 455 shape = array_ops.shape(value) 456 check = control_flow_ops.Assert( 457 math_ops.reduce_all(shape >= size), 458 ["Need value.shape >= size, got ", shape, size], 459 summarize=1000) 460 shape = control_flow_ops.with_dependencies([check], shape) 461 limit = shape - size + 1 462 offset = stateless_random_ops.stateless_random_uniform( 463 array_ops.shape(shape), 464 dtype=size.dtype, 465 maxval=size.dtype.max, 466 seed=seed) % limit 467 return array_ops.slice(value, offset, size, name=name) 468 469 470@tf_export(v1=["random.multinomial", "multinomial"]) 471@dispatch.add_dispatch_support 472@deprecation.deprecated( 473 date=None, instructions="Use `tf.random.categorical` instead.") 474def multinomial(logits, num_samples, seed=None, name=None, output_dtype=None): 475 """Draws samples from a multinomial distribution. 476 477 Example: 478 479 ```python 480 # samples has shape [1, 5], where each value is either 0 or 1 with equal 481 # probability. 482 samples = tf.random.categorical(tf.math.log([[0.5, 0.5]]), 5) 483 ``` 484 485 Args: 486 logits: 2-D Tensor with shape `[batch_size, num_classes]`. Each slice 487 `[i, :]` represents the unnormalized log-probabilities for all classes. 488 num_samples: 0-D. Number of independent samples to draw for each row slice. 489 seed: A Python integer. Used to create a random seed for the distribution. 490 See `tf.random.set_seed` for behavior. 491 name: Optional name for the operation. 492 output_dtype: integer type to use for the output. Defaults to int64. 493 494 Returns: 495 The drawn samples of shape `[batch_size, num_samples]`. 496 """ 497 with ops.name_scope(name, "multinomial", [logits]): 498 return multinomial_categorical_impl(logits, num_samples, output_dtype, seed) 499 500 501@tf_export("random.categorical") 502@dispatch.add_dispatch_support 503def categorical(logits, num_samples, dtype=None, seed=None, name=None): 504 """Draws samples from a categorical distribution. 505 506 Example: 507 508 ```python 509 # samples has shape [1, 5], where each value is either 0 or 1 with equal 510 # probability. 511 samples = tf.random.categorical(tf.math.log([[0.5, 0.5]]), 5) 512 ``` 513 514 Args: 515 logits: 2-D Tensor with shape `[batch_size, num_classes]`. Each slice 516 `[i, :]` represents the unnormalized log-probabilities for all classes. 517 num_samples: 0-D. Number of independent samples to draw for each row slice. 518 dtype: integer type to use for the output. Defaults to int64. 519 seed: A Python integer. Used to create a random seed for the distribution. 520 See `tf.random.set_seed` for behavior. 521 name: Optional name for the operation. 522 523 Returns: 524 The drawn samples of shape `[batch_size, num_samples]`. 525 """ 526 with ops.name_scope(name, "categorical", [logits]): 527 return multinomial_categorical_impl(logits, num_samples, dtype, seed) 528 529 530def multinomial_categorical_impl(logits, num_samples, dtype, seed): 531 """Implementation for random.categorical (v1) and random.categorical (v2).""" 532 logits = ops.convert_to_tensor(logits, name="logits") 533 seed1, seed2 = random_seed.get_seed(seed) 534 return gen_random_ops.multinomial( 535 logits, num_samples, seed=seed1, seed2=seed2, output_dtype=dtype) 536 537 538ops.NotDifferentiable("Multinomial") 539 540 541def _maybe_set_static_shape_helper(tensor, shape, postfix_tensor): 542 if (not context.executing_eagerly() and 543 ops.get_default_graph().building_function and 544 not tensor.shape.is_fully_defined()): 545 shape = tensor_util.shape_tensor(shape) 546 const_shape = tensor_util.constant_value_as_shape(shape) 547 postfix_tensor = ops.convert_to_tensor(postfix_tensor) 548 tensor.set_shape(const_shape.concatenate(postfix_tensor.shape)) 549 550 551@tf_export("random.gamma", v1=["random.gamma", "random_gamma"]) 552@dispatch.add_dispatch_support 553@deprecation.deprecated_endpoints("random_gamma") 554def random_gamma(shape, 555 alpha, 556 beta=None, 557 dtype=dtypes.float32, 558 seed=None, 559 name=None): 560 """Draws `shape` samples from each of the given Gamma distribution(s). 561 562 `alpha` is the shape parameter describing the distribution(s), and `beta` is 563 the inverse scale parameter(s). 564 565 Note: Because internal calculations are done using `float64` and casting has 566 `floor` semantics, we must manually map zero outcomes to the smallest 567 possible positive floating-point value, i.e., `np.finfo(dtype).tiny`. This 568 means that `np.finfo(dtype).tiny` occurs more frequently than it otherwise 569 should. This bias can only happen for small values of `alpha`, i.e., 570 `alpha << 1` or large values of `beta`, i.e., `beta >> 1`. 571 572 The samples are differentiable w.r.t. alpha and beta. 573 The derivatives are computed using the approach described in 574 (Figurnov et al., 2018). 575 576 Example: 577 578 ```python 579 samples = tf.random.gamma([10], [0.5, 1.5]) 580 # samples has shape [10, 2], where each slice [:, 0] and [:, 1] represents 581 # the samples drawn from each distribution 582 583 samples = tf.random.gamma([7, 5], [0.5, 1.5]) 584 # samples has shape [7, 5, 2], where each slice [:, :, 0] and [:, :, 1] 585 # represents the 7x5 samples drawn from each of the two distributions 586 587 alpha = tf.constant([[1.],[3.],[5.]]) 588 beta = tf.constant([[3., 4.]]) 589 samples = tf.random.gamma([30], alpha=alpha, beta=beta) 590 # samples has shape [30, 3, 2], with 30 samples each of 3x2 distributions. 591 592 loss = tf.reduce_mean(tf.square(samples)) 593 dloss_dalpha, dloss_dbeta = tf.gradients(loss, [alpha, beta]) 594 # unbiased stochastic derivatives of the loss function 595 alpha.shape == dloss_dalpha.shape # True 596 beta.shape == dloss_dbeta.shape # True 597 ``` 598 599 Args: 600 shape: A 1-D integer Tensor or Python array. The shape of the output samples 601 to be drawn per alpha/beta-parameterized distribution. 602 alpha: A Tensor or Python value or N-D array of type `dtype`. `alpha` 603 provides the shape parameter(s) describing the gamma distribution(s) to 604 sample. Must be broadcastable with `beta`. 605 beta: A Tensor or Python value or N-D array of type `dtype`. Defaults to 1. 606 `beta` provides the inverse scale parameter(s) of the gamma 607 distribution(s) to sample. Must be broadcastable with `alpha`. 608 dtype: The type of alpha, beta, and the output: `float16`, `float32`, or 609 `float64`. 610 seed: A Python integer. Used to create a random seed for the distributions. 611 See 612 `tf.random.set_seed` 613 for behavior. 614 name: Optional name for the operation. 615 616 Returns: 617 samples: a `Tensor` of shape 618 `tf.concat([shape, tf.shape(alpha + beta)], axis=0)` with values of type 619 `dtype`. 620 621 References: 622 Implicit Reparameterization Gradients: 623 [Figurnov et al., 2018] 624 (http://papers.nips.cc/paper/7326-implicit-reparameterization-gradients) 625 ([pdf] 626 (http://papers.nips.cc/paper/7326-implicit-reparameterization-gradients.pdf)) 627 """ 628 with ops.name_scope(name, "random_gamma", [shape, alpha, beta]): 629 shape = ops.convert_to_tensor(shape, name="shape", dtype=dtypes.int32) 630 alpha = ops.convert_to_tensor(alpha, name="alpha", dtype=dtype) 631 beta = ops.convert_to_tensor( 632 beta if beta is not None else 1, name="beta", dtype=dtype) 633 broadcast_shape = array_ops.broadcast_dynamic_shape( 634 array_ops.shape(alpha), array_ops.shape(beta)) 635 alpha_broadcast = array_ops.broadcast_to(alpha, broadcast_shape) 636 seed1, seed2 = random_seed.get_seed(seed) 637 result = math_ops.maximum( 638 np.finfo(alpha.dtype.as_numpy_dtype).tiny, 639 gen_random_ops.random_gamma( 640 shape, alpha_broadcast, seed=seed1, seed2=seed2) / beta) 641 _maybe_set_static_shape_helper(result, shape, alpha_broadcast) 642 return result 643 644 645@tf_export(v1=["random.poisson", "random_poisson"]) 646@dispatch.add_dispatch_support 647@deprecation.deprecated_endpoints("random_poisson") 648def random_poisson(lam, shape, dtype=dtypes.float32, seed=None, name=None): 649 """Draws `shape` samples from each of the given Poisson distribution(s). 650 651 `lam` is the rate parameter describing the distribution(s). 652 653 Example: 654 655 ```python 656 samples = tf.random.poisson([0.5, 1.5], [10]) 657 # samples has shape [10, 2], where each slice [:, 0] and [:, 1] represents 658 # the samples drawn from each distribution 659 660 samples = tf.random.poisson([12.2, 3.3], [7, 5]) 661 # samples has shape [7, 5, 2], where each slice [:, :, 0] and [:, :, 1] 662 # represents the 7x5 samples drawn from each of the two distributions 663 ``` 664 665 Args: 666 lam: A Tensor or Python value or N-D array of type `dtype`. 667 `lam` provides the rate parameter(s) describing the poisson 668 distribution(s) to sample. 669 shape: A 1-D integer Tensor or Python array. The shape of the output samples 670 to be drawn per "rate"-parameterized distribution. 671 dtype: The type of the output: `float16`, `float32`, `float64`, `int32` or 672 `int64`. 673 seed: A Python integer. Used to create a random seed for the distributions. 674 See 675 `tf.random.set_seed` 676 for behavior. 677 name: Optional name for the operation. 678 679 Returns: 680 samples: a `Tensor` of shape `tf.concat([shape, tf.shape(lam)], axis=0)` 681 with values of type `dtype`. 682 """ 683 return random_poisson_v2(shape, lam, dtype, seed, name) 684 685 686@tf_export("random.poisson", v1=[]) 687@dispatch.add_dispatch_support 688def random_poisson_v2(shape, lam, dtype=dtypes.float32, seed=None, name=None): 689 """Draws `shape` samples from each of the given Poisson distribution(s). 690 691 `lam` is the rate parameter describing the distribution(s). 692 693 Example: 694 695 ```python 696 samples = tf.random.poisson([10], [0.5, 1.5]) 697 # samples has shape [10, 2], where each slice [:, 0] and [:, 1] represents 698 # the samples drawn from each distribution 699 700 samples = tf.random.poisson([7, 5], [12.2, 3.3]) 701 # samples has shape [7, 5, 2], where each slice [:, :, 0] and [:, :, 1] 702 # represents the 7x5 samples drawn from each of the two distributions 703 ``` 704 705 Args: 706 shape: A 1-D integer Tensor or Python array. The shape of the output samples 707 to be drawn per "rate"-parameterized distribution. 708 lam: A Tensor or Python value or N-D array of type `dtype`. 709 `lam` provides the rate parameter(s) describing the poisson 710 distribution(s) to sample. 711 dtype: The type of the output: `float16`, `float32`, `float64`, `int32` or 712 `int64`. 713 seed: A Python integer. Used to create a random seed for the distributions. 714 See 715 `tf.random.set_seed` 716 for behavior. 717 name: Optional name for the operation. 718 719 Returns: 720 samples: a `Tensor` of shape `tf.concat([shape, tf.shape(lam)], axis=0)` 721 with values of type `dtype`. 722 """ 723 with ops.name_scope(name, "random_poisson", [lam, shape]): 724 shape = ops.convert_to_tensor(shape, name="shape", dtype=dtypes.int32) 725 seed1, seed2 = random_seed.get_seed(seed) 726 result = gen_random_ops.random_poisson_v2( 727 shape, lam, dtype=dtype, seed=seed1, seed2=seed2) 728 _maybe_set_static_shape_helper(result, shape, lam) 729 return result 730