Foundations
Information Theory for Computer Vision
The quantities information theory supplies to vision, entropy, conditional entropy, mutual information, differential entropy and the KL divergence, how they relate, why forward and reverse KL fit different models, what the data processing inequality and Fano's inequality say about processing images, and the conventions (log base, bin width, normalization) that change the numbers.
intermediate
Information theory measures uncertainty and dependence in bits. In computer vision it supplies the cross-entropy loss that trains classifiers, the entropy bound behind image compression, the mutual information that aligns a CT scan with an MR image, the divergences that compare histograms and fit generative models, and the information gain that chooses a robot’s next view. This article treats the quantities as one system: entropy, joint and conditional entropy, mutual information (MI), differential entropy and the Kullback–Leibler (KL) divergence, also called relative entropy or information gain. It covers how they relate, why minimizing the KL divergence in one direction or the other gives different fits, and what the data processing inequality and Fano’s inequality say about what processing an image can and cannot do. It then maps where each quantity is used in vision.
Definition
Information theory assigns numbers to probability distributions. The entropy of a discrete random variable is the average surprise of its outcomes. The conditional entropy is the uncertainty left about once is known. The mutual information is how much knowing one variable reduces uncertainty about the other. The KL divergence measures how far a distribution is from a distribution . For continuous variables, the differential entropy replaces the sum with an integral over a density. It behaves differently from : it can be negative, and it changes when the variable is rescaled.
The base of the logarithm sets the unit. Base 2 gives bits and base gives nats (Murphy, 2022, §6.1.1). Every quantity in this article is in bits unless it is marked otherwise.
Intuition
Pick a pixel at random from an image of a dark background (three quarters of the area) and a bright object (one quarter). Before you look at the pixel, its region label has entropy bits, a little less than the one bit of a fair coin, because the background is more likely. Now read the pixel’s grey level . If the two regions’ grey levels never overlap, tells you the label exactly. Then , and carries all 0.81 bits about : . If noise makes the grey levels overlap, some uncertainty remains, and falls below . Mutual information is the part of the label’s uncertainty that the measurement removes.
Processing cannot recover lost information. Quantizing the grey level to three bits merges values. Whatever the quantized value tells about the label, the original value told at least as much. This is the data processing inequality. A blur behaves differently, because it reads more than the pixel. It averages the pixel’s neighbours, which usually share its label and carry independent noise. So the blurred value can tell more about the label than the pixel’s own value does. That does not break the inequality: the inequality concerns functions of what you observed, and the blur observed nine pixels. The example below computes all of these numbers exactly.
Formal Definition
Entropy, joint and conditional entropy
For a discrete with distribution over states, . It is largest for the uniform distribution, where , and zero for a distribution concentrated on one state (Murphy, 2022, §6.1.1). Cross-entropy loss gives this definition with the cross-entropy and KL divergence, and the identity that links them. For two variables (MacKay, 2003, eqs. 8.1 and 8.4),
and the chain rule relates them (MacKay, 2003, eq. 8.7):
Applied repeatedly, it gives (Murphy, 2022, eq. 6.18). The joint entropy is at most the sum of the marginal entropies, with equality exactly when the variables are independent, and at least the larger of the two (Murphy, 2022, §6.1.3). Conditioning reduces entropy on average, . One particular observation can still raise the uncertainty, ; only the average over cannot (Murphy, 2022, §6.1.4; MacKay, 2003, Exercise 8.2).
Mutual information
MacKay (2003, eq. 8.8) defines the mutual information as the reduction in uncertainty,
and Murphy (2022, eqs. 6.47, 6.49 and 6.51) gives the equivalent forms
The KL form shows that MI is non-negative and zero exactly when and are independent. It is symmetric, and at most for discrete variables (Murphy, 2022, eq. 6.73). The conditional mutual information is the information adds about when is already known (MacKay, 2003, eq. 8.10). It obeys its own chain rule, (Murphy, 2022, eq. 6.62).
The form , with entropies estimated from a joint intensity histogram, is the one image registration maximizes. That article and the paper by Viola and Wells cover MI as an alignment cost.
Differential entropy
For a continuous variable with density , the differential entropy is (Murphy, 2022, eq. 6.24). A uniform density on has . Densities can exceed 1, so can be negative: has bits. A Gaussian with variance has (Murphy, 2022, eqs. 6.25–6.27).
Murphy (2022, §6.1.6), citing Cover and Thomas, connects with discrete entropy: an -bit quantization of has entropy of about . Written for a bin width , this is (our restatement, with ). So the entropy of a histogram depends on its bin width. It is not a property of the image alone until the bin width is fixed.
Two properties follow from the change-of-variables formula for an invertible, differentiable (our derivation). First, , so : contrast stretching by changes the differential entropy. Second, the Jacobian cancels in the ratio inside , so : mutual information does not change under any invertible map of either variable. MI between continuous variables is also non-negative, unlike (Murphy, 2022, eq. 6.48).
KL divergence
For distributions over the same states, , with the integral form for densities (Murphy, 2022, eqs. 6.29–6.30). It is non-negative and zero only when , which MacKay (2003, §2.6, eqs. 2.45–2.46) calls Gibbs’ inequality. In general , so although it is sometimes called the KL distance, it is not a distance (MacKay, 2003, §2.6). It is infinite wherever and . For two scalar Gaussians (Murphy, 2022, eq. 6.33),
Minimizing from the empirical distribution is maximum likelihood estimation (Murphy, 2022, §6.2.5), as that article and Cross-Entropy Loss explain.
Properties
Forward and reverse KL
To approximate a distribution by a simpler , one can minimize either or , and the two give different fits (Murphy, 2022, §6.2.6).
- Forward KL, , also called the inclusive KL. Its minimization is an M-projection, or moment projection. The divergence is infinite wherever and , so the minimizer puts mass wherever has any. Murphy calls this zero-avoiding or mode-covering behaviour: a unimodal fitted to a bimodal spreads over both modes and typically over-estimates the support of .
- Reverse KL, , also called the exclusive KL. Its minimization is an I-projection, or information projection. The divergence is infinite wherever and , so the minimizer avoids regions does not cover. Murphy calls this zero-forcing or mode-seeking: a unimodal locks onto one mode and typically under-estimates the support.
The name “moment projection” has a concrete reading for exponential families (our derivation). If , then . Because , the gradient vanishes where . For a Gaussian , , so the forward fit has ’s mean and variance. A second derivation of ours gives the value of the reverse fit at a mode. If has well-separated components and , then where has its mass, and . The larger mode therefore gives the smaller reverse divergence.
Which direction can be computed matters in practice. Torralba, Isola and Freeman (2024, §32.4.1) note that the forward direction is maximum likelihood, needing only samples from the data, while the reverse direction usually cannot be computed because the data density is not available. Variational methods work the other way round. MacKay (2003, §33.1) approximates a known but intractable by minimizing over a simple , the setting of the evidence lower bound, whose gap is a reverse KL. In GANs, the reverse-KL term in the generator’s gradient is the one Mode Collapse connects to dropped modes.
The data processing inequality
If forms a Markov chain, that is, is independent of given , then
(Murphy, 2022, Theorem 6.3.1). The proof expands by the chain rule in two orders, . The Markov condition makes , and (Murphy, 2022, eqs. 6.77–6.79). MacKay (2003, Exercise 8.9) states the theorem for the state of the world , the data and the processed data , and remarks that it says as much about the definition of information as about processing. Equality holds when is a sufficient statistic of for (Murphy, 2022, §6.3.9). An invertible map is one case.
For images, the condition is the whole content of the theorem. Thresholding, quantizing or tone-mapping a pixel’s value is a function of , so the chain holds and the pixel’s information about its label can only fall. A filter that reads neighbouring pixels is a function of the neighbourhood, not of the pixel’s value. The theorem then bounds the output by the information in the whole neighbourhood, which can exceed the pixel’s own. No vision pipeline adds information about the scene that is not in its input. In our reading, what processing can do is make information easier to use, which is a different property.
Fano’s inequality
Mutual information bounds classification error. For any estimator with error probability , and with the binary entropy of the error event,
so (Murphy, 2022, Theorem 6.3.2, eqs. 6.82–6.84). Murphy uses it to justify selecting features by their mutual information with the label: maximizing minimizes , which lowers the bound on the error of any classifier. For two classes, and the weakened form is vacuous, but the first form still constrains the error.
Estimating information from images
Exact values need known distributions, which real images do not supply. For scalar variables a simple estimate bins the values into a histogram, and Murphy (2022, §6.3.5) warns that the number and placement of bins can affect the result considerably. The alternative he describes is the k-nearest-neighbour estimator of Kraskov, Stögbauer and Grassberger, which, as he notes, scikit-learn’s mutual_info_regression implements. In higher dimensions binning suffers from the curse of dimensionality (Murphy, 2022, §6.1.6.3). Normalized forms divide MI by an entropy so that it lies between 0 and 1. Murphy (2022, eq. 6.74) uses , scikit-learn’s normalized_mutual_info_score defaults to the arithmetic mean (average_method="arithmetic"), and registration uses Studholme et al.’s (see Image Registration). Clustering covers the partition versions and their chance correction.
Conventions that change the numbers
- Log base.
scipy.stats.entropyuses the natural log unlessbaseis given, and it normalizes both inputs to sum to one before computing (SciPy 1.16.3 source). scikit-learn’smutual_info_scoreandmutual_info_classifreturn nats.mutual_info_classifusesn_neighbors=3, rescales continuous features and adds noise of relative size , so it takes arandom_state. scikit-learn’s decision trees use base 2, as Decision Tree records. - Zeros. SciPy computes the KL terms with
rel_entr, which gives infinity where and . A histogram with an empty bin therefore has infinite KL divergence from any model that gives that bin mass. Similarity and Distance Measures describes the symmetric, finite alternatives used for histograms. - Bin width. Discrete entropy of a quantized continuous variable grows by one bit per halving of the bin width, as above. State the bin width whenever a density is histogrammed.
Examples
Forward and reverse KL on a grey-level histogram, and the data processing inequality on a two-region image. The script runs with NumPy 2.3.5, SciPy 1.16.3 and scikit-learn 1.7.2 on one thread in about one to two seconds. Two runs printed identical output.
Part (a) uses a 128 × 128 image with region A in columns 0–95 and region B in columns 96–127, an area ratio of 3 : 1. Grey levels are binned into 256 bins of width 1/256, with centres . Each region’s grey levels follow a discretized Gaussian: the Gaussian density evaluated at the bin centres and normalized over the 256 bins, with mean 0.3 for A, 0.7 for B and standard deviation 0.05. The exact histogram of the image is then the mixture . A single discretized Gaussian from the same family is fitted by BFGS on with analytic gradients:
- once by forward KL, from ;
- nine times by reverse KL, from , all with .
Further checks:
- the gradients against central differences;
- the forward fit against an independent root-finding solution of the moment equations;
scipy.stats.entropyagainst the hand sums;- the image itself, sampled pixel by pixel from its region’s distribution with seed 0, whose empirical histogram has empty bins.
Part (b) asks how much a pixel’s value tells about its region label . The label image is 130 × 130, with (region B) in columns 97–129. The analysed pixels are the 128 × 128 whose 3 × 3 window lies inside the image, so exactly. A pixel’s continuous value is with standard normal. Three processed versions are derived from it:
- , the stored 8-bit value;
- , its top three bits;
- , where is the sum of over the pixel’s 3 × 3 window: a box mean followed by the top three bits, in integer arithmetic.
All three mutual informations are exact:
- from normal CDF differences;
- the window sum’s distribution by convolving the nine per-pixel distributions for each count of B labels in the window;
- by quadrature, computed two ways.
A Monte Carlo run passes 40 noisy images (seed 1) through the actual NumPy and SciPy pipeline and scores them with scikit-learn’s mutual_info_score. The script also checks Fano’s inequality with the Bayes error . It applies two invertible maps to : a scaling by 1/4 and a tone curve . Finally it compares the entropy of without clipping (bin width 1/255) with .
import os
for var in ("OMP_NUM_THREADS", "OPENBLAS_NUM_THREADS", "MKL_NUM_THREADS"):
os.environ[var] = "1" # one BLAS thread, before NumPy loads
import numpy as np
from scipy import ndimage, optimize, special, stats
from sklearn.metrics import mutual_info_score
LN2 = np.log(2.0)
# ---------------------------------------------------------------- (a) forward and reverse KL
K = 256
x = (np.arange(K) + 0.5) / K # grey-level bin centres, bin width 1/256
def log_c(mu, sigma):
"""log of the discretized Gaussian: exp(-(x-mu)^2 / 2 sigma^2) normalized over the bins."""
a = -0.5 * ((x - mu) / sigma) ** 2
return a - special.logsumexp(a)
w = np.array([0.75, 0.25]) # area fractions of regions A and B
logp = np.logaddexp(np.log(w[0]) + log_c(0.3, 0.05), np.log(w[1]) + log_c(0.7, 0.05))
p = np.exp(logp) # exact histogram of the image's grey levels
def kl_bits(a, b):
"""sum a log2(a/b), with 0 log 0 = 0 and inf where a > 0 and b = 0."""
m = a > 0
with np.errstate(divide="ignore"):
return np.sum(a[m] * (np.log(a[m]) - np.log(b[m]))) / LN2
def moments(r):
m = np.sum(r * x)
return m, np.sqrt(np.sum(r * (x - m) ** 2))
def fwd(t): # KL(p || q) in bits, t = (mu, log sigma)
mu, s = t[0], np.exp(t[1]); lq = log_c(mu, s); q = np.exp(lq)
val = np.sum(p * (logp - lq)) / LN2
gm = (np.sum(q * x) - np.sum(p * x)) / s**2
gs = (np.sum(q * (x - mu) ** 2) - np.sum(p * (x - mu) ** 2)) / s**2
return val, np.array([gm, gs]) / LN2
def rev(t): # KL(q || p) in bits
mu, s = t[0], np.exp(t[1]); lq = log_c(mu, s); q = np.exp(lq)
f = lq - logp
sm, ss = (x - mu) / s**2, (x - mu) ** 2 / s**2 # d log q / d mu, d log q / d log sigma
g = [np.sum(q * (u - np.sum(q * u)) * f) for u in (sm, ss)]
return np.sum(q * f) / LN2, np.array(g) / LN2
def fit(fun, mu0, s0):
r = optimize.minimize(fun, [mu0, np.log(s0)], jac=True, method="BFGS",
options={"gtol": 1e-8, "maxiter": 1000})
return r.x[0], np.exp(r.x[1]), r.success, np.linalg.norm(fun(r.x)[1])
# C9: analytic gradients against central differences
t0, e = np.array([0.45, np.log(0.12)]), 1e-6
for name, fun in (("KL(p||q)", fwd), ("KL(q||p)", rev)):
num = np.array([(fun(t0 + d)[0] - fun(t0 - d)[0]) / (2 * e) for d in e * np.eye(2)])
print(f"C9 {name} gradient check: max rel error {np.max(np.abs(num - fun(t0)[1]) / np.abs(num)):.1e}")
mp, sp = moments(p)
print(f"p: mean {mp:.5f}, s.d. {sp:.5f}")
fits = [("forward", 0.5) + fit(fwd, 0.5, 0.1)]
fits += [("reverse", m0) + fit(rev, m0, 0.1) for m0 in np.arange(1, 10) / 10]
print("fit start mu sigma KL(p||q) KL(q||p) success |grad|")
for kind, m0, mu, s, ok, g in fits:
q = np.exp(log_c(mu, s))
print(f"{kind:8s} {m0:5.1f} {mu:7.5f} {s:7.5f} {kl_bits(p, q):9.5f} {kl_bits(q, p):9.5f}"
f" {str(ok):7s} {g:.1e}")
# C1: moment matching, and an independent root-finding solution of the moment equations
_, _, mu_f, s_f, *_ = fits[0]
qf = np.exp(log_c(mu_f, s_f))
mq, sq = moments(qf)
root = optimize.root(lambda t: np.array(moments(np.exp(log_c(t[0], np.exp(t[1]))))) - [mp, sp],
[mp, np.log(sp)], method="hybr", tol=1e-14)
print(f"C1 forward fit: |mean_q - mean_p| {abs(mq - mp):.1e}, |sd_q - sd_p| {abs(sq - sp):.1e}; "
f"root-finding mu {root.x[0]:.6f}, sigma {np.exp(root.x[1]):.6f}, "
f"max param diff {max(abs(root.x[0] - mu_f), abs(np.exp(root.x[1]) - s_f)):.1e}")
qn = np.exp(log_c(mp, sp)) # naive closed form: mu, sigma = p's moments
print(f"C2 naive mu = mean_p, sigma = sd_p: KL(p||q) {kl_bits(p, qn):.6f}, "
f"minus forward optimum {kl_bits(p, qn) - kl_bits(p, qf):.1e}")
# C3: scipy.stats.entropy against the hand sums
diffs = []
for _, _, m_, s_, *_ in fits:
q = np.exp(log_c(m_, s_))
diffs += [abs(stats.entropy(p, q, base=2) - kl_bits(p, q)),
abs(stats.entropy(q, p, base=2) - kl_bits(q, p))]
print(f"C3 scipy.stats.entropy vs hand sums: max abs diff {max(diffs):.1e}")
# The image itself: region A in columns 0-95, region B in columns 96-127
rng = np.random.default_rng(0)
img = np.empty((128, 128), np.uint8)
img[:, :96] = rng.choice(K, size=(128, 96), p=np.exp(log_c(0.3, 0.05)))
img[:, 96:] = rng.choice(K, size=(128, 32), p=np.exp(log_c(0.7, 0.05)))
gA, gB = x[img[:, :96]], x[img[:, 96:]]
print(f"D1 region B pixels: {img[:, 96:].size} of {img.size}")
print(f"D2 region A mean {gA.mean():.4f} s.d. {gA.std():.4f}; region B mean {gB.mean():.4f} s.d. {gB.std():.4f}")
p_emp = np.bincount(img.ravel(), minlength=K) / img.size
print(f"C4 empirical histogram: {np.sum(p_emp == 0)} empty bins; KL(q_fwd||p_emp) hand {kl_bits(qf, p_emp)}, "
f"scipy {stats.entropy(qf, p_emp, base=2)}; KL(p_emp||q_fwd) {kl_bits(p_emp, qf):.5f}")
# ---------------------------------------------------------------- (b) data processing inequality
lab = np.zeros((130, 130), np.int64)
lab[:, 97:] = 1 # X = 1 in region B
valid = (slice(1, 129), slice(1, 129)) # pixels whose 3x3 window lies inside the image
X = lab[valid].ravel()
mu, sn = np.array([0.3, 0.7]), 0.1 # grey level of each region, noise s.d.
print(f"D3 analysed pixels with X = 1: {X.sum()} of {X.size}")
PX = np.bincount(X) / X.size
def H_bits(r):
r = r[r > 0]
return -np.sum(r * np.log2(r))
def mi_bits(joint): # joint table, rows x, columns z
return H_bits(joint.sum(1)) + H_bits(joint.sum(0)) - H_bits(joint.ravel())
def pmf_v(m): # P(v = k) for v = clip(round(255 y), 0, 255)
cdf = stats.norm.cdf(((np.arange(256) + 0.5) / 255 - m) / sn)
cdf[-1] = 1.0
return np.diff(np.concatenate([[0.0], cdf]))
PV = np.array([pmf_v(m) for m in mu]) # P(v | x)
PZ3 = PV.reshape(2, 8, 32).sum(2) # top 3 bits: v // 32
cnt = ndimage.correlate(lab, np.ones((3, 3), np.int64), mode="constant")[valid].ravel()
nxc = np.zeros((2, 10)) # pixels with label x and c B-labels in the window
np.add.at(nxc, (X, cnt), 1.0)
PZb_c = np.zeros((10, 8)) # P(Zb | c), Zb = (window sum of v) // 288
for c in range(10):
s = np.array([1.0])
for k in range(9):
s = np.convolve(s, PV[1] if k < c else PV[0])
PZb_c[c] = np.bincount(np.arange(s.size) // 288, weights=s, minlength=8)
J = {"v": PX[:, None] * PV, "Z3": PX[:, None] * PZ3, "Zb": nxc @ PZb_c / X.size}
I = {k: mi_bits(j) for k, j in J.items()}
# I(X; Y_c) for the continuous value, two ways on one grid
y, dy = np.linspace(-0.6, 1.6, 2_200_001, retstep=True)
fx = np.array([stats.norm.pdf(y, m, sn) for m in mu])
f = PX @ fx
def h_grid(dens, step): # differential entropy in bits by quadrature
d = dens[dens > 0]
return -np.sum(d * np.log2(d)) * step
hY, hYX = h_grid(f, dy), 0.5 * np.log2(2 * np.pi * np.e * sn**2)
post = PX[1] * fx[1] / f
Hb = lambda r: -(special.xlogy(r, r) + special.xlogy(1 - r, 1 - r)) / LN2
I_c = hY - hYX
print(f"C5 I(X;Yc): h(Y)-h(Y|X) {I_c:.9f}, H(X)-H(X|Y) {H_bits(PX) - np.sum(f * Hb(post)) * dy:.9f}")
print(f"H(X) = {H_bits(PX):.7f} bits")
print(f"I(X;Yc) {I_c:.7f} >= I(X;v) {I['v']:.7f} >= I(X;Z3) {I['Z3']:.7f}; I(X;Zb) {I['Zb']:.7f}")
print(f" differences: Yc-v {I_c - I['v']:.2e}, v-Z3 {I['v'] - I['Z3']:.2e}, Zb-v {I['Zb'] - I['v']:.2e}")
# Monte Carlo through the actual pipeline, scored with scikit-learn (nats -> bits)
rng = np.random.default_rng(1)
mc = {"v": [], "Z3": [], "Zb": []}
for _ in range(40):
Yc = mu[lab] + sn * rng.standard_normal(lab.shape)
v = np.clip(np.round(255 * Yc), 0, 255).astype(np.int64)
zb = ndimage.correlate(v, np.ones((3, 3), np.int64), mode="constant") // 288
for k, z in (("v", v), ("Z3", v // 32), ("Zb", zb)):
mc[k].append(z[valid].ravel())
for k in mc:
est = mutual_info_score(np.tile(X, 40), np.concatenate(mc[k])) / LN2
print(f"C6 I(X;{k}): exact {I[k]:.5f}, Monte Carlo {est:.5f}, diff {est - I[k]:+.1e}")
# Fano's inequality: H(X|Z) <= H_b(Pe) + Pe log2 2, Pe the Bayes error
for k, j in J.items():
pe = j.min(0).sum()
print(f"H8 {k:2s}: H(X|Z) {H_bits(PX) - I[k]:.5f} <= H_b(Pe) + Pe = {Hb(pe) + pe:.5f} (Pe {pe:.5f})")
# Invertible maps of Yc: MI unchanged, differential entropy not
def mapped(ginv, dginv, lo, hi): # densities of g(Yc) on a grid in the new variable
u, du = np.linspace(lo, hi, 1_500_001, retstep=True)
yy = ginv(u)
with np.errstate(over="ignore"):
gx = np.array([stats.norm.pdf(yy, m, sn) * np.abs(dginv(u)) for m in mu])
gx = np.nan_to_num(gx)
hg = h_grid(PX @ gx, du)
return hg, hg - sum(PX[i] * h_grid(gx[i], du) for i in range(2))
h1, I1 = mapped(lambda u: 4 * u, lambda u: 4 + 0 * u, -0.15, 0.4)
e2 = 1e-15
h2, I2 = mapped(lambda u: 0.5 + np.log(u / (1 - u)) / 8, lambda u: 1 / (8 * u * (1 - u)), e2, 1 - e2)
sg = special.expit(8 * (y - 0.5))
Elog = np.sum(f * np.log2(8 * sg * (1 - sg))) * dy
print(f"H6 Yc/4: h {h1:.6f} (h(Yc) {hY:.6f}, change {h1 - hY:+.7f}), I diff {I1 - I_c:+.1e}")
print(f"H6 tone curve: h {h2:.6f} (change {h2 - hY:+.7f}, E[log2 g'] {Elog:+.7f}), I diff {I2 - I_c:+.1e}")
# Quantization: entropy of round(255 Yc) without clipping is about h(Yc) + log2 255
k = np.arange(-300, 556)
P = PX @ np.array([np.diff(stats.norm.cdf((np.r_[k - 0.5, k[-1] + 0.5] / 255 - m) / sn)) for m in mu])
print(f"H7 H(v unclipped) {H_bits(P):.6f}, h(Yc) + log2 255 {hY + np.log2(255):.6f}, "
f"diff {H_bits(P) - hY - np.log2(255):+.1e}")
Output:
C9 KL(p||q) gradient check: max rel error 4.3e-11
C9 KL(q||p) gradient check: max rel error 3.8e-10
p: mean 0.40000, s.d. 0.18028
fit start mu sigma KL(p||q) KL(q||p) success |grad|
forward 0.5 0.39074 0.19157 1.01461 2.65298 True 3.3e-10
reverse 0.1 0.30001 0.05002 10.71896 0.41496 True 1.2e-10
reverse 0.2 0.30001 0.05002 10.71896 0.41496 True 2.2e-10
reverse 0.3 0.30001 0.05002 10.71896 0.41496 True 5.4e-10
reverse 0.4 0.30001 0.05002 10.71896 0.41496 True 1.1e-10
reverse 0.5 0.30001 0.05002 10.71896 0.41496 True 1.1e-11
reverse 0.6 0.69997 0.05007 33.71518 1.99976 False 1.2e-07
reverse 0.7 0.69997 0.05007 33.71518 1.99976 True 7.8e-09
reverse 0.8 0.30001 0.05002 10.71896 0.41496 True 4.7e-10
reverse 0.9 0.30001 0.05002 10.71896 0.41496 True 2.7e-13
C1 forward fit: |mean_q - mean_p| 8.3e-12, |sd_q - sd_p| 2.3e-12; root-finding mu 0.390741, sigma 0.191575, max param diff 1.1e-11
C2 naive mu = mean_p, sigma = sd_p: KL(p||q) 1.019177, minus forward optimum 4.6e-03
C3 scipy.stats.entropy vs hand sums: max abs diff 1.8e-15
D1 region B pixels: 4096 of 16384
D2 region A mean 0.3001 s.d. 0.0502; region B mean 0.7008 s.d. 0.0501
C4 empirical histogram: 79 empty bins; KL(q_fwd||p_emp) hand inf, scipy inf; KL(p_emp||q_fwd) 1.02260
D3 analysed pixels with X = 1: 4096 of 16384
C5 I(X;Yc): h(Y)-h(Y|X) 0.737303341, H(X)-H(X|Y) 0.737303341
H(X) = 0.8112781 bits
I(X;Yc) 0.7373033 >= I(X;v) 0.7372819 >= I(X;Z3) 0.7160762; I(X;Zb) 0.8085480
differences: Yc-v 2.14e-05, v-Z3 2.12e-02, Zb-v 7.13e-02
C6 I(X;v): exact 0.73728, Monte Carlo 0.73719, diff -9.6e-05
C6 I(X;Z3): exact 0.71608, Monte Carlo 0.71543, diff -6.5e-04
C6 I(X;Zb): exact 0.80855, Monte Carlo 0.80865, diff +9.8e-05
H8 v : H(X|Z) 0.07400 <= H_b(Pe) + Pe = 0.15583 (Pe 0.01916)
H8 Z3: H(X|Z) 0.09520 <= H_b(Pe) + Pe = 0.17937 (Pe 0.02275)
H8 Zb: H(X|Z) 0.00273 <= H_b(Pe) + Pe = 0.00495 (Pe 0.00036)
H6 Yc/4: h -2.537529 (h(Yc) -0.537529, change -2.0000000), I diff -2.2e-16
H6 tone curve: h -0.507369 (change +0.0301603, E[log2 g'] +0.0301603), I diff +0.0e+00
H7 H(v unclipped) 7.456895, h(Yc) + log2 255 7.456824, diff +7.1e-05
The checks held. The data have the planned properties: region B holds 4,096 of the 16,384 pixels in both parts, and the sampled regions have the planned means and standard deviations to within 0.003. The analytic gradients agree with finite differences. The forward fit matches ’s moments, and its parameters agree with the root-finding solution. scipy.stats.entropy agrees with the hand sums, and the two formulas for agree. The Monte Carlo estimates differ from the exact values by at most bits. The naive parameter choice does not beat the optimizer, and the reverse divergence from the sampled image’s histogram is infinite both by hand and in SciPy.
Forward KL covers, reverse KL seeks. The forward fit sits between the modes with a standard deviation near four times a component’s, as hypothesized (held). Its own mean and standard deviation on the grid equal ’s, 0.40000 and 0.18028. Its parameters, and , do not. In our reading, the reason is that the grid stops at 0 and 1, so a Gaussian with these parameters loses some tail, and the fitted parameters compensate for it. Setting the parameters to ‘s moments directly costs bits more. The reverse fits reached exactly two optima, one on each mode, with within 0.2% of the components’ 0.05. At each optimum the divergence is close to : 0.41496 bits against , and 1.99976 against 2. The larger mode gives the lower value; every part of this hypothesis held. Starts at 0.1–0.5, 0.8 and 0.9 reached the optimum at 0.3, and starts at 0.6 and 0.7 reached the one at 0.7.
Each fit is poor by the other measure, as hypothesized (held). The forward fit’s reverse divergence is 2.65 bits, more than either reverse optimum. The reverse fits’ forward divergences are 10.7 and 33.7 bits, against 1.01 for the forward fit, because each leaves a whole mode in its far tail. On the sampled image’s histogram, 79 of the 256 bins are empty. The reverse divergence from the forward fit is then infinite, both by hand and in SciPy, while the forward divergence stays near its exact value. Zero-forcing is not an abstraction for real histograms: any empty bin makes the reverse KL of a Gaussian infinite.
Processing a pixel loses information; pooling pixels does not contradict that. Along the chain the information falls at every step (held). Storing 8 bits loses bits, and keeping three bits loses 0.021 bits, about 3% of what the pixel carries. merges each run of 32 grey levels into one value. The blurred, quantized value carries 0.809 bits, more than the stored pixel’s 0.737 and close to the label’s entropy of 0.811 (held). This is not a violation of the inequality (our derivation from the construction). is computed from the nine values in the window, not from alone, so and are not independent given , and Theorem 6.3.1’s condition fails for the chain . The neighbours mostly share the pixel’s label, and their noise is independent, so their mean is a less noisy reading of the label. The inequality still holds for the chain through the whole window, whose information about is at least 0.809 bits.
Fano’s inequality held in all three cases. The bound is loose: for the stored pixel, bits against a bound of 0.156.
Differential entropy moves, mutual information does not. These two checks illustrate identities rather than test them: their residuals were known from a planning script before the run. Both held. The pixel’s differential entropy is already negative, −0.54 bits, which is possible because a density can exceed 1. Dividing by 4 lowers it by exactly 2 bits, and the tone curve raises it by bits. The mutual information with the label is unchanged under both maps, to rounding error. Quantizing without clipping gives an entropy of 7.4569 bits, within of , our restatement of Murphy’s §6.1.6 for this bin width.
Process note. The batch plan’s entry for part (b) reads “Region label X, noisy pixel Y and processed Z (Gaussian blur, then 3-bit quantization): exact I(X; Y) ≥ I(X; Z) (PML1 Thm 6.3.1)”. Before any script ran, we made five departures from it, logged them and had them approved at the pilot:
- The blur is a 3 × 3 box mean on integers, whose distribution is an exact convolution.
- Because the blur breaks the Markov chain when is the pixel’s own value, the inequality is tested on , and the blur is a separate case with the hypothesis .
- The noise standard deviation (0.1), the 130 × 130 image with its 128 × 128 analysed pixels, and the 8-bit rounding, which the batch plan leaves open, were fixed in our plan.
- Checks were added: the root-finding reference, the naive moment-matched , the empirical histogram, the second MI formula, the Monte Carlo cross-check, the convergence and gradient checks, the tone curve, the quantization identity and Fano’s inequality.
- The discretized Gaussian is the density at bin centres, normalized over the bins.
One bar was changed after a planning script printed a value that failed it. The convergence check’s first form was “every BFGS fit (one forward, nine reverse) reports success and ends with gradient norm < 1e-7”. The planning script printed “success False, |grad| 1.2e-07” for the reverse fit started at 0.6, and that check failed. The run above prints the same. The check was changed before the pilot to a gradient norm below for every fit, with BFGS’s success flag (its line-search status) printed but not scored. The changed check held, with a largest norm of . Because it was set after the value was seen, it is an illustration, not a test. Also after that planning script, the quadrature grid for the mapped variables was changed from 2,200,001 to 1,500,001 points. With equal point counts, the sums for were the sums for scaled point by point, so they agreed by construction. The pilot was the full script, and the run shown is the same script with the same seeds; its output is identical to the pilot’s.
Common Misconceptions
- “The KL divergence is a distance.” It is not symmetric (MacKay, 2003, §2.6). Murphy (2022, §6.2) introduces it as a divergence, which, unlike a metric, need not be symmetric or satisfy the triangle inequality, and Similarity and Distance Measures reports from Rubner et al. that it does not satisfy it. In the example, the forward fit is 1.01 bits from in one direction and 2.65 in the other. Which direction is minimized decides what the fit looks like.
- “The data processing inequality means no filter can help.” It says that no function of the data adds information about the quantity of interest. A filter that pools neighbours uses more data than one pixel, and in the example it raises the pixel-level information from 0.737 to 0.809 bits. Processing can also make information usable, for example for a threshold, without adding any.
- “Differential entropy is the information content of an image.” It can be negative, and it shifts with the units: the same pixel values have a differential entropy 2 bits lower when divided by 4. Murphy (2022, §6.1.6) shows that it can be negative. Mutual information between continuous variables has no such dependence (our derivation above, from the change of variables).
- “Histogram entropy is a fixed property of the image.” It depends on the bin width, by about one bit per halving (Murphy, 2022, §6.1.6), and estimates of MI depend on the number and placement of bins (Murphy, 2022, §6.3.5).
- “Three-variable information can be drawn as a Venn diagram.” MacKay (2003, Exercise 8.8) calls this representation misleading and points to the case with independent fair bits and . In our working of that case, but bit: conditioning can increase mutual information, which overlapping circles cannot show.
- “Conditioning on an observation always reduces uncertainty.” Only on average. A particular observation can leave the posterior more uncertain than the prior (MacKay, 2003, Exercise 8.2; Murphy, 2022, §6.1.4).
Where It Is Used
- Training losses. The cross-entropy loss and label smoothing are cross-entropies. Knowledge distillation matches a student to a teacher by cross-entropy or KL. Maximum likelihood is forward KL from the data.
- Compression. Image compression bounds the cost of a prefix code by the first-order entropy of its symbols.
- Registration and stereo. Image registration, medical image registration and the Viola–Wells paper maximize MI between intensities. Semi-global matching can use MI as a matching cost.
- Segmentation and features. Kapur’s method in thresholding chooses the threshold that maximizes the sum of the two classes’ entropies. Decision trees split by information gain. Fano’s inequality motivates choosing features by their MI with the label.
- Comparing distributions. Similarity and distance measures uses KL and its symmetric relatives for histograms. Clustering scores partitions by (normalized, adjusted) MI. t-SNE minimizes a KL divergence between neighbourhood distributions and sets its scale by perplexity, an exponentiated entropy.
- Generative models. Generative models are fitted by forward KL when their likelihood is tractable. The evidence lower bound of the variational autoencoder has a reverse-KL gap. GAN analyses connect the reverse KL to mode collapse. The Inception Score is the exponential of an expected KL divergence. Latent Space describes MI-based disentanglement scores.
- Representation learning and uncertainty. The InfoNCE loss is a lower bound on MI between views, capped at , and underlies contrastive learning. Uncertainty estimation separates disagreement between models (an MI) from each model’s own entropy. Active perception chooses the next view by expected information gain.
Related
- Image Compression
How images are stored in fewer bits, losslessly or with controlled loss; the transform, quantization and entropy-coding stages of JPEG, how a quality setting becomes a quantization table, what JPEG 2000 changes, and how rate is traded against distortion.
- Alignment by Maximization of Mutual Information
Paul Viola and William Wells's ICCV 1995 paper and its 1997 journal version, which aligned a model to an image, or one imaging modality to another, by maximizing the mutual information between their intensities, estimated with Parzen windows from small random samples and maximized by stochastic gradient ascent.
- Similarity and Distance Measures
The functions that score how alike two feature vectors, histograms or binary codes are (Euclidean and other ℓp distances, cosine similarity and the dot product, Mahalanobis, Hamming, histogram measures such as χ², intersection and Hellinger, and the earth mover's distance), which of them are true metrics, and where each is used in descriptor matching, histogram comparison and embedding retrieval.
- InfoNCE Loss
The softmax loss that asks a model to pick the true partner of a sample, such as the matching view of an image patch, among K candidates; it is a lower bound on mutual information that can never exceed log K, descends from noise-contrastive estimation, and underlies CPC, SimCLR, MoCo and CLIP.
- Evidence Lower Bound (ELBO)
The tractable lower bound on the log-likelihood of an image that latent-variable generative models maximize instead of the likelihood itself; its two derivations, why the gap equals the KL divergence to the true posterior, the reconstruction and KL terms, the reparameterization trick, importance-weighted bounds and its role in VAEs and diffusion models.
- Maximum Likelihood Estimation
The method of choosing model parameters under which the observed data are most probable; it turns noise models into losses such as least squares and cross-entropy, and its large-sample properties explain when estimates from images can be trusted.
References
- Murphy, K. P. (2022). Probabilistic Machine Learning: An Introduction, §6.1–§6.3. MIT Press. Online version of 18 April 2025.
- MacKay, D. J. C. (2003). Information Theory, Inference, and Learning Algorithms. Cambridge University Press. Version 7.2 (fourth printing, 2005), §2.6, chapter 8 and §33.1 (read on-screen).
- Torralba, A., Isola, P. & Freeman, W. T. (2024). Foundations of Computer Vision. MIT Press. Chapter 32, Generative Models, §32.4.1 (read in the online edition).
- Shannon, C. E. (1948). A Mathematical Theory of Communication. Bell System Technical Journal, 27(3), 379–423 (not read).
- Kraskov, A., Stögbauer, H. & Grassberger, P. (2004). Estimating Mutual Information. Physical Review E, 69(6), 066138 (not read; details as Murphy (2022) lists them).
- SciPy developers. scipy/stats/_entropy.py (scipy.stats.entropy), source code of SciPy 1.16.3 (installed copy read).
- scikit-learn developers. sklearn/metrics/cluster/_supervised.py (mutual_info_score) and sklearn/feature_selection/_mutual_info.py (mutual_info_classif), source code of scikit-learn 1.7.2 (installed copy read).