函数逼近¶
函数逼近用足够接近原函数的简单函数来替代复杂函数。本章涵盖线性化、泰勒级数、多项式逼近、傅里叶级数以及万能逼近定理——这是神经网络能够学习任意映射的理论基础。
-
我们遇到的许多函数都过于复杂,难以直接处理。在纸上计算 \(e^{0.1}\)、预测卫星轨迹等等,都涉及没有简单闭式答案的函数。
-
函数逼近用在我们所关心的区域上“足够接近”的简单函数来替代复杂函数。
-
最自然的逼近是多项式。多项式只是 \(x\) 的幂次与系数的和,它们易于求值、求导和积分。
-
但为什么多项式作为逼近工具效果这么好?考虑 \(x\) 的各次幂所起的作用。
- 常数项 \(a_0\) 设定基值。
- \(a_1 x\) 项增加斜率。
- \(a_2 x^2\) 项增加曲率。
- 每个更高的幂次捕捉函数形状的更精细细节。
-
通过选择合适的系数,我们可以逐一匹配函数在某一点的值、斜率、曲率以及更高阶的行为。
-
只要有足够的项,多项式几乎可以模仿任何光滑函数。
-
问题变成:如何找到合适的系数?
-
线性化是最简单的逼近。在 \(x = a\) 附近,我们用该点的切线代替函数:
-
这是一阶泰勒逼近。它说:从已知值 \(f(a)\) 出发,然后加上斜率乘以到 \(a\) 的距离。
-
例如,在 \(x = 0\) 处线性化 \(\sin(x)\):\(f(0) = 0\),\(f'(0) = \cos(0) = 1\),所以 \(L(x) = x\)。在零附近,\(\sin(x) \approx x\)。试试看:\(\sin(0.1) = 0.0998\ldots \approx 0.1\)。
-
但线性化只在非常接近 \(a\) 时有效。离得更远,逼近就会失效。为了做得更好,我们需要包含更高阶的项。
-
泰勒级数将函数表示为一个无穷多项式之和,每个项捕捉函数在一点 \(a\) 附近行为的更精细细节:
-
每个后续项都会添加一个修正。第一项匹配函数值,第二项匹配斜率,第三项匹配曲率,依此类推。我们包含的项越多,逼近准确的范围就越大。
-
分母中的 \(n!\) 不是任意的。当你对 \((x - a)^n\) 恰好求 \(n\) 次导时,得到 \(n!\)。阶乘将其抵消,确保泰勒多项式的 \(n\) 阶导数等于原函数在 \(x = a\) 处的 \(n\) 阶导数。
-
麦克劳林级数就是以 \(a = 0\) 为中心的泰勒级数:
- 一些著名的麦克劳林级数:
-
注意 \(\sin x\) 只有奇次幂(它是奇函数),\(\cos x\) 只有偶次幂(它是偶函数)。交替的符号使得逼近在真实值上下振荡,从两侧收敛。
-
让我们用四项逼近 \(e^{0.5}\):\(1 + 0.5 + \frac{0.25}{2} + \frac{0.125}{6} = 1 + 0.5 + 0.125 + 0.02083 \approx 1.6458\)。真值为 \(1.6487\ldots\),四项已经给出三位正确小数。
-
并非所有泰勒级数处处收敛。收敛半径告诉我们从中心 \(a\) 出发多远时级数给出有效结果。在半径之内,通过增加项数可以使多项式逼近达到任意精度。在半径之外,级数发散。
-
幂级数的一般形式是:\(\sum_{n=0}^{\infty} a_n (x - c)^n\)。泰勒级数是系数由导数确定的幂级数。其他幂级数可能由其他规则定义。比值判别法确定收敛性:计算 \(\lim_{n \to \infty} \left|\frac{a_{n+1}}{a_n}\right|\)。如果这个极限是 \(L\),则收敛半径为 \(R = 1/L\)。
-
当我们在 \(n\) 项后截断泰勒级数时,会产生误差。拉格朗日余项界定了这个误差:
-
这里 \(c\) 是位于 \(a\) 和 \(x\) 之间的某个未知点。我们无法确切知道 \(c\),但通常可以界定 \(|f^{(n+1)}(c)|\) 从而得到最坏情况下的误差估计。分母中的 \((n+1)!\) 增长极快,因此随着项数增加(在收敛半径内的函数),误差会迅速缩小。
-
对于多变量函数,泰勒展开包含混合偏导数。\(f(\mathbf{x})\) 在点 \(\mathbf{a}\) 附近的二阶逼近为:
-
第一项是函数值,第二项使用梯度(如我们在多元微积分中所见,是一个向量),第三项使用海森矩阵(捕捉曲率)。这把我们矩阵章节的内容直接与微积分联系了起来:海森矩阵是一个二阶导数矩阵,描述了函数曲面的形状。
-
这个多元二阶逼近是牛顿法和其他二阶优化技术的基础,我们将在下一份文件中看到它们。
-
除了多项式,还有其他值得了解的逼近方法:
- 样条插值:不是使用一个高次多项式,而是使用许多低次多项式平滑地拼接在一起。这避免了高次多项式可能产生的剧烈振荡。
- 傅里叶级数:用正弦和余弦的和来逼近周期函数。在信号处理和音频中至关重要。
- 神经网络:万能逼近器。只要有足够多的神经元,它们可以以任意精度逼近任何连续函数。这是深度学习的理论依据。
-
如果一个函数具有使逼近可靠的特性,则称其为“良态”的:连续性(没有跳跃)、可微性(没有尖点)、光滑性(各阶导数存在)和有界性(输出保持有限)。
-
多项式、指数函数和三角函数都是良态的。函数越良态,获得良好逼近所需的泰勒项就越少。
编程任务(使用 CoLab 或 notebook)¶
-
使用越来越多的泰勒项逼近 \(e^x\),并可视化逼近如何改进。
import jax.numpy as jnp import matplotlib.pyplot as plt x = jnp.linspace(-2, 3, 300) plt.plot(x, jnp.exp(x), "k-", linewidth=2, label="eˣ (精确)") colors = ["#e74c3c", "#3498db", "#27ae60", "#9b59b6"] for n, color in zip([1, 2, 4, 8], colors): # 计算泰勒多项式:sum_{k=0}^n x^k/k! approx = sum(x**k / jnp.array(float(jnp.prod(jnp.arange(1, k+1)) if k > 0 else 1)) for k in range(n+1)) plt.plot(x, approx, color=color, linestyle="--", label=f"{n} 项") plt.ylim(-2, 15) plt.legend() plt.title("eˣ 的泰勒逼近") plt.show() -
计算拉格朗日余项,用以界定用不同泰勒项数逼近 \(\sin(1)\) 的误差。
import jax.numpy as jnp x = 1.0 exact = jnp.sin(x) taylor = 0.0 for n in range(8): sign = (-1)**n factorial = float(jnp.prod(jnp.arange(1, 2*n+2))) taylor += sign * x**(2*n+1) / factorial error = abs(exact - taylor) bound = x**(2*n+3) / float(jnp.prod(jnp.arange(1, 2*n+4))) print(f"项数={n+1} 逼近值={taylor:.10f} 误差={error:.2e} 余项界={bound:.2e}") -
比较 \(\cos(x)\) 在 \(x=0\) 附近的线性化与二次泰勒逼近。将两者与原函数一起绘制,观察各自准确的区间。
import jax.numpy as jnp import matplotlib.pyplot as plt x = jnp.linspace(-3, 3, 300) plt.plot(x, jnp.cos(x), "k-", linewidth=2, label="cos(x)") plt.plot(x, jnp.ones_like(x), "--", color="#e74c3c", label="线性化: 1") plt.plot(x, 1 - x**2/2, "--", color="#3498db", label="二次: 1 - x²/2") plt.plot(x, 1 - x**2/2 + x**4/24, "--", color="#27ae60", label="四阶") plt.ylim(-2, 2) plt.legend() plt.title("cos(x) 的泰勒逼近") plt.show()