mirror of
https://github.com/3b1b/manim.git
synced 2025-09-01 00:48:45 +00:00
Preliminary end to eop/independence
This commit is contained in:
parent
ceb7f467ad
commit
25bd813486
2 changed files with 407 additions and 22 deletions
|
@ -29,6 +29,7 @@ from mobject.svg_mobject import *
|
||||||
from mobject.tex_mobject import *
|
from mobject.tex_mobject import *
|
||||||
|
|
||||||
from scene.scene import ProgressDisplay
|
from scene.scene import ProgressDisplay
|
||||||
|
import scipy
|
||||||
|
|
||||||
#revert_to_original_skipping_status
|
#revert_to_original_skipping_status
|
||||||
|
|
||||||
|
@ -59,17 +60,18 @@ def get_quiz(*questions):
|
||||||
return quiz
|
return quiz
|
||||||
|
|
||||||
def get_slot_group(bool_list, buff = MED_LARGE_BUFF, include_qs = True):
|
def get_slot_group(bool_list, buff = MED_LARGE_BUFF, include_qs = True):
|
||||||
|
n = len(bool_list)
|
||||||
lines = VGroup(*[
|
lines = VGroup(*[
|
||||||
Line(ORIGIN, MED_LARGE_BUFF*RIGHT)
|
Line(ORIGIN, MED_LARGE_BUFF*RIGHT)
|
||||||
for x in range(3)
|
for x in range(n)
|
||||||
])
|
])
|
||||||
lines.arrange_submobjects(RIGHT, buff = buff)
|
lines.arrange_submobjects(RIGHT, buff = buff)
|
||||||
if include_qs:
|
if include_qs:
|
||||||
labels = VGroup(*[
|
labels = VGroup(*[
|
||||||
TextMobject("Q%d"%d) for d in range(1, 4)
|
TextMobject("Q%d"%d) for d in range(1, n+1)
|
||||||
])
|
])
|
||||||
else:
|
else:
|
||||||
labels = VGroup(*[VectorizedPoint() for d in range(3)])
|
labels = VGroup(*[VectorizedPoint() for d in range(n)])
|
||||||
for label, line in zip(labels, lines):
|
for label, line in zip(labels, lines):
|
||||||
label.scale(0.7)
|
label.scale(0.7)
|
||||||
label.next_to(line, DOWN, SMALL_BUFF)
|
label.next_to(line, DOWN, SMALL_BUFF)
|
||||||
|
@ -100,7 +102,7 @@ def get_slot_group(bool_list, buff = MED_LARGE_BUFF, include_qs = True):
|
||||||
return slot_group
|
return slot_group
|
||||||
|
|
||||||
def get_probability_of_slot_group(bool_list, conditioned_list = None):
|
def get_probability_of_slot_group(bool_list, conditioned_list = None):
|
||||||
filler_tex = "Filler"
|
filler_tex = "Fi"*len(bool_list)
|
||||||
if conditioned_list is None:
|
if conditioned_list is None:
|
||||||
result = TexMobject("P(", filler_tex, ")")
|
result = TexMobject("P(", filler_tex, ")")
|
||||||
else:
|
else:
|
||||||
|
@ -2748,8 +2750,6 @@ class CorrectForDependence(NameBinomial):
|
||||||
self.revert_to_original_skipping_status()
|
self.revert_to_original_skipping_status()
|
||||||
|
|
||||||
def construct(self):
|
def construct(self):
|
||||||
self.force_skipping()
|
|
||||||
|
|
||||||
self.mention_dependence()
|
self.mention_dependence()
|
||||||
self.show_tendency_to_align()
|
self.show_tendency_to_align()
|
||||||
self.adjust_chart()
|
self.adjust_chart()
|
||||||
|
@ -2757,12 +2757,16 @@ class CorrectForDependence(NameBinomial):
|
||||||
def mention_dependence(self):
|
def mention_dependence(self):
|
||||||
brace = Brace(self.checkmarks, LEFT)
|
brace = Brace(self.checkmarks, LEFT)
|
||||||
words = brace.get_text("What if there's \\\\ correlation?")
|
words = brace.get_text("What if there's \\\\ correlation?")
|
||||||
|
formula = self.formula
|
||||||
|
cross = Cross(formula)
|
||||||
|
|
||||||
self.play(
|
self.play(
|
||||||
GrowFromCenter(brace),
|
GrowFromCenter(brace),
|
||||||
Write(words)
|
Write(words)
|
||||||
)
|
)
|
||||||
self.dither(2)
|
self.dither()
|
||||||
|
self.play(ShowCreation(cross))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
def show_tendency_to_align(self):
|
def show_tendency_to_align(self):
|
||||||
checkmarks = self.checkmarks
|
checkmarks = self.checkmarks
|
||||||
|
@ -2776,15 +2780,52 @@ class CorrectForDependence(NameBinomial):
|
||||||
top_rect.highlight(GREEN)
|
top_rect.highlight(GREEN)
|
||||||
indices_to_follow = [1, 4, 5, 7]
|
indices_to_follow = [1, 4, 5, 7]
|
||||||
|
|
||||||
self.revert_to_original_skipping_status()
|
|
||||||
self.play(ShowCreation(top_rect))
|
self.play(ShowCreation(top_rect))
|
||||||
self.play(*self.get_arrow_flip_anims([0]))
|
self.play(*self.get_arrow_flip_anims([0]))
|
||||||
self.dither()
|
self.dither()
|
||||||
self.play(*self.get_arrow_flip_anims(indices_to_follow))
|
self.play(*self.get_arrow_flip_anims(indices_to_follow))
|
||||||
self.dither()
|
self.play(FocusOn(self.chart.bars))
|
||||||
|
|
||||||
def adjust_chart(self):
|
def adjust_chart(self):
|
||||||
pass
|
chart = self.chart
|
||||||
|
bars = chart.bars
|
||||||
|
old_bars = bars.copy()
|
||||||
|
old_bars.generate_target()
|
||||||
|
bars.generate_target()
|
||||||
|
for group, vect in (old_bars, LEFT), (bars, RIGHT):
|
||||||
|
for bar in group.target:
|
||||||
|
side = bar.get_edge_center(vect)
|
||||||
|
bar.stretch(0.5, 0)
|
||||||
|
bar.move_to(side, vect)
|
||||||
|
for bar in old_bars.target:
|
||||||
|
bar.highlight(average_color(RED_E, BLACK))
|
||||||
|
|
||||||
|
dist = get_binomial_distribution(10, 0.65)
|
||||||
|
values = np.array(map(dist, range(11)))
|
||||||
|
alt_values = values + 0.1
|
||||||
|
alt_values[0] -= 0.06
|
||||||
|
alt_values[1] -= 0.03
|
||||||
|
alt_values /= sum(alt_values)
|
||||||
|
arrows = VGroup()
|
||||||
|
arrow_template = Arrow(
|
||||||
|
0.5*UP, ORIGIN, buff = 0,
|
||||||
|
tip_length = 0.15,
|
||||||
|
color = WHITE
|
||||||
|
)
|
||||||
|
for value, alt_value, bar in zip(values, alt_values, bars):
|
||||||
|
arrow = arrow_template.copy()
|
||||||
|
if value < alt_value:
|
||||||
|
arrow.rotate(np.pi)
|
||||||
|
arrow.next_to(bar, UP)
|
||||||
|
arrows.add(arrow)
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
MoveToTarget(old_bars),
|
||||||
|
MoveToTarget(bars),
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(*map(ShowCreation, arrows))
|
||||||
|
self.play(chart.change_bar_values, alt_values)
|
||||||
|
|
||||||
######
|
######
|
||||||
|
|
||||||
|
@ -2825,18 +2866,362 @@ class CorrectForDependence(NameBinomial):
|
||||||
for mover in movers
|
for mover in movers
|
||||||
]
|
]
|
||||||
|
|
||||||
|
class ButWhatsTheAnswer(TeacherStudentsScene):
|
||||||
|
def construct(self):
|
||||||
|
self.student_says(
|
||||||
|
"But what's the \\\\ actual answer?",
|
||||||
|
target_mode = "confused"
|
||||||
|
)
|
||||||
|
self.change_student_modes(*["confused"]*3)
|
||||||
|
self.dither()
|
||||||
|
self.play(self.teacher.change, "pondering")
|
||||||
|
self.dither(3)
|
||||||
|
|
||||||
|
class AssumeOrderDoesntMatter(Scene):
|
||||||
|
def construct(self):
|
||||||
|
self.add_title()
|
||||||
|
self.show_equality()
|
||||||
|
self.mention_correlation()
|
||||||
|
|
||||||
|
def add_title(self):
|
||||||
|
title = TextMobject(
|
||||||
|
"Softer simplifying assumption: " +\
|
||||||
|
"Order doesn't matter"
|
||||||
|
)
|
||||||
|
title.to_edge(UP)
|
||||||
|
|
||||||
|
self.add(title)
|
||||||
|
self.title = title
|
||||||
|
|
||||||
|
def show_equality(self):
|
||||||
|
n = 3
|
||||||
|
prob_groups = VGroup(*[
|
||||||
|
VGroup(*map(
|
||||||
|
get_probability_of_slot_group,
|
||||||
|
filter(
|
||||||
|
lambda t : sum(t) == k,
|
||||||
|
it.product(*[[True, False]]*n)
|
||||||
|
)
|
||||||
|
))
|
||||||
|
for k in range(n+1)
|
||||||
|
])
|
||||||
|
for prob_group in prob_groups:
|
||||||
|
for prob in prob_group[:-1]:
|
||||||
|
equals = TexMobject("=")
|
||||||
|
equals.next_to(prob, RIGHT)
|
||||||
|
prob.add(equals)
|
||||||
|
prob_group.arrange_submobjects(RIGHT)
|
||||||
|
max_width = 2*SPACE_WIDTH - 1
|
||||||
|
if prob_group.get_width() > max_width:
|
||||||
|
prob_group.scale_to_fit_width(max_width)
|
||||||
|
prob_groups.arrange_submobjects(DOWN, buff = 0.7)
|
||||||
|
prob_groups.next_to(self.title, DOWN, MED_LARGE_BUFF)
|
||||||
|
|
||||||
|
self.play(FadeIn(
|
||||||
|
prob_groups[1],
|
||||||
|
run_time = 2,
|
||||||
|
submobject_mode = "lagged_start"
|
||||||
|
))
|
||||||
|
self.dither(2)
|
||||||
|
self.play(FadeIn(
|
||||||
|
VGroup(prob_groups[0], *prob_groups[2:]),
|
||||||
|
run_time = 3,
|
||||||
|
submobject_mode = "lagged_start"
|
||||||
|
))
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
self.prob_groups = prob_groups
|
||||||
|
|
||||||
|
def mention_correlation(self):
|
||||||
|
everything = VGroup(*self.get_top_level_mobjects())
|
||||||
|
question = TextMobject("But what is ``correlation''?")
|
||||||
|
question.highlight(BLUE)
|
||||||
|
question.to_edge(UP)
|
||||||
|
bottom = question.get_bottom()
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
Write(question),
|
||||||
|
everything.next_to, bottom, DOWN, LARGE_BUFF
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
class FormulaCanBeRediscovered(PointOutSimplicityOfFormula):
|
||||||
|
def construct(self):
|
||||||
|
prob = self.get_probability_expression(full = False)
|
||||||
|
corner = self.teacher.get_corner(UP+LEFT)
|
||||||
|
prob.next_to(corner, UP, MED_LARGE_BUFF)
|
||||||
|
brace = Brace(prob, UP)
|
||||||
|
rediscover = brace.get_text("Rediscover")
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
Write(prob),
|
||||||
|
self.teacher.change, "hesitant", prob
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.play(
|
||||||
|
GrowFromCenter(brace),
|
||||||
|
Write(rediscover, run_time = 1)
|
||||||
|
)
|
||||||
|
self.change_student_modes(*["happy"]*3)
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
|
class CompareTwoSituations(PiCreatureScene):
|
||||||
|
def construct(self):
|
||||||
|
randy = self.randy
|
||||||
|
top_left, top_right = screens = [
|
||||||
|
ScreenRectangle(height = 3).to_corner(vect)
|
||||||
|
for vect in UP+LEFT, UP+RIGHT
|
||||||
|
]
|
||||||
|
arrow = DoubleArrow(*screens, buff = SMALL_BUFF)
|
||||||
|
arrow.highlight(BLUE)
|
||||||
|
|
||||||
|
for screen, s in zip(screens, ["left", "right"]):
|
||||||
|
self.play(
|
||||||
|
randy.change, "raise_%s_hand"%s, screen,
|
||||||
|
ShowCreation(screen)
|
||||||
|
)
|
||||||
|
self.dither(3)
|
||||||
|
self.play(
|
||||||
|
randy.change, "pondering", arrow,
|
||||||
|
ShowCreation(arrow)
|
||||||
|
)
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
|
####
|
||||||
|
|
||||||
|
def create_pi_creature(self):
|
||||||
|
self.randy = Randolph().to_edge(DOWN)
|
||||||
|
return self.randy
|
||||||
|
|
||||||
|
class SkepticalOfDistributions(TeacherStudentsScene):
|
||||||
|
CONFIG = {
|
||||||
|
"chart_height" : 3,
|
||||||
|
}
|
||||||
|
def construct(self):
|
||||||
|
self.show_binomial()
|
||||||
|
self.show_alternate_distributions()
|
||||||
|
self.emphasize_underweighted_tails()
|
||||||
|
|
||||||
|
def show_binomial(self):
|
||||||
|
binomial = self.get_binomial()
|
||||||
|
binomial.next_to(self.teacher.get_corner(UP+LEFT), UP)
|
||||||
|
title = TextMobject("Probable scores")
|
||||||
|
title.scale(0.85)
|
||||||
|
title.next_to(binomial.bars, UP, 1.5*LARGE_BUFF)
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
Write(title, run_time = 1),
|
||||||
|
FadeIn(binomial, run_time = 1, submobject_mode = "lagged_start"),
|
||||||
|
self.teacher.change, "raise_right_hand"
|
||||||
|
)
|
||||||
|
for values in binomial.values_list:
|
||||||
|
self.play(binomial.change_bar_values, values)
|
||||||
|
self.dither()
|
||||||
|
self.student_says(
|
||||||
|
"Is that valid?", target_mode = "sassy",
|
||||||
|
student_index = 0,
|
||||||
|
run_time = 1
|
||||||
|
)
|
||||||
|
self.play(self.teacher.change, "guilty")
|
||||||
|
self.dither()
|
||||||
|
|
||||||
|
binomial.add(title)
|
||||||
|
self.binomial = binomial
|
||||||
|
|
||||||
|
def show_alternate_distributions(self):
|
||||||
|
poisson = self.get_poisson()
|
||||||
|
VGroup(poisson, poisson.title).next_to(
|
||||||
|
self.students, UP, LARGE_BUFF
|
||||||
|
).shift(RIGHT)
|
||||||
|
gaussian = self.get_gaussian()
|
||||||
|
VGroup(gaussian, gaussian.title).next_to(
|
||||||
|
poisson, RIGHT, LARGE_BUFF
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
self.play(
|
||||||
|
FadeIn(poisson, submobject_mode = "lagged_start"),
|
||||||
|
RemovePiCreatureBubble(self.students[0]),
|
||||||
|
self.teacher.change, "raise_right_hand",
|
||||||
|
self.binomial.scale, 0.5,
|
||||||
|
self.binomial.to_corner, UP+LEFT,
|
||||||
|
)
|
||||||
|
self.play(Write(poisson.title, run_time = 1))
|
||||||
|
self.play(FadeIn(gaussian, submobject_mode = "lagged_start"))
|
||||||
|
self.play(Write(gaussian.title, run_time = 1))
|
||||||
|
self.dither(2)
|
||||||
|
self.change_student_modes(
|
||||||
|
*["sassy"]*3,
|
||||||
|
added_anims = [self.teacher.change, "plain"]
|
||||||
|
)
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
|
self.poisson = poisson
|
||||||
|
self.gaussian = gaussian
|
||||||
|
|
||||||
|
def emphasize_underweighted_tails(self):
|
||||||
|
poisson_arrows = VGroup()
|
||||||
|
arrow_template = Arrow(
|
||||||
|
ORIGIN, UP, color = GREEN,
|
||||||
|
tip_length = 0.15
|
||||||
|
)
|
||||||
|
for bar in self.poisson.bars[-4:]:
|
||||||
|
arrow = arrow_template.copy()
|
||||||
|
arrow.next_to(bar, UP, SMALL_BUFF)
|
||||||
|
poisson_arrows.add(arrow)
|
||||||
|
|
||||||
|
gaussian_arrows = VGroup()
|
||||||
|
for prop in 0.2, 0.8:
|
||||||
|
point = self.gaussian[0][0].point_from_proportion(prop)
|
||||||
|
arrow = arrow_template.copy()
|
||||||
|
arrow.next_to(point, UP, SMALL_BUFF)
|
||||||
|
gaussian_arrows.add(arrow)
|
||||||
|
|
||||||
|
for arrows in poisson_arrows, gaussian_arrows:
|
||||||
|
self.play(
|
||||||
|
ShowCreation(
|
||||||
|
arrows,
|
||||||
|
submobject_mode = "lagged_start",
|
||||||
|
run_time = 2
|
||||||
|
),
|
||||||
|
*[
|
||||||
|
ApplyMethod(pi.change, "thinking", arrows)
|
||||||
|
for pi in self.pi_creatures
|
||||||
|
]
|
||||||
|
)
|
||||||
|
self.dither()
|
||||||
|
self.dither(2)
|
||||||
|
|
||||||
|
####
|
||||||
|
|
||||||
|
def get_binomial(self):
|
||||||
|
k_range = range(11)
|
||||||
|
dists = [
|
||||||
|
get_binomial_distribution(10, p)
|
||||||
|
for p in 0.2, 0.8, 0.5
|
||||||
|
]
|
||||||
|
values_list = [
|
||||||
|
map(dist, k_range)
|
||||||
|
for dist in dists
|
||||||
|
]
|
||||||
|
chart = BarChart(
|
||||||
|
values = values_list[-1],
|
||||||
|
bar_names = k_range
|
||||||
|
)
|
||||||
|
chart.scale_to_fit_height(self.chart_height)
|
||||||
|
chart.values_list = values_list
|
||||||
|
return chart
|
||||||
|
|
||||||
|
def get_poisson(self):
|
||||||
|
k_range = range(11)
|
||||||
|
L = 2
|
||||||
|
values = [
|
||||||
|
np.exp(-L) * (L**k) / (scipy.special.gamma(k+1))
|
||||||
|
for k in k_range
|
||||||
|
]
|
||||||
|
chart = BarChart(
|
||||||
|
values = values,
|
||||||
|
bar_names = k_range,
|
||||||
|
bar_colors = [RED, YELLOW]
|
||||||
|
)
|
||||||
|
chart.scale_to_fit_height(self.chart_height)
|
||||||
|
title = TextMobject(
|
||||||
|
"Poisson distribution \\\\",
|
||||||
|
"$e^{-\\lambda}\\frac{\\lambda^k}{k!}$"
|
||||||
|
)
|
||||||
|
title.scale(0.75)
|
||||||
|
title.move_to(chart, UP)
|
||||||
|
title.shift(MED_SMALL_BUFF*RIGHT)
|
||||||
|
title[0].shift(SMALL_BUFF*UP)
|
||||||
|
chart.title = title
|
||||||
|
|
||||||
|
return chart
|
||||||
|
|
||||||
|
def get_gaussian(self):
|
||||||
|
axes = VGroup(self.binomial.x_axis, self.binomial.y_axis).copy()
|
||||||
|
graph = FunctionGraph(
|
||||||
|
lambda x : 5*np.exp(-x**2),
|
||||||
|
mark_paths_closed = True,
|
||||||
|
fill_color = BLUE_E,
|
||||||
|
fill_opacity = 1,
|
||||||
|
stroke_color = BLUE,
|
||||||
|
)
|
||||||
|
graph.scale_to_fit_width(axes.get_width())
|
||||||
|
graph.move_to(axes[0], DOWN)
|
||||||
|
|
||||||
|
title = TextMobject(
|
||||||
|
"Gaussian distribution \\\\ ",
|
||||||
|
"$\\frac{1}{\\sqrt{2\\pi \\sigma^2}} e^{-\\frac{(x-\\mu)^2}{2\\sigma^2}}$"
|
||||||
|
)
|
||||||
|
title.scale(0.75)
|
||||||
|
title.move_to(axes, UP)
|
||||||
|
title.shift(MED_SMALL_BUFF*RIGHT)
|
||||||
|
title[0].shift(SMALL_BUFF*UP)
|
||||||
|
result = VGroup(axes, graph)
|
||||||
|
result.title = title
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
class IndependencePatreonThanks(PatreonThanks):
|
||||||
|
CONFIG = {
|
||||||
|
"specific_patrons" : [
|
||||||
|
"Ali Yahya",
|
||||||
|
"Desmos",
|
||||||
|
"Burt Humburg",
|
||||||
|
"CrypticSwarm",
|
||||||
|
"Juan Benet",
|
||||||
|
"Mayank M. Mehrotra",
|
||||||
|
"Lukas Biewald",
|
||||||
|
"Samantha D. Suplee",
|
||||||
|
"James Park",
|
||||||
|
"Erik Sundell",
|
||||||
|
"Yana Chernobilsky",
|
||||||
|
"Kaustuv DeBiswas",
|
||||||
|
"Kathryn Schmiedicke",
|
||||||
|
"Karan Bhargava",
|
||||||
|
"Yu Jun",
|
||||||
|
"Dave Nicponski",
|
||||||
|
"Damion Kistler",
|
||||||
|
"Markus Persson",
|
||||||
|
"Yoni Nazarathy",
|
||||||
|
"Corey Ogburn",
|
||||||
|
"Ed Kellett",
|
||||||
|
"Joseph John Cox",
|
||||||
|
"Dan Buchoff",
|
||||||
|
"Luc Ritchie",
|
||||||
|
"Tianyu Ge",
|
||||||
|
"Ted Suzman",
|
||||||
|
"Amir Fayazi",
|
||||||
|
"Linh Tran",
|
||||||
|
"Andrew Busey",
|
||||||
|
"Michael McGuffin",
|
||||||
|
"John Haley",
|
||||||
|
"Mourits de Beer",
|
||||||
|
"Ankalagon",
|
||||||
|
"Eric Lavault",
|
||||||
|
"Tomohiro Furusawa",
|
||||||
|
"Boris Veselinovich",
|
||||||
|
"Julian Pulgarin",
|
||||||
|
"Jeff Linse",
|
||||||
|
"Cooper Jones",
|
||||||
|
"Ryan Dahl",
|
||||||
|
"Mark Govea",
|
||||||
|
"Robert Teed",
|
||||||
|
"Jason Hise",
|
||||||
|
"Meshal Alshammari",
|
||||||
|
"Bernd Sing",
|
||||||
|
"Nils Schneider",
|
||||||
|
"James Thornton",
|
||||||
|
"Mustafa Mahdi",
|
||||||
|
"Mathew Bramson",
|
||||||
|
"Jerry Ling",
|
||||||
|
"Vecht",
|
||||||
|
"Shimin Kuang",
|
||||||
|
"Rish Kundalia",
|
||||||
|
"Achille Brighton",
|
||||||
|
"Ripta Pasay",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue