Skip to content

Neural-network API

Module

Module discovers nested parameters, provides stable names for visualization, and supports compact model summaries.

Module

Base class for all neural network modules.

Subclass this and implement forward(). Parameters are discovered automatically by scanning instance attributes for Variable objects.

forward

forward(*inputs: Variable) -> Variable
Source code in MiniTorch/nn/module.py
def forward(self, *inputs: Variable) -> Variable:
    raise NotImplementedError

parameters

parameters() -> list[Variable]

Return all leaf Variable parameters (recursive).

Source code in MiniTorch/nn/module.py
def parameters(self) -> list[Variable]:
    """Return all leaf Variable parameters (recursive)."""
    return [parameter for _, parameter in self.named_parameters()]

named_parameters

named_parameters(prefix: str = '') -> list[tuple[str, Variable]]

Return stable, deduplicated parameter names and values.

Source code in MiniTorch/nn/module.py
def named_parameters(self, prefix: str = "") -> list[tuple[str, Variable]]:
    """Return stable, deduplicated parameter names and values."""
    result: list[tuple[str, Variable]] = []
    seen: set[int] = set()

    def visit(value, path: str) -> None:
        if isinstance(value, Variable):
            if id(value) not in seen:
                seen.add(id(value))
                result.append((path, value))
        elif isinstance(value, Module):
            for name, child in value.__dict__.items():
                visit(child, f"{path}.{name}" if path else name)
        elif isinstance(value, (list, tuple)):
            for index, child in enumerate(value):
                visit(child, f"{path}.{index}" if path else str(index))

    for name, value in self.__dict__.items():
        visit(value, f"{prefix}.{name}" if prefix else name)
    return result

named_modules

named_modules(prefix: str = '') -> list[tuple[str, Module]]

Return this module and all registered child modules.

Source code in MiniTorch/nn/module.py
def named_modules(self, prefix: str = "") -> list[tuple[str, Module]]:
    """Return this module and all registered child modules."""
    result: list[tuple[str, Module]] = [(prefix, self)]
    seen = {id(self)}

    def visit(value, path: str) -> None:
        if isinstance(value, Module):
            if id(value) in seen:
                return
            seen.add(id(value))
            result.append((path, value))
            for name, child in value.__dict__.items():
                visit(child, f"{path}.{name}" if path else name)
        elif isinstance(value, (list, tuple)):
            for index, child in enumerate(value):
                visit(child, f"{path}.{index}" if path else str(index))

    for name, value in self.__dict__.items():
        visit(value, f"{prefix}.{name}" if prefix else name)
    return result

summary

summary() -> str

Return a compact architecture and parameter summary.

Source code in MiniTorch/nn/module.py
def summary(self) -> str:
    """Return a compact architecture and parameter summary."""
    lines = ["Name                  Type             Parameters"]
    lines.append("-" * 55)
    total = 0
    for name, module in self.named_modules():
        if not name:
            continue
        count = sum(parameter.size for parameter in module.parameters())
        total += count if not any(
            other_name.startswith(name + ".")
            for other_name, _ in self.named_modules()
            if other_name != name
        ) else 0
        lines.append(
            f"{name:<21} {module.__class__.__name__:<16} {count:>10,}"
        )
    lines.append("-" * 55)
    lines.append(f"Total parameters: {len(self.parameters()):,} tensors / "
                 f"{sum(p.size for p in self.parameters()):,} values")
    return "\n".join(lines)

zero_grad

zero_grad() -> None
Source code in MiniTorch/nn/module.py
def zero_grad(self) -> None:
    for p in self.parameters():
        p.clear_grad()

Linear

Linear

Linear(in_features: int, out_features: int, bias: bool = True, dtype: dtype | type = np.float32)

Bases: Module

Fully-connected linear layer: y = x @ W + b

Parameters

in_features : input dimension out_features : output dimension bias : whether to include a bias term (default True)

Source code in MiniTorch/nn/linear.py
def __init__(
    self,
    in_features: int,
    out_features: int,
    bias: bool = True,
    dtype: np.dtype | type = np.float32,
) -> None:
    scale = np.sqrt(2.0 / in_features)
    self.W = Variable(
        (np.random.randn(in_features, out_features) * scale).astype(dtype),
        name="W",
    )
    self.b: Variable | None = None
    self._last_input_ref: weakref.ReferenceType[Variable] | None = None
    self._last_output_ref: weakref.ReferenceType[Variable] | None = None
    if bias:
        self.b = Variable(
            np.zeros(out_features, dtype=dtype),
            name="b",
        )

forward

forward(x: Variable) -> Variable
Source code in MiniTorch/nn/linear.py
def forward(self, x: Variable) -> Variable:  # type: ignore[override]
    self._last_input_ref = weakref.ref(x)
    y = matmul(x, self.W)
    if self.b is not None:
        y = y + self.b
    self._last_output_ref = weakref.ref(y)
    return y  # type: ignore[return-value]

Weights use He initialization and float32 by default.

Sequential

Sequential

Sequential(*layers: Module)

Bases: Module

A container that chains modules in order.

Example

model = Sequential( Linear(784, 256), Linear(256, 10), ) out = model(x)

Source code in MiniTorch/nn/sequential.py
def __init__(self, *layers: Module) -> None:
    self.layers: list[Module] = list(layers)

forward

forward(x: Variable) -> Variable
Source code in MiniTorch/nn/sequential.py
def forward(self, x: Variable) -> Variable:  # type: ignore[override]
    for layer in self.layers:
        x = layer(x)
    return x

parameters

parameters() -> list[Variable]
Source code in MiniTorch/nn/sequential.py
def parameters(self) -> list[Variable]:
    params: list[Variable] = []
    for layer in self.layers:
        if isinstance(layer, Module):
            params.extend(layer.parameters())
    return params

Activation modules

ReLU, Sigmoid, and Tanh wrap their matching differentiable operations so they can be placed directly inside Sequential.

ReLU

Bases: Module

Sigmoid

Bases: Module

Tanh

Bases: Module