mirror of
https://github.com/3b1b/manim.git
synced 2025-11-14 14:47:44 +00:00
Published pdf video
This commit is contained in:
parent
6e523ed960
commit
965564853b
2 changed files with 766 additions and 190 deletions
|
|
@ -1,6 +1,7 @@
|
|||
from manimlib.imports import *
|
||||
from from_3b1b.active.bayes.beta_helpers import *
|
||||
from from_3b1b.active.bayes.beta1 import *
|
||||
from from_3b1b.old.hyperdarts import Dartboard
|
||||
|
||||
import scipy.stats
|
||||
|
||||
|
|
@ -441,7 +442,7 @@ class LabelH(Scene):
|
|||
self.wait()
|
||||
|
||||
|
||||
class Underline(Scene):
|
||||
class DrawUnderline(Scene):
|
||||
def construct(self):
|
||||
line = Line(2 * LEFT, 2 * RIGHT)
|
||||
line.set_stroke(PINK, 5)
|
||||
|
|
@ -1396,7 +1397,7 @@ class ShowLimitToPdf(Scene):
|
|||
class FiniteVsContinuum(Scene):
|
||||
def construct(self):
|
||||
# Title
|
||||
f_title = TextMobject("Finite context")
|
||||
f_title = TextMobject("Discrete context")
|
||||
f_title.set_height(0.5)
|
||||
f_title.to_edge(UP)
|
||||
f_underline = Underline(f_title)
|
||||
|
|
@ -1406,7 +1407,7 @@ class FiniteVsContinuum(Scene):
|
|||
|
||||
# Equations
|
||||
dice = get_die_faces()[::2]
|
||||
cards = [PlayingCard("A" + sym) for sym in "SHCD"]
|
||||
cards = [PlayingCard(letter + "H") for letter in "A35"]
|
||||
|
||||
eqs = VGroup(
|
||||
self.get_union_equation(dice),
|
||||
|
|
@ -1474,8 +1475,6 @@ class FiniteVsContinuum(Scene):
|
|||
self.play(ShowCreation(e_cross))
|
||||
self.wait()
|
||||
|
||||
self.embed()
|
||||
|
||||
def get_union_equation(self, mobs):
|
||||
mob_copies1 = VGroup()
|
||||
mob_copies2 = VGroup()
|
||||
|
|
@ -1675,9 +1674,444 @@ class HalfFiniteHalfContinuous(Scene):
|
|||
self.wait(30)
|
||||
|
||||
|
||||
class SumToIntegral(Scene):
|
||||
def construct(self):
|
||||
# Titles
|
||||
titles = VGroup(
|
||||
TextMobject("Discrete context"),
|
||||
TextMobject("Continuous context"),
|
||||
)
|
||||
titles.set_height(0.5)
|
||||
for title, vect in zip(titles, [LEFT, RIGHT]):
|
||||
title.move_to(vect * FRAME_WIDTH / 4)
|
||||
title.to_edge(UP, buff=MED_SMALL_BUFF)
|
||||
|
||||
v_line = Line(UP, DOWN).set_height(FRAME_HEIGHT)
|
||||
h_line = Line(LEFT, RIGHT).set_width(FRAME_WIDTH)
|
||||
h_line.next_to(titles, DOWN)
|
||||
h_line.set_x(0)
|
||||
v_line.center()
|
||||
|
||||
self.play(
|
||||
ShowCreation(VGroup(h_line, v_line)),
|
||||
LaggedStartMap(
|
||||
FadeInFrom, titles,
|
||||
lambda m: (m, -0.2 * m.get_center()[0] * RIGHT),
|
||||
run_time=1,
|
||||
lag_ratio=0.1,
|
||||
),
|
||||
)
|
||||
self.wait()
|
||||
|
||||
# Sum and int
|
||||
kw = {"tex_to_color_map": {"S": BLUE}}
|
||||
s_sym = TexMobject("\\sum", "_{x \\in S} P(x)", **kw)
|
||||
i_sym = TexMobject("\\int_{S} p(x)", "\\text{d}x", **kw)
|
||||
syms = VGroup(s_sym, i_sym)
|
||||
syms.scale(2)
|
||||
for sym, title in zip(syms, titles):
|
||||
sym.shift(-sym[-1].get_center())
|
||||
sym.match_x(title)
|
||||
|
||||
arrow = Arrow(
|
||||
s_sym[0].get_corner(UP),
|
||||
i_sym[0].get_corner(UP),
|
||||
path_arc=-90 * DEGREES,
|
||||
)
|
||||
arrow.set_color(YELLOW)
|
||||
|
||||
self.play(Write(s_sym, run_time=1))
|
||||
anims = [ShowCreation(arrow)]
|
||||
for i, j in [(0, 0), (2, 1), (3, 2)]:
|
||||
source = s_sym[i].deepcopy()
|
||||
target = i_sym[j]
|
||||
target.save_state()
|
||||
source.generate_target()
|
||||
target.replace(source, stretch=True)
|
||||
source.target.replace(target, stretch=True)
|
||||
target.set_opacity(0)
|
||||
source.target.set_opacity(0)
|
||||
anims += [
|
||||
Restore(target, path_arc=-60 * DEGREES),
|
||||
MoveToTarget(source, path_arc=-60 * DEGREES),
|
||||
]
|
||||
self.play(LaggedStart(*anims))
|
||||
self.play(FadeInFromDown(i_sym[3]))
|
||||
self.add(i_sym)
|
||||
self.wait()
|
||||
self.play(
|
||||
FadeOutAndShift(arrow, UP),
|
||||
syms.next_to, h_line, DOWN, {"buff": MED_LARGE_BUFF},
|
||||
syms.match_x, syms,
|
||||
)
|
||||
|
||||
# Add curve area in editing
|
||||
# Add bar chart
|
||||
axes = Axes(
|
||||
x_min=0,
|
||||
x_max=10,
|
||||
y_min=0,
|
||||
y_max=7,
|
||||
y_axis_config={
|
||||
"unit_size": 0.75,
|
||||
}
|
||||
)
|
||||
axes.set_width(0.5 * FRAME_WIDTH - 1)
|
||||
axes.next_to(s_sym, DOWN)
|
||||
axes.y_axis.add_numbers(2, 4, 6)
|
||||
|
||||
bars = VGroup()
|
||||
for x, y in [(1, 1), (4, 3), (7, 2)]:
|
||||
bar = Rectangle()
|
||||
bar.set_stroke(WHITE, 1)
|
||||
bar.set_fill(BLUE_D, 1)
|
||||
line = Line(axes.c2p(x, 0), axes.c2p(x + 2, y))
|
||||
bar.replace(line, stretch=True)
|
||||
bars.add(bar)
|
||||
|
||||
addition_formula = TexMobject(*"1+3+2")
|
||||
addition_formula.space_out_submobjects(2.1)
|
||||
addition_formula.next_to(bars, UP)
|
||||
|
||||
for bar in bars:
|
||||
bar.save_state()
|
||||
bar.stretch(0, 1, about_edge=DOWN)
|
||||
|
||||
self.play(
|
||||
Write(axes),
|
||||
LaggedStartMap(Restore, bars),
|
||||
LaggedStartMap(FadeInFromDown, addition_formula),
|
||||
)
|
||||
self.wait()
|
||||
|
||||
# Confusion
|
||||
morty = Mortimer()
|
||||
morty.to_corner(DR)
|
||||
morty.look_at(i_sym)
|
||||
self.play(
|
||||
*map(FadeOut, [axes, bars, addition_formula]),
|
||||
FadeIn(morty)
|
||||
)
|
||||
self.play(morty.change, "maybe")
|
||||
self.play(Blink(morty))
|
||||
self.play(morty.change, "confused", i_sym.get_right())
|
||||
self.play(Blink(morty))
|
||||
self.wait()
|
||||
|
||||
# Focus on integral
|
||||
self.play(
|
||||
Uncreate(VGroup(v_line, h_line)),
|
||||
FadeOutAndShift(titles, UP),
|
||||
FadeOutAndShift(morty, RIGHT),
|
||||
FadeOutAndShift(s_sym, LEFT),
|
||||
i_sym.center,
|
||||
i_sym.to_edge, LEFT
|
||||
)
|
||||
|
||||
arrows = VGroup()
|
||||
for vect in [UP, DOWN]:
|
||||
corner = i_sym[-1].get_corner(RIGHT + vect)
|
||||
arrows.add(Arrow(
|
||||
corner,
|
||||
corner + 2 * RIGHT + 2 * vect,
|
||||
path_arc=-np.sign(vect[1]) * 60 * DEGREES,
|
||||
))
|
||||
|
||||
self.play(*map(ShowCreation, arrows))
|
||||
|
||||
# Types of integration
|
||||
dist = scipy.stats.beta(7 + 1, 3 + 1)
|
||||
axes_pair = VGroup()
|
||||
graph_pair = VGroup()
|
||||
for arrow in arrows:
|
||||
axes = get_beta_dist_axes(y_max=5, y_unit=1)
|
||||
axes.set_width(4)
|
||||
axes.next_to(arrow.get_end(), RIGHT)
|
||||
graph = axes.get_graph(dist.pdf)
|
||||
graph.set_stroke(BLUE, 2)
|
||||
graph.set_fill(BLUE_E, 0)
|
||||
graph.make_smooth()
|
||||
axes_pair.add(axes)
|
||||
graph_pair.add(graph)
|
||||
|
||||
r_axes, l_axes = axes_pair
|
||||
r_graph, l_graph = graph_pair
|
||||
r_name = TextMobject("Riemann\\\\Integration")
|
||||
r_name.next_to(r_axes, RIGHT)
|
||||
l_name = TextMobject("Lebesgue\\\\Integration$^*$")
|
||||
l_name.next_to(l_axes, RIGHT)
|
||||
footnote = TextMobject("*a bit more complicated than\\\\these bars make it look")
|
||||
footnote.match_width(l_name)
|
||||
footnote.next_to(l_name, DOWN)
|
||||
|
||||
self.play(LaggedStart(
|
||||
FadeIn(r_axes),
|
||||
FadeIn(r_graph),
|
||||
FadeIn(r_name),
|
||||
FadeIn(l_axes),
|
||||
FadeIn(l_graph),
|
||||
FadeIn(l_name),
|
||||
run_time=1,
|
||||
))
|
||||
|
||||
# Approximation bars
|
||||
def get_riemann_rects(dx, axes=r_axes, func=dist.pdf):
|
||||
bars = VGroup()
|
||||
for x in np.arange(0, 1, dx):
|
||||
bar = Rectangle()
|
||||
line = Line(
|
||||
axes.c2p(x, 0),
|
||||
axes.c2p(x + dx, func(x)),
|
||||
)
|
||||
bar.replace(line, stretch=True)
|
||||
bar.set_stroke(BLUE_E, width=10 * dx, opacity=1)
|
||||
bar.set_fill(BLUE, 0.5)
|
||||
bars.add(bar)
|
||||
return bars
|
||||
|
||||
def get_lebesgue_bars(dy, axes=l_axes, func=dist.pdf, mx=0.7, y_max=dist.pdf(0.7)):
|
||||
bars = VGroup()
|
||||
for y in np.arange(dy, y_max + dy, dy):
|
||||
x0 = binary_search(func, y, 0, mx) or mx
|
||||
x1 = binary_search(func, y, mx, 1) or mx
|
||||
line = Line(axes.c2p(x0, y - dy), axes.c2p(x1, y))
|
||||
bar = Rectangle()
|
||||
bar.set_stroke(RED_E, 0)
|
||||
bar.set_fill(RED_E, 0.5)
|
||||
bar.replace(line, stretch=True)
|
||||
bars.add(bar)
|
||||
return bars
|
||||
|
||||
r_bar_groups = []
|
||||
l_bar_groups = []
|
||||
Ns = [10, 20, 40, 80, 160]
|
||||
Ms = [2, 4, 8, 16, 32]
|
||||
for N, M in zip(Ns, Ms):
|
||||
r_bar_groups.append(get_riemann_rects(dx=1 / N))
|
||||
l_bar_groups.append(get_lebesgue_bars(dy=1 / M))
|
||||
self.play(
|
||||
FadeIn(r_bar_groups[0], lag_ratio=0.1),
|
||||
FadeIn(l_bar_groups[0], lag_ratio=0.1),
|
||||
FadeIn(footnote),
|
||||
)
|
||||
self.wait()
|
||||
for rbg0, rbg1, lbg0, lbg1 in zip(r_bar_groups, r_bar_groups[1:], l_bar_groups, l_bar_groups[1:]):
|
||||
self.play(
|
||||
ReplacementTransform(
|
||||
rbg0, rbg1,
|
||||
lag_ratio=1 / len(rbg0),
|
||||
run_time=2,
|
||||
),
|
||||
ReplacementTransform(
|
||||
lbg0, lbg1,
|
||||
lag_ratio=1 / len(lbg0),
|
||||
run_time=2,
|
||||
),
|
||||
)
|
||||
self.wait()
|
||||
self.play(
|
||||
FadeOut(r_bar_groups[-1]),
|
||||
FadeOut(l_bar_groups[-1]),
|
||||
r_graph.set_fill, BLUE_E, 1,
|
||||
l_graph.set_fill, RED_E, 1,
|
||||
)
|
||||
|
||||
|
||||
class MeasureTheoryLeadsTo(Scene):
|
||||
def construct(self):
|
||||
words = TextMobject("Measure Theory")
|
||||
words.set_color(RED)
|
||||
arrow = Vector(DOWN)
|
||||
arrow.next_to(words, DOWN, buff=SMALL_BUFF)
|
||||
arrow.set_stroke(width=7)
|
||||
arrow.rotate(45 * DEGREES, about_point=arrow.get_start())
|
||||
self.play(
|
||||
FadeInFrom(words, DOWN),
|
||||
GrowArrow(arrow),
|
||||
UpdateFromAlphaFunc(arrow, lambda m, a: m.set_opacity(a)),
|
||||
)
|
||||
self.wait()
|
||||
|
||||
|
||||
class WhenIWasFirstLearning(TeacherStudentsScene):
|
||||
def construct(self):
|
||||
self.teacher.change_mode("raise_right_hand")
|
||||
self.play(
|
||||
self.get_student_changes("pondering", "thinking", "tease"),
|
||||
self.teacher.change, "thinking",
|
||||
)
|
||||
|
||||
younger = BabyPiCreature(color=GREY_BROWN)
|
||||
younger.set_height(2)
|
||||
younger.move_to(self.students, DL)
|
||||
|
||||
self.look_at(self.screen)
|
||||
self.wait()
|
||||
self.play(
|
||||
ReplacementTransform(self.teacher, younger),
|
||||
LaggedStartMap(
|
||||
FadeOutAndShift, self.students,
|
||||
lambda m: (m, DOWN),
|
||||
)
|
||||
)
|
||||
|
||||
# Bubble
|
||||
bubble = ThoughtBubble()
|
||||
bubble[-1].set_fill(GREEN_SCREEN, 1)
|
||||
bubble.move_to(younger.get_corner(UR), DL)
|
||||
|
||||
self.play(
|
||||
Write(bubble),
|
||||
younger.change, "maybe", bubble.get_bubble_center(),
|
||||
)
|
||||
self.play(Blink(younger))
|
||||
for mode in ["confused", "angry", "pondering", "maybe"]:
|
||||
self.play(younger.change, mode)
|
||||
for x in range(2):
|
||||
self.wait()
|
||||
if random.random() < 0.5:
|
||||
self.play(Blink(younger))
|
||||
|
||||
|
||||
class PossibleYetProbabilityZero(Scene):
|
||||
def construct(self):
|
||||
poss = TextMobject("Possible")
|
||||
prob = TextMobject("Probability = 0")
|
||||
total = TextMobject("P(dart hits somewhere) = 1")
|
||||
# total[1].next_to(total[0][0], RIGHT)
|
||||
words = VGroup(poss, prob, total)
|
||||
words.scale(1.5)
|
||||
words.arrange(DOWN, aligned_edge=LEFT, buff=MED_LARGE_BUFF)
|
||||
|
||||
self.play(Write(poss, run_time=0.5))
|
||||
self.wait()
|
||||
self.play(FadeInFrom(prob, UP))
|
||||
self.wait()
|
||||
self.play(FadeInFrom(total, UP))
|
||||
self.wait()
|
||||
|
||||
|
||||
class TiePossibleToDensity(Scene):
|
||||
def construct(self):
|
||||
poss = TextMobject("Possibility")
|
||||
prob = TextMobject("Probability", " $>$ 0")
|
||||
dens = TextMobject("Probability \\emph{density}", " $>$ 0")
|
||||
dens[0].set_color(BLUE)
|
||||
implies = TexMobject("\\Rightarrow")
|
||||
implies2 = implies.copy()
|
||||
|
||||
poss.next_to(implies, LEFT)
|
||||
prob.next_to(implies, RIGHT)
|
||||
dens.next_to(implies, RIGHT)
|
||||
cross = Cross(implies)
|
||||
|
||||
self.camera.frame.scale(0.7, about_point=dens.get_center())
|
||||
|
||||
self.add(poss)
|
||||
self.play(
|
||||
FadeInFrom(prob, LEFT),
|
||||
Write(implies, run_time=1)
|
||||
)
|
||||
self.wait()
|
||||
self.play(ShowCreation(cross))
|
||||
self.wait()
|
||||
|
||||
self.play(
|
||||
VGroup(implies, cross, prob).shift, UP,
|
||||
FadeIn(implies2),
|
||||
FadeIn(dens),
|
||||
)
|
||||
self.wait()
|
||||
|
||||
self.embed()
|
||||
|
||||
|
||||
class DrawBigRect(Scene):
|
||||
def construct(self):
|
||||
rect = Rectangle(width=7, height=2.5)
|
||||
rect.set_stroke(RED, 5)
|
||||
rect.to_edge(RIGHT)
|
||||
|
||||
words = TextMobject("Not how to\\\\think about it")
|
||||
words.set_color(RED)
|
||||
words.align_to(rect, LEFT)
|
||||
words.to_edge(UP)
|
||||
|
||||
arrow = Arrow(
|
||||
words.get_bottom(),
|
||||
rect.get_top(),
|
||||
buff=0.25,
|
||||
color=RED,
|
||||
)
|
||||
|
||||
self.play(ShowCreation(rect))
|
||||
self.play(
|
||||
FadeInFromDown(words),
|
||||
GrowArrow(arrow),
|
||||
)
|
||||
self.wait()
|
||||
|
||||
|
||||
class Thumbnail(Scene):
|
||||
def construct(self):
|
||||
pass
|
||||
dartboard = Dartboard()
|
||||
axes = NumberPlane(
|
||||
x_min=-1.25,
|
||||
x_max=1.25,
|
||||
y_min=-1.25,
|
||||
y_max=1.25,
|
||||
axis_config={
|
||||
"unit_size": 0.5 * dartboard.get_width(),
|
||||
"tick_frequency": 0.25,
|
||||
},
|
||||
x_line_frequency=1.0,
|
||||
y_line_frequency=1.0,
|
||||
)
|
||||
group = VGroup(dartboard, axes)
|
||||
group.to_edge(LEFT, buff=0)
|
||||
|
||||
# Arrow
|
||||
arrow = Vector(DR, max_stroke_width_to_length_ratio=np.inf)
|
||||
arrow.move_to(axes.c2p(PI / 10, np.exp(1) / 10), DR)
|
||||
arrow.scale(1.5, about_edge=DR)
|
||||
arrow.set_stroke(WHITE, 10)
|
||||
|
||||
black_arrow = arrow.copy()
|
||||
black_arrow.set_color(BLACK)
|
||||
black_arrow.set_stroke(width=20)
|
||||
|
||||
arrow.points[0] += 0.025 * DR
|
||||
|
||||
# Coords
|
||||
coords = TexMobject("(x, y) = (0.31415\\dots, 0.27182\\dots)")
|
||||
coords.set_width(5.5)
|
||||
coords.set_stroke(BLACK, 10, background=True)
|
||||
coords.next_to(axes.get_bottom(), UP, buff=0)
|
||||
|
||||
# Words
|
||||
words = VGroup(
|
||||
TextMobject("Probability = 0"),
|
||||
TextMobject("$\\dots$but still possible"),
|
||||
)
|
||||
for word in words:
|
||||
word.set_width(6)
|
||||
words.arrange(DOWN, buff=MED_LARGE_BUFF)
|
||||
words.next_to(axes, RIGHT)
|
||||
words.to_edge(UP, buff=LARGE_BUFF)
|
||||
|
||||
# Pi
|
||||
morty = Mortimer()
|
||||
morty.to_corner(DR)
|
||||
morty.change("confused", words)
|
||||
|
||||
self.add(group)
|
||||
self.add(black_arrow)
|
||||
self.add(arrow)
|
||||
self.add(coords)
|
||||
self.add(words)
|
||||
self.add(morty)
|
||||
|
||||
self.embed()
|
||||
|
||||
|
||||
class Part2EndScreen(PatreonEndScreen):
|
||||
|
|
|
|||
|
|
@ -1,22 +1,16 @@
|
|||
from manimlib.imports import *
|
||||
from from_3b1b.active.bayes.beta_helpers import *
|
||||
from from_3b1b.active.bayes.beta1 import *
|
||||
from from_3b1b.active.bayes.beta2 import *
|
||||
from from_3b1b.active.bayes.beta2 import ShowLimitToPdf
|
||||
|
||||
import scipy.stats
|
||||
|
||||
OUTPUT_DIRECTORY = "bayes/beta3"
|
||||
|
||||
|
||||
class WeightedCoin(Scene):
|
||||
class RemindOfWeightedCoin(Scene):
|
||||
def construct(self):
|
||||
# Coin grid
|
||||
bools = 50 * [True] + 50 * [False]
|
||||
random.shuffle(bools)
|
||||
grid = get_coin_grid(bools)
|
||||
|
||||
sorted_grid = VGroup(*grid)
|
||||
sorted_grid.submobjects.sort(key=lambda m: m.symbol)
|
||||
# Largely copied from beta2
|
||||
|
||||
# Prob label
|
||||
p_label = get_prob_coin_label()
|
||||
|
|
@ -24,165 +18,164 @@ class WeightedCoin(Scene):
|
|||
p_label.to_edge(UP)
|
||||
|
||||
rhs = p_label[-1]
|
||||
rhs_box = SurroundingRectangle(rhs, color=RED)
|
||||
rhs_label = TextMobject("Not necessarily")
|
||||
rhs_label.next_to(rhs_box, DOWN, LARGE_BUFF)
|
||||
rhs_label.to_edge(RIGHT)
|
||||
rhs_label.match_color(rhs_box)
|
||||
q_box = get_q_box(rhs)
|
||||
p_label.add(q_box)
|
||||
|
||||
rhs_arrow = Arrow(
|
||||
rhs_label.get_top(),
|
||||
rhs_box.get_right(),
|
||||
buff=SMALL_BUFF,
|
||||
path_arc=60 * DEGREES,
|
||||
color=rhs_box.get_color()
|
||||
)
|
||||
self.add(p_label)
|
||||
|
||||
# Introduce coin
|
||||
self.play(FadeIn(
|
||||
grid,
|
||||
run_time=2,
|
||||
rate_func=linear,
|
||||
lag_ratio=3 / len(grid),
|
||||
# Coin grid
|
||||
def get_random_coin_grid(p):
|
||||
bools = np.random.random(100) < p
|
||||
grid = get_coin_grid(bools)
|
||||
return grid
|
||||
|
||||
grid = get_random_coin_grid(0.5)
|
||||
grid.next_to(p_label, DOWN, MED_LARGE_BUFF)
|
||||
|
||||
self.play(LaggedStartMap(
|
||||
FadeIn, grid,
|
||||
lag_ratio=2 / len(grid),
|
||||
run_time=3,
|
||||
))
|
||||
self.wait()
|
||||
self.play(
|
||||
grid.set_height, 5,
|
||||
grid.to_edge, DOWN,
|
||||
FadeInFromDown(p_label)
|
||||
)
|
||||
|
||||
for coin in grid:
|
||||
coin.generate_target()
|
||||
sorted_coins = list(grid)
|
||||
sorted_coins.sort(key=lambda m: m.symbol)
|
||||
for c1, c2 in zip(sorted_coins, grid):
|
||||
c1.target.move_to(c2)
|
||||
# Label as h
|
||||
brace = Brace(q_box, DOWN, buff=SMALL_BUFF)
|
||||
h_label = TexMobject("h")
|
||||
h_label.next_to(brace, DOWN)
|
||||
eq = TexMobject("=")
|
||||
eq.next_to(h_label, RIGHT)
|
||||
h_decimal = DecimalNumber(0.5)
|
||||
h_decimal.next_to(eq, RIGHT)
|
||||
|
||||
self.play(
|
||||
FadeIn(rhs_label, lag_ratio=0.1),
|
||||
ShowCreation(rhs_arrow),
|
||||
ShowCreation(rhs_box),
|
||||
LaggedStartMap(
|
||||
MoveToTarget, grid,
|
||||
path_arc=30 * DEGREES,
|
||||
lag_ratio=0.01,
|
||||
),
|
||||
GrowFromCenter(brace),
|
||||
FadeInFrom(h_label, UP),
|
||||
grid.scale, 0.8, {"about_edge": DOWN},
|
||||
)
|
||||
self.wait()
|
||||
|
||||
# Alternate weightings
|
||||
old_grid = VGroup(*sorted_coins)
|
||||
rhs_junk_on_screen = True
|
||||
for value in [0.2, 0.9, 0.31]:
|
||||
n = int(100 * value)
|
||||
new_grid = get_coin_grid([True] * n + [False] * (100 - n))
|
||||
new_grid.replace(grid)
|
||||
tail_grid = get_random_coin_grid(0)
|
||||
head_grid = get_random_coin_grid(1)
|
||||
grid70 = get_random_coin_grid(0.7)
|
||||
alt_grids = [tail_grid, head_grid, grid70]
|
||||
for ag in alt_grids:
|
||||
ag.replace(grid)
|
||||
|
||||
anims = []
|
||||
if rhs_junk_on_screen:
|
||||
anims += [
|
||||
FadeOut(rhs_box),
|
||||
FadeOut(rhs_label),
|
||||
FadeOut(rhs_arrow),
|
||||
]
|
||||
rhs_junk_on_screen = False
|
||||
for coins in [grid, *alt_grids]:
|
||||
for coin in coins:
|
||||
coin.generate_target()
|
||||
coin.target.rotate(90 * DEGREES, axis=UP)
|
||||
coin.target.set_opacity(0)
|
||||
|
||||
self.wait()
|
||||
self.play(
|
||||
FadeOutAndShift(
|
||||
old_grid,
|
||||
0.1 * DOWN,
|
||||
lag_ratio=0.01,
|
||||
run_time=1.5
|
||||
),
|
||||
FadeIn(new_grid, lag_ratio=0.01, run_time=1.5),
|
||||
ChangeDecimalToValue(rhs, value),
|
||||
*anims,
|
||||
)
|
||||
old_grid = new_grid
|
||||
def get_grid_swap_anims(g1, g2):
|
||||
return [
|
||||
LaggedStartMap(MoveToTarget, g1, lag_ratio=0.02, run_time=1.5, remover=True),
|
||||
LaggedStartMap(MoveToTarget, g2, lag_ratio=0.02, run_time=1.5, rate_func=reverse_smooth),
|
||||
]
|
||||
|
||||
long_rhs = DecimalNumber(
|
||||
0.31415926,
|
||||
num_decimal_places=8,
|
||||
show_ellipsis=True,
|
||||
)
|
||||
long_rhs.match_height(rhs)
|
||||
long_rhs.move_to(rhs, DL)
|
||||
|
||||
self.play(ShowIncreasingSubsets(long_rhs, rate_func=linear))
|
||||
self.wait()
|
||||
|
||||
# You just don't know
|
||||
box = get_q_box(rhs)
|
||||
|
||||
self.remove(rhs)
|
||||
self.play(
|
||||
FadeOut(old_grid, lag_ratio=0.1),
|
||||
FadeOutAndShift(long_rhs, 0.1 * RIGHT, lag_ratio=0.1),
|
||||
Write(box),
|
||||
FadeIn(eq),
|
||||
UpdateFromAlphaFunc(h_decimal, lambda m, a: m.set_opacity(a)),
|
||||
ChangeDecimalToValue(h_decimal, 0, run_time=2),
|
||||
*get_grid_swap_anims(grid, tail_grid)
|
||||
)
|
||||
p_label.add(box)
|
||||
self.wait()
|
||||
|
||||
# 7/10 heads
|
||||
bools = [True] * 7 + [False] * 3
|
||||
random.shuffle(bools)
|
||||
coins = VGroup(*[
|
||||
get_coin("H" if heads else "T")
|
||||
for heads in bools
|
||||
])
|
||||
coins.arrange(RIGHT)
|
||||
coins.set_height(0.7)
|
||||
coins.next_to(p_label, DOWN, buff=LARGE_BUFF)
|
||||
|
||||
heads_arrows = VGroup(*[
|
||||
Vector(
|
||||
0.5 * UP,
|
||||
max_stroke_width_to_length_ratio=15,
|
||||
max_tip_length_to_length_ratio=0.4,
|
||||
).next_to(coin, DOWN)
|
||||
for coin in coins
|
||||
if coin.symbol == "H"
|
||||
])
|
||||
numbers = VGroup(*[
|
||||
Integer(i + 1).next_to(arrow, DOWN, SMALL_BUFF)
|
||||
for i, arrow in enumerate(heads_arrows)
|
||||
])
|
||||
|
||||
for coin in coins:
|
||||
coin.save_state()
|
||||
coin.stretch(0, 0)
|
||||
coin.set_opacity(0)
|
||||
|
||||
self.play(LaggedStartMap(Restore, coins), run_time=1)
|
||||
self.play(
|
||||
ShowIncreasingSubsets(heads_arrows),
|
||||
ShowIncreasingSubsets(numbers),
|
||||
rate_func=linear,
|
||||
ChangeDecimalToValue(h_decimal, 1, run_time=1.5),
|
||||
*get_grid_swap_anims(tail_grid, head_grid)
|
||||
)
|
||||
self.wait()
|
||||
self.play(
|
||||
ChangeDecimalToValue(h_decimal, 0.7, run_time=1.5),
|
||||
*get_grid_swap_anims(head_grid, grid70)
|
||||
)
|
||||
self.wait()
|
||||
|
||||
# Plot
|
||||
# axes = scaled_pdf_axes(scale_factor=2)
|
||||
# Graph
|
||||
axes = scaled_pdf_axes()
|
||||
axes.to_edge(DOWN, buff=MED_SMALL_BUFF)
|
||||
axes.y_axis.numbers.set_opacity(0)
|
||||
axes.y_axis_label.set_opacity(0)
|
||||
|
||||
h_lines = VGroup()
|
||||
for y in range(15):
|
||||
h_line = Line(axes.c2p(0, y), axes.c2p(1, y))
|
||||
h_lines.add(h_line)
|
||||
h_lines.set_stroke(WHITE, 0.5, opacity=0.5)
|
||||
axes.add(h_lines)
|
||||
|
||||
x_axis_label = p_label[:4].copy()
|
||||
x_axis_label.set_height(0.4)
|
||||
x_axis_label.next_to(axes.c2p(1, 0), UR, buff=SMALL_BUFF)
|
||||
axes.x_axis.add(x_axis_label)
|
||||
|
||||
n_heads = 7
|
||||
n_tails = 3
|
||||
graph = get_beta_graph(axes, n_heads, n_tails)
|
||||
dist = scipy.stats.beta(n_heads + 1, n_tails + 1)
|
||||
true_graph = axes.get_graph(dist.pdf)
|
||||
n_heads_tracker = ValueTracker(3)
|
||||
n_tails_tracker = ValueTracker(3)
|
||||
|
||||
region = get_region_under_curve(axes, true_graph, 0.6, 0.8)
|
||||
region.set_fill(GREY, 0.85)
|
||||
region.set_stroke(YELLOW, 1)
|
||||
def get_graph(axes=axes, nht=n_heads_tracker, ntt=n_tails_tracker):
|
||||
dist = scipy.stats.beta(nht.get_value() + 1, ntt.get_value() + 1)
|
||||
graph = axes.get_graph(dist.pdf, step_size=0.05)
|
||||
graph.set_stroke(BLUE, 3)
|
||||
graph.set_fill(BLUE_E, 1)
|
||||
return graph
|
||||
|
||||
graph = always_redraw(get_graph)
|
||||
|
||||
area_label = TextMobject("Area = 1")
|
||||
area_label.set_height(0.5)
|
||||
area_label.move_to(axes.c2p(0.5, 1))
|
||||
|
||||
# pdf label
|
||||
pdf_label = TextMobject("probability ", "density ", "function")
|
||||
pdf_label.next_to(axes.input_to_graph_point(0.5, graph), UP)
|
||||
pdf_target_template = TextMobject("p", "d", "f")
|
||||
pdf_target_template.next_to(axes.input_to_graph_point(0.7, graph), UR)
|
||||
pdf_label.generate_target()
|
||||
for part, letter2 in zip(pdf_label.target, pdf_target_template):
|
||||
for letter1 in part:
|
||||
letter1.move_to(letter2)
|
||||
part[1:].set_opacity(0)
|
||||
|
||||
# Add plot
|
||||
self.add(axes, *self.mobjects)
|
||||
self.play(
|
||||
FadeOut(eq),
|
||||
FadeOut(h_decimal),
|
||||
LaggedStartMap(MoveToTarget, grid70, run_time=1, remover=True),
|
||||
FadeIn(axes),
|
||||
)
|
||||
self.play(
|
||||
DrawBorderThenFill(graph),
|
||||
FadeIn(area_label, rate_func=squish_rate_func(smooth, 0.5, 1), run_time=2),
|
||||
Write(pdf_label, run_time=1),
|
||||
)
|
||||
self.wait()
|
||||
|
||||
# Region
|
||||
lh_tracker = ValueTracker(0.7)
|
||||
rh_tracker = ValueTracker(0.7)
|
||||
|
||||
def get_region(axes=axes, graph=graph, lh_tracker=lh_tracker, rh_tracker=rh_tracker):
|
||||
lh = lh_tracker.get_value()
|
||||
rh = rh_tracker.get_value()
|
||||
region = get_region_under_curve(axes, graph, lh, rh)
|
||||
region.set_fill(GREY, 0.85)
|
||||
region.set_stroke(YELLOW, 1)
|
||||
return region
|
||||
|
||||
region = always_redraw(get_region)
|
||||
|
||||
region_area_label = DecimalNumber(num_decimal_places=3)
|
||||
region_area_label.next_to(axes.c2p(0.7, 0), UP, MED_LARGE_BUFF)
|
||||
|
||||
def update_ra_label(label, nht=n_heads_tracker, ntt=n_tails_tracker, lht=lh_tracker, rht=rh_tracker):
|
||||
dist = scipy.stats.beta(nht.get_value() + 1, ntt.get_value() + 1)
|
||||
area = dist.cdf(rht.get_value()) - dist.cdf(lht.get_value())
|
||||
label.set_value(area)
|
||||
|
||||
region_area_label.add_updater(update_ra_label)
|
||||
|
||||
range_label = VGroup(
|
||||
TexMobject("0.6 \\le"),
|
||||
|
|
@ -203,73 +196,119 @@ class WeightedCoin(Scene):
|
|||
pp_label.arrange(RIGHT, buff=SMALL_BUFF)
|
||||
pp_label.move_to(axes.c2p(0.3, 3))
|
||||
|
||||
self.play(
|
||||
FadeOut(heads_arrows),
|
||||
FadeOut(numbers),
|
||||
Write(axes),
|
||||
DrawBorderThenFill(graph),
|
||||
)
|
||||
self.play(
|
||||
FadeIn(pp_label[::2]),
|
||||
FadeIn(region),
|
||||
MoveToTarget(pdf_label),
|
||||
FadeOut(area_label),
|
||||
)
|
||||
self.wait()
|
||||
self.play(TransformFromCopy(p_label[:4], range_label[1]))
|
||||
self.play(GrowFromPoint(range_label[0], axes.c2p(0.6, 0)))
|
||||
self.play(GrowFromPoint(range_label[2], axes.c2p(0.8, 0)))
|
||||
self.wait()
|
||||
self.play(TransformFromCopy(axes.x_axis.numbers[2], range_label[0]))
|
||||
self.play(TransformFromCopy(axes.x_axis.numbers[3], range_label[2]))
|
||||
self.wait()
|
||||
|
||||
# Remind what the title is
|
||||
title = TextMobject(
|
||||
"Probabilities", "of", "Probabilities"
|
||||
self.add(region)
|
||||
self.play(
|
||||
lh_tracker.set_value, 0.6,
|
||||
rh_tracker.set_value, 0.8,
|
||||
UpdateFromAlphaFunc(
|
||||
region_area_label,
|
||||
lambda m, a: m.set_opacity(a),
|
||||
rate_func=squish_rate_func(smooth, 0.25, 1)
|
||||
),
|
||||
run_time=3,
|
||||
)
|
||||
self.wait()
|
||||
|
||||
# 7/10 heads
|
||||
bools = [True] * 7 + [False] * 3
|
||||
random.shuffle(bools)
|
||||
coins = VGroup(*[
|
||||
get_coin("H" if heads else "T")
|
||||
for heads in bools
|
||||
])
|
||||
coins.arrange(RIGHT)
|
||||
coins.set_height(0.7)
|
||||
coins.next_to(h_label, DOWN, buff=MED_LARGE_BUFF)
|
||||
|
||||
heads = [c for c in coins if c.symbol == "H"]
|
||||
numbers = VGroup(*[
|
||||
Integer(i + 1).set_height(0.2).next_to(coin, DOWN, SMALL_BUFF)
|
||||
for i, coin in enumerate(heads)
|
||||
])
|
||||
|
||||
for coin in coins:
|
||||
coin.save_state()
|
||||
coin.rotate(90 * DEGREES, UP)
|
||||
coin.set_opacity(0)
|
||||
|
||||
pp_label.generate_target()
|
||||
pp_label.target.set_height(0.5)
|
||||
pp_label.target.next_to(axes.c2p(0, 2), RIGHT, MED_LARGE_BUFF)
|
||||
|
||||
self.play(
|
||||
LaggedStartMap(Restore, coins),
|
||||
MoveToTarget(pp_label),
|
||||
run_time=1,
|
||||
)
|
||||
self.play(ShowIncreasingSubsets(numbers))
|
||||
self.wait()
|
||||
|
||||
# Move plot
|
||||
self.play(
|
||||
n_heads_tracker.set_value, 7,
|
||||
n_tails_tracker.set_value, 3,
|
||||
FadeOut(pdf_label, rate_func=squish_rate_func(smooth, 0, 0.5)),
|
||||
run_time=2
|
||||
)
|
||||
title.arrange(DOWN, aligned_edge=LEFT)
|
||||
title.next_to(axes.c2p(0, 0), UR, buff=MED_LARGE_BUFF)
|
||||
title.align_to(pp_label, LEFT)
|
||||
|
||||
self.play(ShowIncreasingSubsets(title, rate_func=linear))
|
||||
self.wait()
|
||||
self.play(FadeOut(title))
|
||||
|
||||
# How does the answer change with more data
|
||||
new_bools = [True] * 63 + [False] * 27
|
||||
random.shuffle(new_bools)
|
||||
bools += new_bools
|
||||
bools = [c.symbol == "H" for c in coins] + new_bools
|
||||
grid = get_coin_grid(bools)
|
||||
grid.set_height(3.5)
|
||||
grid.next_to(axes.c2p(0, 3), RIGHT, MED_LARGE_BUFF)
|
||||
|
||||
pp_label.generate_target()
|
||||
pp_label.target.next_to(p_label, DOWN, MED_LARGE_BUFF)
|
||||
pp_label.target.match_x(pp_label)
|
||||
rhs.set_opacity(0)
|
||||
|
||||
grid.next_to(pp_label.target, DOWN, MED_LARGE_BUFF, aligned_edge=LEFT)
|
||||
|
||||
self.remove(coins)
|
||||
self.add(p_label)
|
||||
self.play(
|
||||
ReplacementTransform(coins, grid[:10], path_arc=-30 * DEGREES),
|
||||
FadeOut(numbers),
|
||||
ReplacementTransform(coins, grid[:10]),
|
||||
)
|
||||
self.play(
|
||||
FadeIn(grid[10:], lag_ratio=0.1, rate_func=linear),
|
||||
MoveToTarget(pp_label, path_arc=-30 * DEGREES),
|
||||
p_label.align_to, pp_label.target, LEFT,
|
||||
pp_label.next_to, grid, DOWN,
|
||||
)
|
||||
self.wait()
|
||||
self.add(graph, region, region_area_label, p_label, q_box, brace, h_label)
|
||||
self.play(
|
||||
n_heads_tracker.set_value, 70,
|
||||
n_tails_tracker.set_value, 30,
|
||||
)
|
||||
self.wait()
|
||||
origin = axes.c2p(0, 0)
|
||||
self.play(
|
||||
axes.y_axis.stretch, 0.5, 1, {"about_point": origin},
|
||||
h_lines.stretch, 0.5, 1, {"about_point": origin},
|
||||
)
|
||||
self.wait()
|
||||
|
||||
n_heads = 70
|
||||
n_tails = 30
|
||||
graph100 = get_beta_graph(axes, n_heads, n_tails)
|
||||
dist = scipy.stats.beta(n_heads + 1, n_tails + 1)
|
||||
true_graph100 = axes.get_graph(dist.pdf, step_size=0.01)
|
||||
region100 = get_region_under_curve(axes, true_graph100, 0.6, 0.8)
|
||||
region100.match_style(region)
|
||||
|
||||
self.play(
|
||||
graph.set_opacity, 0.2,
|
||||
region.set_opacity, 0.2,
|
||||
FadeIn(graph100),
|
||||
FadeIn(region100),
|
||||
)
|
||||
self.play(FadeIn(region100))
|
||||
# Shift the shape around
|
||||
pairs = [
|
||||
(70 * 3, 30 * 3),
|
||||
(35, 15),
|
||||
(35 + 20, 15 + 20),
|
||||
(7, 3),
|
||||
(70, 30),
|
||||
]
|
||||
for nh, nt in pairs:
|
||||
self.play(
|
||||
n_heads_tracker.set_value, nh,
|
||||
n_tails_tracker.set_value, nt,
|
||||
run_time=2,
|
||||
)
|
||||
self.wait()
|
||||
|
||||
# End
|
||||
self.embed()
|
||||
|
|
@ -300,6 +339,110 @@ class ComplainAboutSimplisticModel(ExternallyAnimatedScene):
|
|||
pass
|
||||
|
||||
|
||||
class BayesianFrequentistDivide(Scene):
|
||||
def construct(self):
|
||||
# Setup Bayesian vs. Frequentist divide
|
||||
b_label = TextMobject("Bayesian")
|
||||
f_label = TextMobject("Frequentist")
|
||||
labels = VGroup(b_label, f_label)
|
||||
for label, vect in zip(labels, [LEFT, RIGHT]):
|
||||
label.set_height(0.7)
|
||||
label.move_to(vect * FRAME_WIDTH / 4)
|
||||
label.to_edge(UP, buff=0.35)
|
||||
|
||||
h_line = Line(LEFT, RIGHT)
|
||||
h_line.set_width(FRAME_WIDTH)
|
||||
h_line.next_to(labels, DOWN)
|
||||
v_line = Line(UP, DOWN)
|
||||
v_line.set_height(FRAME_HEIGHT)
|
||||
v_line.center()
|
||||
|
||||
for label in labels:
|
||||
label.save_state()
|
||||
label.set_y(0)
|
||||
self.play(
|
||||
FadeInFrom(label, -normalize(label.get_center())),
|
||||
)
|
||||
self.wait()
|
||||
self.play(
|
||||
ShowCreation(VGroup(v_line, h_line)),
|
||||
*map(Restore, labels),
|
||||
)
|
||||
self.wait()
|
||||
|
||||
# Overlay ShowBayesianUpdating in editing
|
||||
# Frequentist list (ignore?)
|
||||
kw = {
|
||||
"tex_to_color_map": {
|
||||
"$p$-value": YELLOW,
|
||||
"$H_0$": PINK,
|
||||
"$\\alpha$": BLUE,
|
||||
},
|
||||
"alignment": "",
|
||||
}
|
||||
freq_list = VGroup(
|
||||
TextMobject("1. State a null hypothesis $H_0$", **kw),
|
||||
TextMobject("2. Choose a test statistic,\\\\", "$\\qquad$ compute its value", **kw),
|
||||
TextMobject("3. Calculate a $p$-value", **kw),
|
||||
TextMobject("4. Choose a significance value $\\alpha$", **kw),
|
||||
TextMobject("5. Reject $H_0$ if $p$-value\\\\", "$\\qquad$ is less than $\\alpha$", **kw),
|
||||
)
|
||||
|
||||
freq_list.set_width(0.5 * FRAME_WIDTH - 1)
|
||||
freq_list.arrange(DOWN, buff=MED_LARGE_BUFF, aligned_edge=LEFT)
|
||||
freq_list.move_to(FRAME_WIDTH * RIGHT / 4)
|
||||
freq_list.to_edge(DOWN, buff=LARGE_BUFF)
|
||||
|
||||
# Frequentist icon
|
||||
axes = get_beta_dist_axes(y_max=5, y_unit=1)
|
||||
axes.set_width(0.5 * FRAME_WIDTH - 1)
|
||||
axes.move_to(FRAME_WIDTH * RIGHT / 4 + DOWN)
|
||||
|
||||
dist = scipy.stats.norm(0.5, 0.1)
|
||||
graph = axes.get_graph(dist.pdf)
|
||||
graphs = VGroup()
|
||||
for x_min, x_max in [(0, 0.3), (0.3, 0.7), (0.7, 1.0)]:
|
||||
graph = axes.get_graph(dist.pdf, x_min=x_min, x_max=x_max)
|
||||
graph.add_line_to(axes.c2p(x_max, 0))
|
||||
graph.add_line_to(axes.c2p(x_min, 0))
|
||||
graph.add_line_to(graph.get_start())
|
||||
graphs.add(graph)
|
||||
|
||||
graphs.set_stroke(width=0)
|
||||
graphs.set_fill(RED, 1)
|
||||
graphs[1].set_fill(GREY_D, 1)
|
||||
|
||||
H_words = VGroup(*[TextMobject("Reject\\\\$H_0$") for x in range(2)])
|
||||
for H_word, graph, vect in zip(H_words, graphs[::2], [RIGHT, LEFT]):
|
||||
H_word.next_to(graph, UP, MED_LARGE_BUFF)
|
||||
arrow = Arrow(
|
||||
H_word.get_bottom(),
|
||||
graph.get_center() + 0.75 * vect,
|
||||
buff=SMALL_BUFF
|
||||
)
|
||||
H_word.add(arrow)
|
||||
|
||||
H_words.set_color(RED)
|
||||
self.add(H_words)
|
||||
|
||||
self.add(axes)
|
||||
self.add(graphs)
|
||||
|
||||
self.embed()
|
||||
|
||||
# Transition to 2x2
|
||||
# Go back to prior
|
||||
# Label uniform prior
|
||||
# Talk about real coin prior
|
||||
# Update ad infinitum
|
||||
|
||||
|
||||
class ArgumentBetweenBayesianAndFrequentist(Scene):
|
||||
def construct(self):
|
||||
pass
|
||||
|
||||
|
||||
# From version 1
|
||||
class ShowBayesianUpdating(Scene):
|
||||
CONFIG = {
|
||||
"true_p": 0.72,
|
||||
|
|
@ -597,7 +740,6 @@ class ShowBayesianUpdating(Scene):
|
|||
return p_label, prob, prob_box
|
||||
|
||||
|
||||
# From version 1
|
||||
class HighlightReviewPartsReversed(HighlightReviewParts):
|
||||
CONFIG = {
|
||||
"reverse_order": True,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue