本文的核心论点:指数分布、正态分布、玻尔兹曼分布不是三个独立的分布,而是同一个原理(最大熵)在不同约束下的三种表现。
\[\text{最大化 } H = -\!\int p(x)\ln p(x)\,dx \quad \text{subject to constraints} \quad \Longrightarrow \quad p(x) \propto e^{-\lambda\, f(x)}\]
在最大化熵之前,先回答一个更根本的问题:凭什么要最大化熵? 有两条独立的路都通向它——物理的计数论证,和统计的无偏推断论证。
做 \(N\) 次观测,每次结果落入 \(k\) 个类别之一。记 \(n_i\) 为类别 \(i\) 出现的次数(\(i = 1, \dots, k\),满足 \(n_1 + n_2 + \cdots + n_k = N\))。宏观状态是计数向量 \((n_1, \dots, n_k)\)——只记”每类出现多少次”;微观状态是具体的观测序列——还记”哪一次是哪一类”。一个宏观状态对应的微观排列数是多项式系数:
\[W = \frac{N!}{n_1!\,n_2!\cdots n_k!}\]
抛硬币是 \(k=2\) 的特例:类别只有正/反,\(n_1 = k_{\text{正}}\),\(n_2 = N - k_{\text{正}}\),于是
\[W = \frac{N!}{k_{\text{正}}!\,(N-k_{\text{正}})!} = \binom{N}{k_{\text{正}}}\]
证明 \(\ln W \approx N \cdot H\):
\[ \begin{aligned} \ln W &= \ln N! - \sum_i \ln n_i! \\[2pt] &\approx \bigl(N\ln N - N\bigr) - \sum_i \bigl(n_i \ln n_i - n_i\bigr) && \text{Stirling: } \ln n! \approx n\ln n - n \\[2pt] &= N\ln N - \sum_i n_i \ln n_i && \textstyle\sum_i n_i = N \text{,两个线性项相消} \\[2pt] &= \sum_i n_i \ln N - \sum_i n_i \ln n_i && \textstyle N\ln N = \bigl(\sum_i n_i\bigr)\ln N \text{,常数 } \ln N \text{ 乘进求和} \\[2pt] &= \sum_i n_i \bigl(\ln N - \ln n_i\bigr) && \text{同一求和指标,合并并提出 } n_i \\[2pt] &= -\sum_i n_i \ln\frac{n_i}{N} && \textstyle\ln N - \ln n_i = -\ln\frac{n_i}{N} \text{(对数商法则),负号提出} \\[2pt] &= N \cdot \left(-\sum_i p_i \ln p_i\right) && p_i = n_i / N \\[2pt] &= N \cdot H(p) \qquad \blacksquare \end{aligned} \]
即 \(W \approx e^{N H}\):熵是每次观测平摊到的”排列数指数”。两个分布的熵哪怕只差一点点,排列数就差 \(e^{N\cdot\Delta H}\) 倍——\(N\) 大时是天文数字。所以”熵最大的分布”不是抽象偏好,而是压倒性地更可能出现的宏观状态。
## ── 计数直觉:熵大 = 微观排列数多 = 压倒性地更可能 ──────────
par(mfrow = c(1, 2), mar = c(4.6, 5.0, 3.5, 1))
# 左图:抛 30 次硬币,正面次数 k 对应的排列数 W = C(30, k)
n_flip <- 30
k <- 0:n_flip
W <- choose(n_flip, k)
plot(k / n_flip, W, type = "h", lwd = 3, col = "steelblue",
main = paste0("W = C(", n_flip, ", k): microstates per macrostate"),
xlab = "Fraction of heads k/N", ylab = "Number of arrangements W",
cex.lab = 1.35, cex.main = 1.15)
points(0.5, choose(n_flip, n_flip/2), pch = 16, col = "tomato", cex = 1.4)
text(0.02, 1.3e8, adj = 0,
paste0("k/N = 1/2:\nW = ", format(choose(n_flip, n_flip/2), big.mark = ",")),
col = "tomato", cex = 1.15)
text(0.92, 3.2e7, "k/N = 1:\nW = 1\n(bar invisible)", col = "gray40", cex = 1.05)
arrows(0.97, 2.0e7, 1.0, 2e6, length = 0.08, col = "gray40", lwd = 1.5)
# 右图:(1/N) ln C(N, pN) 随 N 增大收敛到二元熵 H(p)
p_grid <- seq(0.001, 0.999, length.out = 400)
Ns <- c(10, 50, 1000)
cols <- c("forestgreen", "purple", "steelblue")
plot(NA, xlim = c(0, 1), ylim = c(0, 0.75),
main = "ln(W)/N converges to entropy H(p)",
xlab = "p (fraction of heads)", ylab = "ln(W) / N",
cex.lab = 1.35, cex.main = 1.15)
for (i in seq_along(Ns)) {
N_i <- Ns[i]
lines(p_grid, lchoose(N_i, round(p_grid * N_i)) / N_i,
col = cols[i], lwd = 2)
}
H_bin <- -p_grid * log(p_grid) - (1 - p_grid) * log(1 - p_grid)
lines(p_grid, H_bin, col = "tomato", lwd = 3, lty = 2)
legend("bottom", c(paste0("N = ", Ns), "H(p) = -p ln p - (1-p) ln(1-p)"),
col = c(cols, "tomato"), lwd = c(2, 2, 2, 3),
lty = c(1, 1, 1, 2), bty = "n", cex = 0.95)左图:每根柱子是一个宏观状态(正面占比 \(k/N\)),柱高是它对应的微观排列数 \(W = \binom{30}{k}\)。注意 \(k/N = 0\) 和 \(1\) 的柱子画了但看不见——高度是 \(W = 1\)(全反/全正只有一种排法),在 1.55 亿的纵轴下肉眼就是零。这正是要传达的信息:\(k/N = 1/2\) 的排列数是两端的 1.5 亿倍,公平硬币下你”看到”一半正面,不是有什么力量在推它,纯粹是排列数碾压。右图:\(\frac{1}{N}\ln W\) 随 \(N\) 增大收敛到 \(H(p)\),正是上面 Stirling 证明的数值验证。
上图有个容易起疑的地方:说好的”碾压”,中间几根柱子怎么差得不大?比如 \(\binom{30}{14}/\binom{30}{15} = 0.94\),只差 6%。这不是矛盾,是二阶展开的必然。
\(W_1/W_2 = e^{N\Delta H}\) 说的确实是 \(W\) 本身的比值,但关键在 \(\Delta H\) 有多大。\(H(p)\) 在 \(p = 1/2\) 处是光滑极大值,一阶导数为零,Taylor 展开从二阶开始(记 \(\delta = p - 1/2\)):
\[\Delta H = H(1/2) - H(1/2+\delta) \approx \tfrac{1}{2}\bigl|H''(1/2)\bigr|\,\delta^2 = 2\delta^2\]
于是峰附近:
\[\frac{W(p)}{W_{\max}} \approx e^{-2N\delta^2}\]
两个结论直接读出来:
所以”碾压”是对固定的宏观差异(固定 \(\Delta H\))、随 \(N\) 增大而言的;\(N\) 固定时峰附近永远有一个 \(O(1/\sqrt{N})\) 宽的”没被碾压”窗口,\(N\to\infty\) 时窗口本身收缩成零。
## ── 碾压是 N 的函数:窗口收缩 + 固定 ΔH 的指数塌缩 ──────────
par(mfrow = c(1, 2), mar = c(4.6, 5.0, 3.5, 1))
# 左图:W/W_max 随 N 增大收缩成尖峰(宽度 ~ 1/sqrt(N))
Ns_w <- c(30, 300, 3000)
cols_w <- c("steelblue", "purple", "tomato")
plot(NA, xlim = c(0.2, 0.8), ylim = c(0, 1.08),
main = "Relative arrangements W / W_max",
xlab = "p = k/N", ylab = "W(k) / W(N/2)",
cex.lab = 1.35, cex.main = 1.15)
for (i in seq_along(Ns_w)) {
N_i <- Ns_w[i]
k_i <- 0:N_i
rel <- exp(lchoose(N_i, k_i) - lchoose(N_i, round(N_i / 2)))
lines(k_i / N_i, rel, col = cols_w[i], lwd = 2.5)
}
abline(v = 0.5, col = "gray70", lty = 3)
legend("topleft", paste0("N = ", Ns_w),
col = cols_w, lwd = 2.5, bty = "n", cex = 1.1,
title = "width ~ 1/sqrt(N)", title.col = "gray30")
# 右图:固定宏观差异 p=0.6 vs p=0.5,W 比值随 N 指数塌缩
Ns_r <- seq(10, 1000, by = 10)
ratio <- sapply(Ns_r, function(N_i)
exp(lchoose(N_i, round(0.6 * N_i)) - lchoose(N_i, round(0.5 * N_i))))
plot(Ns_r, ratio, type = "l", lwd = 2.5, col = "steelblue", log = "y",
main = "Fixed contrast: W(p=0.6) / W(p=0.5)",
xlab = "N", ylab = "Ratio (log scale)",
cex.lab = 1.35, cex.main = 1.15)
dH <- (-0.5*log(0.5)-0.5*log(0.5)) - (-0.6*log(0.6)-0.4*log(0.4))
lines(Ns_r, exp(-Ns_r * dH), col = "tomato", lwd = 2, lty = 2)
pts_N <- c(30, 1000)
pts_r <- sapply(pts_N, function(N_i)
exp(lchoose(N_i, round(0.6 * N_i)) - lchoose(N_i, round(0.5 * N_i))))
points(pts_N, pts_r, pch = 16, col = "forestgreen", cex = 1.5)
text(pts_N[1], pts_r[1], pos = 4,
paste0("N = 30: ratio = ", round(pts_r[1], 2)), col = "forestgreen", cex = 1.15)
text(pts_N[2], pts_r[2] * 1e3, pos = 2,
paste0("N = 1000: ratio = ", format(pts_r[2], digits = 2)),
col = "forestgreen", cex = 1.15)
legend("bottomleft", c("exact (binomial)", "e^(-N dH), dH = 0.0201"),
col = c("steelblue", "tomato"), lwd = c(2.5, 2), lty = c(1, 2),
bty = "n", cex = 1.0)左图:把每个 \(N\) 的排列数都除以自己的峰值,\(N = 30 \to 3000\),窗口按 \(1/\sqrt{N}\) 收缩。右图:固定比较 \(p = 0.6\) 对 \(p = 0.5\)(\(\Delta H \approx 0.0201\)),\(W\) 比值在对数轴上是一条直线 \(e^{-N\Delta H}\)——\(N=30\) 时只差一半(0.56,毫不起眼),\(N=1000\) 时已是 \(10^{-9}\)。精确二项计算(蓝)和 \(e^{-N\Delta H}\)(红虚线)几乎重合。
上面的推导看着像信息论,历史上却是物理先走通的——\(-\sum p_i \ln p_i\) 这个量被独立发现了两次,路径完全不同:
1730 年前后,de Moivre 与 Stirling:de Moivre 研究抛硬币的二项分布,先推出 \(n! \sim C\, n^{n+1/2} e^{-n}\) 的形状;Stirling 定出常数 \(C = \sqrt{2\pi}\)。工具就位。
1877 年,Boltzmann:本节的证明就是他这年论文的工作(《论热理论第二定律与概率论的关系》)——把气体分子的能量切成离散小份,数每种分配的排列数(他称 Komplexionen,即 \(W\)),上 Stirling,带约束最大化 → 最可能的宏观状态。\(S = k_B \ln W\) 后来刻在他的墓碑上;除以 \(N\),就是 \(-\sum p_i \ln p_i\)。
数学在今天看是本科习题,但公式的难度 ≠ 洞见的难度——每一步在当时都是异端:(a) 宣称”熵是概率的东西、第二定律只是统计规律”,等于说熵增可以被违反(只是概率极小),遭到猛烈围攻(Loschmidt 可逆性佯谬、Zermelo 回归佯谬,论战二十年);(b) 整个论证建立在原子实在性上,而 Mach、Ostwald 为首的主流学界不承认原子,Boltzmann 后半生都在打这场仗,1906 年自杀,没能看到几年后 Perrin 的布朗运动实验坐实原子论;(c) 能量离散化 \(\epsilon, 2\epsilon, 3\epsilon,\dots\) 对他只是最后要取极限的计算技巧,Planck 1900 年处理黑体辐射时发现不取极限才对——量子论就从这个”技巧”里长出来。\(S = k\ln W\) 的写法和常数 \(k\) 其实都是 Planck 给出的,他把 \(k\) 命名为 Boltzmann 常数。
1948 年,Shannon(《A Mathematical Theory of Communication》):走公理化路线——要求不确定性度量对 \(p\) 连续、等概率时随类别数单调增、分步选择时可加权分解,证明唯一解是 \(-K\sum p_i \log p_i\)。推导里没有排列数、没有 Stirling。但他论文中的典型序列又绕回了计数:长度 \(N\) 的序列里”典型”的约有 \(e^{NH}\) 条——正是 \(W \approx e^{NH}\) 的信息论化身。
命名轶事:Shannon 问 von Neumann 这个量该叫什么,von Neumann 建议叫”熵”,理由之一是”没人真正懂熵是什么,辩论时你永远占优”。
1957 年,Jaynes(《Information Theory and Statistical Mechanics》):把两条路正式焊在一起——统计力学的最大熵不是物理定律,而是推断原理的特例。这就是下一小节。
第二条路不谈物理,谈推断(Jaynes, 1957)。当你只知道一个分布的部分信息(比如只知道均值),却要选出一个完整的分布时:
所以最大熵不是自然界的神秘偏好,而是约束之外保持最大无知的唯一一致做法。物理系统”选”它是因为排列数碾压,统计学家”选”它是因为诚实——两条路殊途同归,都指向同一个变分问题:
\[\max_p \; H[p] \quad \text{s.t. 已知约束} \;\Longrightarrow\; p(x) \propto e^{-\lambda f(x)}\]
后面三节就是把不同的 \(f(x)\) 代进去。
对连续分布 \(p(x)\),微分熵定义为:
\[H[p] = -\int p(x) \ln p(x)\, dx\]
\(H\) 越大,分布越”分散”、越”不确定”、越”没有偏见”。
定义里的乘积 \(-p\ln p\) 值得拆开看。改写成 \(H = \int p(x)\cdot\bigl(-\ln p(x)\bigr)\,dx = E\bigl[-\ln p(X)\bigr]\):
## ── 拆开被积函数:p(x) × (-ln p(x)) ──────────────────────────
x_e <- seq(-4, 4, length.out = 2000)
p_e <- dnorm(x_e) # 概率权重
s_e <- -log(p_e) # 信息量(惊讶度)
g_e <- p_e * s_e # 熵密度 = 两者乘积
pts <- c(0, 1.5, 3) # 三个跟踪点:中心 / 中段 / 尾部
pt_cols <- c("tomato", "purple", "forestgreen")
par(mfrow = c(1, 3), mar = c(4.6, 4.8, 3.5, 1))
# 面板 1:概率权重 p(x)
plot(x_e, p_e, type = "l", lwd = 3, col = "steelblue",
main = "Weight p(x)", xlab = "x", ylab = "p(x)",
cex.lab = 1.4, cex.main = 1.3)
points(pts, dnorm(pts), pch = 16, col = pt_cols, cex = 1.6)
text(3, dnorm(3) + 0.05, "p almost 0", col = "forestgreen", pos = 2, cex = 1.2)
# 面板 2:信息量 -ln p(x)
plot(x_e, s_e, type = "l", lwd = 3, col = "steelblue",
main = "Surprise -ln p(x)", xlab = "x", ylab = "-ln p(x)",
cex.lab = 1.4, cex.main = 1.3)
points(pts, -log(dnorm(pts)), pch = 16, col = pt_cols, cex = 1.6)
text(3, -log(dnorm(3)) - 0.6, "huge surprise", col = "forestgreen",
pos = 2, cex = 1.2)
# 面板 3:乘积 = 熵密度,阴影面积 = H
plot(x_e, g_e, type = "l", lwd = 3, col = "steelblue",
main = "Product p(x) * (-ln p(x))", xlab = "x",
ylab = "p(x) * (-ln p(x))", cex.lab = 1.4, cex.main = 1.3)
polygon(c(x_e, rev(x_e)), c(g_e, rep(0, length(g_e))),
col = adjustcolor("steelblue", 0.25), border = NA)
points(pts, dnorm(pts) * (-log(dnorm(pts))), pch = 16, col = pt_cols, cex = 1.6)
H_val <- 0.5 * log(2 * pi * exp(1))
text(0, 0.18, paste0("Area = H = ", round(H_val, 3)),
col = "steelblue", cex = 1.3)
text(3, dnorm(3) * (-log(dnorm(3))) + 0.04,
"tiny x huge = ~0", col = "forestgreen", pos = 2, cex = 1.2)跟踪三个点(标准正态):
尾部不失控是因为 \(\lim_{p\to 0} p\ln p = 0\):\(p\) 趋于 0 的速度(指数级)永远快过 \(\ln p\) 发散的速度(对数级)。所以熵的贡献主要来自”中等概率”区域,第三幅图阴影面积就是 \(H = \tfrac{1}{2}\ln(2\pi e) \approx 1.419\)。
## ── 直觉:熵衡量分布的"展开程度" ──────────────────────────
# 辅助函数:数值计算微分熵
h_diff <- function(p_vals, dx) {
p_vals <- pmax(p_vals, 1e-300)
-sum(p_vals * log(p_vals)) * dx
}
x_grid <- seq(-6, 6, length.out = 5000)
dx <- diff(x_grid)[1]
# 不同 sigma 的正态分布
sigmas <- c(0.5, 1, 2, 3)
h_vals <- sapply(sigmas, function(s) h_diff(dnorm(x_grid, 0, s), dx))
h_theory <- 0.5 * log(2 * pi * exp(1) * sigmas^2)
par(mfrow = c(1, 2), mar = c(4, 4, 3.5, 1))
# 左图:分布越宽 → 熵越大
plot(NA, xlim = c(-6, 6), ylim = c(0, 0.85),
main = "Wider distribution = higher entropy",
xlab = "x", ylab = "Density")
cols <- c("steelblue", "tomato", "forestgreen", "purple")
for (i in seq_along(sigmas)) {
lines(x_grid, dnorm(x_grid, 0, sigmas[i]), col = cols[i], lwd = 2.5)
}
legend("topright",
as.expression(lapply(seq_along(sigmas), function(i)
bquote(list(sigma == .(sigmas[i]), H == .(round(h_theory[i], 2)))))),
col = cols, lwd = 2.5, bty = "n", cex = 0.9)
# 右图:sigma vs entropy
plot(sigmas, h_theory, type = "b", pch = 16, col = "steelblue", lwd = 2,
cex = 1.5, main = "Entropy grows with spread",
xlab = expression(sigma), ylab = "Differential entropy H")
lines(seq(0.3, 3.2, 0.01),
0.5 * log(2*pi*exp(1)*seq(0.3,3.2,0.01)^2),
col = "tomato", lwd = 2, lty = 2)
legend("bottomright",
expression("Numerical",
"Analytic: " * H == frac(1, 2) ~ ln(2 * pi * e * sigma^2)),
col = c("steelblue","tomato"), lwd = 2, pch = c(16, NA),
lty = c(1, 2), bty = "n", y.intersp = 1.4)直觉总结:
当你只知道关于数据的某些统计量(均值、方差……),最诚实的做法是选择满足这些约束、但其他方面尽可能”不做假设”的分布——即熵最大的分布。
(英文 Maximum Entropy,缩写 MaxEnt,本文图内英文标注用它。)
这不是一个任意的审美偏好,而是一个逻辑必然:
下一小节要用 Lagrange 乘子法,先把这个工具本身讲清楚。核心就一张图,数学只有一行。
问题形态。普通极值问题:\(f(x,y)\) 哪里最大?——导数为零,\(\nabla f = 0\)。带约束的极值问题:在满足 \(g(x,y) = c\) 的前提下 \(f\) 哪里最大?你只能在约束曲线上走,最优点处 \(f\) 的导数一般不是零——只是你被约束拦住了。
几何直觉(整个方法的灵魂)。沿约束曲线走,盯着 \(f\):
而 \(\nabla g\) 永远垂直于曲线 \(g = c\)(沿线 \(g\) 不变)。两个向量垂直于同一条曲线 → 平行:
\[\boxed{\nabla f = \lambda\, \nabla g}\]
\(\lambda\) 就是 Lagrange 乘子——它的全部含义就是”最优点处两个梯度平行”的比例系数。
操作配方。构造 Lagrangian 把约束吃进目标函数:
\[L(x, y, \lambda) = f(x,y) - \lambda\,\bigl(g(x,y) - c\bigr)\]
对所有变量(含 \(\lambda\))求偏导设零:前两个方程给出 \(\nabla f = \lambda\nabla g\),\(\partial L/\partial\lambda = 0\) 自动还原约束。带约束问题变成了无约束问题——这就是它好用的原因。
例:周长 20 的矩形,面积最大?最大化 \(f = xy\),约束 \(x + y = 10\):
\[L = xy - \lambda(x + y - 10), \qquad \frac{\partial L}{\partial x} = y - \lambda = 0, \quad \frac{\partial L}{\partial y} = x - \lambda = 0 \;\Rightarrow\; x = y = \lambda = 5\]
正方形,面积 25。
下图把这件事画成一座山:曲面是完整的 \(f = xy\),整座山一直朝 \((10,10)\) 方向涨上去。蓝色环线是等高线(地形图画法,每条线上 \(f\) 相同);\(\nabla f\) 的方向由此一眼可读——垂直穿过等高线、指向更高一环,这就是最陡上坡方向。约束线抬升到曲面上是横穿山坡的一条路(红色),约束优化 = 只许沿这条路走,找路上的最高点。关键看紫色点 \((5,5)\):\(\nabla f\) 在这里并不为零——绿色箭头垂直于等高线指向上坡,\(f\) 还能继续变大,但那个方向离开了约束线,不许走;为零的只是 \(\nabla f\) 沿路的切向分量(右图:路的高度剖面在此处坡度为零)。而在紫色点处约束线恰好与等高线 \(f = 25\) 相切——路贴着等高线走的瞬间,\(f\) 不增不减,正是极值。
图中还画了两样东西。半透明的竖墙是约束 \(g = 10\) 在三维里的形象:\(g(x,y) = x+y\) 不含 \(z\),所以 \(\{x + y = 10\}\) 在三维里是一面 \(z\) 自由伸展的墙(这里只画到山体表面为止),红路就是墙切进山体的截口;地面虚线是墙脚,即约束集本身。橙色箭头是 \(\nabla g\) 升维成 \((1,1,0)\) 后的样子:它是这面墙的唯一法向——垂直于三维里的一条曲线有无穷多个方向(一整个法平面),但垂直于一张曲面只有一个方向,所以”\(\nabla g\) 垂直于约束”用墙来想最不容易误会。地面二维版是同一句话:\(\nabla g = (1,1)\) 只有两个分量、出不了地面,在平面内垂直于虚线,方向同样唯一。
梯度是几维的? 分量数 = 输入个数。\(f(x,y) = xy\) 两个输入,所以 \(\nabla f = (y,\ x)\) 是二维向量,\(\nabla f(5,5) = (5,\ 5)\);\(z = 25\) 是输出,不占分量。图像点 \((5,5,25)\) 在三维,但 \(f\) 和它的梯度都住在二维定义域(“地图”)里。方向 \((1,1)\) 给出最陡上坡,模长给出坡度:\(|\nabla f| = \sqrt{50} \approx 7.07\),即沿最陡方向水平走 1,\(f\) 涨 7.07。
亲手验证一遍。沿 \((1,1)\) 方向走,先归一化成单位向量 \(\bigl(\tfrac{1}{\sqrt2}, \tfrac{1}{\sqrt2}\bigr)\)(向量 \((1,1)\) 长 \(\sqrt2\),不归一化 \(t\) 就不是走过的距离),走过距离 \(t\) 后位置是 \(x(t) = y(t) = 5 + \tfrac{t}{\sqrt2}\),于是:
\[f(t) = x(t)\,y(t) = \Bigl(5 + \tfrac{t}{\sqrt2}\Bigr)^{2} = 25 + \tfrac{10}{\sqrt2}\,t + \tfrac{t^2}{2} \;\Rightarrow\; f'(0) = \tfrac{10}{\sqrt2} = \sqrt{50} \approx 7.07\ \checkmark\]
同一结果也可由方向导数公式一步得到:\(\nabla f \cdot \hat u = (5,5)\cdot\bigl(\tfrac{1}{\sqrt2}, \tfrac{1}{\sqrt2}\bigr) = \tfrac{10}{\sqrt2}\)——\(\hat u\) 与 \(\nabla f\) 同向时点积最大,恰为 \(|\nabla f|\)。“梯度模长 = 最陡坡度”不是定义,是算出来的。
据此校准图例:绿箭头是贴着山坡的可视化向量,其水平投影才是 \(\nabla f\);\(\nabla g\) 画成 \((1,1,0)\) 同理(补 0 入图)。真正三维的梯度属于另一个函数——\(F(x,y,z) = z - xy\) 的 \(\nabla F = (-y, -x, 1)\),垂直于山坡曲面本身。一般规律:\(n\) 元函数的梯度是 \(n\) 维向量,垂直于 \((n-1)\) 维等值集。Lagrange 条件用的是 \(\nabla f\)。
## ── Lagrange 乘子的几何:约束线是曲面上的一条"山路" ──────────
par(mfrow = c(1, 2), mar = c(1, 1, 3.5, 0.5))
# 左图:曲面 z = xy,约束 x + y = 10 抬到曲面上是一条山路
x_s <- seq(0, 10, length.out = 41)
y_s <- seq(0, 10, length.out = 41)
z_s <- outer(x_s, y_s)
pm <- persp(x_s, y_s, z_s, zlim = c(0, 100),
theta = -63, phi = 24, expand = 0.65,
col = "gray92", border = "gray78",
xlab = "x", ylab = "y", zlab = "f = xy",
main = "Full surface f = xy;\nconstraint = a path across the hillside",
cex.main = 1.1)
# 补全边框立方体:persp 只画了靠近原点的隐藏边,把 x=10 / y=10 侧补齐
bx <- function(x0, y0, z0, x1, y1, z1)
lines(trans3d(c(x0, x1), c(y0, y1), c(z0, z1), pm),
col = "gray20", lty = 3, lwd = 1.8)
bx(10, 10, 0, 10, 10, 100) # (10,10) 角的竖边
bx(10, 0, 0, 10, 10, 0) # 底面后边 x = 10
bx( 0, 10, 0, 10, 10, 0) # 底面后边 y = 10
bx(10, 0, 100, 10, 10, 100) # 顶面后边 x = 10
bx( 0, 10, 100, 10, 10, 100) # 顶面后边 y = 10
# 竖墙:g = 10 沿 z 方向延伸(x+y=10, z 自由),墙切山的截口 = 红路
xw <- seq(0, 10, length.out = 120)
wall <- trans3d(c(xw, rev(xw)), c(10 - xw, rev(10 - xw)),
c(rep(0, 120), rev(xw * (10 - xw))), pm)
polygon(wall$x, wall$y, col = adjustcolor("slateblue", 0.28), border = NA)
# grad g = (1,1,0):墙的唯一法向(水平,垂直于墙面)
gw <- trans3d(c(7.5, 8.7), c(2.5, 3.7), c(0, 0), pm)
arrows(gw$x[1], gw$y[1], gw$x[2], gw$y[2],
col = "darkorange", lwd = 3, length = 0.12)
points(trans3d(7.5, 2.5, 0, pm), pch = 16, col = "darkorange", cex = 1.1)
text(trans3d(10.8, 3.6, 18, pm), "grad g = (1,1,0):\nthe wall's\nunique normal",
col = "darkorange3", cex = 1.0)
# 山体表面的等高线(地形图环线):grad f 处处垂直于它们
cls <- contourLines(x_s, y_s, z_s, levels = c(9, 16, 25, 36, 49, 64, 81))
for (cl in cls) lines(trans3d(cl$x, cl$y, cl$level, pm), col = "steelblue", lwd = 1.4)
x_p <- seq(0, 10, length.out = 200)
# 约束线(地面上)
lines(trans3d(x_p, 10 - x_p, 0, pm), col = "gray30", lwd = 2, lty = 2)
# 山路:约束线抬升到曲面上,高度 f = x(10-x)
lines(trans3d(x_p, 10 - x_p, x_p * (10 - x_p), pm), col = "tomato", lwd = 3.5)
# 非最优点 (2,8) 与最优点 (5,5)
points(trans3d(2, 8, 16, pm), pch = 16, col = "tomato", cex = 1.3)
points(trans3d(5, 5, 25, pm), pch = 16, col = "purple", cex = 1.7)
# 最优点垂线
lines(trans3d(c(5, 5), c(5, 5), c(0, 25), pm), col = "purple", lty = 3, lwd = 1.5)
# grad f 在 (5,5) 不为零:指向上坡(离开约束线)
gr <- trans3d(c(5, 6.6), c(5, 6.6), c(25, 6.6^2), pm)
arrows(gr$x[1], gr$y[1], gr$x[2], gr$y[2], col = "forestgreen", lwd = 3, length = 0.12)
text(trans3d(7.2, 7.2, 62, pm),
"grad f != 0: steepest ascent,\nperpendicular to contours,\nbut leaves the constraint",
col = "forestgreen", cex = 1.0)
text(trans3d(2.2, 2.2, 16, pm), "top of the path\n(5, 5), f = 25", col = "purple", cex = 1.1)
text(trans3d(1.0, 9.4, 30, pm), "still climbing", col = "tomato", cex = 1.05)
text(trans3d(2.2, 7.8, -8, pm), "x + y = 10", col = "gray30", cex = 1.05)
# 右图:沿约束线走,f 的值 = x(10-x)(山路的侧面展开)
par(mar = c(4.6, 5.0, 3.5, 1))
x_c <- seq(0, 10, length.out = 300)
plot(x_c, x_c * (10 - x_c), type = "l", lwd = 3, col = "tomato",
main = "Height along the path: f = x (10 - x)",
xlab = "x (position on the line)", ylab = "f = xy",
cex.lab = 1.35, cex.main = 1.15)
points(5, 25, pch = 16, col = "purple", cex = 1.6)
points(2, 16, pch = 16, col = "tomato", cex = 1.4)
arrows(2.3, 16.8, 3.4, 21, col = "tomato", lwd = 2, length = 0.1)
text(3.0, 12.6, "still climbing", col = "tomato", cex = 1.05)
text(5, 22.2, "top: tangential slope = 0", col = "purple", cex = 1.1)\(\lambda\) 的含义:约束的”价格”。一个漂亮的定理:最优值对约束的敏感度就是乘子本身,
\[\frac{df^*}{dc} = \lambda\]
上例 \(\lambda = 5\):周长的一半从 10 放松到 11,最大面积涨约 5(精确值 \(5.5^2 - 5^2 = 5.25\))。(\(\lambda\) 的数值绑定在约束的写法上:把 \(g\) 乘 2,\(\lambda\) 减半,\(df^*/dc\) 同步减半,定理在任何写法下自洽;量纲是 \([f]/[g]\)。)
这个”约束的价格”在各领域都有自己的名字:
| 领域 | \(\lambda\) 的名字 | 例子 |
|---|---|---|
| 优化/数学 | 对偶变量、KKT 乘子 | 线性规划对偶问题的解 |
| 分析力学 | 约束力 | 钢丝给珠子的法向支持力、绳的张力 |
| 统计物理 | 共轭强度量 | \(\beta = 1/k_BT\)(能量约束) |
| 化学 | 化学势 \(\mu\) | 粒子数约束 |
| 经济学 | 影子价格 | 预算约束 = 边际效用 |
力学那行最直观:小球被约束在斜面上,拉格朗日方程解出的 \(\lambda\) 就是斜面顶住小球的法向力——“支持力垂直于接触面”和”\(\nabla g\) 垂直于约束集”是同一句话。热力学的强度量–广延量配对表(\(T\)–\(S\)、\(p\)–\(V\)、\(\mu\)–\(N\))本质上是一张 Lagrange 乘子登记表:每个强度量都是某个守恒量约束的乘子,这也是它们天生不随系统变大的原因——乘子是比率 \(\partial f^*/\partial c\)。第 6 节会看到其中第一行:温度就是能量约束的影子价格,\(\partial S/\partial E = 1/T\)。
推广到分布:最大熵问题里”变量”不是两个数,而是每一点的密度值 \(p(x)\)——无穷多个变量,每个 \(x\) 一个。配方不变(这一步叫变分法),下一小节就做这件事。物理里这套方法无处不在,因为物理问题几乎全是”某量取极值 + 守恒律当约束”,而乘子往往就是有名字的物理量:温度(能量约束)、化学势(粒子数约束)、压强(体积约束)。
最大化 \(H = -\int p \ln p\, dx\),约束条件:
(约束 2 不是推导出来的,是问题的输入:你测到或守恒律给定了某个平均量,“知道一个平均量”写成数学就是期望值形式——\(f(x)\) 指明测的是什么量,\(\langle f\rangle\) 是测出来的那个数。对照:
\(f\) 和 \(\langle f\rangle\) 都由已知信息决定,最大熵原理只负责已知之外不多假设——所以换一个 \(f\) 就换一个分布。)
构造 Lagrangian:
\[L = -\int p \ln p\, dx - \lambda_0\!\left(\int p\, dx - 1\right) - \lambda_1\!\left(\int p\, f(x)\, dx - \langle f\rangle\right)\]
对 \(p(x)\) 求变分并令其为零:
“求变分”是什么意思? 普通微积分优化一个数,这里优化一整条函数(找哪条 \(p\) 让 \(H[p]\) 最大)——这就是变分法。实操上只需一条规则:被积函数 \(F(p)\) 对 \(p\) 当普通变量求导即可,
\[\frac{\delta}{\delta p(x)} \int F(p)\, dx = \frac{\partial F}{\partial p}\]
用到熵项:\(F = p\ln p\),\(\frac{\partial}{\partial p}(p\ln p) = \ln p + 1\)(乘积法则,\(+1\) 来自 \(p\cdot\frac{1}{p}\))。所以 \(-\int p\ln p\) 贡献 \(-\ln p - 1\),归一化项贡献 \(-\lambda_0\),期望项贡献 \(-\lambda_1 f(x)\),相加即下式。(\(+1\) 最后并进 \(Z = e^{1+\lambda_0}\),不影响解。)
\[\frac{\delta L}{\delta p} = -\ln p(x) - 1 - \lambda_0 - \lambda_1 f(x) = 0\]
解出:
\[\boxed{p(x) = \frac{1}{Z}\, e^{-\lambda_1 f(x)}}\]
其中 \(Z = e^{1+\lambda_0}\) 是归一化常数(配分函数),\(\lambda_1\) 由约束 \(\langle f\rangle\) 决定。
这就是全部的推导。 所有分布都从这一个公式出来,区别只在于 \(f(x)\) 是什么。
par(mfrow = c(2, 2), mar = c(4, 4, 3.5, 1))
# ── 1. 无约束(有界区间) → Uniform ──
x1 <- seq(-0.5, 1.5, length.out = 300)
plot(x1, dunif(x1, 0, 1), type = "l", col = "steelblue", lwd = 2.5,
main = "No constraint (bounded)\n=> Uniform",
xlab = "x", ylab = "p(x)", ylim = c(0, 1.5))
text(0.5, 1.3, "f(x) = none", font = 3, col = "gray40")
text(0.5, 0.4, "Maximum disorder\non [0, 1]", col = "gray40", cex = 0.85)
# ── 2. 固定均值(非负) → Exponential ──
x2 <- seq(0, 8, length.out = 300)
plot(x2, dexp(x2, rate = 1), type = "l", col = "steelblue", lwd = 2.5,
main = "Constraint: E[X] = mu, X >= 0\n=> Exponential(1/mu)",
xlab = "x", ylab = "p(x)", ylim = c(0, 1.1))
text(4, 0.8, expression(f(x) == x), font = 3, col = "gray40", cex = 1.1)
text(4, 0.6, expression(lambda[1] == 1/mu), col = "tomato", cex = 0.95)
# ── 3. 固定均值 + 方差 → Normal ──
x3 <- seq(-4, 4, length.out = 300)
plot(x3, dnorm(x3), type = "l", col = "steelblue", lwd = 2.5,
main = "Constraint: E[X]=mu, Var(X)=sigma^2\n=> Normal(mu, sigma^2)",
xlab = "x", ylab = "p(x)", ylim = c(0, 0.45))
text(2, 0.38, expression(f(x) == x^2), font = 3, col = "gray40", cex = 1.1)
text(2, 0.30, expression(lambda[2] == 1/(2*sigma^2)), col = "tomato", cex = 0.95)
# ── 4. 能量约束 → Boltzmann ──
x4 <- seq(0, 8, length.out = 300)
plot(NA, xlim = c(0, 8), ylim = c(0, 1.1),
main = "Constraint: E[Energy] = <E>\n=> Boltzmann = Exp(beta)",
xlab = "Energy E", ylab = "P(E)")
for (i in 1:3) {
beta <- c(2, 1, 0.5)[i]
lines(x4, dexp(x4, rate = beta), col = cols[i], lwd = 2.5)
}
legend("topright", paste("beta =", c(2, 1, 0.5), " (kT =", c(0.5, 1, 2), ")"),
col = cols[1:3], lwd = 2.5, bty = "n", cex = 0.85)
text(4, 0.8, "f(x) = E", font = 3, col = "gray40", cex = 1.1)
text(4, 0.6, expression(lambda[1] == beta~"="~1/(k[B]*T)), col = "tomato", cex = 0.95)| 约束 | \(f(x)\) | \(\lambda\) | 最大熵分布 \(p(x)\) |
|---|---|---|---|
| 无约束(有界) | — | — | Uniform:\(\dfrac{1}{b-a}\) |
| \(E[X] = \mu\),\(X \geq 0\) | \(x\) | \(1/\mu\) | Exponential:\(\lambda e^{-\lambda x}\) |
| \(E[X] = \mu\),\(\text{Var}(X) = \sigma^2\) | \(x^2\) | \(1/(2\sigma^2)\) | Normal:\(\dfrac{1}{\sqrt{2\pi}\,\sigma}\,e^{-(x-\mu)^2/(2\sigma^2)}\) |
| \(E[\text{Energy}] = \langle E \rangle\) | \(E\) | \(\beta = 1/k_BT\) | Boltzmann:\(\beta\, e^{-\beta E}\) |
所有这些分布来自同一个方程的不同解。 区别只在于你”知道什么”(约束)。
约束:\(X \geq 0\),\(E[X] = \mu\)。代入通解:
\[p(x) = \frac{1}{Z} e^{-\lambda x} = \lambda e^{-\lambda x}, \quad \lambda = 1/\mu\]
归一化常数 \(Z = 1/\lambda\),微分熵:
\[H[\text{Exp}(\lambda)] = 1 + \ln\mu\]
在均值 \(= 2\) 的所有非负分布中比较熵:
# 在 [0, max] 网格上数值计算微分熵
x_pos <- seq(0.001, 20, length.out = 8000)
dx_p <- diff(x_pos)[1]
h_pos <- function(p_vals) {
p_vals <- pmax(p_vals, 1e-300)
p_norm <- p_vals / (sum(p_vals) * dx_p)
-sum(p_norm * log(p_norm)) * dx_p
}
mu <- 2 # 固定均值
# 均值 = 2 的各种分布
dists <- list(
"Exp(1/2)" = dexp(x_pos, rate = 1/mu),
"Gamma(2, 1)" = dgamma(x_pos, shape = 2, rate = 2/mu),
"Gamma(5, 2.5)" = dgamma(x_pos, shape = 5, rate = 5/mu),
"Gamma(20, 10)" = dgamma(x_pos, shape = 20, rate = 20/mu),
"Weibull(k=2)" = dweibull(x_pos, shape = 2,
scale = mu / gamma(1 + 1/2)),
"LogNormal" = dlnorm(x_pos, meanlog = log(mu) - 0.5, sdlog = 1)
)
entropies <- sapply(dists, h_pos)
h_theory <- 1 + log(mu) # Exp(1/mu) 的解析熵
par(mfrow = c(1, 2), mar = c(4, 7, 3.5, 1))
# 左图:密度对比
plot(NA, xlim = c(0, 10), ylim = c(0, 0.55),
main = "Distributions with same mean = 2",
xlab = "x", ylab = "Density")
dist_cols <- c("tomato", "steelblue", "forestgreen", "orange", "purple", "brown")
for (i in seq_along(dists)) {
lines(x_pos, dists[[i]], col = dist_cols[i], lwd = 2,
lty = ifelse(i == 1, 1, 2))
}
legend("topright", names(dists), col = dist_cols, lwd = 2,
lty = c(1, rep(2, 5)), bty = "n", cex = 0.75)
# 右图:熵的比较(横向条形图)
barplot(rev(entropies), horiz = TRUE, col = rev(dist_cols),
border = "white", las = 1, xlim = c(0, max(entropies) * 1.15),
main = "Entropy comparison (mean = 2)",
xlab = "Differential entropy H")
abline(v = h_theory, col = "tomato", lwd = 2, lty = 2)
text(h_theory, 7.5, paste(" Exp theoretical =", round(h_theory, 3)),
col = "tomato", adj = 0, cex = 0.85)Exp(1/2) 的红色条最长——在均值 \(= 2\) 的所有非负分布中,指数分布的熵确实最大。
Gamma(k) 随着 \(k\) 增大(形状越像正态),熵越来越低,因为分布越来越”确定”。
指数分布还有一个独立于最大熵的特殊性质:唯一满足无记忆性的连续分布。
\[P(X > s + t \mid X > s) = P(X > t) \quad \forall\, s, t > 0\]
X_mem <- rexp(N, rate = 1)
s <- 1.5
residual <- X_mem[X_mem > s] - s
par(mfrow = c(1, 3), mar = c(4, 4, 3.5, 1))
hist(X_mem, breaks = 100, freq = FALSE, col = "steelblue", border = "white",
main = "Original Exp(1)", xlab = "x", xlim = c(0, 8), ylim = c(0, 1.05))
curve(dexp(x, 1), add = TRUE, col = "tomato", lwd = 2)
hist(residual, breaks = 100, freq = FALSE, col = "steelblue", border = "white",
main = paste0("Residual (given X > ", s, ")"),
xlab = "residual", xlim = c(0, 8), ylim = c(0, 1.05))
curve(dexp(x, 1), add = TRUE, col = "tomato", lwd = 2)
legend("topright", "Same Exp(1)!", col = "tomato", lwd = 2, bty = "n")
t_vals <- seq(0, 5, by = 0.5)
p_original <- pexp(t_vals, lower.tail = FALSE)
p_condition <- sapply(t_vals, function(t) mean(residual > t))
plot(t_vals, p_original, type = "l", col = "steelblue", lwd = 2,
main = "Memoryless property verified",
xlab = "t", ylab = "P(> t)")
points(t_vals, p_condition, col = "tomato", pch = 16, cex = 1.2)
legend("topright",
c("P(X > t) [unconditional]",
paste0("P(X > t | X > ", s, ")")),
col = c("steelblue", "tomato"), lwd = c(2, NA), pch = c(NA, 16), bty = "n")数学本质:\(P(X > t) = e^{-\lambda t}\)——指数函数的”每增加一点、概率按固定比例下降”直接蕴含无记忆性。
等温大气公式。一个空气分子在高度 \(h\) 处的重力势能是 \(E = mgh\)——能量随高度线性。这正是”线性约束 → 指数”的实物版,Boltzmann 因子直接给出:
\[P(h) \propto e^{-mgh/k_BT}\]
标高 \(H = k_BT/mg \approx 8.5\) km(地球大气,\(T \approx 288\) K):每升高 8.5 km,气压掉到 \(1/e\)。这也是第 6 节玻尔兹曼分布的预告——同一个公式,那里换成能级。
放射性衰变。原子核不老化:一个已经存在了一万年的 \(^{14}\)C 核,接下来一秒衰变的概率和刚生成的核完全一样——这就是上一小节的无记忆性,所以寿命只能服从指数分布。半衰期 \(t_{1/2} = \ln 2/\lambda\) 等间距地把存活比例砍半:\(1/2, 1/4, 1/8, \dots\)。化学里的一级反应动力学(\(-d[A]/dt = k[A]\))和荧光寿命衰减是同一个数学。
## ── 物理实例:等温大气 + 放射性衰变 ──────────────────────────
par(mfrow = c(1, 2), mar = c(4.6, 5.0, 3.5, 1))
# 左图:等温大气公式 P(h) = exp(-h/H),H = kT/mg ≈ 8.5 km
h_seq <- seq(0, 35, length.out = 400)
H_scale <- 8.5 # km,地球大气标高
plot(h_seq, exp(-h_seq / H_scale), type = "l", lwd = 3, col = "steelblue",
main = "Barometric formula: P(h) = exp(-mgh / kT)",
xlab = "Altitude h (km)", ylab = "Pressure relative to sea level",
cex.lab = 1.35, cex.main = 1.1)
landmarks <- data.frame(h = c(8.85, 11, 30))
points(landmarks$h, exp(-landmarks$h / H_scale), pch = 16, col = "tomato", cex = 1.4)
text(9.3, 0.47, "Everest 8.8 km: 35%", col = "tomato", adj = 0, cex = 1.05)
text(11.5, 0.20, "cruise 11 km: 27%", col = "tomato", adj = 0, cex = 1.05)
text(29.5, 0.12, "stratosphere 30 km: 3%", col = "tomato", adj = 1, cex = 1.05)
text(22, 0.75, "scale height\nH = kT/mg = 8.5 km", col = "gray40", cex = 1.1)
# 右图:放射性衰变,存活曲线 + 等间距半衰期
lam <- 1 # 衰变常数
t_half <- log(2) / lam
lifetimes <- rexp(N, rate = lam) # 模拟 N 个原子核的寿命
t_seq <- seq(0, 5, length.out = 300)
surv_sim <- sapply(t_seq, function(t) mean(lifetimes > t))
plot(t_seq, surv_sim, type = "l", lwd = 3, col = "steelblue",
main = "Radioactive decay: survival = exp(-t / tau)",
xlab = "Time t", ylab = "Fraction of nuclei surviving",
cex.lab = 1.35, cex.main = 1.1)
curve(exp(-lam * x), add = TRUE, col = "tomato", lwd = 2, lty = 2)
halves <- t_half * (1:4)
points(halves, 0.5^(1:4), pch = 16, col = "forestgreen", cex = 1.4)
segments(halves, 0, halves, 0.5^(1:4), col = "forestgreen", lty = 3)
text(halves, 0.5^(1:4) + 0.06,
c("1/2", "1/4", "1/8", "1/16"), col = "forestgreen", cex = 1.15)
legend("topright",
c("simulated 100k nuclei", "exp(-t/tau) theory",
paste0("half-life = ln2/lambda = ", round(t_half, 2))),
col = c("steelblue", "tomato", "forestgreen"),
lwd = c(3, 2, NA), lty = c(1, 2, NA), pch = c(NA, NA, 16),
bty = "n", cex = 1.0)约束:\(E[X] = \mu\),\(\text{Var}(X) = \sigma^2\)。需要两个约束函数 \(f_1(x) = x\) 和 \(f_2(x) = x^2\),代入通解:
\[p(x) = \frac{1}{Z}\, e^{-\lambda_1 x - \lambda_2 x^2}\]
配方后:
\[p(x) = \frac{1}{\sqrt{2\pi\sigma^2}}\, e^{-(x - \mu)^2 / (2\sigma^2)}\]
其中 \(\lambda_2 = \frac{1}{2\sigma^2}\),\(\lambda_1 = -\frac{\mu}{\sigma^2}\)。微分熵:
\[H[\text{Normal}(\mu, \sigma^2)] = \frac{1}{2}\ln(2\pi e\, \sigma^2)\]
在 \(\mu = 0\),\(\sigma^2 = 1\) 的所有分布中比较熵:
x_full <- seq(-8, 8, length.out = 8000)
dx_f <- diff(x_full)[1]
h_full <- function(p_vals) {
p_vals <- pmax(p_vals, 1e-300)
p_norm <- p_vals / (sum(p_vals) * dx_f)
-sum(p_norm * log(p_norm)) * dx_f
}
# 均值 = 0,方差 = 1 的各种分布
sigma_target <- 1
# Laplace: Var = 2b^2, so b = 1/sqrt(2)
b_lap <- 1 / sqrt(2)
# Logistic: Var = pi^2 * s^2 / 3, so s = sqrt(3)/pi
s_log <- sqrt(3) / pi
# Uniform: Var = (2a)^2/12, so a = sqrt(3)
a_unif <- sqrt(3)
dists_n <- list(
"Normal(0,1)" = dnorm(x_full, 0, sigma_target),
"Laplace(0, b)" = 0.5/b_lap * exp(-abs(x_full)/b_lap),
"Logistic(0, s)" = dlogis(x_full, 0, s_log),
"Uniform[-a, a]" = dunif(x_full, -a_unif, a_unif),
"t(df=5) scaled" = dt(x_full * sqrt(5/3), df = 5) * sqrt(5/3)
)
ent_n <- sapply(dists_n, h_full)
h_theory_n <- 0.5 * log(2 * pi * exp(1))
par(mfrow = c(1, 2), mar = c(4, 7, 3.5, 1))
plot(NA, xlim = c(-4, 4), ylim = c(0, 0.45),
main = "Distributions with mean=0, var=1",
xlab = "x", ylab = "Density")
dist_cols_n <- c("tomato", "steelblue", "forestgreen", "orange", "purple")
for (i in seq_along(dists_n)) {
lines(x_full, dists_n[[i]], col = dist_cols_n[i], lwd = 2,
lty = ifelse(i == 1, 1, 2))
}
legend("topright", names(dists_n), col = dist_cols_n, lwd = 2,
lty = c(1, rep(2, 4)), bty = "n", cex = 0.75)
barplot(rev(ent_n), horiz = TRUE, col = rev(dist_cols_n),
border = "white", las = 1, xlim = c(0, max(ent_n) * 1.1),
main = "Entropy comparison (mean=0, var=1)",
xlab = "Differential entropy H")
abline(v = h_theory_n, col = "tomato", lwd = 2, lty = 2)
text(h_theory_n, 6.3, paste(" Normal theoretical =", round(h_theory_n, 3)),
col = "tomato", adj = 0, cex = 0.85)Normal 的红色条最长——在均值和方差都固定时,正态分布的熵确实最大。
Laplace 和 Logistic 尽管形状接近,但尾部行为不同——要么太重(Laplace),要么太轻(Uniform),都额外注入了假设。
中心极限定理说的是:无论原始分布是什么,大量独立样本的均值趋向正态。
n_sim <- 5000
par(mfrow = c(2, 3), mar = c(4, 3, 3, 1))
for (gen_info in list(
list(gen = function(n) runif(n, -1, 1), name = "Uniform(-1, 1)"),
list(gen = function(n) rexp(n) - 1, name = "Exp(1) - 1 [right skew]"),
list(gen = function(n) rbinom(n,1,0.1) - 0.1, name = "Bernoulli(0.1) [extreme skew]")
)) {
for (n_avg in c(5, 50)) {
mat <- matrix(gen_info$gen(n_sim * n_avg), nrow = n_sim, ncol = n_avg)
z <- scale(rowMeans(mat))
hist(z, breaks = 55, freq = FALSE, col = "steelblue", border = "white",
main = paste0(gen_info$name, " (n=", n_avg, ")"),
xlab = "Standardized mean", xlim = c(-4, 4), ylim = c(0, 0.47),
cex.main = 0.85)
curve(dnorm(x), add = TRUE, col = "tomato", lwd = 2)
}
}CLT 和最大熵是到达正态分布的两条独立道路:
它们的结论一致,但逻辑完全独立。CLT 不需要熵的概念,最大熵不需要求和的概念。
化学键振动。把化学键近似成弹簧,偏离平衡位置 \(x\) 的势能是二次的:\(E = \frac{1}{2}\kappa x^2\)。泡在温度 \(T\) 的热浴里,Boltzmann 因子作用到二次能量上:
\[p(x) \propto e^{-\kappa x^2 / 2k_BT} = \text{Normal}\!\left(0,\ \sigma^2 = k_BT/\kappa\right)\]
“二次约束 → 正态”的分子级实例:原子在平衡键长附近做高斯分布的热涨落,温度越高分布越宽(\(\sigma \propto \sqrt{T}\)),振动光谱里直接可测。气体分子的速度分量是同一个逻辑(动能 \(\frac{1}{2}mv_x^2\) 也是二次的),见第 6 节。
布朗扩散。墨水滴进水里,每个色素粒子的位移是无数次分子碰撞冲量的累加——这正是上一小节 CLT 的物理化身(Einstein 1905)。\(t\) 时刻的位置分布是方差 \(\propto t\) 的高斯,剖面随 \(\sqrt{t}\) 展宽。
## ── 物理实例:化学键振动 + 布朗扩散 ──────────────────────────
par(mfrow = c(1, 2), mar = c(4.6, 5.0, 3.5, 1))
# 左图:谐振子势 E = kappa x^2 / 2 泡在热浴里 → 位置分布是正态
kappa <- 1
x_b <- seq(-3.5, 3.5, length.out = 400)
E_pot <- 0.5 * kappa * x_b^2
plot(x_b, E_pot / max(E_pot) * 0.9, type = "l", lwd = 2.5, col = "gray50",
ylim = c(0, 1.0),
main = "Bond vibration: p(x) ~ exp(-kappa x^2 / 2kT)",
xlab = "Displacement x from equilibrium", ylab = "(rescaled)",
cex.lab = 1.35, cex.main = 1.1)
kT_b <- c(0.3, 1.5)
cols_b <- c("steelblue", "tomato")
for (i in seq_along(kT_b)) {
sd_i <- sqrt(kT_b[i] / kappa)
lines(x_b, dnorm(x_b, 0, sd_i) / dnorm(0, 0, sqrt(kT_b[1]/kappa)) * 0.9,
col = cols_b[i], lwd = 3)
}
legend("topright",
c("potential E = kappa x^2/2",
paste0("p(x) at kT = ", kT_b, " (sd = ", round(sqrt(kT_b/kappa), 2), ")")),
col = c("gray50", cols_b), lwd = c(2.5, 3, 3), bty = "n", cex = 1.0)
# 右图:布朗扩散——随机行走的位置分布是变宽的高斯
n_part <- 20000
t_snap <- c(25, 100, 400)
cols_d <- c("steelblue", "purple", "tomato")
# 每个粒子 = 许多次独立碰撞冲量的累加(每步 ~ N(0,1))
pos_at <- lapply(t_snap, function(t_i)
rowSums(matrix(rnorm(n_part * t_i), nrow = n_part)))
plot(NA, xlim = c(-70, 70), ylim = c(0, 0.085),
main = "Diffusion: Gaussian spreading, sd ~ sqrt(t)",
xlab = "Position", ylab = "Density",
cex.lab = 1.35, cex.main = 1.1)
for (i in seq_along(t_snap)) {
d_i <- density(pos_at[[i]])
lines(d_i, col = cols_d[i], lwd = 3)
curve(dnorm(x, 0, sqrt(t_snap[i])), add = TRUE,
col = cols_d[i], lwd = 1.5, lty = 2)
}
legend("topright",
c(paste0("t = ", t_snap, " (sd = ", sqrt(t_snap), ")"),
"N(0, t) theory (dashed)"),
col = c(cols_d, "gray40"), lwd = c(3, 3, 3, 1.5),
lty = c(1, 1, 1, 2), bty = "n", cex = 1.0)热力学系统在温度 \(T\) 下:
\[\boxed{P(\text{state}) \propto e^{-E / k_B T}}\]
这个公式常被当作一个”物理定律”来记忆。但它的推导就是最大熵:
\(\lambda\) 就是 Lagrange 乘子。物理学家给它取了个名字:\(\beta = 1/(k_BT)\)。
也就是说:温度不是一个独立的物理量,而是最大熵推导中 Lagrange 乘子的倒数。
par(mfrow = c(1, 2), mar = c(4, 4, 3.5, 1))
E_seq <- seq(0, 10, length.out = 400)
kT_vals <- c(0.5, 1, 2, 4)
cols <- c("steelblue", "tomato", "forestgreen", "purple")
# 左图:不同温度的能量分布
plot(NA, xlim = c(0, 10), ylim = c(0, 2.1),
main = "Boltzmann: P(E) = beta * exp(-beta * E)\nbeta = Lagrange multiplier = 1/kT",
xlab = "Energy E", ylab = "P(E)")
for (i in seq_along(kT_vals)) {
lines(E_seq, dexp(E_seq, rate = 1/kT_vals[i]), col = cols[i], lwd = 2.5)
}
legend("topright", paste("kT =", kT_vals, " (beta =", 1/kT_vals, ")"),
col = cols, lwd = 2.5, bty = "n", cex = 0.85)
# 右图:温度 vs 熵
# H[Exp(beta)] = 1 + ln(1/beta) = 1 + ln(kT)
kT_range <- seq(0.2, 5, length.out = 200)
H_boltz <- 1 + log(kT_range)
plot(kT_range, H_boltz, type = "l", col = "tomato", lwd = 2.5,
main = "Temperature controls entropy\nH = 1 + ln(kT)",
xlab = "kT (temperature)", ylab = "Entropy H")
abline(h = 0, col = "gray70", lty = 3)
text(3.5, 0.5, "Higher T = higher entropy\n= more \"spread out\"",
col = "gray40", cex = 0.9)“\(\lambda\) 就是 \(1/k_BT\)”不只是换个记号——它是热力学温度定义和最大熵乘子的严格等同。对最大熵解 \(p(E) = \frac{1}{Z}e^{-\lambda E}\) 直接算熵:
\[H = -\int p \ln p = -\int p\,\bigl(-\lambda E - \ln Z\bigr) = \lambda \langle E\rangle + \ln Z\]
对 \(\langle E\rangle\) 求导(注意 \(Z\) 通过 \(\lambda\) 依赖 \(\langle E\rangle\),用 \(\frac{d\ln Z}{d\lambda} = -\langle E\rangle\)):
\[\frac{dH}{d\langle E\rangle} = \lambda + \underbrace{\left(\langle E\rangle + \frac{d\ln Z}{d\lambda}\right)}_{=\,0}\frac{d\lambda}{d\langle E\rangle} = \lambda\]
而热力学里温度的定义(Clausius,\(dS = \delta Q / T\))正是 \(\dfrac{1}{T} = \dfrac{\partial S}{\partial E}\)。两式对照(\(S = k_B H\)):
\[\lambda = \frac{1}{k_B T}\]
用本节的指数分布验证:\(H = 1 + \ln\langle E\rangle\),\(\frac{dH}{d\langle E\rangle} = \frac{1}{\langle E\rangle} = \frac{1}{k_BT}\)。✓
物理直觉:温度衡量”每注入一单位能量,熵涨多少”——冷系统涨得多(\(1/T\) 大),热系统涨得少。两个系统接触时,能量从热流向冷,是因为同一份能量在冷系统那边换到的熵更多,总熵增大——热传导的方向也是最大熵推出来的,不需要额外假设。
当能量态密度均匀(如量子谐振子的等间距能级,或二维气体的动能),归一化后:
\[P(E) = \beta\, e^{-\beta E} = \text{Exponential}(\beta = 1/k_BT)\]
这就是指数分布。Boltzmann 分布和指数分布不是”类似”——它们是同一个东西。
kT <- 1
par(mfrow = c(1, 2), mar = c(4, 4, 3.5, 1))
E_samples <- -kT * log(1 - runif(N))
hist(E_samples, breaks = 80, freq = FALSE, col = "steelblue", border = "white",
main = "Sampling Boltzmann via -kT * log(1 - U)",
xlab = "Energy E")
curve(dexp(x, rate = 1/kT), add = TRUE, col = "tomato", lwd = 2)
legend("topright", "Exp(1/kT) theory", col = "tomato", lwd = 2, bty = "n")
# Arrhenius:反应速率是 Boltzmann 尾巴
Ea_vals <- c(0.5, 1, 2, 3)
kT_range2 <- seq(0.3, 5, length.out = 200)
plot(NA, xlim = c(0, 5), ylim = c(0, 1.05),
main = "Arrhenius: k ~ exp(-Ea/kT)\nReaction rate = Boltzmann tail",
xlab = "kT (temperature)", ylab = "exp(-Ea / kT)")
arr_cols <- c("steelblue","tomato","forestgreen","purple")
for (i in seq_along(Ea_vals)) {
lines(kT_range2, exp(-Ea_vals[i] / kT_range2), col = arr_cols[i], lwd = 2)
}
legend("bottomright", paste("Ea =", Ea_vals), col = arr_cols, lwd = 2, bty = "n")化学反应的 Arrhenius 公式 \(k = A\, e^{-E_a/(k_BT)}\) 就是 Boltzmann 分布的尾部概率——能越过能垒 \(E_a\) 的分子比例。
三维气体分子的动能是速度的二次函数:\(E_x = \frac{1}{2}mv_x^2\)
将 Boltzmann 因子作用到动能上:
\[P(v_x) \propto e^{-mv_x^2 / (2k_BT)} = e^{-v_x^2 / (2\sigma^2)}, \quad \sigma = \sqrt{k_BT/m}\]
这正是正态分布。对比最大熵视角:\(f(x) = x^2\),Lagrange 乘子 \(\lambda_2 = m/(2k_BT) = 1/(2\sigma^2)\)——物理里的 \(m/(2k_BT)\) 就是最大熵推导里的 \(\lambda_2\)。
sigma <- 1
vx <- rnorm(N, 0, sigma)
vy <- rnorm(N, 0, sigma)
vz <- rnorm(N, 0, sigma)
par(mfrow = c(1, 3), mar = c(4, 4, 3.5, 1))
for (comp in list(list(v = vx, name = "vx"),
list(v = vy, name = "vy"),
list(v = vz, name = "vz"))) {
hist(comp$v, breaks = 80, freq = FALSE, col = "steelblue", border = "white",
main = paste("Velocity", comp$name, "~ N(0, kT/m)"),
xlab = comp$name, xlim = c(-4, 4))
curve(dnorm(x, 0, sigma), add = TRUE, col = "tomato", lwd = 2)
}速率 \(v = \sqrt{v_x^2 + v_y^2 + v_z^2}\),由三个独立正态分量合成:
\[f(v) = \sqrt{\frac{2}{\pi}} \frac{v^2}{\sigma^3} e^{-v^2/(2\sigma^2)}\]
speed <- sqrt(vx^2 + vy^2 + vz^2)
mb_pdf <- function(v, sigma) sqrt(2/pi) * v^2 / sigma^3 * exp(-v^2 / (2*sigma^2))
v_peak <- sqrt(2) * sigma
v_mean <- 2/sqrt(pi) * sigma
v_rms <- sqrt(3) * sigma
par(mfrow = c(1, 2), mar = c(4, 4, 3.5, 1))
v_seq <- seq(0, 5.5, length.out = 400)
hist(speed, breaks = 80, freq = FALSE, col = "steelblue", border = "white",
main = "Maxwell-Boltzmann speed distribution",
xlab = "Speed v", xlim = c(0, 5.5))
lines(v_seq, mb_pdf(v_seq, sigma), col = "tomato", lwd = 2.5)
abline(v = v_peak, col = "orange", lty = 2, lwd = 1.8)
abline(v = v_mean, col = "forestgreen", lty = 2, lwd = 1.8)
abline(v = v_rms, col = "purple", lty = 2, lwd = 1.8)
legend("topright",
c("MB theory",
paste0("Mode = sqrt(2)*sigma = ", round(v_peak, 2)),
paste0("Mean = 2*sigma/sqrt(pi) = ", round(v_mean, 2)),
paste0("RMS = sqrt(3)*sigma = ", round(v_rms, 2))),
col = c("tomato","orange","forestgreen","purple"),
lwd = c(2.5,1.8,1.8,1.8), lty = c(1,2,2,2), bty = "n", cex = 0.82)
plot(NA, xlim = c(0, 8), ylim = c(0, 0.85),
main = "Effect of temperature on MB distribution",
xlab = "Speed v", ylab = "Density")
kTm_vals <- c(0.5, 1, 2, 4)
for (i in seq_along(kTm_vals)) {
lines(v_seq, mb_pdf(v_seq, sqrt(kTm_vals[i])), col = cols[i], lwd = 2.5)
}
legend("topright", paste("kT/m =", kTm_vals), col = cols, lwd = 2.5, bty = "n")回到第 1 节的通解:
\[p(x) \propto e^{-\lambda_1 f_1(x) - \lambda_2 f_2(x) - \cdots}\]
这在统计学中称为指数族(exponential family)。自然界反复出现这几个分布,不是因为它们”好看”,而是因为它们是在有限信息下最不偏不倚的选择。
par(mar = c(1, 1, 2, 1))
plot(NA, xlim = c(0, 12), ylim = c(0, 8.5), axes = FALSE, bty = "n",
xlab = "", ylab = "",
main = "Unified view: MaxEnt + constraint => distribution")
draw_box <- function(x, y, label, col, w = 3.5, h = 0.7) {
rect(x-w/2, y-h/2, x+w/2, y+h/2, col = col, border = "white", lwd = 2)
text(x, y, label, col = "white", font = 2, cex = 0.8)
}
draw_arr <- function(x0, y0, x1, y1, label = "") {
arrows(x0, y0, x1, y1, length = 0.12, lwd = 1.8, col = "gray40")
mx <- (x0+x1)/2; my <- (y0+y1)/2
if (nchar(label) > 0) text(mx + 0.15, my, label, cex = 0.7, col = "gray30", font = 3)
}
# Top: MaxEnt principle
draw_box(6, 8, "Maximize H = -int p ln p dx\nsubject to constraints",
"gray25", w = 7.5, h = 0.9)
# General solution
draw_box(6, 6.3, "General solution: p(x) ~ exp( -lambda * f(x) )",
"gray45", w = 8, h = 0.7)
draw_arr(6, 7.55, 6, 6.7, "Lagrange multipliers")
# Three branches
draw_box(2, 4.3, "f(x) = x\nlambda = 1/mu", "steelblue")
draw_box(6, 4.3, "f(x) = x^2\nlambda = 1/(2*sigma^2)", "tomato")
draw_box(10, 4.3, "f(x) = Energy\nlambda = beta = 1/kT", "forestgreen")
draw_arr(3.5, 5.95, 2, 4.65)
draw_arr(6, 5.95, 6, 4.65)
draw_arr(8.5, 5.95, 10, 4.65)
# Results
draw_box(2, 2.5, "Exponential(1/mu)", "steelblue")
draw_box(6, 2.5, "Normal(mu, sigma^2)", "tomato")
draw_box(10, 2.5, "Boltzmann = Exp(beta)", "forestgreen")
draw_arr(2, 3.95, 2, 2.85)
draw_arr(6, 3.95, 6, 2.85)
draw_arr(10, 3.95, 10, 2.85)
# Physical examples
text(2, 1.6, "Waiting times\nDecay processes\nPoisson process",
cex = 0.7, col = "gray40")
text(6, 1.6, "Measurement error\nCLT (sum of many)\nDiffusion",
cex = 0.7, col = "gray40")
text(10, 1.6, "Energy at temperature T\nArrhenius rates\nVelocity components (quadratic)",
cex = 0.7, col = "gray40")
# Connection between Boltzmann → Exp and Normal
draw_arr(10, 2.15, 2.8, 2.15)
text(6.4, 1.95, "linear E => Exp; quadratic E => Normal",
cex = 0.65, col = "gray50", font = 3)不是因为自然”选择”了这些函数形式,而是因为:
在约束条件下,微观实现方式最多的宏观状态就是最大熵状态。
自然界不追求最低能量,也不追求最高能量,而是追求最容易实现的状态——即微观排列数最多的分布。指数型衰减 \(e^{-\lambda f(x)}\) 之所以反复出现,是因为它是约束优化问题的通解。
一条主线贯穿全篇:优化一个量 + 施加若干约束 → 唯一确定的结构。
| 约束 \(f(x)\) | 得到的分布 | 乘子的物理身份 | 实例 |
|---|---|---|---|
| 无(仅有界) | 均匀分布 | — | — |
| \(x\)(均值,非负) | 指数分布 | — | 等温大气、放射性衰变 |
| \(x,\ x^2\)(均值+方差) | 正态分布 | — | 化学键振动、布朗扩散 |
| \(E(x)\)(能量) | 玻尔兹曼分布 | \(\lambda = 1/k_BT\)(温度) | Maxwell 速率、Arrhenius |
三个”独立”的分布因此是同一个方程在不同约束下的三张脸。而这套”优化 + 约束”的模板远不止于此:Lagrange 乘子在力学里是约束力、在热力学里是温度/化学势/压强、在优化里是对偶变量——它是连接数学、物理、化学的一根共同轴。
一句话带走:指数族不是自然界的审美偏好,而是”在有限信息下最诚实”这件事的数学必然。
最后更新:2026-07-08 11:00 EDT