mirror of
https://github.com/3b1b/manim.git
synced 2025-07-30 21:44:19 +08:00
Preliminary end to bayes animations
This commit is contained in:
580
eop/bayes.py
580
eop/bayes.py
@ -1091,10 +1091,59 @@ class UpdatePokerPrior(SampleSpaceScene):
|
||||
new_label_kwargs = {"labels" : [label]},
|
||||
)
|
||||
|
||||
class BayesRuleInMemory(Scene):
|
||||
def construct(self):
|
||||
randy = Randolph()
|
||||
randy.to_corner(DOWN+LEFT)
|
||||
bubble = ThoughtBubble(height = 4)
|
||||
bubble.pin_to(randy)
|
||||
B = "\\text{Belief}"
|
||||
D = "\\text{Data}"
|
||||
rule = TexMobject(
|
||||
"P(", B, "|", D, ")", "=",
|
||||
"P(", "B", ")",
|
||||
"{P(", D, "|", B, ")", "\\over", "P(", D, ")}"
|
||||
)
|
||||
rule.highlight_by_tex(B, RED)
|
||||
rule.highlight_by_tex(D, GREEN)
|
||||
rule.next_to(randy, RIGHT, LARGE_BUFF, UP)
|
||||
rule.generate_target()
|
||||
bubble.add_content(rule.target)
|
||||
screen_rect = ScreenRectangle()
|
||||
screen_rect.next_to(randy, UP+RIGHT)
|
||||
|
||||
self.add(randy)
|
||||
self.play(
|
||||
LaggedStart(FadeIn, rule),
|
||||
randy.change, "erm", rule
|
||||
)
|
||||
self.play(Blink(randy))
|
||||
self.play(
|
||||
ShowCreation(bubble),
|
||||
MoveToTarget(rule),
|
||||
randy.change, "pondering",
|
||||
)
|
||||
self.dither()
|
||||
self.play(rule.fade, 0.7, run_time = 2)
|
||||
self.play(randy.change, "confused", rule)
|
||||
self.play(Blink(randy))
|
||||
self.dither(2)
|
||||
self.play(
|
||||
FadeOut(VGroup(bubble, rule)),
|
||||
randy.change, "pondering", screen_rect,
|
||||
)
|
||||
self.play(
|
||||
randy.look_at, screen_rect.get_right(),
|
||||
ShowCreation(screen_rect),
|
||||
)
|
||||
self.dither(4)
|
||||
|
||||
class NextVideoWrapper(TeacherStudentsScene):
|
||||
CONFIG = {
|
||||
"title" : "Next chapter: Bayesian networks"
|
||||
}
|
||||
def construct(self):
|
||||
title = TextMobject("Next video: Bayesian networks")
|
||||
title = TextMobject(self.title)
|
||||
title.scale(0.8)
|
||||
title.to_edge(UP, buff = SMALL_BUFF)
|
||||
screen = ScreenRectangle(height = 4)
|
||||
@ -1108,7 +1157,10 @@ class NextVideoWrapper(TeacherStudentsScene):
|
||||
self.teacher.change, "raise_right_hand"
|
||||
)
|
||||
self.play(ShowCreation(screen))
|
||||
self.change_student_modes(*["pondering"]*3)
|
||||
self.change_student_modes(
|
||||
*["pondering"]*3,
|
||||
look_at_arg = screen
|
||||
)
|
||||
self.play(Animation(screen))
|
||||
self.dither(5)
|
||||
|
||||
@ -1415,21 +1467,24 @@ class MoreExamples(TeacherStudentsScene):
|
||||
|
||||
class MusicExample(SampleSpaceScene, PiCreatureScene):
|
||||
def construct(self):
|
||||
self.force_skipping()
|
||||
|
||||
self.introduce_musician()
|
||||
self.add_prior()
|
||||
self.record_track()
|
||||
self.add_bottom_conditionl()
|
||||
self.friend_gives_compliment()
|
||||
self.friends_dont_like()
|
||||
self.false_compliment()
|
||||
self.add_top_conditionl()
|
||||
self.get_positive_review()
|
||||
self.restrict_space()
|
||||
self.show_posterior_rectangles()
|
||||
self.show_prior_rectangle_areas()
|
||||
self.show_posterior_probability()
|
||||
self.intuition_of_positive_feedback()
|
||||
self.make_friends_honest()
|
||||
self.fade_out_post_rect()
|
||||
self.get_negative_feedback()
|
||||
self.show_negative_feedback_posterior()
|
||||
self.compare_prior_to_post_given_negative()
|
||||
self.intuition_of_negative_feedback()
|
||||
|
||||
def introduce_musician(self):
|
||||
@ -1438,7 +1493,7 @@ class MusicExample(SampleSpaceScene, PiCreatureScene):
|
||||
randy.arms = randy.get_arm_copies()
|
||||
guitar = randy.guitar = Guitar()
|
||||
guitar.move_to(randy)
|
||||
guitar.shift(0.35*RIGHT + 0.6*UP)
|
||||
guitar.shift(0.31*RIGHT + 0.6*UP)
|
||||
|
||||
randy.change_mode("plain")
|
||||
self.play(
|
||||
@ -1456,58 +1511,444 @@ class MusicExample(SampleSpaceScene, PiCreatureScene):
|
||||
self.change_pi_creature_with_guitar("concerned_musician")
|
||||
self.dither(2)
|
||||
self.play(
|
||||
randy.scale, 0.5,
|
||||
randy.scale, 0.7,
|
||||
randy.to_corner, UP+LEFT,
|
||||
)
|
||||
self.play_notes(guitar)
|
||||
|
||||
def add_prior(self):
|
||||
pass
|
||||
sample_space = SampleSpace()
|
||||
sample_space.shift(DOWN)
|
||||
sample_space.divide_horizontally(0.8, colors = [MAROON_D, BLUE_E])
|
||||
labels = VGroup(
|
||||
TexMobject("P(S) = ", "0.8"),
|
||||
TexMobject("P(\\text{not } S) = ", "0.2"),
|
||||
)
|
||||
labels.scale(0.7)
|
||||
braces, labels = sample_space.get_side_braces_and_labels(labels)
|
||||
VGroup(sample_space, braces, labels).to_edge(LEFT)
|
||||
words = map(TextMobject, [
|
||||
"Blunt honesty", "Some confidence"
|
||||
])
|
||||
for word, part in zip(words, sample_space.horizontal_parts):
|
||||
word.scale(0.6)
|
||||
word.move_to(part)
|
||||
|
||||
self.play(LaggedStart(FadeIn, sample_space, run_time = 1))
|
||||
self.play(*map(GrowFromCenter, braces))
|
||||
for label in labels:
|
||||
self.play(Write(label, run_time = 2))
|
||||
self.dither()
|
||||
for word, mode in zip(words, ["maybe", "soulful_musician"]):
|
||||
self.play(LaggedStart(FadeIn, word, run_time = 1))
|
||||
self.change_pi_creature_with_guitar(mode)
|
||||
self.dither()
|
||||
self.dither()
|
||||
self.play(*map(FadeOut, words))
|
||||
|
||||
self.sample_space = sample_space
|
||||
|
||||
def record_track(self):
|
||||
pass
|
||||
randy = self.pi_creature
|
||||
friends = VGroup(*[
|
||||
PiCreature(mode = "happy", color = color).flip()
|
||||
for color in BLUE_B, GREY_BROWN, MAROON_E
|
||||
])
|
||||
friends.scale(0.6)
|
||||
friends.arrange_submobjects(RIGHT)
|
||||
friends.next_to(randy, RIGHT, LARGE_BUFF, DOWN)
|
||||
friends.to_edge(RIGHT)
|
||||
for friend in friends:
|
||||
friend.look_at(randy.eyes)
|
||||
|
||||
headphones = VGroup(*map(Headphones, friends))
|
||||
|
||||
self.play(FadeIn(friends))
|
||||
self.pi_creatures.add(*friends)
|
||||
self.play(
|
||||
FadeIn(headphones),
|
||||
Animation(friends)
|
||||
)
|
||||
self.play_notes(randy.guitar)
|
||||
self.play(LaggedStart(
|
||||
ApplyMethod, friends,
|
||||
lambda pi : (pi.change, "hooray"),
|
||||
run_time = 2,
|
||||
))
|
||||
|
||||
self.friends = friends
|
||||
self.headphones = headphones
|
||||
|
||||
def add_bottom_conditionl(self):
|
||||
pass
|
||||
p = 0.99
|
||||
bottom_part = self.sample_space[1]
|
||||
bottom_part.divide_vertically(p, colors = [GREEN_E, YELLOW])
|
||||
label = self.get_conditional_label(p, False)
|
||||
braces, labels = bottom_part.get_bottom_braces_and_labels([label])
|
||||
brace = braces[0]
|
||||
|
||||
self.play(FadeIn(bottom_part.vertical_parts))
|
||||
self.play(GrowFromCenter(brace))
|
||||
self.play(Write(label))
|
||||
self.dither()
|
||||
|
||||
def friend_gives_compliment(self):
|
||||
friends = self.friends
|
||||
bubble = SpeechBubble(
|
||||
height = 1.25, width = 3, direction = RIGHT,
|
||||
fill_opacity = 0,
|
||||
)
|
||||
content = TextMobject("Phenomenal!")
|
||||
content.scale(0.75)
|
||||
bubble.add_content(content)
|
||||
VGroup(bubble, content).next_to(friends, LEFT, SMALL_BUFF)
|
||||
VGroup(bubble, content).to_edge(UP, SMALL_BUFF)
|
||||
|
||||
self.play(LaggedStart(
|
||||
ApplyMethod, friends,
|
||||
lambda pi : (pi.change_mode, "conniving")
|
||||
))
|
||||
self.dither()
|
||||
self.play(
|
||||
ShowCreation(bubble),
|
||||
Write(bubble.content, run_time = 1),
|
||||
ApplyMethod(friends[0].change_mode, "hooray"),
|
||||
LaggedStart(
|
||||
ApplyMethod, VGroup(*friends[1:]),
|
||||
lambda pi : (pi.change_mode, "happy")
|
||||
),
|
||||
)
|
||||
self.dither(2)
|
||||
self.play(*map(FadeOut, [bubble, content]))
|
||||
|
||||
def friends_dont_like(self):
|
||||
friends = self.friends
|
||||
pi1, pi2, pi3 = friends
|
||||
for friend in friends:
|
||||
friend.generate_target()
|
||||
pi1.target.change("guilty", pi2.eyes)
|
||||
pi2.target.change("hesitant", pi1.eyes)
|
||||
pi3.target.change("pondering", pi2.eyes)
|
||||
|
||||
self.play(LaggedStart(
|
||||
MoveToTarget, friends
|
||||
))
|
||||
self.change_pi_creature_with_guitar("concerned_musician")
|
||||
self.dither()
|
||||
|
||||
def false_compliment(self):
|
||||
friend = self.friends[0]
|
||||
bubble = SpeechBubble(
|
||||
height = 1.25, width = 4.5, direction = RIGHT,
|
||||
fill_opacity = 0,
|
||||
)
|
||||
content = TextMobject("The beat was consistent.")
|
||||
content.scale(0.75)
|
||||
bubble.add_content(content)
|
||||
VGroup(bubble, content).next_to(friend, LEFT, SMALL_BUFF)
|
||||
VGroup(bubble, content).to_edge(UP, SMALL_BUFF)
|
||||
|
||||
self.play(
|
||||
friend.change_mode, "maybe",
|
||||
ShowCreation(bubble),
|
||||
Write(content)
|
||||
)
|
||||
self.change_pi_creature_with_guitar("happy")
|
||||
self.dither()
|
||||
self.play(*map(FadeOut, [bubble, content]))
|
||||
|
||||
self.bubble = bubble
|
||||
|
||||
def add_top_conditionl(self):
|
||||
pass
|
||||
p = 0.9
|
||||
top_part = self.sample_space[0]
|
||||
top_part.divide_vertically(p, colors = [TEAL_E, RED_E])
|
||||
label = self.get_conditional_label(p, True)
|
||||
braces, labels = top_part.get_top_braces_and_labels([label])
|
||||
brace = braces[0]
|
||||
|
||||
self.play(FadeIn(top_part.vertical_parts))
|
||||
self.play(GrowFromCenter(brace))
|
||||
self.play(Write(label, run_time = 2))
|
||||
self.dither()
|
||||
|
||||
def get_positive_review(self):
|
||||
pass
|
||||
friends = self.friends
|
||||
|
||||
self.change_pi_creature_with_guitar(
|
||||
"soulful_musician",
|
||||
LaggedStart(
|
||||
ApplyMethod, friends,
|
||||
lambda pi : (pi.change, "happy"),
|
||||
run_time = 1,
|
||||
)
|
||||
)
|
||||
self.play_notes(self.pi_creature.guitar)
|
||||
|
||||
def restrict_space(self):
|
||||
pass
|
||||
positive_space, negative_space = [
|
||||
VGroup(*[
|
||||
self.sample_space[i][j]
|
||||
for i in range(2)
|
||||
])
|
||||
for j in range(2)
|
||||
]
|
||||
negative_space.save_state()
|
||||
|
||||
self.play(negative_space.fade, 0.8)
|
||||
self.play(LaggedStart(
|
||||
ApplyMethod, positive_space,
|
||||
lambda m : (m.highlight, YELLOW),
|
||||
rate_func = there_and_back,
|
||||
run_time = 2,
|
||||
lag_ratio = 0.7,
|
||||
))
|
||||
self.dither()
|
||||
|
||||
self.negative_space = negative_space
|
||||
|
||||
def show_posterior_rectangles(self):
|
||||
pass
|
||||
prior_rects = self.get_prior_rectangles()
|
||||
post_rects = self.get_posterior_rectangles()
|
||||
label = TexMobject("P(S | ", "\\checkmark", ")")
|
||||
label.scale(0.7)
|
||||
label.highlight_by_tex("\\checkmark", GREEN)
|
||||
braces, labels = self.get_posterior_rectangle_braces_and_labels(
|
||||
post_rects, [label]
|
||||
)
|
||||
brace = braces[0]
|
||||
|
||||
self.play(ReplacementTransform(
|
||||
prior_rects.copy(), post_rects,
|
||||
run_time = 2
|
||||
))
|
||||
self.play(GrowFromCenter(brace))
|
||||
self.play(Write(label))
|
||||
self.dither()
|
||||
|
||||
self.post_rects = post_rects
|
||||
self.post_tex = label
|
||||
|
||||
def show_prior_rectangle_areas(self):
|
||||
prior_rects = self.get_prior_rectangles()
|
||||
products = VGroup(
|
||||
TexMobject("(", "0.8", ")(", "0.9", ")"),
|
||||
TexMobject("(", "0.2", ")(", "0.99", ")"),
|
||||
)
|
||||
top_product, bottom_product = products
|
||||
for product, rect in zip(products, prior_rects):
|
||||
product.scale(0.7)
|
||||
product.move_to(rect)
|
||||
side_labels = self.sample_space.horizontal_parts.labels
|
||||
top_labels = self.sample_space[0].vertical_parts.labels
|
||||
bottom_labels = self.sample_space[1].vertical_parts.labels
|
||||
|
||||
self.play(
|
||||
ReplacementTransform(
|
||||
side_labels[0][-1].copy(),
|
||||
top_product[1],
|
||||
),
|
||||
ReplacementTransform(
|
||||
top_labels[0][-1].copy(),
|
||||
top_product[3],
|
||||
),
|
||||
Write(VGroup(*top_product[::2]))
|
||||
)
|
||||
self.dither(2)
|
||||
self.play(
|
||||
ReplacementTransform(
|
||||
side_labels[1][-1].copy(),
|
||||
bottom_product[1],
|
||||
),
|
||||
ReplacementTransform(
|
||||
bottom_labels[0][-1].copy(),
|
||||
bottom_product[3],
|
||||
),
|
||||
Write(VGroup(*bottom_product[::2]))
|
||||
)
|
||||
self.dither(2)
|
||||
|
||||
self.products = products
|
||||
|
||||
def show_posterior_probability(self):
|
||||
pass
|
||||
post_tex = self.post_tex
|
||||
rhs = TexMobject("\\approx", "0.78")
|
||||
rhs.scale(0.7)
|
||||
rhs.next_to(post_tex, RIGHT)
|
||||
ratio = TexMobject(
|
||||
"{(0.8)(0.9)", "\\over",
|
||||
"(0.8)(0.9)", "+", "(0.2)(0.99)}"
|
||||
)
|
||||
ratio.scale(0.6)
|
||||
ratio.next_to(VGroup(post_tex, rhs), DOWN, LARGE_BUFF)
|
||||
ratio.to_edge(RIGHT)
|
||||
arrow_kwargs = {
|
||||
"tip_length" : 0.15,
|
||||
"color" : WHITE,
|
||||
"buff" : 2*SMALL_BUFF,
|
||||
}
|
||||
to_ratio_arrow = Arrow(
|
||||
post_tex.get_bottom(), ratio.get_top(), **arrow_kwargs
|
||||
)
|
||||
to_rhs_arrow = Arrow(
|
||||
ratio.get_top(), rhs[1].get_bottom(), **arrow_kwargs
|
||||
)
|
||||
|
||||
self.play(
|
||||
ShowCreation(to_ratio_arrow),
|
||||
FadeIn(ratio)
|
||||
)
|
||||
self.dither()
|
||||
self.play(ShowCreation(to_rhs_arrow))
|
||||
self.play(Write(rhs, run_time = 1))
|
||||
self.dither(2)
|
||||
|
||||
self.post_rhs = rhs
|
||||
self.ratio_group = VGroup(ratio, to_ratio_arrow, to_rhs_arrow)
|
||||
|
||||
def intuition_of_positive_feedback(self):
|
||||
pass
|
||||
friends = self.friends
|
||||
prior_num = self.sample_space.horizontal_parts.labels[0][-1]
|
||||
post_num = self.post_rhs[-1]
|
||||
prior_rect = SurroundingRectangle(prior_num)
|
||||
post_rect = SurroundingRectangle(post_num)
|
||||
dot = Dot(prior_rect.get_center())
|
||||
dot.set_fill(WHITE, 0.5)
|
||||
|
||||
self.play(ShowCreation(prior_rect))
|
||||
self.play(
|
||||
dot.move_to, post_rect,
|
||||
dot.set_fill, None, 0,
|
||||
path_arc = -np.pi/6,
|
||||
run_time = 2,
|
||||
)
|
||||
self.play(ShowCreation(post_rect))
|
||||
self.dither(2)
|
||||
for mode, time in ("shruggie", 2), ("hesitant", 0):
|
||||
self.play(LaggedStart(
|
||||
ApplyMethod, friends,
|
||||
lambda pi : (pi.change, mode),
|
||||
run_time = 2,
|
||||
))
|
||||
self.dither(time)
|
||||
self.play(*map(FadeOut, [
|
||||
prior_rect, post_rect,
|
||||
self.ratio_group, self.post_rhs
|
||||
]))
|
||||
|
||||
self.prior_num_rect = prior_rect
|
||||
|
||||
def make_friends_honest(self):
|
||||
pass
|
||||
post_rects = self.post_rects
|
||||
|
||||
self.play(FadeOut(self.products))
|
||||
for value in 0.5, 0.1, 0.9:
|
||||
label = self.get_conditional_label(value)
|
||||
self.play(*self.get_top_conditional_change_anims(
|
||||
value, post_rects,
|
||||
new_label_kwargs = {"labels" : [label]},
|
||||
), run_time = 2)
|
||||
self.dither(2)
|
||||
|
||||
def fade_out_post_rect(self):
|
||||
self.play(*map(FadeOut, [
|
||||
self.post_rects,
|
||||
self.post_rects.braces,
|
||||
self.post_rects.labels,
|
||||
]))
|
||||
self.play(self.negative_space.restore)
|
||||
|
||||
def get_negative_feedback(self):
|
||||
pass
|
||||
friends = self.friends
|
||||
old_prior_rects = self.get_prior_rectangles()
|
||||
for part in self.sample_space.horizontal_parts:
|
||||
part.vertical_parts.submobjects.reverse()
|
||||
new_prior_rects = self.get_prior_rectangles()
|
||||
post_rects = self.get_posterior_rectangles()
|
||||
label = TexMobject(
|
||||
"P(S | \\text{not } ", "\\checkmark", ")",
|
||||
"\\approx", "0.98"
|
||||
)
|
||||
label.scale(0.7)
|
||||
label.highlight_by_tex("\\checkmark", GREEN)
|
||||
braces, labels = self.get_posterior_rectangle_braces_and_labels(
|
||||
post_rects, [label]
|
||||
)
|
||||
brace = braces[0]
|
||||
|
||||
def show_negative_feedback_posterior(self):
|
||||
pass
|
||||
self.play(old_prior_rects.fade, 0.8)
|
||||
self.play(LaggedStart(
|
||||
ApplyMethod, friends,
|
||||
lambda pi : (pi.change, "pondering", post_rects),
|
||||
run_time = 1
|
||||
))
|
||||
self.dither()
|
||||
self.play(ReplacementTransform(
|
||||
new_prior_rects.copy(), post_rects,
|
||||
run_time = 2
|
||||
))
|
||||
self.play(GrowFromCenter(brace))
|
||||
self.dither(2)
|
||||
self.play(Write(label))
|
||||
self.dither(3)
|
||||
|
||||
self.post_rects = post_rects
|
||||
|
||||
def compare_prior_to_post_given_negative(self):
|
||||
post_num = self.post_rects.labels[0][-1]
|
||||
post_num_rect = SurroundingRectangle(post_num)
|
||||
|
||||
self.play(ShowCreation(self.prior_num_rect))
|
||||
self.dither()
|
||||
self.play(ShowCreation(post_num_rect))
|
||||
self.dither()
|
||||
|
||||
self.post_num_rect = post_num_rect
|
||||
|
||||
def intuition_of_negative_feedback(self):
|
||||
pass
|
||||
friends = self.friends
|
||||
randy = self.pi_creature
|
||||
bubble = self.bubble
|
||||
|
||||
modes = ["sassy", "pleading", "horrified"]
|
||||
for friend, mode in zip(friends, modes):
|
||||
friend.generate_target()
|
||||
friend.target.change(mode, randy.eyes)
|
||||
content = TextMobject("Horrible. Just horrible.")
|
||||
content.scale(0.6)
|
||||
bubble.add_content(content)
|
||||
|
||||
self.play(*map(MoveToTarget, friends))
|
||||
self.play(
|
||||
ShowCreation(bubble),
|
||||
Write(bubble.content)
|
||||
)
|
||||
self.change_pi_creature_with_guitar("sad")
|
||||
self.dither()
|
||||
self.change_pi_creature_with_guitar("concerned_musician")
|
||||
self.dither(3)
|
||||
|
||||
######
|
||||
|
||||
def create_pi_creature(self):
|
||||
randy = Randolph()
|
||||
randy.left_arm_range = [.36, .45]
|
||||
self.randy = randy
|
||||
return randy
|
||||
|
||||
def change_pi_creature_with_guitar(self, target_mode):
|
||||
def get_conditional_label(self, value, given_suck = True):
|
||||
positive_str = "\\checkmark"
|
||||
label = TexMobject(
|
||||
"P(", positive_str, "|",
|
||||
"" if given_suck else "\\text{not }",
|
||||
"S", ")",
|
||||
"=", str(value)
|
||||
)
|
||||
label.highlight_by_tex(positive_str, GREEN)
|
||||
label.scale(0.7)
|
||||
return label
|
||||
|
||||
def change_pi_creature_with_guitar(self, target_mode, *added_anims):
|
||||
randy = self.pi_creature
|
||||
randy.remove(randy.arms, randy.guitar)
|
||||
target = randy.copy()
|
||||
@ -1516,7 +1957,7 @@ class MusicExample(SampleSpaceScene, PiCreatureScene):
|
||||
target.guitar = randy.guitar.copy()
|
||||
for pi in randy, target:
|
||||
pi.add(pi.guitar, pi.arms)
|
||||
self.play(Transform(randy, target))
|
||||
self.play(Transform(randy, target), *added_anims)
|
||||
|
||||
def play_notes(self, guitar):
|
||||
note = SVGMobject(file_name = "8th_note")
|
||||
@ -1524,6 +1965,7 @@ class MusicExample(SampleSpaceScene, PiCreatureScene):
|
||||
note.set_stroke(width = 0)
|
||||
note.set_fill(BLUE, 1)
|
||||
note.move_to(guitar)
|
||||
note.shift(MED_SMALL_BUFF*(DOWN+2*LEFT))
|
||||
notes = VGroup(*[note.copy() for x in range(10)])
|
||||
sine_wave = FunctionGraph(np.sin, x_min = -5, x_max = 5)
|
||||
sine_wave.scale(0.75)
|
||||
@ -1541,9 +1983,95 @@ class MusicExample(SampleSpaceScene, PiCreatureScene):
|
||||
rate_func = lambda t : t,
|
||||
))
|
||||
|
||||
|
||||
|
||||
|
||||
class FinalWordsOnRule(SampleSpaceScene):
|
||||
def construct(self):
|
||||
self.add_sample_space()
|
||||
self.add_uses()
|
||||
self.tweak_values()
|
||||
|
||||
def add_sample_space(self):
|
||||
sample_space = self.sample_space = SampleSpace()
|
||||
prior = 0.2
|
||||
top_conditional = 0.8
|
||||
bottom_condional = 0.3
|
||||
sample_space.divide_horizontally(prior)
|
||||
sample_space[0].divide_vertically(
|
||||
top_conditional, colors = [GREEN, RED]
|
||||
)
|
||||
sample_space[1].divide_vertically(
|
||||
bottom_condional, colors = [GREEN_E, RED_E]
|
||||
)
|
||||
B = "\\text{Belief}"
|
||||
D = "\\text{Data}"
|
||||
P_B = TexMobject("P(", B, ")")
|
||||
P_D_given_B = TexMobject("P(", D, "|", B, ")")
|
||||
P_D_given_not_B = TexMobject(
|
||||
"P(", D, "|", "\\text{not }", B, ")"
|
||||
)
|
||||
P_B_given_D = TexMobject("P(", B, "|", D, ")")
|
||||
labels = VGroup(P_B, P_D_given_B, P_D_given_not_B, P_B_given_D)
|
||||
for label in labels:
|
||||
label.scale(0.7)
|
||||
label.highlight_by_tex(B, BLUE)
|
||||
label.highlight_by_tex(D, GREEN)
|
||||
|
||||
prior_rects = self.get_prior_rectangles()
|
||||
post_rects = self.get_posterior_rectangles()
|
||||
for i in range(2):
|
||||
sample_space[i][1].fade(0.7)
|
||||
|
||||
braces = VGroup()
|
||||
bs, ls = sample_space.get_side_braces_and_labels([P_B])
|
||||
braces.add(*bs)
|
||||
bs, ls = sample_space[0].get_top_braces_and_labels([P_D_given_B])
|
||||
braces.add(*bs)
|
||||
bs, ls = sample_space[1].get_bottom_braces_and_labels([P_D_given_not_B])
|
||||
braces.add(*bs)
|
||||
bs, ls = self.get_posterior_rectangle_braces_and_labels(
|
||||
post_rects, [P_B_given_D]
|
||||
)
|
||||
braces.add(*bs)
|
||||
|
||||
group = VGroup(sample_space, braces, labels, post_rects)
|
||||
group.to_corner(DOWN + LEFT)
|
||||
self.add(group)
|
||||
|
||||
self.post_rects = post_rects
|
||||
|
||||
def add_uses(self):
|
||||
uses = TextMobject(
|
||||
"Machine learning, ",
|
||||
"scientific inference, $\\dots$",
|
||||
)
|
||||
uses.to_edge(UP)
|
||||
for use in uses:
|
||||
self.play(Write(use, run_time = 2))
|
||||
self.dither()
|
||||
|
||||
def tweak_values(self):
|
||||
post_rects = self.post_rects
|
||||
new_value_lists = [
|
||||
(0.85, 0.1, 0.11),
|
||||
(0.3, 0.9, 0.4),
|
||||
(0.97, 0.3, 1./22),
|
||||
]
|
||||
for new_values in new_value_lists:
|
||||
for i, value in zip(range(2), new_values):
|
||||
self.play(*self.get_conditional_change_anims(
|
||||
i, value, post_rects
|
||||
))
|
||||
self.dither()
|
||||
self.play(*it.chain(
|
||||
self.get_horizontal_division_change_animations(new_values[-1]),
|
||||
self.get_posterior_rectangle_change_anims(post_rects)
|
||||
))
|
||||
self.dither()
|
||||
self.dither(2)
|
||||
|
||||
class FootnoteWrapper(NextVideoWrapper):
|
||||
CONFIG = {
|
||||
"title" : "Thoughts on the classic Bayes example"
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -38,7 +38,6 @@ class SunGlasses(SVGMobject):
|
||||
)
|
||||
self.move_to(pi_creature.eyes, UP)
|
||||
|
||||
|
||||
class Speedometer(VMobject):
|
||||
CONFIG = {
|
||||
"arc_angle" : 4*np.pi/3,
|
||||
@ -280,13 +279,18 @@ class Headphones(SVGMobject):
|
||||
"y_stretch_factor" : 0.5,
|
||||
"color" : GREY,
|
||||
}
|
||||
def __init__(self, **kwargs):
|
||||
def __init__(self, pi_creature = None, **kwargs):
|
||||
digest_config(self, kwargs)
|
||||
SVGMobject.__init__(self, file_name = self.file_name, **kwargs)
|
||||
self.stretch(self.y_stretch_factor, 1)
|
||||
self.scale_to_fit_height(self.height)
|
||||
self.set_stroke(width = 0)
|
||||
self.set_fill(color = self.color)
|
||||
if pi_creature is not None:
|
||||
eyes = pi_creature.eyes
|
||||
self.scale_to_fit_height(3*eyes.get_height())
|
||||
self.move_to(eyes, DOWN)
|
||||
self.shift(DOWN*eyes.get_height()/4)
|
||||
|
||||
class Clock(VGroup):
|
||||
CONFIG = {
|
||||
|
@ -156,7 +156,7 @@ class SampleSpace(VGroup):
|
||||
"height" : 3,
|
||||
"width" : 3,
|
||||
"fill_color" : DARK_GREY,
|
||||
"fill_opacity" : 0.8,
|
||||
"fill_opacity" : 1,
|
||||
"stroke_width" : 0.5,
|
||||
"stroke_color" : LIGHT_GREY,
|
||||
},
|
||||
@ -204,7 +204,7 @@ class SampleSpace(VGroup):
|
||||
|
||||
def get_horizontal_division(
|
||||
self, p_list,
|
||||
colors = [GREEN_E, BLUE],
|
||||
colors = [GREEN_E, BLUE_E],
|
||||
vect = DOWN
|
||||
):
|
||||
return self.get_division_along_dimension(p_list, 1, colors, vect)
|
||||
|
Reference in New Issue
Block a user