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