Spaces:
No application file
No application file
Create animation.py
Browse files- animation.py +137 -0
animation.py
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from manim import *
|
| 2 |
+
import numpy as np
|
| 3 |
+
|
| 4 |
+
class FullVideo(Scene):
|
| 5 |
+
def construct(self):
|
| 6 |
+
# Part 1: Introduction
|
| 7 |
+
title = Text("Gradients, Optimization, and Bayesian Updating").scale(0.8).to_edge(UP)
|
| 8 |
+
intro_text = Text(
|
| 9 |
+
"Exploring how gradients guide optimization\nand how beliefs evolve with evidence.",
|
| 10 |
+
font_size=24
|
| 11 |
+
).next_to(title, DOWN)
|
| 12 |
+
self.play(Write(title), Write(intro_text))
|
| 13 |
+
self.wait(2)
|
| 14 |
+
self.play(FadeOut(intro_text))
|
| 15 |
+
|
| 16 |
+
# Transition to gradients
|
| 17 |
+
self.play(FadeOut(title))
|
| 18 |
+
self.wait(0.5)
|
| 19 |
+
|
| 20 |
+
# Part 2: Understanding Gradients
|
| 21 |
+
axes = Axes(
|
| 22 |
+
x_range=[0, 10, 1],
|
| 23 |
+
y_range=[0, 25, 5],
|
| 24 |
+
axis_config={"include_numbers": True},
|
| 25 |
+
)
|
| 26 |
+
graph = axes.plot(lambda x: (x - 5)**2, color=BLUE)
|
| 27 |
+
func_label = MathTex("f(x) = (x - 5)^2").next_to(axes, UP)
|
| 28 |
+
self.play(Create(axes), Write(func_label))
|
| 29 |
+
self.play(Create(graph))
|
| 30 |
+
self.wait(1)
|
| 31 |
+
|
| 32 |
+
# Gradient descent animation
|
| 33 |
+
dot_min = Dot(axes.coords_to_point(7, (7 - 5)**2), color=RED)
|
| 34 |
+
self.play(FadeIn(dot_min))
|
| 35 |
+
for _ in range(5):
|
| 36 |
+
new_x = dot_min.get_center()[0] - 0.5
|
| 37 |
+
new_y = (new_x - 5)**2
|
| 38 |
+
new_dot = Dot(axes.coords_to_point(new_x, new_y), color=RED)
|
| 39 |
+
self.play(Transform(dot_min, new_dot), run_time=0.5)
|
| 40 |
+
self.wait(1)
|
| 41 |
+
|
| 42 |
+
# Zoom effect on the minimum point
|
| 43 |
+
self.play(
|
| 44 |
+
axes.animate.scale(0.8).shift(LEFT * 2),
|
| 45 |
+
dot_min.animate.scale(1.5),
|
| 46 |
+
run_time=1.5
|
| 47 |
+
)
|
| 48 |
+
self.wait(1)
|
| 49 |
+
self.play(FadeOut(axes), FadeOut(dot_min), FadeOut(func_label))
|
| 50 |
+
|
| 51 |
+
# Part 3: Comfort Score Function
|
| 52 |
+
axes_3d = ThreeDAxes(
|
| 53 |
+
x_range=[60, 80, 5],
|
| 54 |
+
y_range=[30, 50, 5],
|
| 55 |
+
z_range=[0, 100, 20],
|
| 56 |
+
x_length=8,
|
| 57 |
+
y_length=8,
|
| 58 |
+
z_length=6
|
| 59 |
+
)
|
| 60 |
+
def comfort_score(t, h):
|
| 61 |
+
return 72 - (t - 70)**2 - 2 * (h - 40)**2
|
| 62 |
+
|
| 63 |
+
surface = Surface(
|
| 64 |
+
lambda u, v: axes_3d.c2p(u, v, comfort_score(u, v)),
|
| 65 |
+
u_range=[60, 80],
|
| 66 |
+
v_range=[30, 50],
|
| 67 |
+
resolution=(20, 20),
|
| 68 |
+
fill_opacity=0.7
|
| 69 |
+
)
|
| 70 |
+
surface.set_fill_by_value(
|
| 71 |
+
axes=axes_3d,
|
| 72 |
+
colors=[(RED, 0), (YELLOW, 50), (GREEN, 100)]
|
| 73 |
+
)
|
| 74 |
+
|
| 75 |
+
# Set camera orientation and animate rotation
|
| 76 |
+
self.set_camera_orientation(phi=75 * DEGREES, theta=-45 * DEGREES)
|
| 77 |
+
self.add(axes_3d, surface)
|
| 78 |
+
self.begin_ambient_camera_rotation(rate=0.2)
|
| 79 |
+
self.wait(5)
|
| 80 |
+
self.stop_ambient_camera_rotation()
|
| 81 |
+
|
| 82 |
+
# Zoom into the peak of the surface
|
| 83 |
+
self.move_camera(phi=90 * DEGREES, theta=-90 * DEGREES, zoom=1.5, run_time=2)
|
| 84 |
+
self.wait(1)
|
| 85 |
+
self.play(FadeOut(axes_3d), FadeOut(surface))
|
| 86 |
+
|
| 87 |
+
# Part 4: Bayesian Updating
|
| 88 |
+
prior = [0.3, 0.7]
|
| 89 |
+
bar_chart = BarChart(
|
| 90 |
+
prior,
|
| 91 |
+
max_value=1,
|
| 92 |
+
bar_names=["Rain", "No Rain"],
|
| 93 |
+
bar_colors=[BLUE, YELLOW]
|
| 94 |
+
)
|
| 95 |
+
prior_label = Text("Prior Probabilities").next_to(bar_chart, DOWN)
|
| 96 |
+
self.play(Create(bar_chart), Write(prior_label))
|
| 97 |
+
self.wait(2)
|
| 98 |
+
|
| 99 |
+
posterior = [0.6, 0.4]
|
| 100 |
+
updated_bar_chart = BarChart(
|
| 101 |
+
posterior,
|
| 102 |
+
max_value=1,
|
| 103 |
+
bar_names=["Rain", "No Rain"],
|
| 104 |
+
bar_colors=[BLUE, YELLOW]
|
| 105 |
+
)
|
| 106 |
+
posterior_label = Text("Posterior Probabilities").next_to(updated_bar_chart, DOWN)
|
| 107 |
+
self.play(Transform(bar_chart, updated_bar_chart), Transform(prior_label, posterior_label))
|
| 108 |
+
self.wait(2)
|
| 109 |
+
|
| 110 |
+
bayes_formula = MathTex(r"P(H|E) = \frac{P(E|H)P(H)}{P(E)}").next_to(bar_chart, DOWN)
|
| 111 |
+
self.play(Write(bayes_formula))
|
| 112 |
+
self.wait(2)
|
| 113 |
+
|
| 114 |
+
# Zoom out for conclusion
|
| 115 |
+
self.play(
|
| 116 |
+
bar_chart.animate.scale(0.8).shift(LEFT * 2),
|
| 117 |
+
bayes_formula.animate.scale(0.8).shift(RIGHT * 2),
|
| 118 |
+
run_time=1.5
|
| 119 |
+
)
|
| 120 |
+
self.wait(1)
|
| 121 |
+
|
| 122 |
+
# Part 5: Connecting the Dots
|
| 123 |
+
self.clear()
|
| 124 |
+
conclusion = Text(
|
| 125 |
+
"Gradients and Bayesian updating both rely\non iterative refinement to achieve their goals.",
|
| 126 |
+
font_size=24
|
| 127 |
+
).to_edge(UP)
|
| 128 |
+
self.play(Write(conclusion))
|
| 129 |
+
self.wait(3)
|
| 130 |
+
|
| 131 |
+
# Part 6: Call to Action
|
| 132 |
+
call_to_action = Text(
|
| 133 |
+
"Explore more about optimization and Bayesian methods!",
|
| 134 |
+
font_size=24
|
| 135 |
+
).next_to(conclusion, DOWN)
|
| 136 |
+
self.play(Write(call_to_action))
|
| 137 |
+
self.wait(3)
|