AI Knowledge Tree

Transformations of random variables

Push a distribution through a function with the change-of-variables formula.

You often know the distribution of XX but need the distribution of Y=g(X)Y = g(X): sampling a uniform and turning it into a Gaussian, or pushing a latent variable through a neural network in a normalizing flow. The change-of-variables formula tells you exactly how a density transforms, and the determinant from linear algebra reappears as the local volume-stretching factor.

The CDF route (always works)

The safe, general method is to compute the CDF of YY and differentiate. For an increasing gg,

FY(y)=P(Y≤y)=P(g(X)≤y)=P(X≤g−1(y))=FX(g−1(y)).F_Y(y) = P(Y \le y) = P(g(X) \le y) = P(X \le g^{-1}(y)) = F_X(g^{-1}(y)).

Differentiating with the chain rule gives the density. This route handles non-monotone gg too, by splitting into monotone pieces.

The change-of-variables formula (1D)

For a differentiable, strictly monotone gg with inverse x=g−1(y)x = g^{-1}(y), differentiating FY(y)=FX(g−1(y))F_Y(y) = F_X(g^{-1}(y))[1]:

fY(y)=fX ⁣(g−1(y)) ∣ddyg−1(y)∣.f_Y(y) = f_X\!\big(g^{-1}(y)\big)\,\left|\frac{d}{dy}g^{-1}(y)\right|.

The absolute value covers decreasing gg (where FY(y)=1−FX(g−1(y))F_Y(y) = 1 - F_X(g^{-1}(y)), and the derivative is negative). The factor ∣dg−1/dy∣|dg^{-1}/dy| corrects for how gg stretches or compresses the axis: where gg spreads probability over a wider range, the density thins out.

A useful restatement uses dy/dx=g′(x)dy/dx = g'(x):

fY(y)=fX(x)∣g′(x)∣∣x=g−1(y).f_Y(y) = \frac{f_X(x)}{|g'(x)|}\bigg|_{x = g^{-1}(y)}.

Probability mass is conserved, fY(y) ∣dy∣=fX(x) ∣dx∣f_Y(y)\,|dy| = f_X(x)\,|dx|; only its density per unit length changes.

The multivariate formula

For an invertible differentiable map y=g(x)\mathbf{y} = g(\mathbf{x}) on Rn\mathbb{R}^n, the single derivative becomes the Jacobian determinant[2]:

fY(y)=fX ⁣(g−1(y)) ∣det⁡Jg−1(y)∣,f_Y(\mathbf{y}) = f_X\!\big(g^{-1}(\mathbf{y})\big)\,\left|\det J_{g^{-1}}(\mathbf{y})\right|,

where Jg−1J_{g^{-1}} is the Jacobian matrix of the inverse map. The determinant is the local volume-scaling factor of the transformation (its meaning from linear algebra), now applied pointwise to a nonlinear map. This is the identity normalizing flows exploit: stack invertible maps with cheap log-determinants to build a flexible density whose normalization stays tractable.

Worked example: inverse-CDF sampling

If U∼Uniform(0,1)U \sim \text{Uniform}(0,1) and FF is a target CDF, then X=F−1(U)X = F^{-1}(U) has CDF FF. Check it:

P(X≤x)=P(F−1(U)≤x)=P(U≤F(x))=F(x),P(X \le x) = P(F^{-1}(U) \le x) = P(U \le F(x)) = F(x),

using that FF is increasing and UU is uniform on [0,1][0,1] (so P(U≤u)=uP(U \le u) = u). This is how a single uniform random source generates samples from any distribution with an invertible CDF, for example the exponential via X=−1λlog⁡(1−U)X = -\frac{1}{\lambda}\log(1-U).

A monotonic transform reshapes a density: the Jacobian stretches or compresses probability mass as X ~ Exp(1) maps through Y = X².
A monotonic transform reshapes a density: the Jacobian stretches or compresses probability mass as X ~ Exp(1) maps through Y = X².

Check it on arrays

python · numpy
import numpy as np

rng = np.random.default_rng(8)
N = 1_000_000

# Inverse-CDF sampling for Exponential(rate=lambda): X = -ln(1-U)/lambda
lam = 1.5
U = rng.random(N)
X = -np.log(1 - U) / lam
print("inverse-CDF exp mean:", round(X.mean(), 4), "  exact 1/lambda =", round(1/lam, 4))
print("numpy exp mean:      ", round(rng.exponential(1/lam, N).mean(), 4))

# Change of variables: Y = X^2 for X ~ N(0,1); density check via histogram
Xn = rng.normal(size=N)
Y = Xn**2                                   # chi-square with 1 dof
hist, edges = np.histogram(Y, bins=200, range=(0.01, 5), density=True)
centers = 0.5 * (edges[:-1] + edges[1:])
# f_Y(y) = f_X(sqrt y)/|g'(x)| summed over the two roots +/-sqrt(y):
#        = 2 * phi(sqrt y) * (1/(2 sqrt y)) = phi(sqrt y)/sqrt y
phi = lambda x: np.exp(-x**2/2)/np.sqrt(2*np.pi)
f_theory = phi(np.sqrt(centers)) / np.sqrt(centers)
print("max |hist - theory|:", round(np.max(np.abs(hist - f_theory)), 4))

Inverse-CDF sampling reproduces the exponential mean, and the analytic density of X2X^2 (with the Jacobian factor and both roots accounted for) matches its histogram.

Exercises

Exercise 1. Let X∼Uniform(0,1)X \sim \text{Uniform}(0, 1) and Y=−log⁡XY = -\log X. Use the 1D change-of-variables formula to find the density fY(y)f_Y(y) and name the resulting distribution.

Solution

Step 1. The map g(x)=−log⁡xg(x) = -\log x is strictly decreasing on (0,1)(0, 1), with inverse x=g−1(y)=e−yx = g^{-1}(y) = e^{-y} for y>0y > 0. Its derivative is ddyg−1(y)=−e−y\frac{d}{dy}g^{-1}(y) = -e^{-y}.

Step 2. Apply fY(y)=fX(g−1(y)) ∣ddyg−1(y)∣f_Y(y) = f_X(g^{-1}(y))\,\left|\frac{d}{dy}g^{-1}(y)\right|. On (0,1)(0,1) the uniform density is fX(x)=1f_X(x) = 1, so

fY(y)=1⋅∣−e−y∣=e−y,y>0.f_Y(y) = 1 \cdot \left|-e^{-y}\right| = e^{-y}, \qquad y > 0.

This is the Exponential(1) density. Taking the negative log of a uniform is the inverse-CDF recipe for the rate-1 exponential, matching X=−1λlog⁡(1−U)X = -\frac{1}{\lambda}\log(1-U) from the lesson at λ=1\lambda = 1 (with UU and 1−U1-U both uniform on (0,1)(0,1)).

Exercise 2. Let XX have density fXf_X and let Y=aX+bY = aX + b with a≠0a \ne 0, an affine transform. Derive fY(y)f_Y(y) and confirm it specializes correctly: a Gaussian X∼N(μ,σ2)X \sim \mathcal{N}(\mu, \sigma^2) maps to N(aμ+b,a2σ2)\mathcal{N}(a\mu + b, a^2\sigma^2).

Solution

Step 1. Invert: x=g−1(y)=(y−b)/ax = g^{-1}(y) = (y - b)/a, with constant derivative ddyg−1(y)=1/a\frac{d}{dy}g^{-1}(y) = 1/a. The formula gives

fY(y)=fX ⁣(y−ba) 1∣a∣.f_Y(y) = f_X\!\left(\frac{y - b}{a}\right)\,\frac{1}{|a|}.

The 1/∣a∣1/|a| is the Jacobian: stretching the axis by ∣a∣|a| thins the density by the same factor so total mass stays one.

Step 2. Substitute the Gaussian density. With x=(y−b)/ax = (y-b)/a,

fY(y)=1∣a∣2πσ2exp⁡ ⁣(−((y−b)/a−μ)22σ2).f_Y(y) = \frac{1}{|a|\sqrt{2\pi\sigma^2}}\exp\!\left(-\frac{((y-b)/a - \mu)^2}{2\sigma^2}\right).

Step 3. Rewrite the exponent. Since (y−b)/a−μ=(y−(aμ+b))/a(y-b)/a - \mu = (y - (a\mu + b))/a, its square over 2σ22\sigma^2 is (y−(aμ+b))2/(2a2σ2)(y - (a\mu+b))^2 / (2a^2\sigma^2), and the prefactor ∣a∣2πσ2=2πa2σ2|a|\sqrt{2\pi\sigma^2} = \sqrt{2\pi a^2\sigma^2}. So

fY(y)=12πa2σ2exp⁡ ⁣(−(y−(aμ+b))22a2σ2),f_Y(y) = \frac{1}{\sqrt{2\pi a^2\sigma^2}}\exp\!\left(-\frac{(y - (a\mu+b))^2}{2a^2\sigma^2}\right),

the density of N(aμ+b, a2σ2)\mathcal{N}(a\mu + b,\, a^2\sigma^2).

Exercise 3 (code). Verify Exercise 1 numerically: transform a million uniform samples by Y=−log⁡XY = -\log X and confirm the empirical histogram matches the Exponential(1) density e−ye^{-y}.

Solution
python · numpy
import numpy as np

rng = np.random.default_rng(0)
N = 1_000_000

X = rng.random(N)
Y = -np.log(X)

hist, edges = np.histogram(Y, bins=200, range=(0.0, 6.0), density=True)
centers = 0.5 * (edges[:-1] + edges[1:])
f_theory = np.exp(-centers)        # Exponential(1) density

max_err = np.max(np.abs(hist - f_theory))
print("mean of Y:", round(Y.mean(), 4), " exact 1.0")
print("max |hist - theory|:", round(max_err, 4))
assert np.isclose(Y.mean(), 1.0, atol=1e-2)
assert max_err < 0.02

The transformed samples have mean near 1 (the Exponential(1) mean) and their histogram tracks e−ye^{-y}, confirming the derived density.

The next lesson steps back from exact distributions to bounds that hold for all of them: the basic probability inequalities.


References

  1. [1]Casella, G., & Berger, R. L. (2002). Statistical Inference (2nd ed.). Duxbury. §2.1, distributions of functions of a random variable.↩
  2. [2]Wasserman, L. (2004). All of Statistics. Springer. §2.7-2.8, transformations of random variables and the multivariate Jacobian. doi:10.1007/978-0-387-21736-9↩