Beyond Sampling: Exploring `icdf()` for Laplace Quantile Calculations in PyTorch


Functionality

  • In simpler terms, it takes a probability (p) as input and outputs the value (x) at which the cumulative distribution function (CDF) of the Laplace distribution equals p.
  • The icdf method, also known as the inverse cumulative distribution function (ICDF), calculates the quantiles of the Laplace distribution for given probability values.

Laplace Distribution in PyTorch

  • The torch.distributions.laplace.Laplace class represents the Laplace distribution, characterized by two parameters:
    • loc: The mean (center) of the distribution.
    • scale: The scale parameter, controlling the spread of the distribution around the mean.

icdf() Method

  • Output
    The method returns a tensor of the same shape as the input value, containing the quantiles (values) in the Laplace distribution that correspond to the given probabilities.
  • Input
    The icdf method takes a single argument, value (usually a tensor), representing the probability values for which you want to find the corresponding quantiles.

Mathematical Background

  • The Laplace distribution's CDF (F(x)) is defined as:

    F(x) = 0.5 * (1 + sign(x - loc) * exp(-abs(x - loc) / scale))
    

Example

import torch
from torch.distributions import laplace

# Create a Laplace distribution with loc=2 and scale=1
loc = torch.tensor(2.0)
scale = torch.tensor(1.0)
dist = laplace.Laplace(loc, scale)

# Sample some probability values
probabilities = torch.tensor([0.1, 0.5, 0.9])

# Calculate the corresponding quantiles (values)
quantiles = dist.icdf(probabilities)

print(quantiles)  # Output: tensor([1.3863, 2.0000, 2.6137])

In this example:

  • quantiles holds the corresponding values in the Laplace distribution that have those probabilities.
  • probabilities is a tensor containing example probability values.
  • The dist object represents a Laplace distribution with loc=2 and scale=1.


Plotting Quantiles

import torch
import matplotlib.pyplot as plt
from torch.distributions import laplace

# Create a Laplace distribution
loc = 5.0
scale = 2.0
dist = laplace.Laplace(loc, scale)

# Sample a range of probability values
num_samples = 100
probabilities = torch.linspace(0.01, 0.99, num_samples)

# Calculate the quantiles
quantiles = dist.icdf(probabilities)

# Plot the CDF and the quantiles
plt.plot(probabilities, dist.cdf(quantiles))  # Plot the CDF
plt.scatter(probabilities, quantiles, label='Quantiles')
plt.xlabel('Probability')
plt.ylabel('Value')
plt.title('Laplace Distribution CDF and Quantiles')
plt.legend()
plt.show()

This code plots the CDF of the Laplace distribution and overlays the quantiles corresponding to a range of probabilities. This visually demonstrates how the icdf method relates to the CDF.

Generating Samples from Specific Quantiles

import torch
from torch.distributions import laplace

# Create a Laplace distribution
loc = 3.0
scale = 0.5
dist = laplace.Laplace(loc, scale)

# Define target quantiles
target_quantiles = torch.tensor([0.2, 0.7])

# Get the corresponding probabilities using the CDF
probabilities = dist.cdf(target_quantiles)

# Sample from the distribution using the obtained probabilities
samples = dist.sample(sample_shape=torch.Size([]))  # Sample a single value

# This approach is less efficient for many samples due to multiple CDF calls

print("Target quantiles:", target_quantiles)
print("Corresponding probabilities:", probabilities)
print("Sampled value:", samples)

This code demonstrates how you can use icdf to get the probabilities corresponding to desired quantiles and then sample from the distribution using those probabilities. This approach might be less efficient if you need to generate many samples from specific quantiles.

import torch
from torch.distributions import laplace

# Create a Laplace distribution
loc = 1.0
scale = 1.5
dist = laplace.Laplace(loc, scale)

# Sample directly from the distribution
direct_samples = dist.sample(sample_shape=torch.Size([10]))

# Sample using target quantiles (might be less efficient for many samples)
num_samples = 10
target_quantiles = torch.rand(num_samples) * 2 - 1  # Random values between -1 and 1
probabilities = dist.cdf(target_quantiles)
quantile_samples = dist.sample(sample_shape=torch.Size([num_samples]), cond=probabilities)

print("Direct samples:", direct_samples)
print("Samples from target quantiles (might be less efficient):", quantile_samples)


Numerical Approximation

  • If you need the inverse CDF for other continuous distributions without a built-in icdf method, you can resort to numerical methods like the bisection search or Brent's method. These algorithms iteratively refine an initial guess until a desired level of accuracy is achieved.

Symbolic Libraries (For Research/Exploration)

Inverse Transform Sampling

  • If your primary goal is to sample from the Laplace distribution, consider using the inverse transform sampling method. This technique involves generating random uniform values between 0 and 1 and then applying the inverse CDF of the Laplace distribution (which doesn't have a closed-form solution) to obtain samples from the desired distribution. This approach can be implemented using numerical methods.

Choosing the Right Approach

The best option for you depends on your specific use case:

  • If you primarily need to sample from the Laplace distribution, inverse transform sampling is a viable option.
  • For research or exploration, symbolic libraries could be helpful.
  • For other continuous distributions without built-in icdf, numerical methods might be necessary.
  • If you only need Laplace distribution quantiles occasionally, using icdf is a convenient choice.
  • Inverse transform sampling requires implementing the numerical solution for the inverse CDF, which can be more complex.
  • Symbolic libraries might be slower than built-in functions like icdf.
  • Numerical methods can introduce some level of error depending on the chosen algorithm and desired accuracy.