Published pdf video

This commit is contained in:
Grant Sanderson 2020-04-12 09:54:20 -07:00
parent 6e523ed960
commit 965564853b
2 changed files with 766 additions and 190 deletions

View file

@ -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):

View file

@ -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,