多元微积分可视化

二元函数的泰勒展开

围绕二元函数的泰勒展开,观察泰勒级数、多元函数、局部线性化之间的关系与推理路径。

打开原视频

taylor_animation.py
1from manim import *2import numpy as np3 4class TaylorSeriesDemo(ThreeDScene):5    def construct(self):6        # 设置3D场景7        self.set_camera_orientation(phi=75 * DEGREES, theta=30 * DEGREES)8        9        # 标题10        title = Text("二元函数泰勒展开", font="PingFang SC")11        title.to_corner(UL)12        self.add_fixed_in_frame_mobjects(title)13        self.play(Write(title))14        self.wait()15        16        # 在左侧显示一般函数的泰勒公式(展开式形式)17        general_taylor = MathTex(18            r"f(x,y) &= f(0,0) + \frac{\partial f}{\partial x}(0,0)x + \frac{\partial f}{\partial y}(0,0)y \\",19            r"&+ \frac{1}{2!}\frac{\partial^2 f}{\partial x^2}(0,0)x^2 + \frac{1}{1!1!}\frac{\partial^2 f}{\partial x \partial y}(0,0)xy + \frac{1}{2!}\frac{\partial^2 f}{\partial y^2}(0,0)y^2 \\",20            r"&+ \frac{1}{3!}\frac{\partial^3 f}{\partial x^3}(0,0)x^3 + \ldots",21            font_size=2022        )23        general_taylor.to_edge(LEFT, buff=1.3)  # 增加左侧边距,使公式更靠左24        general_taylor.shift(UP * 2 + LEFT * 1)  # 额外向左移动25        self.add_fixed_in_frame_mobjects(general_taylor)26        self.play(Write(general_taylor))27        self.wait()28        29        # 使用 f(x,y) = e^(-x^2-y^2) 作为例子,高斯函数30        def f(x, y):31            return np.exp(-x**2 - y**2)32        33        # 创建坐标轴,调整范围以更好地显示函数,缩小范围34        axes = ThreeDAxes(35            x_range=[-1.5, 1.5, 0.5],36            y_range=[-1.5, 1.5, 0.5],37            z_range=[0, 1.2, 0.2],38            x_length=6,39            y_length=6,40            z_length=3,41        )42        self.add(axes)43        44        # 创建原始曲面,缩小范围45        original_surface = Surface(46            lambda u, v: axes.c2p(u, v, f(u, v)),47            u_range=[-1.5, 1.5],48            v_range=[-1.5, 1.5],49            resolution=(25, 25),  # 增加分辨率使曲面更平滑50            fill_opacity=0.7,51            checkerboard_colors=[BLUE_D, BLUE_E]52        )53        54        # 显示原始曲面55        self.play(Create(original_surface))56        57        # 添加原始函数说明58        original_func = MathTex(r"f(x,y) = e^{-x^2-y^2}", font_size=28, color=BLUE)59        original_func.to_edge(UP, buff=0.2)  # 将函数说明移到顶部中间位置60        self.add_fixed_in_frame_mobjects(original_func)61        self.play(Write(original_func))62        self.wait()63        64        # 泰勒展开零阶65        def taylor_0_func(x, y):66            # f(0,0) = 167            return 168        69        taylor_0 = Surface(70            lambda u, v: axes.c2p(u, v, taylor_0_func(u, v)),71            u_range=[-1.5, 1.5],72            v_range=[-1.5, 1.5],73            resolution=(25, 25),74            fill_opacity=0.5,75            checkerboard_colors=[RED_D, RED_E]76        )77        78        # 公式显示在右侧,位于T0下方79        taylor_0_eq = MathTex(r"T_0(x,y) = 1", font_size=28, color=RED)80        taylor_0_eq.to_edge(RIGHT, buff=0.7)  # 增加右侧边距81        taylor_0_eq.shift(UP * 3)  # 移到屏幕上方82        self.add_fixed_in_frame_mobjects(taylor_0_eq)83        84        self.play(Create(taylor_0), Write(taylor_0_eq))85        self.wait()86        87        # 泰勒展开一阶88        def taylor_1_func(x, y):89            # 一阶展开: f(0,0) = 190            # ∂f/∂x(0,0) = ∂f/∂y(0,0) = 091            return 192        93        taylor_1 = Surface(94            lambda u, v: axes.c2p(u, v, taylor_1_func(u, v)),95            u_range=[-1.5, 1.5],96            v_range=[-1.5, 1.5],97            resolution=(25, 25),98            fill_opacity=0.5,99            checkerboard_colors=[GOLD_D, GOLD_E]100        )101        102        # 公式显示在右侧,位于T0下方103        taylor_1_eq = MathTex(r"T_1(x,y) = 1", font_size=28, color=GOLD)104        taylor_1_eq.to_edge(RIGHT, buff=0.7)105        taylor_1_eq.shift(UP * 2.4)106        self.add_fixed_in_frame_mobjects(taylor_1_eq)107        108        self.play(109            ReplacementTransform(taylor_0, taylor_1),110            FadeIn(taylor_1_eq)111        )112        self.wait()113        114        # 泰勒展开二阶115        def taylor_2_func(x, y):116            # 二阶展开: 添加二阶项117            # ∂²f/∂x²(0,0) = ∂²f/∂y²(0,0) = -2118            # ∂²f/∂x∂y(0,0) = 0119            return 1 - x**2 - y**2120        121        taylor_2 = Surface(122            lambda u, v: axes.c2p(u, v, taylor_2_func(u, v)),123            u_range=[-1.5, 1.5],124            v_range=[-1.5, 1.5],125            resolution=(25, 25),126            fill_opacity=0.5,127            checkerboard_colors=[GREEN_D, GREEN_E]128        )129        130        # 公式显示在右侧,位于T1下方131        taylor_2_eq = MathTex(r"T_2(x,y) = 1 - x^2 - y^2", font_size=28, color=GREEN)132        taylor_2_eq.to_edge(RIGHT, buff=0.7)133        taylor_2_eq.shift(UP * 1.8)134        self.add_fixed_in_frame_mobjects(taylor_2_eq)135        136        self.play(137            ReplacementTransform(taylor_1, taylor_2),138            FadeIn(taylor_2_eq)139        )140        self.wait()141        142        # 泰勒展开三阶143        def taylor_3_func(x, y):144            # 三阶展开,三阶导数在(0,0)处均为0145            return 1 - x**2 - y**2146        147        taylor_3 = Surface(148            lambda u, v: axes.c2p(u, v, taylor_3_func(u, v)),149            u_range=[-1.5, 1.5],150            v_range=[-1.5, 1.5],151            resolution=(25, 25),152            fill_opacity=0.5,153            checkerboard_colors=[TEAL_D, TEAL_E]154        )155        156        # 公式显示在右侧,位于T2下方157        # 三阶导数在(0,0)处为0,所以T3 = T2158        taylor_3_eq = MathTex(r"T_3(x,y) = T_2(x,y)", font_size=26, color=TEAL)159        taylor_3_eq.to_edge(RIGHT, buff=0.7)160        taylor_3_eq.shift(UP * 1.2)161        self.add_fixed_in_frame_mobjects(taylor_3_eq)162        163        self.play(164            ReplacementTransform(taylor_2, taylor_3),165            FadeIn(taylor_3_eq)166        )167        self.wait()168        169        # 泰勒展开四阶170        def taylor_4_func(x, y):171            # 四阶展开,增加四阶项172            # ∂⁴f/∂x⁴(0,0) = ∂⁴f/∂y⁴(0,0) = 12173            # ∂⁴f/∂x²∂y²(0,0) = 4174            return 1 - x**2 - y**2 + x**4/2 + x**2*y**2 + y**4/2175        176        taylor_4 = Surface(177            lambda u, v: axes.c2p(u, v, taylor_4_func(u, v)),178            u_range=[-1.5, 1.5],179            v_range=[-1.5, 1.5],180            resolution=(25, 25),181            fill_opacity=0.5,182            checkerboard_colors=[PURPLE_D, PURPLE_E]183        )184        185        # 公式显示在右侧,位于T3下方,由于长度较长,字体稍小186        taylor_4_eq = MathTex(r"T_4(x,y) = 1 - x^2 - y^2", r"+ \frac{1}{2}x^4 + x^2y^2 + \frac{1}{2}y^4", font_size=24, color=PURPLE)187        taylor_4_eq.arrange(DOWN, aligned_edge=LEFT)188        taylor_4_eq.to_edge(RIGHT, buff=0.7)189        taylor_4_eq.shift(UP * 0.3)  # 调整向下移动190        self.add_fixed_in_frame_mobjects(taylor_4_eq)191        192        self.play(193            ReplacementTransform(taylor_3, taylor_4),194            FadeIn(taylor_4_eq)195        )196        self.wait()197        198        # 泰勒展开五阶199        def taylor_5_func(x, y):200            # 五阶展开,五阶导数在(0,0)处均为0201            return 1 - x**2 - y**2 + x**4/2 + x**2*y**2 + y**4/2202        203        taylor_5 = Surface(204            lambda u, v: axes.c2p(u, v, taylor_5_func(u, v)),205            u_range=[-1.5, 1.5],206            v_range=[-1.5, 1.5],207            resolution=(25, 25),208            fill_opacity=0.5,209            checkerboard_colors=[YELLOW_D, YELLOW_E]210        )211        212        # 公式显示在右侧,位于T4下方213        taylor_5_eq = MathTex(r"T_5(x,y) = T_4(x,y)", font_size=26, color=YELLOW)214        taylor_5_eq.to_edge(RIGHT, buff=0.7)215        taylor_5_eq.shift(DOWN * 0.6)  # 调整位置以适应T4的新位置216        self.add_fixed_in_frame_mobjects(taylor_5_eq)217        218        self.play(219            ReplacementTransform(taylor_4, taylor_5),220            FadeIn(taylor_5_eq)221        )222        self.wait()223        224        # 泰勒展开六阶225        def taylor_6_func(x, y):226            # 六阶展开,增加六阶项227            # ∂⁶f/∂x⁶(0,0) = ∂⁶f/∂y⁶(0,0) = -120228            # ∂⁶f/∂x⁴∂y²(0,0) = ∂⁶f/∂x²∂y⁴(0,0) = -24229            return (1 - x**2 - y**2 + x**4/2 + x**2*y**2 + y**4/2 - 230                   x**6/6 - x**4*y**2/2 - x**2*y**4/2 - y**6/6)231        232        taylor_6 = Surface(233            lambda u, v: axes.c2p(u, v, taylor_6_func(u, v)),234            u_range=[-1.5, 1.5],235            v_range=[-1.5, 1.5],236            resolution=(25, 25),237            fill_opacity=0.5,238            checkerboard_colors=[MAROON_D, MAROON_E]239        )240        241        # 公式显示在右侧,位于T5下方,简化显示,将公式分成两行以避免过长242        taylor_6_eq = MathTex(r"T_6(x,y) = T_5(x,y) - \frac{1}{6}x^6", r"- \frac{1}{2}x^4y^2 - \frac{1}{2}x^2y^4 - \frac{1}{6}y^6", font_size=24, color=MAROON)243        taylor_6_eq.arrange(DOWN, aligned_edge=LEFT)244        taylor_6_eq.to_edge(RIGHT, buff=0.7)245        taylor_6_eq.shift(DOWN * 1.5)  # 调整为更低的位置246        self.add_fixed_in_frame_mobjects(taylor_6_eq)247        248        self.play(249            ReplacementTransform(taylor_5, taylor_6),250            FadeIn(taylor_6_eq)251        )252        self.wait()253        254        # 对比原始曲面和最终的泰勒展开曲面255        self.play(256            FadeOut(taylor_6),257            original_surface.animate.set_fill_opacity(0.8)258        )259        self.wait()260        261        # 重新创建一个新的泰勒六阶曲面,避免使用之前可能存在残影的对象262        new_taylor_6 = Surface(263            lambda u, v: axes.c2p(u, v, taylor_6_func(u, v)),264            u_range=[-1.5, 1.5],265            v_range=[-1.5, 1.5],266            resolution=(25, 25),267            fill_opacity=0.4,  # 直接设置为半透明268            checkerboard_colors=[MAROON_D, MAROON_E]269        )270        271        self.play(272            FadeIn(new_taylor_6)273        )274        self.wait()275        276        # 改变视角以更好地观察差异277        self.move_camera(phi=60 * DEGREES, theta=60 * DEGREES, run_time=2)278        self.wait()279        280        # 旋转相机观察匹配程度281        self.begin_ambient_camera_rotation(rate=0.2)282        self.wait(3)283        self.stop_ambient_camera_rotation()284        285        # 结论286        conclusion = Text("随着泰勒展开阶数增加,近似度不断提高", font="PingFang SC", font_size=28)287        conclusion.to_edge(DOWN, buff=0.5)288        self.add_fixed_in_frame_mobjects(conclusion)289        self.play(Write(conclusion))290        self.wait(2)

讲解

这个视频围绕「二元函数的泰勒展开」展开。画面把问题、图像和公式放在同一条理解路径中,让抽象关系先被看见。

开头先建立问题背景和主要对象,让观察从标题、坐标或第一组关系进入。

画面中出现的文字「二元函数泰勒展开」给出视觉入口。随后画面通过对象创建、移动、淡入淡出和高亮,把抽象命题拆成可以跟随的步骤。

随后出现更具体的图像或公式提示,动画会把局部对象和整体结论联系起来。这里可以重点观察变量、曲线、区域或向量如何随镜头推进而变化。

核心公式可以写成:

f(x,y)=ex2y2f(x,y) = e^{-x^2-y^2}

这类公式可以和画面中的符号一一对应。

观察路径

观察路径可以分三步:先锁定「二元函数的泰勒展开」中的核心对象,尤其留意泰勒级数、多元函数、局部线性化之间的联系;再跟随画面中变量、图像或向量的变化;最后回到公式或结论,判断局部变化如何支撑整体关系。

本页可以从泰勒级数、多元函数、局部线性化、Hessian 矩阵这些概念进入,继续沿相邻问题观察同一类数学结构。