mirror of
https://github.com/3b1b/manim.git
synced 2025-07-29 13:03:31 +08:00
Finished draft of part1
This commit is contained in:
@ -63,12 +63,12 @@ RIGHT_SIDE = SPACE_WIDTH*RIGHT
|
||||
# Change this to point to where you want
|
||||
# animation files to output
|
||||
MOVIE_DIR = os.path.join(os.path.expanduser('~'), "Dropbox/3b1b_videos/animations/")
|
||||
STAGED_SCENES_DIR = os.path.join(MOVIE_DIR, "staged_scenes")
|
||||
###
|
||||
THIS_DIR = os.path.dirname(os.path.realpath(__file__))
|
||||
FILE_DIR = os.path.join(THIS_DIR, "files")
|
||||
IMAGE_DIR = os.path.join(FILE_DIR, "images")
|
||||
GIF_DIR = os.path.join(FILE_DIR, "gifs")
|
||||
STAGED_SCENES_DIR = os.path.join(FILE_DIR, "staged_scenes")
|
||||
TEX_DIR = os.path.join(FILE_DIR, "Tex")
|
||||
TEX_IMAGE_DIR = os.path.join(IMAGE_DIR, "Tex")
|
||||
MOBJECT_DIR = os.path.join(FILE_DIR, "mobjects")
|
||||
|
@ -21,13 +21,14 @@ import cPickle
|
||||
from nn.mnist_loader import load_data_wrapper
|
||||
|
||||
NN_DIRECTORY = os.path.dirname(os.path.realpath(__file__))
|
||||
# PRETRAINED_DATA_FILE = os.path.join(NN_DIRECTORY, "pretrained_weights_and_biases_36")
|
||||
PRETRAINED_DATA_FILE = os.path.join(NN_DIRECTORY, "pretrained_weights_and_biases")
|
||||
IMAGE_MAP_DATA_FILE = os.path.join(NN_DIRECTORY, "image_map")
|
||||
# PRETRAINED_DATA_FILE = "/Users/grant/cs/manim/nn/pretrained_weights_and_biases_on_zero"
|
||||
# DEFAULT_LAYER_SIZES = [28**2, 36, 10]
|
||||
DEFAULT_LAYER_SIZES = [28**2, 16, 16, 10]
|
||||
|
||||
class Network(object):
|
||||
|
||||
def __init__(self, sizes):
|
||||
"""The list ``sizes`` contains the number of neurons in the
|
||||
respective layers of the network. For example, if the list
|
||||
@ -192,12 +193,12 @@ def test_network():
|
||||
network = get_pretrained_network()
|
||||
training_data, validation_data, test_data = load_data_wrapper()
|
||||
n_right, n_wrong = 0, 0
|
||||
for test_in, test_out in test_data[:30]:
|
||||
for test_in, test_out in test_data:
|
||||
if np.argmax(network.feedforward(test_in)) == test_out:
|
||||
n_right += 1
|
||||
else:
|
||||
n_wrong += 1
|
||||
print float(n_right)/(n_right + n_wrong)
|
||||
print n_right, n_wrong, float(n_right)/(n_right + n_wrong)
|
||||
|
||||
def layer_to_image_array(layer):
|
||||
w = int(np.ceil(np.sqrt(len(layer))))
|
||||
|
4248
nn/part1.py
Normal file
4248
nn/part1.py
Normal file
File diff suppressed because it is too large
Load Diff
63
nn/pretrained_weights_and_biases_36
Normal file
63
nn/pretrained_weights_and_biases_36
Normal file
File diff suppressed because one or more lines are too long
649
nn/scenes.py
649
nn/scenes.py
@ -27,6 +27,7 @@ from topics.objects import *
|
||||
from topics.probability import *
|
||||
from topics.complex_numbers import *
|
||||
from topics.graph_scene import *
|
||||
from topics.common_scenes import *
|
||||
from scene import Scene
|
||||
from scene.reconfigurable_scene import ReconfigurableScene
|
||||
from scene.zoomed_scene import *
|
||||
@ -529,6 +530,31 @@ class ExampleThrees(PiCreatureScene):
|
||||
three_mobs.add(three_mob)
|
||||
return three_mobs
|
||||
|
||||
class BrainAndHow(Scene):
|
||||
def construct(self):
|
||||
brain = SVGMobject(file_name = "brain")
|
||||
brain.scale_to_fit_height(2)
|
||||
brain.set_fill(LIGHT_GREY)
|
||||
brain_outline = brain.copy()
|
||||
brain_outline.set_fill(opacity = 0)
|
||||
brain_outline.set_stroke(BLUE_B, 3)
|
||||
|
||||
how = TextMobject("How?!?")
|
||||
how.scale(2)
|
||||
how.next_to(brain, UP)
|
||||
|
||||
self.add(brain)
|
||||
self.play(Write(how))
|
||||
for x in range(2):
|
||||
self.play(
|
||||
ShowPassingFlash(
|
||||
brain_outline,
|
||||
time_width = 0.5,
|
||||
run_time = 2
|
||||
)
|
||||
)
|
||||
self.dither()
|
||||
|
||||
class WriteAProgram(Scene):
|
||||
def construct(self):
|
||||
three_array = get_organized_images()[3][0]
|
||||
@ -608,6 +634,7 @@ class LayOutPlan(TeacherStudentsScene, NetworkScene):
|
||||
self.show_math()
|
||||
self.ask_about_layers()
|
||||
self.show_learning()
|
||||
self.show_videos()
|
||||
|
||||
def show_words(self):
|
||||
words = VGroup(
|
||||
@ -722,6 +749,37 @@ class LayOutPlan(TeacherStudentsScene, NetworkScene):
|
||||
self.play(MoveToTarget(edge_group))
|
||||
self.dither()
|
||||
|
||||
self.learning_word = word
|
||||
|
||||
def show_videos(self):
|
||||
network_mob = self.network_mob
|
||||
learning = self.learning_word
|
||||
videos = VGroup(*[
|
||||
VideoIcon().set_fill(RED)
|
||||
for x in range(2)
|
||||
])
|
||||
videos.scale_to_fit_height(1.5)
|
||||
videos.arrange_submobjects(RIGHT, buff = LARGE_BUFF)
|
||||
videos.next_to(self.students, UP, LARGE_BUFF)
|
||||
|
||||
network_mob.generate_target()
|
||||
network_mob.target.scale_to_fit_height(0.8*videos[0].get_height())
|
||||
network_mob.target.move_to(videos[0])
|
||||
learning.generate_target()
|
||||
learning.target.next_to(videos[1], UP)
|
||||
|
||||
self.play(
|
||||
MoveToTarget(network_mob),
|
||||
MoveToTarget(learning)
|
||||
)
|
||||
self.play(
|
||||
DrawBorderThenFill(videos[0]),
|
||||
self.get_student_changes(*["pondering"]*3)
|
||||
)
|
||||
self.dither()
|
||||
self.play(DrawBorderThenFill(videos[1]))
|
||||
self.dither()
|
||||
|
||||
class PreviewMNistNetwork(NetworkScene):
|
||||
CONFIG = {
|
||||
"n_examples" : 15,
|
||||
@ -737,6 +795,7 @@ class PreviewMNistNetwork(NetworkScene):
|
||||
def feed_in_image(self, in_vect):
|
||||
image = PixelsFromVect(in_vect)
|
||||
image.next_to(self.network_mob, LEFT, LARGE_BUFF, UP)
|
||||
image.shift_onto_screen()
|
||||
image_rect = SurroundingRectangle(image, color = BLUE)
|
||||
start_neurons = self.network_mob.layers[0].neurons.copy()
|
||||
start_neurons.set_stroke(WHITE, width = 0)
|
||||
@ -1598,6 +1657,20 @@ class BreakUpMacroPatterns(IntroduceEachLayer):
|
||||
image_mob.pixel_array[:,:,3] = alpha_vect
|
||||
return image_mob
|
||||
|
||||
class GenerallyLoopyPattern(Scene):
|
||||
def construct(self):
|
||||
image_map = get_organized_images()
|
||||
images = map(MNistMobject, it.chain(
|
||||
image_map[8], image_map[9],
|
||||
))
|
||||
random.shuffle(images)
|
||||
|
||||
for image in images:
|
||||
image.to_corner(DOWN+RIGHT)
|
||||
self.add(image)
|
||||
self.dither(0.2)
|
||||
self.remove(image)
|
||||
|
||||
class HowWouldYouRecognizeSubcomponent(TeacherStudentsScene):
|
||||
def construct(self):
|
||||
self.student_says(
|
||||
@ -2624,6 +2697,7 @@ class IncludeBias(IntroduceWeights):
|
||||
self.setup_start()
|
||||
self.revert_to_original_skipping_status()
|
||||
|
||||
self.add_sigmoid_label()
|
||||
self.words_on_activation()
|
||||
self.comment_on_need_for_bias()
|
||||
self.add_bias()
|
||||
@ -2657,10 +2731,29 @@ class IncludeBias(IntroduceWeights):
|
||||
).update(1)
|
||||
|
||||
self.add(self.weighted_sum, digit, weight_grid)
|
||||
self.add_sigmoid_label()
|
||||
self.digit = digit
|
||||
self.weight_grid = weight_grid
|
||||
|
||||
def add_sigmoid_label(self):
|
||||
name = TextMobject("Sigmoid")
|
||||
sigma = self.weighted_sum[0][0]
|
||||
name.next_to(sigma, UP)
|
||||
name.to_edge(UP, SMALL_BUFF)
|
||||
|
||||
arrow = Arrow(
|
||||
name.get_bottom(), sigma.get_top(),
|
||||
buff = SMALL_BUFF,
|
||||
use_rectangular_stem = False,
|
||||
max_tip_length_to_length_ratio = 0.3
|
||||
)
|
||||
|
||||
self.play(
|
||||
Write(name),
|
||||
ShowCreation(arrow),
|
||||
)
|
||||
self.sigmoid_name = name
|
||||
self.sigmoid_arrow = arrow
|
||||
|
||||
def words_on_activation(self):
|
||||
neuron = self.neuron
|
||||
weighted_sum = self.weighted_sum
|
||||
@ -2702,11 +2795,11 @@ class IncludeBias(IntroduceWeights):
|
||||
words.next_to(neuron, RIGHT)
|
||||
|
||||
self.play(Write(words, run_time = 2))
|
||||
self.play(LaggedStart(
|
||||
ApplyMethod, colored_pixels,
|
||||
lambda p : (p.shift, MED_LARGE_BUFF*UP),
|
||||
self.play(ApplyMethod(
|
||||
colored_pixels.shift, MED_LARGE_BUFF*UP,
|
||||
rate_func = there_and_back,
|
||||
run_time = 2
|
||||
run_time = 2,
|
||||
submobject_mode = "lagged_start"
|
||||
))
|
||||
self.dither()
|
||||
|
||||
@ -2775,26 +2868,25 @@ class IncludeBias(IntroduceWeights):
|
||||
|
||||
return weighted_sum
|
||||
|
||||
def add_sigmoid_label(self):
|
||||
name = TextMobject("Sigmoid")
|
||||
sigma = self.weighted_sum[0][0]
|
||||
name.next_to(sigma, UP)
|
||||
name.to_edge(UP, SMALL_BUFF)
|
||||
class BiasForInactiviyWords(Scene):
|
||||
def construct(self):
|
||||
words = TextMobject("Bias for inactivity")
|
||||
words.highlight(BLUE)
|
||||
words.scale_to_fit_width(2*SPACE_WIDTH - 1)
|
||||
words.to_edge(UP)
|
||||
|
||||
arrow = Arrow(
|
||||
name.get_bottom(), sigma.get_top(),
|
||||
buff = SMALL_BUFF,
|
||||
use_rectangular_stem = False,
|
||||
max_tip_length_to_length_ratio = 0.3
|
||||
)
|
||||
|
||||
self.add(name, arrow)
|
||||
self.sigmoid_name = name
|
||||
self.sigmoid_arrow = arrow
|
||||
self.play(Write(words))
|
||||
self.dither(3)
|
||||
|
||||
class ContinualEdgeUpdate(ContinualAnimation):
|
||||
CONFIG = {
|
||||
"max_stroke_width" : 3,
|
||||
"stroke_width_exp" : 7,
|
||||
"n_cycles" : 5,
|
||||
}
|
||||
def __init__(self, network_mob, **kwargs):
|
||||
n_cycles = 5
|
||||
digest_config(self, kwargs)
|
||||
n_cycles = self.n_cycles
|
||||
edges = VGroup(*it.chain(*network_mob.edge_groups))
|
||||
self.move_to_targets = []
|
||||
for edge in edges:
|
||||
@ -2802,8 +2894,9 @@ class ContinualEdgeUpdate(ContinualAnimation):
|
||||
random.choice([GREEN, GREEN, GREEN, RED])
|
||||
for x in range(n_cycles)
|
||||
]
|
||||
msw = self.max_stroke_width
|
||||
edge.widths = [
|
||||
3*random.random()**7
|
||||
msw*random.random()**self.stroke_width_exp
|
||||
for x in range(n_cycles)
|
||||
]
|
||||
edge.cycle_time = 1 + random.random()
|
||||
@ -3177,7 +3270,6 @@ class IntroduceWeightMatrix(NetworkScene):
|
||||
self.show_first_neuron_weighted_sum()
|
||||
self.add_bias()
|
||||
self.add_sigmoid()
|
||||
self.dither()
|
||||
##
|
||||
|
||||
def fade_many_neurons(self):
|
||||
@ -3356,9 +3448,11 @@ class IntroduceWeightMatrix(NetworkScene):
|
||||
post_bracketes = self.get_brackets(column)
|
||||
pre_brackets.set_fill(opacity = 0)
|
||||
|
||||
self.play(FocusOn(self.a_labels[0]))
|
||||
self.play(LaggedStart(
|
||||
Indicate, self.a_labels,
|
||||
rate_func = there_and_back
|
||||
rate_func = there_and_back,
|
||||
run_time = 1
|
||||
))
|
||||
self.play(
|
||||
MoveToTarget(a_labels),
|
||||
@ -3593,6 +3687,7 @@ class IntroduceWeightMatrix(NetworkScene):
|
||||
neuron_anims += [
|
||||
neuron.edges_in.restore
|
||||
]
|
||||
neurons.add_to_back(self.network_mob.layers[1].neurons[0])
|
||||
|
||||
self.play(ReplacementTransform(
|
||||
VGroup(
|
||||
@ -3646,27 +3741,497 @@ class IntroduceWeightMatrix(NetworkScene):
|
||||
rb.next_to(mob, RIGHT, SMALL_BUFF)
|
||||
return both
|
||||
|
||||
|
||||
|
||||
class EoLA3Wrapper(Scene):
|
||||
class HorrifiedMorty(Scene):
|
||||
def construct(self):
|
||||
morty = Mortimer()
|
||||
morty.flip()
|
||||
morty.scale(2)
|
||||
|
||||
for mode in "horrified", "hesitant":
|
||||
self.play(
|
||||
morty.change, mode,
|
||||
morty.look, UP,
|
||||
)
|
||||
self.play(Blink(morty))
|
||||
self.dither(2)
|
||||
|
||||
class SigmoidAppliedToVector(Scene):
|
||||
def construct(self):
|
||||
tex = TexMobject("""
|
||||
\\sigma \\left(
|
||||
\\left[\\begin{array}{c}
|
||||
x \\\\ y \\\\ z
|
||||
\\end{array}\\right]
|
||||
\\right) =
|
||||
\\left[\\begin{array}{c}
|
||||
\\sigma(x) \\\\ \\sigma(y) \\\\ \\sigma(z)
|
||||
\\end{array}\\right]
|
||||
""")
|
||||
tex.scale_to_fit_width(2*SPACE_WIDTH - 1)
|
||||
tex.to_edge(DOWN)
|
||||
indices = it.chain(
|
||||
[0], range(1, 5), range(16, 16+4),
|
||||
range(25, 25+2), [25+3],
|
||||
range(29, 29+2), [29+3],
|
||||
range(33, 33+2), [33+3],
|
||||
)
|
||||
for i in indices:
|
||||
tex[i].highlight(YELLOW)
|
||||
self.add(tex)
|
||||
self.dither()
|
||||
|
||||
class EoLA3Wrapper(PiCreatureScene):
|
||||
def construct(self):
|
||||
morty = self.pi_creature
|
||||
rect = ScreenRectangle(height = 5)
|
||||
rect.next_to(morty, UP+LEFT)
|
||||
rect.to_edge(UP, buff = LARGE_BUFF)
|
||||
title = TextMobject("Essence of linear algebra")
|
||||
title.next_to(rect, UP)
|
||||
|
||||
self.play(
|
||||
ShowCreation(rect),
|
||||
FadeIn(title),
|
||||
morty.change, "raise_right_hand", rect
|
||||
)
|
||||
self.dither(4)
|
||||
|
||||
class FeedForwardCode(ExternallyAnimatedScene):
|
||||
pass
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class NeuronIsFunction(MoreHonestMNistNetworkPreview):
|
||||
CONFIG = {
|
||||
"network_mob_config" : {
|
||||
"layer_to_layer_buff" : 2
|
||||
}
|
||||
}
|
||||
def construct(self):
|
||||
self.setup_network_mob()
|
||||
self.activate_network()
|
||||
self.write_neuron_holds_a_number()
|
||||
self.feed_in_new_image(8, 7)
|
||||
self.neuron_is_function()
|
||||
self.show_neuron_as_function()
|
||||
self.fade_network_back_in()
|
||||
self.network_is_a_function()
|
||||
self.feed_in_new_image(9, 4)
|
||||
self.dither(2)
|
||||
|
||||
|
||||
def setup_network_mob(self):
|
||||
self.network_mob.scale(0.7)
|
||||
self.network_mob.to_edge(DOWN)
|
||||
self.network_mob.shift(LEFT)
|
||||
|
||||
def activate_network(self):
|
||||
network_mob = self.network_mob
|
||||
self.image_map = get_organized_images()
|
||||
in_vect = self.image_map[3][0]
|
||||
mnist_mob = MNistMobject(in_vect)
|
||||
mnist_mob.next_to(network_mob, LEFT, MED_LARGE_BUFF, UP)
|
||||
activations = self.network.get_activation_of_all_layers(in_vect)
|
||||
for i, activation in enumerate(activations):
|
||||
layer = self.network_mob.layers[i]
|
||||
Transform(
|
||||
layer, self.network_mob.get_active_layer(i, activation)
|
||||
).update(1)
|
||||
self.add(mnist_mob)
|
||||
|
||||
self.image_rect, self.curr_image = mnist_mob
|
||||
|
||||
def write_neuron_holds_a_number(self):
|
||||
neuron_word = TextMobject("Neuron")
|
||||
arrow = Arrow(ORIGIN, DOWN, color = BLUE)
|
||||
thing_words = TextMobject("Thing that holds \\\\ a number")
|
||||
group = VGroup(neuron_word, arrow, thing_words)
|
||||
group.arrange_submobjects(DOWN)
|
||||
group.to_corner(UP+RIGHT, buff = LARGE_BUFF)
|
||||
|
||||
neuron = self.network_mob.layers[2].neurons[2]
|
||||
decimal = DecimalNumber(neuron.get_fill_opacity())
|
||||
decimal.scale_to_fit_width(0.7*neuron.get_width())
|
||||
decimal.move_to(neuron)
|
||||
neuron_group = VGroup(neuron, decimal)
|
||||
neuron_group.save_state()
|
||||
decimal.set_fill(opacity = 0)
|
||||
|
||||
self.play(
|
||||
neuron_group.restore,
|
||||
neuron_group.scale, 3,
|
||||
neuron_group.next_to, neuron_word, LEFT,
|
||||
FadeIn(neuron_word),
|
||||
GrowArrow(arrow),
|
||||
FadeIn(
|
||||
thing_words, run_time = 2,
|
||||
rate_func = squish_rate_func(smooth, 0.3, 1)
|
||||
)
|
||||
)
|
||||
self.dither()
|
||||
self.play(neuron_group.restore)
|
||||
|
||||
self.neuron_word = neuron_word
|
||||
self.neuron_word_arrow = arrow
|
||||
self.thing_words = thing_words
|
||||
self.neuron = neuron
|
||||
self.decimal = decimal
|
||||
|
||||
def feed_in_new_image(self, digit, choice):
|
||||
in_vect = self.image_map[digit][choice]
|
||||
|
||||
args = []
|
||||
for s in "answer_rect", "curr_image", "image_rect":
|
||||
if hasattr(self, s):
|
||||
args.append(getattr(self, s))
|
||||
else:
|
||||
args.append(VectorizedPoint())
|
||||
MoreHonestMNistNetworkPreview.reset_display(self, *args)
|
||||
self.feed_in_image(in_vect)
|
||||
|
||||
def neuron_is_function(self):
|
||||
thing_words = self.thing_words
|
||||
cross = Cross(thing_words)
|
||||
function_word = TextMobject("Function")
|
||||
function_word.move_to(thing_words, UP)
|
||||
|
||||
self.play(
|
||||
thing_words.fade,
|
||||
ShowCreation(cross)
|
||||
)
|
||||
self.play(
|
||||
FadeIn(function_word),
|
||||
VGroup(thing_words, cross).to_edge, DOWN,
|
||||
)
|
||||
self.dither()
|
||||
|
||||
self.function_word = function_word
|
||||
|
||||
def show_neuron_as_function(self):
|
||||
neuron = self.neuron.copy()
|
||||
edges = neuron.edges_in.copy()
|
||||
prev_layer = self.network_mob.layers[1].copy()
|
||||
|
||||
arrow = Arrow(ORIGIN, RIGHT, color = BLUE)
|
||||
arrow.next_to(neuron, RIGHT, SMALL_BUFF)
|
||||
decimal = DecimalNumber(neuron.get_fill_opacity())
|
||||
decimal.next_to(arrow, RIGHT)
|
||||
|
||||
self.play(
|
||||
FadeOut(self.network_mob),
|
||||
*map(Animation, [neuron, edges, prev_layer])
|
||||
)
|
||||
self.play(LaggedStart(
|
||||
ShowCreationThenDestruction,
|
||||
edges.copy().set_stroke(YELLOW, 4),
|
||||
))
|
||||
self.play(
|
||||
GrowArrow(arrow),
|
||||
Transform(self.decimal, decimal)
|
||||
)
|
||||
self.dither(2)
|
||||
|
||||
self.non_faded_network_parts = VGroup(
|
||||
neuron, edges, prev_layer
|
||||
)
|
||||
self.neuron_arrow = arrow
|
||||
|
||||
def fade_network_back_in(self):
|
||||
anims = [
|
||||
FadeIn(
|
||||
mob,
|
||||
run_time = 2,
|
||||
submobject_mode = "lagged_start"
|
||||
)
|
||||
for mob in self.network_mob.layers, self.network_mob.edge_groups
|
||||
]
|
||||
anims += [
|
||||
FadeOut(self.neuron_arrow),
|
||||
FadeOut(self.decimal),
|
||||
]
|
||||
anims.append(Animation(self.non_faded_network_parts))
|
||||
|
||||
self.play(*anims)
|
||||
self.remove(self.non_faded_network_parts)
|
||||
|
||||
def network_is_a_function(self):
|
||||
neuron_word = self.neuron_word
|
||||
network_word = TextMobject("Network")
|
||||
network_word.highlight(YELLOW)
|
||||
network_word.move_to(neuron_word)
|
||||
|
||||
func_tex = TexMobject(
|
||||
"f(a_0, \\dots, a_{783}) = ",
|
||||
"""\\left[
|
||||
\\begin{array}{c}
|
||||
y_0 \\\\ \\vdots \\\\ y_{9}
|
||||
\\end{array}
|
||||
\\right]"""
|
||||
)
|
||||
func_tex.to_edge(UP)
|
||||
func_tex.shift(MED_SMALL_BUFF*LEFT)
|
||||
|
||||
self.play(
|
||||
ReplacementTransform(neuron_word, network_word),
|
||||
FadeIn(func_tex)
|
||||
)
|
||||
|
||||
###
|
||||
|
||||
def reset_display(self, answer_rect, image, image_rect):
|
||||
#Don't do anything, just record these args
|
||||
self.answer_rect = answer_rect
|
||||
self.curr_image = image
|
||||
self.image_rect = image_rect
|
||||
return
|
||||
|
||||
class ComplicationIsReassuring(TeacherStudentsScene):
|
||||
def construct(self):
|
||||
self.student_says(
|
||||
"It kind of has to \\\\ be complicated, right?",
|
||||
target_mode = "speaking",
|
||||
student_index = 0
|
||||
)
|
||||
self.play(self.teacher.change, "happy")
|
||||
self.dither(4)
|
||||
|
||||
class NextVideo(MoreHonestMNistNetworkPreview, PiCreatureScene):
|
||||
CONFIG = {
|
||||
"network_mob_config" : {
|
||||
"neuron_stroke_color" : WHITE,
|
||||
"layer_to_layer_buff" : 2.5,
|
||||
"brace_for_large_layers" : False,
|
||||
}
|
||||
}
|
||||
def setup(self):
|
||||
MoreHonestMNistNetworkPreview.setup(self)
|
||||
PiCreatureScene.setup(self)
|
||||
|
||||
def construct(self):
|
||||
self.network_and_data()
|
||||
self.show_next_video()
|
||||
self.talk_about_subscription()
|
||||
self.show_video_neural_network()
|
||||
|
||||
def network_and_data(self):
|
||||
morty = self.pi_creature
|
||||
network_mob = self.network_mob
|
||||
network_mob.to_edge(LEFT)
|
||||
for obj in network_mob, self:
|
||||
obj.remove(network_mob.output_labels)
|
||||
network_mob.scale(0.7)
|
||||
network_mob.shift(RIGHT)
|
||||
edge_update = ContinualEdgeUpdate(network_mob)
|
||||
|
||||
training_data, validation_data, test_data = load_data_wrapper()
|
||||
data_mobs = VGroup()
|
||||
for vect, num in test_data[:30]:
|
||||
image = MNistMobject(vect)
|
||||
image.scale_to_fit_height(0.7)
|
||||
arrow = Arrow(ORIGIN, RIGHT, color = BLUE)
|
||||
num_mob = TexMobject(str(num))
|
||||
group = Group(image, arrow, num_mob)
|
||||
group.arrange_submobjects(RIGHT, buff = SMALL_BUFF)
|
||||
group.next_to(ORIGIN, RIGHT)
|
||||
data_mobs.add(group)
|
||||
|
||||
data_mobs.next_to(network_mob, UP)
|
||||
|
||||
self.add(edge_update)
|
||||
self.play(morty.change, "confused", network_mob)
|
||||
self.dither(2)
|
||||
for data_mob in data_mobs:
|
||||
self.add(data_mob)
|
||||
self.dither(0.2)
|
||||
self.remove(data_mob)
|
||||
|
||||
self.content = network_mob
|
||||
self.edge_update = edge_update
|
||||
|
||||
def show_next_video(self):
|
||||
morty = self.pi_creature
|
||||
content = self.content
|
||||
|
||||
video = VideoIcon()
|
||||
video.scale_to_fit_height(2)
|
||||
video.set_fill(RED, 0.8)
|
||||
video.next_to(morty, UP+LEFT)
|
||||
|
||||
rect = SurroundingRectangle(video)
|
||||
rect.set_stroke(width = 0)
|
||||
rect.set_fill(BLACK, 0.5)
|
||||
|
||||
words = TextMobject("On learning")
|
||||
words.next_to(video, UP)
|
||||
|
||||
if self.edge_update.internal_time < 1:
|
||||
self.edge_update.internal_time = 2
|
||||
self.play(
|
||||
content.scale_to_fit_height, 0.8*video.get_height(),
|
||||
content.move_to, video,
|
||||
morty.change, "raise_right_hand",
|
||||
FadeIn(rect),
|
||||
FadeIn(video),
|
||||
)
|
||||
self.add_foreground_mobjects(rect, video)
|
||||
self.dither(2)
|
||||
self.play(Write(words))
|
||||
self.dither(2)
|
||||
|
||||
self.video = Group(content, rect, video, words)
|
||||
|
||||
def talk_about_subscription(self):
|
||||
morty = self.pi_creature
|
||||
morty.generate_target()
|
||||
morty.target.change("hooray")
|
||||
morty.target.rotate(
|
||||
np.pi, axis = UP, about_point = morty.get_left()
|
||||
)
|
||||
morty.target.shift(LEFT)
|
||||
video = self.video
|
||||
|
||||
|
||||
subscribe_word = TextMobject(
|
||||
"Subscribe", "!",
|
||||
arg_separator = ""
|
||||
)
|
||||
bang = subscribe_word[1]
|
||||
subscribe_word.to_corner(DOWN+RIGHT)
|
||||
subscribe_word.shift(2*UP)
|
||||
q_mark = TextMobject("?")
|
||||
q_mark.move_to(bang, LEFT)
|
||||
arrow = Arrow(ORIGIN, DOWN, color = RED, buff = 0)
|
||||
arrow.next_to(subscribe_word, DOWN)
|
||||
arrow.shift(RIGHT)
|
||||
|
||||
self.play(
|
||||
Write(subscribe_word),
|
||||
self.video.shift, 3*LEFT,
|
||||
MoveToTarget(morty),
|
||||
)
|
||||
self.play(GrowArrow(arrow))
|
||||
self.dither(2)
|
||||
self.play(morty.change, "maybe", arrow)
|
||||
self.play(Transform(bang, q_mark))
|
||||
self.dither(3)
|
||||
|
||||
def show_video_neural_network(self):
|
||||
morty = self.pi_creature
|
||||
|
||||
network_mob, rect, video, words = self.video
|
||||
network_mob.generate_target()
|
||||
network_mob.target.scale_to_fit_height(5)
|
||||
network_mob.target.to_corner(UP+LEFT)
|
||||
neurons = VGroup(*network_mob.target.layers[-1].neurons[:2])
|
||||
neurons.set_stroke(width = 0)
|
||||
|
||||
video.generate_target()
|
||||
video.target.set_fill(opacity = 1)
|
||||
video.target.scale_to_fit_height(neurons.get_height())
|
||||
video.target.move_to(neurons, LEFT)
|
||||
|
||||
self.play(
|
||||
MoveToTarget(network_mob),
|
||||
MoveToTarget(video),
|
||||
FadeOut(words),
|
||||
FadeOut(rect),
|
||||
morty.change, "raise_left_hand"
|
||||
)
|
||||
|
||||
neuron_pairs = VGroup(*[
|
||||
VGroup(*network_mob.layers[-1].neurons[2*i:2*i+2])
|
||||
for i in range(1, 5)
|
||||
])
|
||||
for pair in neuron_pairs:
|
||||
video = video.copy()
|
||||
video.move_to(pair, LEFT)
|
||||
pair.target = video
|
||||
|
||||
self.play(LaggedStart(
|
||||
MoveToTarget, neuron_pairs,
|
||||
run_time = 3
|
||||
))
|
||||
self.play(morty.change, "shruggie")
|
||||
self.dither(10)
|
||||
|
||||
###
|
||||
|
||||
class NNPatreonThanks(PatreonThanks):
|
||||
CONFIG = {
|
||||
"specific_patrons" : [
|
||||
"Desmos",
|
||||
"Burt Humburg",
|
||||
"CrypticSwarm",
|
||||
"Juan Benet",
|
||||
"Ali Yahya",
|
||||
"William",
|
||||
"Mayank M. Mehrotra",
|
||||
"Lukas Biewald",
|
||||
"Samantha D. Suplee",
|
||||
"Yana Chernobilsky",
|
||||
"Kaustuv DeBiswas",
|
||||
"Kathryn Schmiedicke",
|
||||
"Yu Jun",
|
||||
"Dave Nicponski",
|
||||
"Damion Kistler",
|
||||
"Markus Persson",
|
||||
"Yoni Nazarathy",
|
||||
"Ed Kellett",
|
||||
"Joseph John Cox",
|
||||
"Luc Ritchie",
|
||||
"Andy Nichols",
|
||||
"Harsev Singh",
|
||||
"Mads Elvheim",
|
||||
"Erik Sundell",
|
||||
"Xueqi Li",
|
||||
"David G. Stork",
|
||||
"Tianyu Ge",
|
||||
"Ted Suzman",
|
||||
"Linh Tran",
|
||||
"Andrew Busey",
|
||||
"Michael McGuffin",
|
||||
"John Haley",
|
||||
"Ankalagon",
|
||||
"Eric Lavault",
|
||||
"Boris Veselinovich",
|
||||
"Julian Pulgarin",
|
||||
"Jeff Linse",
|
||||
"Cooper Jones",
|
||||
"Ryan Dahl",
|
||||
"Mark Govea",
|
||||
"Robert Teed",
|
||||
"Jason Hise",
|
||||
"Meshal Alshammari",
|
||||
"Bernd Sing",
|
||||
"James Thornton",
|
||||
"Mustafa Mahdi",
|
||||
"Mathew Bramson",
|
||||
"Jerry Ling",
|
||||
"Vecht",
|
||||
"Shimin Kuang",
|
||||
"Rish Kundalia",
|
||||
"Achille Brighton",
|
||||
"Ripta Pasay",
|
||||
]
|
||||
}
|
||||
|
||||
class Thumbnail(NetworkScene):
|
||||
CONFIG = {
|
||||
"network_mob_config" : {
|
||||
'neuron_stroke_color' : WHITE
|
||||
}
|
||||
}
|
||||
def construct(self):
|
||||
network_mob = self.network_mob
|
||||
network_mob.scale_to_fit_height(2*SPACE_HEIGHT - 1)
|
||||
|
||||
edge_update = ContinualEdgeUpdate(
|
||||
network_mob,
|
||||
max_stroke_width = 10,
|
||||
stroke_width_exp = 5,
|
||||
)
|
||||
edge_update.internal_time = 3
|
||||
edge_update.update(0)
|
||||
|
||||
self.add(network_mob)
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user