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