讲解稿 · 第 03 章 第 04 节:函数逼近¶
口播时长:约 15–20 分钟|建议语速:中速偏慢,公式处停顿两拍|字数:约 4100 字
开场钩子(约 1 分钟)¶
先问你一个场景。
你手上有张表,左边是从 0 到 10 秒的时间,右边是小车每秒钟的速度。问题是:速度表指针在某一秒到底指向多少?
速度表读数不是一个"平均值",它告诉你的是此刻。它是把整个过程压到一个瞬间看:过去一点点和未来一点点之间的差距除以那一段有多长。
这就是瞬时变化率。上一节我们讲了导数——曲线在某一点切线的斜率。但大多数真实函数没法直接算,比如 \(e^{0.1}\)、卫星轨迹上某一点的瞬时高度——它们的"切线"在哪?这一节我们就来解决这件事:用简单的函数(多项式、正弦余弦、神经网络)去替代复杂函数,只在关心的区域内"足够接近"就行。这就是函数逼近 (function approximation)。
从线性化到泰勒级数,再到万能逼近定理——这恰好是深度学习为何能拟合任意映射的理论根基。
复习昨日 & 今日路线(约 40 秒)¶
上一节我们讲了多元微积分——梯度、Hessian、Jacobian,把微积分搬到了向量上。
这一节反过来:函数太复杂,没法直接算。怎么办?找一个简单函数替上去。
下一节是优化的最后一站——梯度下降、随机梯度下降、Adam,以及约束优化的拉格朗日乘子。那一节会把泰勒展开用得淋漓尽致。
核心概念一:线性化 = 在家门口贴一张地图(约 3 分钟)¶
先给你一个最朴素的想法。
如果一个函数太复杂没法算,那就挑你最有把握的一个点 \(a\),看函数在那里等于多少、变化率是多少,然后用一条直线(切线)代替函数。走出家门之后,照着地图走,至少在街区内是准的。
这就是线性化 (linearisation),也叫一阶泰勒逼近:
它做两件事——定起点(\(f(a)\))+ 定方向(斜率 \(f'(a)\) 乘以位移 \(x - a\))。这个公式你在上一节已经见过一次了。
我举个具体的例子,把 \(\sin(x)\) 在 \(x = 0\) 处线性化:
- \(f(0) = \sin(0) = 0\)
- \(f'(0) = \cos(0) = 1\)
- 所以 \(L(x) = 0 + 1 \cdot (x - 0) = x\)
也就是 \(\sin(x) \approx x\)。
这个近似在零附近非常好用。验证一下:\(\sin(0.1) = 0.0998\ldots\),跟 \(0.1\) 只差千分之二。你离 \(0\) 越近,近似就越准——这就是"家门口贴地图"的代价:走远了地图就失真。
记一句话:线性化 = 用切线换曲线,只在展开点附近有效。
核心概念二:泰勒级数 = 一次不够,就加二次三次(约 3.5 分钟)¶
线性化只对了值和斜率。函数稍微一弯,二次项就露馅了。
怎么办?再加一项。 加一项匹配曲率(二阶导数),再加一项匹配三阶变化,一路加下去。这就是泰勒级数 (Taylor series):
每一项都在做一次修正:
- \(n = 0\):匹配函数值。
- \(n = 1\):匹配斜率。
- \(n = 2\):匹配曲率。
- \(n = 3, 4, \ldots\):匹配更精细的变化。
你可能想问:分母里那个 \(n!\) 是怎么来的?我给你讲清楚它的来历,免得你背公式背得稀里糊涂。
你想,\((x - a)^n\) 这一项,你求一次导数掉下来一个 \((x - a)^{n-1}\),求 \(n\) 次导数正好掉成 \(n!\)。这个阶乘正好抵消掉前面分子里那个 \((x - a)^n\) 求导 \(n\) 次之后还残留的因子。\(n!\) 的角色就是保证泰勒多项式的 \(n\) 阶导数在 \(x = a\) 处等于原函数的 \(n\) 阶导数。这不是凭空冒出来的,是代数硬约束。
麦克劳林级数 (Maclaurin series) 就是把 \(a\) 取成 \(0\) 的泰勒级数:
下面这三个麦克劳林级数你要背下来——它们后面所有微积分、所有数值分析、所有物理建模天天见:
注意两条规律:
- 奇偶:\(\sin x\) 只有奇数次幂(它是奇函数),\(\cos x\) 只有偶数次幂(它是偶函数)。
- 交替正负:\(\sin\) 和 \(\cos\) 的项一正一负交替着来,这让逼近在真值两侧来回振荡,从两边夹击式地收敛。
来一个端到端的数字例:用四项泰勒展开逼近 \(e^{0.5}\)。
真实值是 \(1.6487\ldots\),四项就给到小数点后三位。这就是阶乘的妙处——\(n!\) 涨得太快,项一加进来误差就被压扁。
⏸️ 暂停思考 · 第一次
算一下 \(\sin(0.5)\) 的三项泰勒逼近。提示:\(\sin x \approx x - x^3/6 + x^5/120\)。
——代入:\(0.5 - 0.125/6 + 0.03125/120 = 0.5 - 0.02083 + 0.00026 \approx 0.47943\)。真实值 \(\sin(0.5) = 0.47943\ldots\),三项已经对到小数点后五位。这就是泰勒逼近的力量。
核心概念三:收敛半径 = 地图的有效边界(约 2 分钟)¶
不是每个泰勒级数处处都收敛。\(1/(1-x)\) 这个函数的麦克劳林展开是 \(1 + x + x^2 + \cdots\),但你把 \(x = 2\) 代进去会得到 \(1 + 2 + 4 + 8 + \cdots\),发散到无穷。
这里就需要收敛半径 (radius of convergence) 这个概念:它告诉你离中心 \(a\) 多远之内,级数还能给出有效结果。在这个半径内,加更多项就能达到任意精度;半径之外,级数直接发散。
判断半径有个标准工具——比值判别法 (ratio test):
拿 \(e^x\) 来验算:\(a_n = 1/n!\),相邻两项之比是 \(1/(n+1) \to 0\),所以 \(L = 0\),\(R = 1/0 = \infty\)。整个实数轴都是它的有效区域。这也是为什么 \(e^x\) 在数值计算里这么受欢迎。
但 \(\ln(1+x) = x - x^2/2 + x^3/3 - \cdots\),比值是 \(n/(n+1) \to 1\),所以 \(R = 1\)。你走到 \(|x| > 1\) 的地方,级数就崩了。
一句话总结:收敛半径是泰勒级数的"有效边界",比值判别法是测边界的尺子。
核心概念四:拉格朗日余项 = 我能保证的最坏情况误差(约 2.5 分钟)¶
我再说一件事:截断泰勒级数必然有误差。
我们把泰勒级数截到第 \(n\) 项,多出来的误差叫拉格朗日余项 (Lagrange remainder):
这里 \(c\) 是 \(a\) 和 \(x\) 之间某个我们不知道的点。虽然 \(c\) 不知道,但通常能对 \(|f^{(n+1)}(c)|\) 做出上界估计,从而得到最坏情况的误差。
关键看分母里的 \((n+1)!\)——它涨得飞快。只要在收敛半径之内,每加一项,误差几乎以阶乘速度衰减。这就是为什么泰勒逼近特别"大方":项数从 1 加到 4,常常能拿到 10 倍以上的精度提升。
我用 \(\sin(1)\) 验算一下。一项是 \(1\),三项是 \(1 - 1/6 = 0.83333\),五项是 \(0.83333 + 1/120 = 0.84167\),七项是 \(0.84167 - 1/5040 = 0.84147\)。真实值 \(\sin(1) = 0.84147\ldots\)。七项就精确到小数点后五位。这就是阶乘在帮你。
一句话总结:拉格朗日余项告诉你"我截到这能保证不差多少",\((n+1)!\) 让加项变得非常划算。
核心概念五:多元二阶泰勒 = 搭桥到 Ch02 矩阵(约 2.5 分钟)¶
好,到这里你已经学会了单变量的泰勒展开。接下来的事更重要——把泰勒搬进向量。
上一节你见过两个东西:梯度 \(\nabla f\)(一个向量)和 Hessian 矩阵 \(H\)(一个二阶导数矩阵)。这一节它们要一起上场。
\(f(\mathbf{x})\) 在 \(\mathbf{a}\) 附近的二阶泰勒逼近:
看清楚这个结构:
- 第一项是标量(函数值)。
- 第二项是行向量 × 列向量 = 标量。你想想 Ch02 矩阵乘法——左行乘右列得到一个数。这就是梯度(一行)和位移(一列)做内积。
- 第三项是行向量 × 方阵 × 列向量 = 标量。Hessian \(H\) 在中间,位移向量在两头。
这一下就把 Ch03 微积分和 Ch02 矩阵乘法直接焊死了。如果你把 \((x - a)\) 想成一个向量 \(\mathbf{v}\),第三项就是 \(\tfrac{1}{2} \mathbf{v}^\top H \mathbf{v}\)——一个二次型。这是后面牛顿法、二阶优化、贝叶斯推断的母公式。
我给你一个数字锚点。设 \(f(x, y) = x^2 + 3xy + 2y^2\),梯度 \(\nabla f = (2x + 3y, 3x + 4y)^\top\),Hessian $$ H = \begin{pmatrix} 2 & 3 \ 3 & 4 \end{pmatrix} $$。在 \(\mathbf{a} = (0, 0)^\top\) 附近,$$ f \approx 0 + 0 + \tfrac{1}{2}(x, y) \begin{pmatrix} 2 & 3 \ 3 & 4 \end{pmatrix} \begin{pmatrix} x \ y \end{pmatrix} = x^2 + 3xy + 2y^2 $$——因为是二次函数,泰勒展开一步到位。
这句话要在你脑子里搭一座桥:微分 \(dy = f'(x) \cdot dx\) 在 Ch02 框架下就是 1×1 矩阵乘法——一个数乘以一个数。多元推广就是 Jacobian @ Jacobian = 复合函数雅可比,这是 Ch02 矩阵乘法的 Ch03 应用。
⏸️ 暂停思考 · 第二次
想一想:单变量的 \(f(x) \approx f(a) + f'(a)(x - a)\),其中 \(f'(a)\) 是一个数(标量)。这相当于 1×1 矩阵的乘法吗?为什么说"导数 = 线性映射的斜率"?
—— 是的。\(f'(a)\) 把一个小的位移 \((x - a)\) 映射成一个小的输出变化,它的几何作用就是把切线方向放大 \(f'(a)\) 倍。这是最最最简单的线性映射——只有一行一列。当我们搬到多变量,这个线性映射就被矩阵(Jacobian、Hessian)替代。所以"导数"和"线性映射"在概念上是同一件事的不同尺寸。
一个走完全程的例子(约 3 分钟)¶
好,咱们用一个例子把今天的概念全串起来。
问:手算 \(\sin(0.5)\) 到小数点后五位。
第一步,回忆麦克劳林展开:\(\sin x = x - x^3/3! + x^5/5! - x^7/7! + \cdots\)
第二步,从线性化起步:\(L(x) = x\)。代入 \(0.5\) 得 \(0.5\),但 \(\sin(0.5) = 0.4794\ldots\),误差 \(0.0206\)。
第三步,加二次修正:\(\sin x \approx x - x^3/6\)。代入 \(0.5\):\(0.5 - 0.02083 = 0.47917\)。误差掉到 \(0.00026\)。一步加项,精度提升接近 100 倍。
第四步,加四次修正:再加 \(x^5/120 = 0.00026\)。总逼近 \(= 0.47943\)。误差 \(\sim 10^{-6}\)。
第五步,验证收敛半径:\(\sin x\) 的麦克劳林展开对所有 \(x\) 都收敛(它的比值判别 \(L = 0\)),所以你不需要担心边界。
第六步,看拉格朗日余项:\(|R_4| \le |x|^5/5! = 0.5^5/120 \approx 2.6 \times 10^{-5}\)。这正是我们观察到的实际误差——上界估计是诚实的。
第七步,连到下一节:如果我们把 \(\sin\) 想成一个目标函数,导数是 \(\cos\),那牛顿法可以用 \(x_{n+1} = x_n - \sin(x_n)/\cos(x_n)\) 直接求解 \(\sin(x) = 0\)。这背后的几何就是二阶泰勒——下一节登场。
整套动作串起来:麦克劳林展开 → 线性化起步 → 逐项加修正 → 收敛半径保证有效 → 拉格朗日余项给出误差上界 → 二阶泰勒推到多变量 → 牛顿法做优化。
易错点回头看(约 1 分钟)¶
三条最常翻车的地方。
-
很多人以为:泰勒级数项数越多,结果越准,无限加。其实是:只在收敛半径之内,项数越多越准。因为半径之外级数是发散的,你加再多项也不会逼近真值——它就是爆炸。数字反例:\(\ln(1+x)\) 的麦克劳林在 \(x = 2\) 处发散,你算 1000 项也救不回来。
-
很多人以为:拉格朗日余项 \(R_n\) 是个精确的数。其实是:误差的上界估计,不是确切误差。因为那个 \(c\) 我们不知道在哪——只知道它在 \(a\) 和 \(x\) 之间。所以余项给的是"最坏情况下你能保证的精度",不是"实际误差是多少"。实操上 \(|f^{(n+1)}(c)|\) 的上界估计往往比实际误差大一两档,这是为了保守。
-
很多人以为:多项式项数越高越好。其实是:项数过高会引入龙格现象 (Runge's phenomenon)——两端剧烈振荡,中间反而失真。因为高次多项式很容易"用力过猛"去拟合某些点,反而牺牲整体平滑。工程解法是样条插值 (spline interpolation)——用许多低次多项式平滑地拼起来,避免高次多项式的狂野振荡。这就是为什么样条在 CAD、计算机图形学里是主力。
与下节的钩子(约 30 秒)¶
今天我们讲了怎么用简单函数替换复杂函数——泰勒展开是核心工具。
下一节——03.05 优化——我们要回答一个问题:怎么把泰勒展开用到极致,把损失函数推到最小? 一阶的梯度下降、牛顿法的二阶逼近、拉格朗日乘子解约束优化——你会看到,今天讲的二阶泰勒恰恰是牛顿法的母公式。带着这个连接,咱们下节见。