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
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
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.