Preliminary end to eop/independence

This commit is contained in:
Grant Sanderson 2017-07-25 12:53:21 -07:00
parent ceb7f467ad
commit 25bd813486
2 changed files with 407 additions and 22 deletions

View file

@ -29,6 +29,7 @@ from mobject.svg_mobject import *
from mobject.tex_mobject import *
from scene.scene import ProgressDisplay
import scipy
#revert_to_original_skipping_status
@ -59,17 +60,18 @@ def get_quiz(*questions):
return quiz
def get_slot_group(bool_list, buff = MED_LARGE_BUFF, include_qs = True):
n = len(bool_list)
lines = VGroup(*[
Line(ORIGIN, MED_LARGE_BUFF*RIGHT)
for x in range(3)
for x in range(n)
])
lines.arrange_submobjects(RIGHT, buff = buff)
if include_qs:
labels = VGroup(*[
TextMobject("Q%d"%d) for d in range(1, 4)
TextMobject("Q%d"%d) for d in range(1, n+1)
])
else:
labels = VGroup(*[VectorizedPoint() for d in range(3)])
labels = VGroup(*[VectorizedPoint() for d in range(n)])
for label, line in zip(labels, lines):
label.scale(0.7)
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
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:
result = TexMobject("P(", filler_tex, ")")
else:
@ -2748,8 +2750,6 @@ class CorrectForDependence(NameBinomial):
self.revert_to_original_skipping_status()
def construct(self):
self.force_skipping()
self.mention_dependence()
self.show_tendency_to_align()
self.adjust_chart()
@ -2757,12 +2757,16 @@ class CorrectForDependence(NameBinomial):
def mention_dependence(self):
brace = Brace(self.checkmarks, LEFT)
words = brace.get_text("What if there's \\\\ correlation?")
formula = self.formula
cross = Cross(formula)
self.play(
GrowFromCenter(brace),
Write(words)
)
self.dither(2)
self.dither()
self.play(ShowCreation(cross))
self.dither()
def show_tendency_to_align(self):
checkmarks = self.checkmarks
@ -2776,15 +2780,52 @@ class CorrectForDependence(NameBinomial):
top_rect.highlight(GREEN)
indices_to_follow = [1, 4, 5, 7]
self.revert_to_original_skipping_status()
self.play(ShowCreation(top_rect))
self.play(*self.get_arrow_flip_anims([0]))
self.dither()
self.play(*self.get_arrow_flip_anims(indices_to_follow))
self.dither()
self.play(FocusOn(self.chart.bars))
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
]
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",
],
}