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) 讲解
这个视频围绕「二元函数的泰勒展开」展开。画面把问题、图像和公式放在同一条理解路径中,让抽象关系先被看见。
开头先建立问题背景和主要对象,让观察从标题、坐标或第一组关系进入。
画面中出现的文字「二元函数泰勒展开」给出视觉入口。随后画面通过对象创建、移动、淡入淡出和高亮,把抽象命题拆成可以跟随的步骤。
随后出现更具体的图像或公式提示,动画会把局部对象和整体结论联系起来。这里可以重点观察变量、曲线、区域或向量如何随镜头推进而变化。
核心公式可以写成:
这类公式可以和画面中的符号一一对应。
观察路径
观察路径可以分三步:先锁定「二元函数的泰勒展开」中的核心对象,尤其留意泰勒级数、多元函数、局部线性化之间的联系;再跟随画面中变量、图像或向量的变化;最后回到公式或结论,判断局部变化如何支撑整体关系。
本页可以从泰勒级数、多元函数、局部线性化、Hessian 矩阵这些概念进入,继续沿相邻问题观察同一类数学结构。