# AUTOGENERATED! DO NOT EDIT! File to edit: ../../modules/source/04_networks/networks_dev.ipynb. # %% auto 0 __all__ = ['Sequential', 'create_mlp'] # %% ../../modules/source/04_networks/networks_dev.ipynb 1 import numpy as np import sys import os from typing import List, Union, Optional, Callable import matplotlib.pyplot as plt import matplotlib.patches as patches from matplotlib.patches import FancyBboxPatch, ConnectionPatch import seaborn as sns # Import all the building blocks we need - try package first, then local modules try: from tinytorch.core.tensor import Tensor from tinytorch.core.layers import Dense from tinytorch.core.activations import ReLU, Sigmoid, Tanh, Softmax except ImportError: # For development, import from local modules sys.path.append(os.path.join(os.path.dirname(__file__), '..', '01_tensor')) sys.path.append(os.path.join(os.path.dirname(__file__), '..', '02_activations')) sys.path.append(os.path.join(os.path.dirname(__file__), '..', '03_layers')) from tensor_dev import Tensor from activations_dev import ReLU, Sigmoid, Tanh, Softmax from layers_dev import Dense # %% ../../modules/source/04_networks/networks_dev.ipynb 2 def _should_show_plots(): """Check if we should show plots (disable during testing)""" # Check multiple conditions that indicate we're in test mode is_pytest = ( 'pytest' in sys.modules or 'test' in sys.argv or os.environ.get('PYTEST_CURRENT_TEST') is not None or any('test' in arg for arg in sys.argv) or any('pytest' in arg for arg in sys.argv) ) # Show plots in development mode (when not in test mode) return not is_pytest # %% ../../modules/source/04_networks/networks_dev.ipynb 7 class Sequential: """ Sequential Network: Composes layers in sequence The most fundamental network architecture. Applies layers in order: f(x) = layer_n(...layer_2(layer_1(x))) """ def __init__(self, layers: List): """ Initialize Sequential network with layers. Args: layers: List of layers to compose in order TODO: Store the layers and implement forward pass APPROACH: 1. Store the layers list as an instance variable 2. This creates the network architecture ready for forward pass EXAMPLE: Sequential([Dense(3,4), ReLU(), Dense(4,2)]) creates a 3-layer network: Dense → ReLU → Dense HINTS: - Store layers in self.layers - This is the foundation for all network architectures """ ### BEGIN SOLUTION self.layers = layers ### END SOLUTION def forward(self, x: Tensor) -> Tensor: """ Forward pass through all layers in sequence. Args: x: Input tensor Returns: Output tensor after passing through all layers TODO: Implement sequential forward pass through all layers APPROACH: 1. Start with the input tensor 2. Apply each layer in sequence 3. Each layer's output becomes the next layer's input 4. Return the final output EXAMPLE: Input: Tensor([[1, 2, 3]]) Layer1 (Dense): Tensor([[1.4, 2.8]]) Layer2 (ReLU): Tensor([[1.4, 2.8]]) Layer3 (Dense): Tensor([[0.7]]) Output: Tensor([[0.7]]) HINTS: - Use a for loop: for layer in self.layers: - Apply each layer: x = layer(x) - The output of one layer becomes input to the next - Return the final result """ ### BEGIN SOLUTION # Apply each layer in sequence for layer in self.layers: x = layer(x) return x ### END SOLUTION def __call__(self, x: Tensor) -> Tensor: """Make network callable: network(x) same as network.forward(x)""" return self.forward(x) # %% ../../modules/source/04_networks/networks_dev.ipynb 11 def create_mlp(input_size: int, hidden_sizes: List[int], output_size: int, activation=ReLU, output_activation=Sigmoid) -> Sequential: """ Create a Multi-Layer Perceptron (MLP) network. Args: input_size: Number of input features hidden_sizes: List of hidden layer sizes output_size: Number of output features activation: Activation function for hidden layers (default: ReLU) output_activation: Activation function for output layer (default: Sigmoid) Returns: Sequential network with MLP architecture TODO: Implement MLP creation with alternating Dense and activation layers. APPROACH: 1. Start with an empty list of layers 2. Add layers in this pattern: - Dense(input_size → first_hidden_size) - Activation() - Dense(first_hidden_size → second_hidden_size) - Activation() - ... - Dense(last_hidden_size → output_size) - Output_activation() 3. Return Sequential(layers) EXAMPLE: create_mlp(3, [4, 2], 1) creates: Dense(3→4) → ReLU → Dense(4→2) → ReLU → Dense(2→1) → Sigmoid HINTS: - Start with layers = [] - Track current_size starting with input_size - For each hidden_size: add Dense(current_size, hidden_size), then activation - Finally add Dense(last_hidden_size, output_size), then output_activation - Return Sequential(layers) """ ### BEGIN SOLUTION layers = [] current_size = input_size # Add hidden layers with activations for hidden_size in hidden_sizes: layers.append(Dense(current_size, hidden_size)) layers.append(activation()) current_size = hidden_size # Add output layer with output activation layers.append(Dense(current_size, output_size)) layers.append(output_activation()) return Sequential(layers) ### END SOLUTION