Skip to main content
Ctrl+K
Logo image
  • Overview

Resources

  • Python
    • Integraded Development Environment (IDE)
    • Standard Python Stack
    • Earth Science Stack
    • Deep Learning Stack
    • Scaling Stack
    • Good Code

Tutorials

  • My JAX Journey
    • Ecosystem
    • vmap
    • Jit
    • Classes
    • Algorithms
      • Bisection search
      • Kernel Derivatives
      • Gaussianization Flows
    • 12 Steps to Navier-Stokes
      • 1D Linear Convection
  • Remote Computing
    • SSH Configuration
    • Conda 4 Remote Servers
    • Jupyter Lab 4 Remote Servers

Notes

  • GMT of Learning
    • Hierarchical Representation
    • Functa
    • Spatial Discretization
    • Temporal Discretization
    • Learning
    • State Estimation
    • Parameter Estimation
    • Bi-Level Optimization
  • Modeling Uncertainty
  • Bayesian
    • Language of Uncertainty
    • Models
    • Inference Schemes
    • Variational Inference
    • Conditional Variational Inference
    • Confidence Intervals
    • Regression
  • Sleeper Concepts
    • Gaussian Distributions
    • Change of Variables
    • Identity Trick
    • Inverse Function Theorem
    • Jensens Inequality
    • Linear Algebra Tricks
  • Kernel Methods
    • Kernel Derivatives
    • RV Coefficient
    • Congruence Coefficient
    • HSIC
    • Maximum Mean Discrepancy (MMD)
  • Gaussian Processes
    • Basics
    • Literature Review
    • Conjugate Gradients
    • Sparse Gaussian Processes
    • Algorithms
      • GP from Scratch
      • Sparse GP From Scratch
    • Input Uncertainty in GPs
  • Similarity
  • Information Theory
    • Measures
      • Information Theory
      • Entropy & Relative Entropy
      • Mutual Information and Total Correlation
    • Information Theory Measures
      • Classic Methods
      • Entropy Estimator - Histogram
      • Experiment - RBIG Sample Consistency
  • Normalizing Flows
    • Linear Layers
    • Coupling Layers
    • Conditional Normalizing Flows
    • Multiscale
    • Minimization Problems
    • Losses
    • Lecture I - Iterative Gaussianization
      • 1.1 - Univariate Gaussianization
      • 1.2 - Marginal Gaussianization
      • 1.2 - Iterative Gaussianization
    • Lecture II - Gaussianization Flows
      • Parameterized Marginal Gaussianization
      • Parameterized Rotations
      • Example - 2D Plane
  • Neural Fields
    • Formulation
    • Literature Review
    • Physics-Informed Loss
  • Data Assimilation
    • Dynamical Systems
    • Optimal Interpolation
    • Interpolation Problem
    • Emulation
    • Inverse Problems
    • Projects
    • Algorithms
      • Markov Models
      • Gauss-Markov Models
      • Kalman Filter
      • Normalizing Kalman Filter
      • Ensemble Kalman Filter
      • Deep Markov Model
      • 4DVarNet
      • Markovian Gaussian Processes
    • Notebooks
  • Miscellaneous Notes
    • Generative Models
    • Diffusion Models
    • Fixed-Point Methods
    • Bi-Level Optimization
    • Differential Operators
    • QG Formulations
    • Elliptical PDE Solvers
    • Inverse Problems

Cheat Sheets

  • Bash
  • Command Line
  • Python
  • Repository
  • Open issue
  • .md

Bisection search

Contents

  • Estimating PDFs
    • Interpolation
    • Bisection Search
  • Estimating CDF / Quantiles
    • CDFs
    • Quantiles
  • Application
  • Other Implementations
    • PyTorch

Bisection search#

This is a very interesting thing that you can do instead of interpolation. This comes from the fact that PyTorch doesn’t have a native interpolation algorithm. Although there are saints on the internet who have implemented their own native algorithm, the library itself doesn’t have a core one. I find it very interesting that they don’t and I’m not sure why. Is there something difficult about automatic differentiation and interpolation?

In any case, one thing that I did see was bisection search instead of interpolation. I’ve also seen it in the rv_histogram function in the scipy library. This function allows you to construct an empirical distribution based on histograms. You construct the histograms using the np.histogram function and then you go through and normalize the PDF estimates found in the bins followed by creating the CDF by using the cumsum function. Now with these, you should be able to calculate the PDF, the CDF, the quantile function and virtually any other distribution function that you may need, even on new data.

So, how do you calculate quantities for new data? Let’s break two functions down step by step: the PDF and the CDF/Quantile.

Estimating PDFs#

Recall, a histogram works by putting bins in intervals along the domain of your data. Then you calculate how many times you get values within those bins. The probability is the number of times you have data within that bin divided by the width of the bin. To make a density, you need to normalize the entire distribution so that it sums to 1. So in order to estimate the PDF for new data, you need to find where are the bins closest to your data.

Interpolation#

One thing you can do is to interpolate. You find the support that is closest to your query points \(X\) and then output the corresponding values for the estimated histogram values. Old school algebra, this looks like:

\[ \frac{x}{?} = \frac{\text{support}}{\text{hist pdf}} \]

So in code, this translates to:

x_pdf_est = np.interp(X_new, X_hist_bins, X_hist_pdf)

The numpy implementation has been shown to be quite fast. Sometimes I’ve used the scipy formula but apparently the numpy implementation it’s maginitudes faster than the scipy implementation. However, I believe the scipy implementation has some extra goodies like extrapolation if you’re outside the bounds of your distribution.

Bisection Search#

Alternatively, we could just do a bisection search. Now, it may not be as precise especially if we don’t have enough bins, but it will be faster than interpolation. This works but 1) find the closest support values and then 2) use the corresponding values in the histogram PDF.

# find the closest bins
X_bins_est = np.search_sorted(X_new, X_hist_bins)

# select the pdf of the bins
X_pdf_est = X_hist_pdf[X_bins_est]

Estimating CDF / Quantiles#

This is

CDFs#

\[ \frac{X}{?} = \frac{Quantiles}{References} \]
X_uniform = np.interp(X, X_cdf, X_ref)

With the bisection search

X_uniform = X_ref[np.search_sorted(X_cdf, X)]

Quantiles#

\[ \frac{X}{?} = \frac{References}{Quantiles} \]
X_approx = np.interp(X_uniform, X_references, X_quantiles)

With the bisection search

X_approx = X_quantiles[np.search_sorted(X_references, X_uniform)]

Application#

In my application, I frequently work with normalizing flows, in particular Gaussianization. Essentially, you transform a univariate distribution to a Guassian distribution by computing the empirical CDF of the distribution followed by the Inverse of the Gaussian CDF. Now you can calculate the probability distribution using samples from the Gaussian distribution

Other Implementations#

PyTorch#

def search_sorted(bin_locations, inputs, eps=1e-6):
    """
    Searches for which bin an input belongs to (in a way that is parallelizable and amenable to autodiff)
    """
    bin_locations[..., -1] += eps
    return torch.sum(
        inputs[..., None] >= bin_locations,
        dim=-1
    ) - 1

This function is a little difficult to understand. Note: this is what happens who you have no comments, no type hints and no documentation about the sizes or what the dimensions are…

So now, let’s update the documentation so that it’s clearer what’s going on.

def search_sorted(bin_locations: torch.Tensor, inputs: torch.Tensor, eps: float=1e-6) -> torch.Tensor:
    """Differentiable bisection search.
    
    Parameters
    ----------
    bin_locations : torch.Tensor, (n_samples, n_features)
    
    inputs : torch.Tensor, (n_samples, n_features)
    
    eps : float, default=1e-6
        regularization to be added
    
    Returns
    -------
    X_bins : torch.Tensor, (n_samples, n_features)
        corresponding bin locations of the inputs
    
    Example
    -------
    """

    return None

Source: Pyro Library | Neural Spline Flows

previous

Algorithms

next

Kernel Derivatives

Contents
  • Estimating PDFs
    • Interpolation
    • Bisection Search
  • Estimating CDF / Quantiles
    • CDFs
    • Quantiles
  • Application
  • Other Implementations
    • PyTorch

By J. Emmanuel Johnson

© Copyright 2023.