mirror of
https://github.com/3b1b/manim.git
synced 2025-07-29 21:12:35 +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
|
# Change this to point to where you want
|
||||||
# animation files to output
|
# animation files to output
|
||||||
MOVIE_DIR = os.path.join(os.path.expanduser('~'), "Dropbox/3b1b_videos/animations/")
|
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__))
|
THIS_DIR = os.path.dirname(os.path.realpath(__file__))
|
||||||
FILE_DIR = os.path.join(THIS_DIR, "files")
|
FILE_DIR = os.path.join(THIS_DIR, "files")
|
||||||
IMAGE_DIR = os.path.join(FILE_DIR, "images")
|
IMAGE_DIR = os.path.join(FILE_DIR, "images")
|
||||||
GIF_DIR = os.path.join(FILE_DIR, "gifs")
|
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_DIR = os.path.join(FILE_DIR, "Tex")
|
||||||
TEX_IMAGE_DIR = os.path.join(IMAGE_DIR, "Tex")
|
TEX_IMAGE_DIR = os.path.join(IMAGE_DIR, "Tex")
|
||||||
MOBJECT_DIR = os.path.join(FILE_DIR, "mobjects")
|
MOBJECT_DIR = os.path.join(FILE_DIR, "mobjects")
|
||||||
|
@ -21,13 +21,14 @@ import cPickle
|
|||||||
from nn.mnist_loader import load_data_wrapper
|
from nn.mnist_loader import load_data_wrapper
|
||||||
|
|
||||||
NN_DIRECTORY = os.path.dirname(os.path.realpath(__file__))
|
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")
|
PRETRAINED_DATA_FILE = os.path.join(NN_DIRECTORY, "pretrained_weights_and_biases")
|
||||||
IMAGE_MAP_DATA_FILE = os.path.join(NN_DIRECTORY, "image_map")
|
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"
|
# 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]
|
DEFAULT_LAYER_SIZES = [28**2, 16, 16, 10]
|
||||||
|
|
||||||
class Network(object):
|
class Network(object):
|
||||||
|
|
||||||
def __init__(self, sizes):
|
def __init__(self, sizes):
|
||||||
"""The list ``sizes`` contains the number of neurons in the
|
"""The list ``sizes`` contains the number of neurons in the
|
||||||
respective layers of the network. For example, if the list
|
respective layers of the network. For example, if the list
|
||||||
@ -192,12 +193,12 @@ def test_network():
|
|||||||
network = get_pretrained_network()
|
network = get_pretrained_network()
|
||||||
training_data, validation_data, test_data = load_data_wrapper()
|
training_data, validation_data, test_data = load_data_wrapper()
|
||||||
n_right, n_wrong = 0, 0
|
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:
|
if np.argmax(network.feedforward(test_in)) == test_out:
|
||||||
n_right += 1
|
n_right += 1
|
||||||
else:
|
else:
|
||||||
n_wrong += 1
|
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):
|
def layer_to_image_array(layer):
|
||||||
w = int(np.ceil(np.sqrt(len(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.probability import *
|
||||||
from topics.complex_numbers import *
|
from topics.complex_numbers import *
|
||||||
from topics.graph_scene import *
|
from topics.graph_scene import *
|
||||||
|
from topics.common_scenes import *
|
||||||
from scene import Scene
|
from scene import Scene
|
||||||
from scene.reconfigurable_scene import ReconfigurableScene
|
from scene.reconfigurable_scene import ReconfigurableScene
|
||||||
from scene.zoomed_scene import *
|
from scene.zoomed_scene import *
|
||||||
@ -529,6 +530,31 @@ class ExampleThrees(PiCreatureScene):
|
|||||||
three_mobs.add(three_mob)
|
three_mobs.add(three_mob)
|
||||||
return three_mobs
|
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):
|
class WriteAProgram(Scene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
three_array = get_organized_images()[3][0]
|
three_array = get_organized_images()[3][0]
|
||||||
@ -608,6 +634,7 @@ class LayOutPlan(TeacherStudentsScene, NetworkScene):
|
|||||||
self.show_math()
|
self.show_math()
|
||||||
self.ask_about_layers()
|
self.ask_about_layers()
|
||||||
self.show_learning()
|
self.show_learning()
|
||||||
|
self.show_videos()
|
||||||
|
|
||||||
def show_words(self):
|
def show_words(self):
|
||||||
words = VGroup(
|
words = VGroup(
|
||||||
@ -722,6 +749,37 @@ class LayOutPlan(TeacherStudentsScene, NetworkScene):
|
|||||||
self.play(MoveToTarget(edge_group))
|
self.play(MoveToTarget(edge_group))
|
||||||
self.dither()
|
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):
|
class PreviewMNistNetwork(NetworkScene):
|
||||||
CONFIG = {
|
CONFIG = {
|
||||||
"n_examples" : 15,
|
"n_examples" : 15,
|
||||||
@ -737,6 +795,7 @@ class PreviewMNistNetwork(NetworkScene):
|
|||||||
def feed_in_image(self, in_vect):
|
def feed_in_image(self, in_vect):
|
||||||
image = PixelsFromVect(in_vect)
|
image = PixelsFromVect(in_vect)
|
||||||
image.next_to(self.network_mob, LEFT, LARGE_BUFF, UP)
|
image.next_to(self.network_mob, LEFT, LARGE_BUFF, UP)
|
||||||
|
image.shift_onto_screen()
|
||||||
image_rect = SurroundingRectangle(image, color = BLUE)
|
image_rect = SurroundingRectangle(image, color = BLUE)
|
||||||
start_neurons = self.network_mob.layers[0].neurons.copy()
|
start_neurons = self.network_mob.layers[0].neurons.copy()
|
||||||
start_neurons.set_stroke(WHITE, width = 0)
|
start_neurons.set_stroke(WHITE, width = 0)
|
||||||
@ -1598,6 +1657,20 @@ class BreakUpMacroPatterns(IntroduceEachLayer):
|
|||||||
image_mob.pixel_array[:,:,3] = alpha_vect
|
image_mob.pixel_array[:,:,3] = alpha_vect
|
||||||
return image_mob
|
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):
|
class HowWouldYouRecognizeSubcomponent(TeacherStudentsScene):
|
||||||
def construct(self):
|
def construct(self):
|
||||||
self.student_says(
|
self.student_says(
|
||||||
@ -2624,6 +2697,7 @@ class IncludeBias(IntroduceWeights):
|
|||||||
self.setup_start()
|
self.setup_start()
|
||||||
self.revert_to_original_skipping_status()
|
self.revert_to_original_skipping_status()
|
||||||
|
|
||||||
|
self.add_sigmoid_label()
|
||||||
self.words_on_activation()
|
self.words_on_activation()
|
||||||
self.comment_on_need_for_bias()
|
self.comment_on_need_for_bias()
|
||||||
self.add_bias()
|
self.add_bias()
|
||||||
@ -2657,10 +2731,29 @@ class IncludeBias(IntroduceWeights):
|
|||||||
).update(1)
|
).update(1)
|
||||||
|
|
||||||
self.add(self.weighted_sum, digit, weight_grid)
|
self.add(self.weighted_sum, digit, weight_grid)
|
||||||
self.add_sigmoid_label()
|
|
||||||
self.digit = digit
|
self.digit = digit
|
||||||
self.weight_grid = weight_grid
|
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):
|
def words_on_activation(self):
|
||||||
neuron = self.neuron
|
neuron = self.neuron
|
||||||
weighted_sum = self.weighted_sum
|
weighted_sum = self.weighted_sum
|
||||||
@ -2702,11 +2795,11 @@ class IncludeBias(IntroduceWeights):
|
|||||||
words.next_to(neuron, RIGHT)
|
words.next_to(neuron, RIGHT)
|
||||||
|
|
||||||
self.play(Write(words, run_time = 2))
|
self.play(Write(words, run_time = 2))
|
||||||
self.play(LaggedStart(
|
self.play(ApplyMethod(
|
||||||
ApplyMethod, colored_pixels,
|
colored_pixels.shift, MED_LARGE_BUFF*UP,
|
||||||
lambda p : (p.shift, MED_LARGE_BUFF*UP),
|
|
||||||
rate_func = there_and_back,
|
rate_func = there_and_back,
|
||||||
run_time = 2
|
run_time = 2,
|
||||||
|
submobject_mode = "lagged_start"
|
||||||
))
|
))
|
||||||
self.dither()
|
self.dither()
|
||||||
|
|
||||||
@ -2775,26 +2868,25 @@ class IncludeBias(IntroduceWeights):
|
|||||||
|
|
||||||
return weighted_sum
|
return weighted_sum
|
||||||
|
|
||||||
def add_sigmoid_label(self):
|
class BiasForInactiviyWords(Scene):
|
||||||
name = TextMobject("Sigmoid")
|
def construct(self):
|
||||||
sigma = self.weighted_sum[0][0]
|
words = TextMobject("Bias for inactivity")
|
||||||
name.next_to(sigma, UP)
|
words.highlight(BLUE)
|
||||||
name.to_edge(UP, SMALL_BUFF)
|
words.scale_to_fit_width(2*SPACE_WIDTH - 1)
|
||||||
|
words.to_edge(UP)
|
||||||
|
|
||||||
arrow = Arrow(
|
self.play(Write(words))
|
||||||
name.get_bottom(), sigma.get_top(),
|
self.dither(3)
|
||||||
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
|
|
||||||
|
|
||||||
class ContinualEdgeUpdate(ContinualAnimation):
|
class ContinualEdgeUpdate(ContinualAnimation):
|
||||||
|
CONFIG = {
|
||||||
|
"max_stroke_width" : 3,
|
||||||
|
"stroke_width_exp" : 7,
|
||||||
|
"n_cycles" : 5,
|
||||||
|
}
|
||||||
def __init__(self, network_mob, **kwargs):
|
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))
|
edges = VGroup(*it.chain(*network_mob.edge_groups))
|
||||||
self.move_to_targets = []
|
self.move_to_targets = []
|
||||||
for edge in edges:
|
for edge in edges:
|
||||||
@ -2802,8 +2894,9 @@ class ContinualEdgeUpdate(ContinualAnimation):
|
|||||||
random.choice([GREEN, GREEN, GREEN, RED])
|
random.choice([GREEN, GREEN, GREEN, RED])
|
||||||
for x in range(n_cycles)
|
for x in range(n_cycles)
|
||||||
]
|
]
|
||||||
|
msw = self.max_stroke_width
|
||||||
edge.widths = [
|
edge.widths = [
|
||||||
3*random.random()**7
|
msw*random.random()**self.stroke_width_exp
|
||||||
for x in range(n_cycles)
|
for x in range(n_cycles)
|
||||||
]
|
]
|
||||||
edge.cycle_time = 1 + random.random()
|
edge.cycle_time = 1 + random.random()
|
||||||
@ -3177,7 +3270,6 @@ class IntroduceWeightMatrix(NetworkScene):
|
|||||||
self.show_first_neuron_weighted_sum()
|
self.show_first_neuron_weighted_sum()
|
||||||
self.add_bias()
|
self.add_bias()
|
||||||
self.add_sigmoid()
|
self.add_sigmoid()
|
||||||
self.dither()
|
|
||||||
##
|
##
|
||||||
|
|
||||||
def fade_many_neurons(self):
|
def fade_many_neurons(self):
|
||||||
@ -3356,9 +3448,11 @@ class IntroduceWeightMatrix(NetworkScene):
|
|||||||
post_bracketes = self.get_brackets(column)
|
post_bracketes = self.get_brackets(column)
|
||||||
pre_brackets.set_fill(opacity = 0)
|
pre_brackets.set_fill(opacity = 0)
|
||||||
|
|
||||||
|
self.play(FocusOn(self.a_labels[0]))
|
||||||
self.play(LaggedStart(
|
self.play(LaggedStart(
|
||||||
Indicate, self.a_labels,
|
Indicate, self.a_labels,
|
||||||
rate_func = there_and_back
|
rate_func = there_and_back,
|
||||||
|
run_time = 1
|
||||||
))
|
))
|
||||||
self.play(
|
self.play(
|
||||||
MoveToTarget(a_labels),
|
MoveToTarget(a_labels),
|
||||||
@ -3593,6 +3687,7 @@ class IntroduceWeightMatrix(NetworkScene):
|
|||||||
neuron_anims += [
|
neuron_anims += [
|
||||||
neuron.edges_in.restore
|
neuron.edges_in.restore
|
||||||
]
|
]
|
||||||
|
neurons.add_to_back(self.network_mob.layers[1].neurons[0])
|
||||||
|
|
||||||
self.play(ReplacementTransform(
|
self.play(ReplacementTransform(
|
||||||
VGroup(
|
VGroup(
|
||||||
@ -3646,27 +3741,497 @@ class IntroduceWeightMatrix(NetworkScene):
|
|||||||
rb.next_to(mob, RIGHT, SMALL_BUFF)
|
rb.next_to(mob, RIGHT, SMALL_BUFF)
|
||||||
return both
|
return both
|
||||||
|
|
||||||
|
class HorrifiedMorty(Scene):
|
||||||
|
|
||||||
class EoLA3Wrapper(Scene):
|
|
||||||
def construct(self):
|
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
|
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