mirror of
https://github.com/helblazer811/ManimML.git
synced 2025-05-21 04:26:43 +08:00
Added padding.
Fixed a bug with ImageLayerToConvolutional2D Padding example
This commit is contained in:
@ -72,8 +72,6 @@ class CombinedScene(ThreeDScene):
|
||||
# group.move_to(ORIGIN)
|
||||
nn.move_to(ORIGIN)
|
||||
# Play animation
|
||||
forward_pass = nn.make_forward_pass_animation(
|
||||
corner_pulses=False, all_filters_at_once=False
|
||||
)
|
||||
forward_pass = nn.make_forward_pass_animation()
|
||||
self.wait(1)
|
||||
self.play(forward_pass)
|
||||
|
@ -65,8 +65,6 @@ class CombinedScene(ThreeDScene):
|
||||
self.add(code)
|
||||
self.wait(5)
|
||||
# Play animation
|
||||
forward_pass = nn.make_forward_pass_animation(
|
||||
corner_pulses=False, all_filters_at_once=False
|
||||
)
|
||||
forward_pass = nn.make_forward_pass_animation()
|
||||
self.wait(1)
|
||||
self.play(forward_pass)
|
@ -68,9 +68,6 @@ class CombinedScene(ThreeDScene):
|
||||
group = Group(nn, code)
|
||||
group.move_to(ORIGIN)
|
||||
# Play animation
|
||||
forward_pass = nn.make_forward_pass_animation(
|
||||
corner_pulses=False,
|
||||
all_filters_at_once=False,
|
||||
)
|
||||
forward_pass = nn.make_forward_pass_animation()
|
||||
self.wait(1)
|
||||
self.play(forward_pass)
|
||||
|
82
examples/cnn/padding_example.py
Normal file
82
examples/cnn/padding_example.py
Normal file
@ -0,0 +1,82 @@
|
||||
from manim import *
|
||||
from manim_ml.neural_network.layers.image import ImageLayer
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
|
||||
from manim_ml.neural_network.layers.convolutional_2d import Convolutional2DLayer
|
||||
from manim_ml.neural_network.layers.feed_forward import FeedForwardLayer
|
||||
from manim_ml.neural_network.neural_network import NeuralNetwork
|
||||
|
||||
ROOT_DIR = Path(__file__).parents[2]
|
||||
|
||||
# Make the specific scene
|
||||
config.pixel_height = 1200
|
||||
config.pixel_width = 1900
|
||||
config.frame_height = 6.0
|
||||
config.frame_width = 6.0
|
||||
|
||||
def make_code_snippet():
|
||||
code_str = """
|
||||
# Make nn
|
||||
nn = NeuralNetwork([
|
||||
ImageLayer(numpy_image),
|
||||
Convolutional2DLayer(1, 6, 1, padding=1),
|
||||
Convolutional2DLayer(3, 6, 3),
|
||||
FeedForwardLayer(3),
|
||||
FeedForwardLayer(1),
|
||||
])
|
||||
# Play animation
|
||||
self.play(nn.make_forward_pass_animation())
|
||||
"""
|
||||
|
||||
code = Code(
|
||||
code=code_str,
|
||||
tab_width=4,
|
||||
background_stroke_width=1,
|
||||
background_stroke_color=WHITE,
|
||||
insert_line_no=False,
|
||||
style="monokai",
|
||||
# background="window",
|
||||
language="py",
|
||||
)
|
||||
code.scale(0.38)
|
||||
|
||||
return code
|
||||
|
||||
class CombinedScene(ThreeDScene):
|
||||
|
||||
def construct(self):
|
||||
# Make nn
|
||||
image = Image.open(ROOT_DIR / "assets/mnist/digit.jpeg")
|
||||
numpy_image = np.asarray(image)
|
||||
# Make nn
|
||||
nn = NeuralNetwork([
|
||||
ImageLayer(numpy_image, height=1.5),
|
||||
Convolutional2DLayer(
|
||||
num_feature_maps=1,
|
||||
feature_map_size=6,
|
||||
padding=1,
|
||||
padding_dashed=True
|
||||
),
|
||||
Convolutional2DLayer(
|
||||
num_feature_maps=3,
|
||||
feature_map_size=6,
|
||||
filter_size=3,
|
||||
padding=0,
|
||||
padding_dashed=False
|
||||
),
|
||||
FeedForwardLayer(3),
|
||||
FeedForwardLayer(1),
|
||||
],
|
||||
layer_spacing=0.25,
|
||||
)
|
||||
# Center the nn
|
||||
self.add(nn)
|
||||
code = make_code_snippet()
|
||||
code.next_to(nn, DOWN)
|
||||
self.add(code)
|
||||
Group(code, nn).move_to(ORIGIN)
|
||||
# Play animation
|
||||
forward_pass = nn.make_forward_pass_animation()
|
||||
self.wait(1)
|
||||
self.play(forward_pass, run_time=20)
|
53
examples/lenet/lenet.py
Normal file
53
examples/lenet/lenet.py
Normal file
@ -0,0 +1,53 @@
|
||||
from pathlib import Path
|
||||
|
||||
from manim import *
|
||||
from PIL import Image
|
||||
import numpy as np
|
||||
|
||||
from manim_ml.neural_network.layers.convolutional_2d import Convolutional2DLayer
|
||||
from manim_ml.neural_network.layers.feed_forward import FeedForwardLayer
|
||||
from manim_ml.neural_network.layers.image import ImageLayer
|
||||
from manim_ml.neural_network.layers.max_pooling_2d import MaxPooling2DLayer
|
||||
from manim_ml.neural_network.neural_network import NeuralNetwork
|
||||
|
||||
# Make the specific scene
|
||||
config.pixel_height = 1200
|
||||
config.pixel_width = 1900
|
||||
config.frame_height = 20.0
|
||||
config.frame_width = 20.0
|
||||
|
||||
ROOT_DIR = Path(__file__).parents[2]
|
||||
|
||||
class CombinedScene(ThreeDScene):
|
||||
def construct(self):
|
||||
image = Image.open(ROOT_DIR / "assets/mnist/digit.jpeg")
|
||||
numpy_image = np.asarray(image)
|
||||
# Make nn
|
||||
nn = NeuralNetwork([
|
||||
ImageLayer(numpy_image, height=4.5),
|
||||
Convolutional2DLayer(1, 28),
|
||||
Convolutional2DLayer(6, 28, 5),
|
||||
MaxPooling2DLayer(kernel_size=2),
|
||||
Convolutional2DLayer(16, 10, 5),
|
||||
MaxPooling2DLayer(kernel_size=2),
|
||||
FeedForwardLayer(8),
|
||||
FeedForwardLayer(3),
|
||||
FeedForwardLayer(2),
|
||||
],
|
||||
layer_spacing=0.25,
|
||||
)
|
||||
# Center the nn
|
||||
nn.move_to(ORIGIN)
|
||||
self.add(nn)
|
||||
# Make code snippet
|
||||
# code = make_code_snippet()
|
||||
# code.next_to(nn, DOWN)
|
||||
# self.add(code)
|
||||
# Group it all
|
||||
# group = Group(nn, code)
|
||||
# group.move_to(ORIGIN)
|
||||
nn.move_to(ORIGIN)
|
||||
# Play animation
|
||||
# forward_pass = nn.make_forward_pass_animation()
|
||||
# self.wait(1)
|
||||
# self.play(forward_pass)
|
@ -37,8 +37,6 @@ class CombinedScene(ThreeDScene):
|
||||
self.add(nn)
|
||||
# Play animation
|
||||
forward_pass = nn.make_forward_pass_animation(
|
||||
corner_pulses=False,
|
||||
all_filters_at_once=False,
|
||||
highlight_active_feature_map=True,
|
||||
)
|
||||
self.wait(1)
|
||||
|
@ -14,12 +14,13 @@ class GriddedRectangle(VGroup):
|
||||
close_new_points=True,
|
||||
grid_xstep=None,
|
||||
grid_ystep=None,
|
||||
grid_stroke_width=0.0, # DEFAULT_STROKE_WIDTH/2,
|
||||
grid_stroke_width=0.0, # DEFAULT_STROKE_WIDTH/2,
|
||||
grid_stroke_color=ORANGE,
|
||||
grid_stroke_opacity=1.0,
|
||||
stroke_width=2.0,
|
||||
fill_opacity=0.2,
|
||||
show_grid_lines=False,
|
||||
dotted_lines=False,
|
||||
**kwargs
|
||||
):
|
||||
super().__init__()
|
||||
@ -37,16 +38,43 @@ class GriddedRectangle(VGroup):
|
||||
self.show_grid_lines = show_grid_lines
|
||||
self.untransformed_width = width
|
||||
self.untransformed_height = height
|
||||
self.dotted_lines = dotted_lines
|
||||
# Make rectangle
|
||||
self.rectangle = Rectangle(
|
||||
width=width,
|
||||
height=height,
|
||||
color=color,
|
||||
stroke_width=stroke_width,
|
||||
fill_color=color,
|
||||
fill_opacity=fill_opacity,
|
||||
shade_in_3d=True
|
||||
)
|
||||
if self.dotted_lines:
|
||||
no_border_rectangle = Rectangle(
|
||||
width=width,
|
||||
height=height,
|
||||
color=color,
|
||||
fill_color=color,
|
||||
stroke_opacity=0.0,
|
||||
fill_opacity=fill_opacity,
|
||||
shade_in_3d=True
|
||||
)
|
||||
self.rectangle = no_border_rectangle
|
||||
border_rectangle = Rectangle(
|
||||
width=width,
|
||||
height=height,
|
||||
color=color,
|
||||
fill_color=color,
|
||||
fill_opacity=fill_opacity,
|
||||
shade_in_3d=True,
|
||||
stroke_width=stroke_width
|
||||
)
|
||||
self.dotted_lines = DashedVMobject(
|
||||
border_rectangle,
|
||||
num_dashes=int((width + height) / 2) * 20,
|
||||
)
|
||||
self.add(self.dotted_lines)
|
||||
else:
|
||||
self.rectangle = Rectangle(
|
||||
width=width,
|
||||
height=height,
|
||||
color=color,
|
||||
stroke_width=stroke_width,
|
||||
fill_color=color,
|
||||
fill_opacity=fill_opacity,
|
||||
shade_in_3d=True
|
||||
)
|
||||
self.add(self.rectangle)
|
||||
# Make grid lines
|
||||
grid_lines = self.make_grid_lines()
|
||||
|
@ -12,6 +12,89 @@ from manim_ml.neural_network.layers.parent_layers import (
|
||||
)
|
||||
from manim_ml.gridded_rectangle import GriddedRectangle
|
||||
|
||||
class FeatureMap(VGroup):
|
||||
"""Class for making a feature map"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
color=ORANGE,
|
||||
feature_map_size=None,
|
||||
fill_color=ORANGE,
|
||||
fill_opacity=0.2,
|
||||
cell_width=0.2,
|
||||
padding=(0, 0),
|
||||
stroke_width=2.0,
|
||||
show_grid_lines=False,
|
||||
padding_dashed=False
|
||||
):
|
||||
super().__init__()
|
||||
self.color = color
|
||||
self.feature_map_size = feature_map_size
|
||||
self.fill_color = fill_color
|
||||
self.fill_opacity = fill_opacity
|
||||
self.cell_width = cell_width
|
||||
self.padding = padding
|
||||
self.stroke_width = stroke_width
|
||||
self.show_grid_lines = show_grid_lines
|
||||
self.padding_dashed = padding_dashed
|
||||
# Check if we have non-zero padding
|
||||
if padding[0] > 0 or padding[1] > 0:
|
||||
# Make the exterior rectangle dashed
|
||||
width_with_padding = (self.feature_map_size[0] + self.padding[0] * 2) * self.cell_width
|
||||
height_with_padding = (self.feature_map_size[1] + self.padding[1] * 2) * self.cell_width
|
||||
self.untransformed_width = width_with_padding
|
||||
self.untransformed_height = height_with_padding
|
||||
|
||||
self.exterior_rectangle = GriddedRectangle(
|
||||
color=self.color,
|
||||
width=width_with_padding,
|
||||
height=height_with_padding,
|
||||
fill_color=self.color,
|
||||
fill_opacity=self.fill_opacity,
|
||||
stroke_color=self.color,
|
||||
stroke_width=self.stroke_width,
|
||||
grid_xstep=self.cell_width,
|
||||
grid_ystep=self.cell_width,
|
||||
grid_stroke_width=self.stroke_width / 2,
|
||||
grid_stroke_color=self.color,
|
||||
show_grid_lines=self.show_grid_lines,
|
||||
dotted_lines=self.padding_dashed
|
||||
)
|
||||
self.add(self.exterior_rectangle)
|
||||
# Add an interior rectangle with no fill color
|
||||
self.interior_rectangle = GriddedRectangle(
|
||||
color=self.color,
|
||||
fill_opacity=0.0,
|
||||
width=self.feature_map_size[0] * self.cell_width,
|
||||
height=self.feature_map_size[1] * self.cell_width,
|
||||
stroke_width=self.stroke_width
|
||||
)
|
||||
self.add(self.interior_rectangle)
|
||||
else:
|
||||
# Just make an exterior rectangle with no dashes.
|
||||
self.untransformed_height = self.feature_map_size[1] * self.cell_width,
|
||||
self.untransformed_width = self.feature_map_size[0] * self.cell_width,
|
||||
# Make the exterior rectangle
|
||||
self.exterior_rectangle = GriddedRectangle(
|
||||
color=self.color,
|
||||
height=self.feature_map_size[1] * self.cell_width,
|
||||
width=self.feature_map_size[0] * self.cell_width,
|
||||
fill_color=self.color,
|
||||
fill_opacity=self.fill_opacity,
|
||||
stroke_color=self.color,
|
||||
stroke_width=self.stroke_width,
|
||||
grid_xstep=self.cell_width,
|
||||
grid_ystep=self.cell_width,
|
||||
grid_stroke_width=self.stroke_width / 2,
|
||||
grid_stroke_color=self.color,
|
||||
show_grid_lines=self.show_grid_lines,
|
||||
)
|
||||
self.add(self.exterior_rectangle)
|
||||
|
||||
def get_corners_dict(self):
|
||||
"""Returns a dictionary of the corners"""
|
||||
# Sort points through clockwise rotation of a vector in the xy plane
|
||||
return self.exterior_rectangle.get_corners_dict()
|
||||
|
||||
class Convolutional2DLayer(VGroupNeuralNetworkLayer, ThreeDLayer):
|
||||
"""Handles rendering a convolutional layer for a nn"""
|
||||
@ -24,33 +107,48 @@ class Convolutional2DLayer(VGroupNeuralNetworkLayer, ThreeDLayer):
|
||||
cell_width=0.2,
|
||||
filter_spacing=0.1,
|
||||
color=BLUE,
|
||||
pulse_color=ORANGE,
|
||||
show_grid_lines=False,
|
||||
active_color=ORANGE,
|
||||
filter_color=ORANGE,
|
||||
show_grid_lines=False,
|
||||
fill_opacity=0.3,
|
||||
stride=1,
|
||||
stroke_width=2.0,
|
||||
activation_function=None,
|
||||
padding=0,
|
||||
padding_dashed=True,
|
||||
**kwargs,
|
||||
):
|
||||
super().__init__(**kwargs)
|
||||
self.num_feature_maps = num_feature_maps
|
||||
self.filter_color = filter_color
|
||||
if isinstance(padding, tuple):
|
||||
assert len(padding) == 2
|
||||
self.padding = padding
|
||||
elif isinstance(padding, int):
|
||||
self.padding = (padding, padding)
|
||||
else:
|
||||
raise Exception(f"Unrecognized type for padding: {type(padding)}")
|
||||
|
||||
if isinstance(feature_map_size, int):
|
||||
self.feature_map_size = (feature_map_size, feature_map_size)
|
||||
else:
|
||||
self.feature_map_size = feature_map_size
|
||||
|
||||
if isinstance(filter_size, int):
|
||||
self.filter_size = (filter_size, filter_size)
|
||||
else:
|
||||
self.filter_size = filter_size
|
||||
|
||||
self.cell_width = cell_width
|
||||
self.filter_spacing = filter_spacing
|
||||
self.color = color
|
||||
self.pulse_color = pulse_color
|
||||
self.active_color = active_color
|
||||
self.stride = stride
|
||||
self.stroke_width = stroke_width
|
||||
self.show_grid_lines = show_grid_lines
|
||||
self.activation_function = activation_function
|
||||
self.fill_opacity = fill_opacity
|
||||
self.padding_dashed = padding_dashed
|
||||
|
||||
def construct_layer(
|
||||
self,
|
||||
@ -92,12 +190,14 @@ class Convolutional2DLayer(VGroupNeuralNetworkLayer, ThreeDLayer):
|
||||
# Draw rectangles that are filled in with opacity
|
||||
feature_maps = []
|
||||
for filter_index in range(self.num_feature_maps):
|
||||
rectangle = GriddedRectangle(
|
||||
# Check if we need to add padding
|
||||
"""
|
||||
feature_map = GriddedRectangle(
|
||||
color=self.color,
|
||||
height=self.feature_map_size[1] * self.cell_width,
|
||||
width=self.feature_map_size[0] * self.cell_width,
|
||||
fill_color=self.color,
|
||||
fill_opacity=0.2,
|
||||
fill_opacity=self.fill_opacity,
|
||||
stroke_color=self.color,
|
||||
stroke_width=self.stroke_width,
|
||||
grid_xstep=self.cell_width,
|
||||
@ -106,52 +206,44 @@ class Convolutional2DLayer(VGroupNeuralNetworkLayer, ThreeDLayer):
|
||||
grid_stroke_color=self.color,
|
||||
show_grid_lines=self.show_grid_lines,
|
||||
)
|
||||
"""
|
||||
# feature_map = GriddedRectangle()
|
||||
feature_map = FeatureMap(
|
||||
color=self.color,
|
||||
feature_map_size=self.feature_map_size,
|
||||
cell_width=self.cell_width,
|
||||
fill_color=self.color,
|
||||
fill_opacity=self.fill_opacity,
|
||||
padding=self.padding,
|
||||
padding_dashed=self.padding_dashed
|
||||
)
|
||||
# Move the feature map
|
||||
rectangle.move_to([0, 0, filter_index * self.filter_spacing])
|
||||
feature_map.move_to([0, 0, filter_index * self.filter_spacing])
|
||||
# rectangle.set_z_index(4)
|
||||
feature_maps.append(rectangle)
|
||||
feature_maps.append(feature_map)
|
||||
|
||||
return VGroup(*feature_maps)
|
||||
|
||||
def highlight_and_unhighlight_feature_maps(self):
|
||||
"""Highlights then unhighlights feature maps"""
|
||||
return Succession(
|
||||
ApplyMethod(self.feature_maps.set_color, self.pulse_color),
|
||||
ApplyMethod(self.feature_maps.set_color, self.active_color),
|
||||
ApplyMethod(self.feature_maps.set_color, self.color),
|
||||
)
|
||||
|
||||
def make_forward_pass_animation(
|
||||
self, run_time=5, corner_pulses=False, layer_args={}, **kwargs
|
||||
self, run_time=5, layer_args={}, **kwargs
|
||||
):
|
||||
"""Convolution forward pass animation"""
|
||||
# Note: most of this animation is done in the Convolution3DToConvolution3D layer
|
||||
if corner_pulses:
|
||||
raise NotImplementedError()
|
||||
passing_flashes = []
|
||||
for line in self.corner_lines:
|
||||
pulse = ShowPassingFlash(
|
||||
line.copy().set_color(self.pulse_color).set_stroke(opacity=1.0),
|
||||
time_width=0.5,
|
||||
run_time=run_time,
|
||||
rate_func=rate_functions.linear,
|
||||
)
|
||||
passing_flashes.append(pulse)
|
||||
|
||||
# per_filter_run_time = run_time / len(self.feature_maps)
|
||||
# Make animation group
|
||||
if not self.activation_function is None:
|
||||
animation_group = AnimationGroup(
|
||||
*passing_flashes,
|
||||
# filter_flashes
|
||||
self.activation_function.make_evaluate_animation(),
|
||||
self.highlight_and_unhighlight_feature_maps(),
|
||||
lag_ratio=0.0,
|
||||
)
|
||||
else:
|
||||
if not self.activation_function is None:
|
||||
animation_group = AnimationGroup(
|
||||
self.activation_function.make_evaluate_animation(),
|
||||
self.highlight_and_unhighlight_feature_maps(),
|
||||
lag_ratio=0.0,
|
||||
)
|
||||
else:
|
||||
animation_group = AnimationGroup()
|
||||
animation_group = AnimationGroup()
|
||||
|
||||
return animation_group
|
||||
|
||||
|
@ -7,7 +7,6 @@ from manim_ml.gridded_rectangle import GriddedRectangle
|
||||
|
||||
from manim.utils.space_ops import rotation_matrix
|
||||
|
||||
|
||||
def get_rotated_shift_vectors(input_layer, normalized=False):
|
||||
"""Rotates the shift vectors"""
|
||||
# Make base shift vectors
|
||||
@ -25,7 +24,6 @@ def get_rotated_shift_vectors(input_layer, normalized=False):
|
||||
|
||||
return right_shift, down_shift
|
||||
|
||||
|
||||
class Filters(VGroup):
|
||||
"""Group for showing a collection of filters connecting two layers"""
|
||||
|
||||
@ -109,6 +107,8 @@ class Filters(VGroup):
|
||||
rectangle_width = self.output_layer.cell_width
|
||||
rectangle_height = self.output_layer.cell_width
|
||||
filter_color = self.output_layer.filter_color
|
||||
right_shift, down_shift = get_rotated_shift_vectors(self.input_layer)
|
||||
left_shift = -1 * right_shift
|
||||
|
||||
for index, feature_map in enumerate(self.output_layer.feature_maps):
|
||||
# Make sure current feature map is the right filter
|
||||
@ -142,6 +142,13 @@ class Filters(VGroup):
|
||||
buff=0.0
|
||||
# aligned_edge=feature_map.get_corners_dict()["top_left"].get_center()
|
||||
)
|
||||
# Shift based on the amount of output layer padding
|
||||
rectangle.shift(
|
||||
self.output_layer.padding[0] * right_shift,
|
||||
)
|
||||
rectangle.shift(
|
||||
self.output_layer.padding[1] * down_shift,
|
||||
)
|
||||
rectangles.append(rectangle)
|
||||
|
||||
feature_map_rectangles = VGroup(*rectangles)
|
||||
@ -280,7 +287,7 @@ class Convolutional2DToConvolutional2D(ConnectiveLayer, ThreeDLayer):
|
||||
color=ORANGE,
|
||||
filter_opacity=0.3,
|
||||
line_color=ORANGE,
|
||||
pulse_color=ORANGE,
|
||||
active_color=ORANGE,
|
||||
cell_width=0.2,
|
||||
show_grid_lines=True,
|
||||
highlight_color=ORANGE,
|
||||
@ -299,10 +306,11 @@ class Convolutional2DToConvolutional2D(ConnectiveLayer, ThreeDLayer):
|
||||
self.num_output_feature_maps = self.output_layer.num_feature_maps
|
||||
self.cell_width = self.output_layer.cell_width
|
||||
self.stride = self.output_layer.stride
|
||||
self.padding = self.input_layer.padding
|
||||
self.filter_opacity = filter_opacity
|
||||
self.cell_width = cell_width
|
||||
self.line_color = line_color
|
||||
self.pulse_color = pulse_color
|
||||
self.active_color = active_color
|
||||
self.show_grid_lines = show_grid_lines
|
||||
self.highlight_color = highlight_color
|
||||
|
||||
@ -333,9 +341,11 @@ class Convolutional2DToConvolutional2D(ConnectiveLayer, ThreeDLayer):
|
||||
# Make the animation
|
||||
num_y_moves = int(
|
||||
(self.feature_map_size[1] - self.filter_size[1]) / self.stride
|
||||
+ self.padding[1] * 2
|
||||
)
|
||||
num_x_moves = int(
|
||||
(self.feature_map_size[0] - self.filter_size[0]) / self.stride
|
||||
+ self.padding[0] * 2
|
||||
)
|
||||
for y_move in range(num_y_moves):
|
||||
# Go right num_x_moves
|
||||
@ -401,9 +411,11 @@ class Convolutional2DToConvolutional2D(ConnectiveLayer, ThreeDLayer):
|
||||
# Make the animation
|
||||
num_y_moves = int(
|
||||
(self.feature_map_size[1] - self.filter_size[1]) / self.stride
|
||||
+ self.padding[1] * 2
|
||||
)
|
||||
num_x_moves = int(
|
||||
(self.feature_map_size[0] - self.filter_size[0]) / self.stride
|
||||
+ self.padding[0] * 2
|
||||
)
|
||||
for y_move in range(num_y_moves):
|
||||
# Go right num_x_moves
|
||||
@ -434,7 +446,10 @@ class Convolutional2DToConvolutional2D(ConnectiveLayer, ThreeDLayer):
|
||||
# Do last row move right
|
||||
for x_move in range(num_x_moves):
|
||||
# Shift right
|
||||
shift_animation = ApplyMethod(filters.shift, self.stride * right_shift)
|
||||
shift_animation = ApplyMethod(
|
||||
filters.shift,
|
||||
self.stride * right_shift
|
||||
)
|
||||
# shift_animation = self.animate.shift(right_shift)
|
||||
animations.append(shift_animation)
|
||||
# Remove the filters
|
||||
@ -445,14 +460,18 @@ class Convolutional2DToConvolutional2D(ConnectiveLayer, ThreeDLayer):
|
||||
# Change the output feature map colors
|
||||
change_color_animations = []
|
||||
change_color_animations.append(
|
||||
ApplyMethod(feature_map.set_color, original_feature_map_color)
|
||||
ApplyMethod(
|
||||
feature_map.set_color,
|
||||
original_feature_map_color
|
||||
)
|
||||
)
|
||||
# Change the input feature map colors
|
||||
input_feature_maps = self.input_layer.feature_maps
|
||||
for input_feature_map in input_feature_maps:
|
||||
change_color_animations.append(
|
||||
ApplyMethod(
|
||||
input_feature_map.set_color, original_feature_map_color
|
||||
input_feature_map.set_color,
|
||||
original_feature_map_color
|
||||
)
|
||||
)
|
||||
# Combine the animations
|
||||
|
@ -10,11 +10,10 @@ Example:
|
||||
NeuralNetwork(layer_node_count)
|
||||
"""
|
||||
import textwrap
|
||||
from manim_ml.neural_network.layers.embedding import EmbeddingLayer
|
||||
import numpy as np
|
||||
from manim import *
|
||||
|
||||
from manim_ml.neural_network.layers.embedding import EmbeddingLayer
|
||||
from manim_ml.neural_network.layers.feed_forward import FeedForwardLayer
|
||||
from manim_ml.neural_network.layers.parent_layers import ConnectiveLayer, ThreeDLayer
|
||||
from manim_ml.neural_network.layers.util import get_connective_layer
|
||||
from manim_ml.list_group import ListGroup
|
||||
@ -23,7 +22,6 @@ from manim_ml.neural_network.neural_network_transformations import (
|
||||
RemoveLayer,
|
||||
)
|
||||
|
||||
|
||||
class NeuralNetwork(Group):
|
||||
"""Neural Network Visualization Container Class"""
|
||||
|
||||
@ -59,7 +57,10 @@ class NeuralNetwork(Group):
|
||||
# Make the connective layers
|
||||
self.connective_layers, self.all_layers = self._construct_connective_layers()
|
||||
# Make overhead title
|
||||
self.title = Text(self.title_text, font_size=DEFAULT_FONT_SIZE / 2)
|
||||
self.title = Text(
|
||||
self.title_text,
|
||||
font_size=DEFAULT_FONT_SIZE / 2
|
||||
)
|
||||
self.title.next_to(self, UP, 1.0)
|
||||
self.add(self.title)
|
||||
# Place layers at correct z index
|
||||
@ -96,6 +97,7 @@ class NeuralNetwork(Group):
|
||||
previous_layer = self.input_layers[layer_index - 1]
|
||||
current_layer = self.input_layers[layer_index]
|
||||
current_layer.move_to(previous_layer.get_center())
|
||||
|
||||
if layout_direction == "left_to_right":
|
||||
x_shift = previous_layer.get_width() / 2 \
|
||||
+ current_layer.get_width() / 2 \
|
||||
@ -106,7 +108,6 @@ class NeuralNetwork(Group):
|
||||
previous_layer.get_width() / 2 \
|
||||
+ current_layer.get_width() / 2
|
||||
) + self.layer_spacing)
|
||||
|
||||
shift_vector = np.array([0, y_shift, 0])
|
||||
else:
|
||||
raise Exception(
|
||||
@ -119,15 +120,13 @@ class NeuralNetwork(Group):
|
||||
# Place activation function
|
||||
if hasattr(current_layer, "activation_function"):
|
||||
if not current_layer.activation_function is None:
|
||||
up_movement = np.array(
|
||||
[
|
||||
0,
|
||||
current_layer.get_height() / 2
|
||||
+ current_layer.activation_function.get_height() / 2
|
||||
+ 0.5 * self.layer_spacing,
|
||||
0,
|
||||
]
|
||||
)
|
||||
up_movement = np.array([
|
||||
0,
|
||||
current_layer.get_height() / 2
|
||||
+ current_layer.activation_function.get_height() / 2
|
||||
+ 0.5 * self.layer_spacing,
|
||||
0,
|
||||
])
|
||||
current_layer.activation_function.move_to(
|
||||
current_layer,
|
||||
)
|
||||
|
2
setup.py
2
setup.py
@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
||||
|
||||
setup(
|
||||
name="manim_ml",
|
||||
version="0.0.14",
|
||||
version="0.0.15",
|
||||
description=(" Machine Learning Animations in python using Manim."),
|
||||
packages=find_packages(),
|
||||
)
|
||||
|
BIN
tests/.DS_Store
vendored
BIN
tests/.DS_Store
vendored
Binary file not shown.
BIN
tests/control_data/padding/ConvPadding.npz
Normal file
BIN
tests/control_data/padding/ConvPadding.npz
Normal file
Binary file not shown.
@ -30,9 +30,6 @@ class CombinedScene(ThreeDScene):
|
||||
nn.move_to(ORIGIN)
|
||||
self.add(nn)
|
||||
# Play animation
|
||||
forward_pass = nn.make_forward_pass_animation(
|
||||
corner_pulses=False,
|
||||
all_filters_at_once=False
|
||||
)
|
||||
forward_pass = nn.make_forward_pass_animation()
|
||||
self.wait(1)
|
||||
self.play(forward_pass)
|
||||
self.play(forward_pass, run_time=30)
|
74
tests/test_conv_padding.py
Normal file
74
tests/test_conv_padding.py
Normal file
@ -0,0 +1,74 @@
|
||||
from manim import *
|
||||
|
||||
from manim_ml.neural_network.layers.convolutional_2d import Convolutional2DLayer
|
||||
from manim_ml.neural_network.layers.feed_forward import FeedForwardLayer
|
||||
from manim_ml.neural_network.neural_network import NeuralNetwork
|
||||
|
||||
from manim_ml.utils.testing.frames_comparison import frames_comparison
|
||||
|
||||
__module_test__ = "padding"
|
||||
|
||||
# Make the specific scene
|
||||
config.pixel_height = 1200
|
||||
config.pixel_width = 1900
|
||||
config.frame_height = 6.0
|
||||
config.frame_width = 6.0
|
||||
|
||||
class CombinedScene(ThreeDScene):
|
||||
|
||||
def construct(self):
|
||||
# Make nn
|
||||
nn = NeuralNetwork([
|
||||
Convolutional2DLayer(
|
||||
num_feature_maps=1,
|
||||
feature_map_size=7,
|
||||
padding=1,
|
||||
padding_dashed=True
|
||||
),
|
||||
Convolutional2DLayer(
|
||||
num_feature_maps=3,
|
||||
feature_map_size=7,
|
||||
filter_size=3,
|
||||
padding=0,
|
||||
padding_dashed=False
|
||||
),
|
||||
FeedForwardLayer(3),
|
||||
],
|
||||
layer_spacing=0.25,
|
||||
)
|
||||
# Center the nn
|
||||
nn.move_to(ORIGIN)
|
||||
self.add(nn)
|
||||
# Play animation
|
||||
forward_pass = nn.make_forward_pass_animation()
|
||||
self.wait(1)
|
||||
self.play(forward_pass, run_time=30)
|
||||
|
||||
@frames_comparison
|
||||
def test_ConvPadding(scene):
|
||||
# Make nn
|
||||
nn = NeuralNetwork([
|
||||
Convolutional2DLayer(
|
||||
num_feature_maps=1,
|
||||
feature_map_size=7,
|
||||
padding=1,
|
||||
padding_dashed=True
|
||||
),
|
||||
Convolutional2DLayer(
|
||||
num_feature_maps=3,
|
||||
feature_map_size=7,
|
||||
filter_size=3,
|
||||
padding=1,
|
||||
filter_spacing=0.35,
|
||||
padding_dashed=False
|
||||
),
|
||||
FeedForwardLayer(3),
|
||||
],
|
||||
layer_spacing=0.25,
|
||||
)
|
||||
# Center the nn
|
||||
nn.move_to(ORIGIN)
|
||||
scene.add(nn)
|
||||
# Play animation
|
||||
forward_pass = nn.make_forward_pass_animation()
|
||||
scene.play(forward_pass, run_time=30)
|
@ -77,9 +77,6 @@ class CombinedScene(ThreeDScene):
|
||||
nn.move_to(ORIGIN)
|
||||
self.add(nn)
|
||||
# Play animation
|
||||
forward_pass = nn.make_forward_pass_animation(
|
||||
corner_pulses=False,
|
||||
all_filters_at_once=False
|
||||
)
|
||||
forward_pass = nn.make_forward_pass_animation()
|
||||
self.wait(1)
|
||||
self.play(forward_pass)
|
@ -14,4 +14,15 @@ def test_FeedForwardScene(scene):
|
||||
FeedForwardLayer(3)
|
||||
])
|
||||
|
||||
scene.add(nn)
|
||||
scene.add(nn)
|
||||
|
||||
class FeedForwardScene(Scene):
|
||||
|
||||
def construct(self):
|
||||
nn = NeuralNetwork([
|
||||
FeedForwardLayer(3),
|
||||
FeedForwardLayer(5),
|
||||
FeedForwardLayer(3)
|
||||
])
|
||||
|
||||
self.add(nn)
|
12
tests/test_gridded_rectangle.py
Normal file
12
tests/test_gridded_rectangle.py
Normal file
@ -0,0 +1,12 @@
|
||||
from manim import *
|
||||
from manim_ml.gridded_rectangle import GriddedRectangle
|
||||
|
||||
class TestGriddedRectangleScene(ThreeDScene):
|
||||
|
||||
def construct(self):
|
||||
rect = GriddedRectangle(
|
||||
color=ORANGE,
|
||||
width=3,
|
||||
height=3
|
||||
)
|
||||
self.add(rect)
|
@ -33,11 +33,7 @@ class CombinedScene(ThreeDScene):
|
||||
self.add(nn)
|
||||
self.wait(5)
|
||||
# Play animation
|
||||
forward_pass = nn.make_forward_pass_animation(
|
||||
corner_pulses=False, all_filters_at_once=False
|
||||
)
|
||||
print(forward_pass)
|
||||
print(forward_pass.animations)
|
||||
forward_pass = nn.make_forward_pass_animation()
|
||||
self.wait(1)
|
||||
self.play(forward_pass)
|
||||
|
||||
@ -57,8 +53,6 @@ class SmallNetwork(ThreeDScene):
|
||||
nn.move_to(ORIGIN)
|
||||
self.add(nn)
|
||||
# Play animation
|
||||
forward_pass = nn.make_forward_pass_animation(
|
||||
corner_pulses=False, all_filters_at_once=False
|
||||
)
|
||||
forward_pass = nn.make_forward_pass_animation()
|
||||
self.wait(1)
|
||||
self.play(forward_pass)
|
@ -31,14 +31,7 @@ class CombinedScene(ThreeDScene):
|
||||
nn.move_to(ORIGIN)
|
||||
nn.scale(1.3)
|
||||
self.add(nn)
|
||||
"""
|
||||
self.play(
|
||||
FadeIn(nn)
|
||||
)
|
||||
"""
|
||||
# Play animation
|
||||
forward_pass = nn.make_forward_pass_animation(
|
||||
corner_pulses=False, all_filters_at_once=False, highlight_filters=True
|
||||
)
|
||||
forward_pass = nn.make_forward_pass_animation()
|
||||
self.wait(1)
|
||||
self.play(forward_pass)
|
||||
|
Reference in New Issue
Block a user