mirror of
https://github.com/MLSysBook/TinyTorch.git
synced 2026-06-04 20:40:54 -05:00
- Restored tools/py_to_notebook.py as a focused, standalone tool - Updated tito notebooks command to use subprocess to call the separate tool - Maintains clean separation of concerns: tito.py for CLI orchestration, py_to_notebook.py for conversion logic - Updated documentation to use 'tito notebooks' command instead of direct tool calls - Benefits: easier debugging, better maintainability, focused single-responsibility modules
239 lines
7.3 KiB
Python
239 lines
7.3 KiB
Python
# AUTOGENERATED! DO NOT EDIT! File to edit: ../../modules/layers/layers_dev.ipynb.
|
|
|
|
# %% auto 0
|
|
__all__ = ['Dense', 'ReLU', 'Sigmoid', 'Tanh']
|
|
|
|
# %% ../../modules/layers/layers_dev.ipynb 2
|
|
import numpy as np
|
|
import math
|
|
import sys
|
|
from typing import Union, Optional, Callable
|
|
from .tensor import Tensor
|
|
|
|
# Import our Tensor class
|
|
# sys.path.append('../../')
|
|
# from modules.tensor.tensor_dev import Tensor
|
|
|
|
# print("🔥 TinyTorch Layers Module")
|
|
# print(f"NumPy version: {np.__version__}")
|
|
# print(f"Python version: {sys.version_info.major}.{sys.version_info.minor}")
|
|
# print("Ready to build neural network layers!")
|
|
|
|
# %% ../../modules/layers/layers_dev.ipynb 4
|
|
class Dense:
|
|
"""
|
|
Dense (Linear) Layer: y = Wx + b
|
|
|
|
The fundamental building block of neural networks.
|
|
Performs linear transformation: matrix multiplication + bias addition.
|
|
|
|
Args:
|
|
input_size: Number of input features
|
|
output_size: Number of output features
|
|
use_bias: Whether to include bias term (default: True)
|
|
|
|
TODO: Implement the Dense layer with weight initialization and forward pass.
|
|
"""
|
|
|
|
def __init__(self, input_size: int, output_size: int, use_bias: bool = True):
|
|
"""
|
|
Initialize Dense layer with random weights.
|
|
|
|
TODO:
|
|
1. Store layer parameters (input_size, output_size, use_bias)
|
|
2. Initialize weights with small random values
|
|
3. Initialize bias to zeros (if use_bias=True)
|
|
"""
|
|
raise NotImplementedError("Student implementation required")
|
|
|
|
def forward(self, x: Tensor) -> Tensor:
|
|
"""
|
|
Forward pass: y = Wx + b
|
|
|
|
Args:
|
|
x: Input tensor of shape (batch_size, input_size)
|
|
|
|
Returns:
|
|
Output tensor of shape (batch_size, output_size)
|
|
|
|
TODO: Implement matrix multiplication and bias addition
|
|
"""
|
|
raise NotImplementedError("Student implementation required")
|
|
|
|
def __call__(self, x: Tensor) -> Tensor:
|
|
"""Make layer callable: layer(x) same as layer.forward(x)"""
|
|
return self.forward(x)
|
|
|
|
# %% ../../modules/layers/layers_dev.ipynb 5
|
|
class Dense:
|
|
"""
|
|
Dense (Linear) Layer: y = Wx + b
|
|
|
|
The fundamental building block of neural networks.
|
|
Performs linear transformation: matrix multiplication + bias addition.
|
|
"""
|
|
|
|
def __init__(self, input_size: int, output_size: int, use_bias: bool = True):
|
|
"""Initialize Dense layer with random weights."""
|
|
self.input_size = input_size
|
|
self.output_size = output_size
|
|
self.use_bias = use_bias
|
|
|
|
# Initialize weights with Xavier/Glorot initialization
|
|
# This helps with gradient flow during training
|
|
limit = math.sqrt(6.0 / (input_size + output_size))
|
|
self.weights = Tensor(
|
|
np.random.uniform(-limit, limit, (input_size, output_size)).astype(np.float32)
|
|
)
|
|
|
|
# Initialize bias to zeros
|
|
if use_bias:
|
|
self.bias = Tensor(np.zeros(output_size, dtype=np.float32))
|
|
else:
|
|
self.bias = None
|
|
|
|
def forward(self, x: Tensor) -> Tensor:
|
|
"""Forward pass: y = Wx + b"""
|
|
# Matrix multiplication: x @ weights
|
|
# x shape: (batch_size, input_size)
|
|
# weights shape: (input_size, output_size)
|
|
# result shape: (batch_size, output_size)
|
|
output = Tensor(x.data @ self.weights.data)
|
|
|
|
# Add bias if present
|
|
if self.bias is not None:
|
|
output = Tensor(output.data + self.bias.data)
|
|
|
|
return output
|
|
|
|
def __call__(self, x: Tensor) -> Tensor:
|
|
"""Make layer callable: layer(x) same as layer.forward(x)"""
|
|
return self.forward(x)
|
|
|
|
# %% ../../modules/layers/layers_dev.ipynb 9
|
|
class ReLU:
|
|
"""
|
|
ReLU Activation: f(x) = max(0, x)
|
|
|
|
The most popular activation function in deep learning.
|
|
Simple, effective, and computationally efficient.
|
|
|
|
TODO: Implement ReLU activation function.
|
|
"""
|
|
|
|
def forward(self, x: Tensor) -> Tensor:
|
|
"""
|
|
Apply ReLU: f(x) = max(0, x)
|
|
|
|
Args:
|
|
x: Input tensor
|
|
|
|
Returns:
|
|
Output tensor with ReLU applied element-wise
|
|
|
|
TODO: Implement element-wise max(0, x) operation
|
|
"""
|
|
raise NotImplementedError("Student implementation required")
|
|
|
|
def __call__(self, x: Tensor) -> Tensor:
|
|
"""Make activation callable: relu(x) same as relu.forward(x)"""
|
|
return self.forward(x)
|
|
|
|
# %% ../../modules/layers/layers_dev.ipynb 10
|
|
class ReLU:
|
|
"""ReLU Activation: f(x) = max(0, x)"""
|
|
|
|
def forward(self, x: Tensor) -> Tensor:
|
|
"""Apply ReLU: f(x) = max(0, x)"""
|
|
return Tensor(np.maximum(0, x.data))
|
|
|
|
def __call__(self, x: Tensor) -> Tensor:
|
|
return self.forward(x)
|
|
|
|
# %% ../../modules/layers/layers_dev.ipynb 11
|
|
class Sigmoid:
|
|
"""
|
|
Sigmoid Activation: f(x) = 1 / (1 + e^(-x))
|
|
|
|
Squashes input to range (0, 1). Often used for binary classification.
|
|
|
|
TODO: Implement Sigmoid activation function.
|
|
"""
|
|
|
|
def forward(self, x: Tensor) -> Tensor:
|
|
"""
|
|
Apply Sigmoid: f(x) = 1 / (1 + e^(-x))
|
|
|
|
Args:
|
|
x: Input tensor
|
|
|
|
Returns:
|
|
Output tensor with Sigmoid applied element-wise
|
|
|
|
TODO: Implement sigmoid function (be careful with numerical stability!)
|
|
"""
|
|
raise NotImplementedError("Student implementation required")
|
|
|
|
def __call__(self, x: Tensor) -> Tensor:
|
|
return self.forward(x)
|
|
|
|
# %% ../../modules/layers/layers_dev.ipynb 12
|
|
class Sigmoid:
|
|
"""Sigmoid Activation: f(x) = 1 / (1 + e^(-x))"""
|
|
|
|
def forward(self, x: Tensor) -> Tensor:
|
|
"""Apply Sigmoid with numerical stability"""
|
|
# Use the numerically stable version to avoid overflow
|
|
# For x >= 0: sigmoid(x) = 1 / (1 + exp(-x))
|
|
# For x < 0: sigmoid(x) = exp(x) / (1 + exp(x))
|
|
x_data = x.data
|
|
result = np.zeros_like(x_data)
|
|
|
|
# Stable computation
|
|
positive_mask = x_data >= 0
|
|
result[positive_mask] = 1.0 / (1.0 + np.exp(-x_data[positive_mask]))
|
|
result[~positive_mask] = np.exp(x_data[~positive_mask]) / (1.0 + np.exp(x_data[~positive_mask]))
|
|
|
|
return Tensor(result)
|
|
|
|
def __call__(self, x: Tensor) -> Tensor:
|
|
return self.forward(x)
|
|
|
|
# %% ../../modules/layers/layers_dev.ipynb 13
|
|
class Tanh:
|
|
"""
|
|
Tanh Activation: f(x) = tanh(x)
|
|
|
|
Squashes input to range (-1, 1). Zero-centered output.
|
|
|
|
TODO: Implement Tanh activation function.
|
|
"""
|
|
|
|
def forward(self, x: Tensor) -> Tensor:
|
|
"""
|
|
Apply Tanh: f(x) = tanh(x)
|
|
|
|
Args:
|
|
x: Input tensor
|
|
|
|
Returns:
|
|
Output tensor with Tanh applied element-wise
|
|
|
|
TODO: Implement tanh function
|
|
"""
|
|
raise NotImplementedError("Student implementation required")
|
|
|
|
def __call__(self, x: Tensor) -> Tensor:
|
|
return self.forward(x)
|
|
|
|
# %% ../../modules/layers/layers_dev.ipynb 14
|
|
class Tanh:
|
|
"""Tanh Activation: f(x) = tanh(x)"""
|
|
|
|
def forward(self, x: Tensor) -> Tensor:
|
|
"""Apply Tanh"""
|
|
return Tensor(np.tanh(x.data))
|
|
|
|
def __call__(self, x: Tensor) -> Tensor:
|
|
return self.forward(x)
|