commit ea63ef5ec0d921df18812885f543e257fd10cb8d Author: Alec Helbling Date: Mon Jan 31 01:27:38 2022 -0500 Created neural network visualization and feed forward animation diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3792cee --- /dev/null +++ b/Makefile @@ -0,0 +1,6 @@ +video: + manim -pqh src/autoencoder.py Autoencoder +checkstyle: + pycodestyle src + pydocstyle src +#docs: diff --git a/src/neural_network.py b/src/neural_network.py new file mode 100644 index 0000000..b501598 --- /dev/null +++ b/src/neural_network.py @@ -0,0 +1,131 @@ +"""Neural Network Manim Visualization + +This module is responsible for generating a neural network visualization with +manim, specifically a fully connected neural network diagram. + +Example: + # Specify how many nodes are in each node layer + layer_node_count = [5, 3, 5] + # Create the object with default style settings + NeuralNetwork(layer_node_count) +""" +from manim import * + +class NeuralNetworkLayer(VGroup): + """Handles rendering a layer for a neural network""" + + def __init__( + self, num_nodes, layer_width=0.3, node_radius=0.2, + node_color=BLUE, node_outline_color=WHITE, rectangle_color=WHITE, + node_spacing=0.6, rectangle_fill_color=BLACK): + super(VGroup, self).__init__() + self.num_nodes = num_nodes + self.layer_width = layer_width + self.node_radius = node_radius + self.node_color = node_color + self.node_outline_color = node_outline_color + self.rectangle_color = rectangle_color + self.node_spacing = node_spacing + self.rectangle_fill_color = rectangle_fill_color + + self.node_group = VGroup() + + self._construct_neural_network_layer() + + def _construct_neural_network_layer(self): + """Creates the neural network layer""" + # Add Nodes + for node_number in range(self.num_nodes): + node_object = Circle(radius=self.node_radius, color=self.node_color) + self.node_group.add(node_object) + # Space the nodes + # Assumes Vertical orientation + for node_index, node_object in enumerate(self.node_group): + location = node_index * self.node_spacing + node_object.move_to([0, location, 0]) + # Create Surrounding Rectangle + surrounding_rectangle = SurroundingRectangle( + self.node_group, color=self.rectangle_color, fill_color=self.rectangle_fill_color, fill_opacity=1.0) + # Add the objects to the class + self.add(surrounding_rectangle, self.node_group) + +class NeuralNetwork(VGroup): + + def __init__( + self, layer_node_count, layer_width=1.0, node_radius=1.0, + node_color=BLUE, edge_color=WHITE, layer_spacing=1.5, + animation_dot_color=ORANGE): + super(VGroup, self).__init__() + self.layer_node_count = layer_node_count + self.layer_width = layer_width + self.node_radius = node_radius + self.node_color = node_color + self.edge_color = edge_color + self.layer_spacing = layer_spacing + self.animation_dot_color = animation_dot_color + + self.layers = self._construct_layers() + self.edge_layers = self._construct_edges() + + self.add(self.edge_layers) + self.add(self.layers) + + def _construct_layers(self): + """Creates the neural network""" + layers = VGroup() + # Create each layer + for layer_index, node_count in enumerate(self.layer_node_count): + layer = NeuralNetworkLayer(node_count) + # Manage spacing + layer.move_to([self.layer_spacing * layer_index, 0, 0]) + # Add layer to VGroup + layers.add(layer) + # Create the connecting edges + layers.z_index = 1 + return layers + + def _construct_edges(self): + """Draws connecting lines between layers""" + edge_layers = VGroup() + for layer_index in range(len(self.layer_node_count) - 1): + current_layer = self.layers[layer_index] + next_layer = self.layers[layer_index + 1] + edge_layer = VGroup() + # Go through each node in the two layers and make a connecting line + for node_i in current_layer.node_group: + for node_j in next_layer.node_group: + line = Line(node_i.get_center(), node_j.get_center(), color=self.edge_color) + edge_layer.add(line) + edge_layers.add(edge_layer) + edge_layers.z_index = 1 + return edge_layers + + def make_forward_propagation_animation(self, run_time=4): + """Generates an animation for feed forward propogation""" + all_animations = [] + per_layer_run_time = run_time / len(self.edge_layers) + for edge_layer in self.edge_layers: + path_animations = [] + for edge in edge_layer: + dot = Dot(color=self.animation_dot_color) + dot.z_index = 0 + anim = MoveAlongPath(dot, edge, run_time=per_layer_run_time, rate_function=linear) + path_animations.append(anim) + path_animation_group = AnimationGroup(*path_animations) + all_animations.append(path_animation_group) + + animation_group = AnimationGroup(*all_animations, lag_ratio=1) + + return animation_group + +class TestNeuralNetworkScene(Scene): + """Test Scene for the Neural Network""" + def construct(self): + # Make the Layer object + num_nodes = [5, 3, 5] + nn = NeuralNetwork(num_nodes) + nn.move_to(ORIGIN) + # Make Animation + self.add(nn) + forward_propagation_animation = nn.make_forward_propagation_animation() + self.play(forward_propagation_animation)