Beyond torch.Tensor.uniform_: Using torch.distributions.uniform.Uniform for Advanced Randomness in PyTorch
Purpose
- Useful for generating random samples within that range for various applications in machine learning, such as initializing weights in neural networks or simulating random events.
- Represents the continuous uniform distribution, a probability distribution where all values within a specified range are equally likely.
Functionality
- Methods
sample(sample_shape=torch.Size([]))
: Generates random samples from the uniform distribution.sample_shape
(torch.Size, optional): Desired output shape. Defaults to a scalar.
log_prob(value)
: Computes the log-probability density of a given value under the uniform distribution.value
(torch.Tensor): The value to compute the log-probability for.
- Other methods for distribution properties like
cdf
(cumulative distribution function),icdf
(inverse cumulative distribution function),entropy
, etc. (refer to PyTorch documentation for details).
- Parameters
low
(float, tensor): Lower bound of the uniform distribution (inclusive). Defaults to 0.high
(float, tensor): Upper bound of the uniform distribution (exclusive). Defaults to 1.validate_args
(bool, optional): IfTrue
, checks for validity of arguments (e.g.,low < high
). Defaults toNone
(follows global PyTorch setting).
- Class
torch.distributions.uniform.Uniform
inherits from the base classtorch.distributions.distribution
.
Example
import torch
from torch.distributions import Uniform
# Create a uniform distribution between 2 and 5
dist = Uniform(low=2.0, high=5.0)
# Generate 5 random samples
samples = dist.sample(torch.Size([5]))
print(samples)
# Example output:
# tensor([4.8221, 3.1805, 2.5302, 3.7438, 4.2002])
# Calculate log-probability of a specific value (e.g., 3.5)
log_prob_value = dist.log_prob(torch.tensor(3.5))
print(log_prob_value)
# Example output:
# tensor(-0.3466) (may vary due to randomness)
Key Points
torch.distributions.uniform
provides a more structured and customizable approach to generating uniform random samples compared to the in-placetorch.Tensor.uniform_
method.- Samples and probabilities are computed on tensors, enabling efficient vectorized operations.
- Explore other probability distributions offered by
torch.distributions
for various scenarios in deep learning and machine learning. - For backpropagation through random samples, explore techniques like REINFORCE or pathwise derivative estimators (refer to PyTorch documentation on probability distributions).
Generating Samples with Different Shapes
import torch
from torch.distributions import Uniform
# Uniform distribution between 0 and 1
dist = Uniform(low=0.0, high=1.0)
# Generate 3 samples
samples_3 = dist.sample(torch.Size([3]))
print(samples_3)
# Generate a 2x2 grid of samples
samples_grid = dist.sample(torch.Size([2, 2]))
print(samples_grid)
This code shows how you can control the shape of the generated samples by passing a desired sample_shape
argument to the sample
method.
Calculating Probability Densities
import torch
from torch.distributions import Uniform
# Uniform distribution between -2 and 4
dist = Uniform(low=-2.0, high=4.0)
# Probability density for values -1, 0, and 2
values = torch.tensor([-1.0, 0.0, 2.0])
probs = dist.log_prob(values)
print(probs)
This code demonstrates using log_prob
to calculate the log-probability density for specific values. Remember that the output is the log probability, not the actual probability itself.
Simulating Events with Rejection Sampling
import torch
from torch.distributions import Uniform
def is_in_circle(x, y):
# Define a circle centered at (0.5, 0.5) with radius 0.25
return (x - 0.5)**2 + (y - 0.5)**2 <= 0.25**2
# Uniform distribution between 0 and 1 for both x and y
dist_x = Uniform(low=0.0, high=1.0)
dist_y = Uniform(low=0.0, high=1.0)
# Number of samples to generate
num_samples = 1000
# Rejection sampling loop
points_inside = []
for _ in range(num_samples):
x = dist_x.sample()
y = dist_y.sample()
if is_in_circle(x, y):
points_inside.append([x, y])
# Convert points to a tensor
points_tensor = torch.tensor(points_inside)
print(points_tensor.shape) # Should be torch.Size([number_of_points_inside, 2])
This code uses rejection sampling to simulate points uniformly distributed within a circle. The idea is to generate random points from a square (using two uniform distributions) and then reject points that fall outside the circle. This approach ensures that the final points are uniformly distributed within the circle's area.
torch.rand
- It's simpler and more concise for basic tasks.
- This is a built-in PyTorch function that directly generates random samples from a uniform distribution between 0 (inclusive) and 1 (exclusive).
Example
import torch
# Generate a tensor of random numbers between 0 and 1 (shape 3x4)
random_tensor = torch.rand(3, 4)
print(random_tensor)
torch.Tensor.uniform_ (In-Place Modification)
- It's efficient for modifying existing tensors, but it can be less readable than using a dedicated distribution class.
- This method modifies an existing tensor in-place, filling it with random samples from a uniform distribution.
Example
import torch
# Create a tensor and fill it with uniform samples between 2 and 5
tensor = torch.zeros(5)
tensor.uniform_(2.0, 5.0)
print(tensor)
Choosing the Right Approach
torch.Tensor.uniform_
is useful when you want to directly modify an existing tensor with uniform samples, but be cautious about in-place modifications.torch.rand
is a simpler option for basic scenarios where you just need to generate random values between 0 and 1.torch.distributions.uniform.Uniform
is ideal when you need more control over the distribution parameters (like specifying bounds), want to calculate probabilities or log-probabilities, or require the flexibility of a dedicated class for advanced distribution operations within your deep learning model.
- Remember to consider the trade-off between simplicity and control when selecting your approach.
- For distributions beyond the uniform case, explore other classes within
torch.distributions
, such asNormal
,Bernoulli
, orCategorical
.