Neural Network Abstractions: Own Parameters, Preserve the Graph

Two structures, two lifetimes

The module structure owns reusable parameter leaves.

The forward pass creates a new temporary computation graph.

Predict what fails if weights are created inside forward.

1 / 8

Registration follows assignments

Value -> parameter; Module -> child; nested lists -> recursive indexed names.

Initialize registries with object.__setattr__, then intercept assignments.

This lab constructs the structure once; later list mutation is outside the registry contract.

2 / 8

Trace one affine layer

x = [3,2]
W = [[2,-1],[0.5,1]]
b = [1,-2]

Compute both outputs and the input gradient of their sum.

3 / 8

Check the trace

Outputs are [5,1.5].

For their sum, dL/dx=[2.5,0]; each weight row receives [3,2], each bias receives 1.

Weight shape is (out,in); output stays a list even when out=1.

4 / 8

Count before training

Linear(2,3) -> Tanh -> Linear(3,2)

First layer: 9 scalars. Activation: 0. Last layer: 8.

Expected total: 17 unique parameters. Without the activation, the composition is still affine.

5 / 8

Find the doubled update

The optimizer sees 34 entries but only 17 distinct identities.

Diagnosis: aliased children were traversed twice.

Deduplicate by identity, not numeric equality. Give aliases one canonical named path.

6 / 8

Modes do not stop gradients

eval() recursively changes flags. These layers have no mode-dependent behavior.

It does not freeze parameters, clear gradients, or disable autograd.

The optimizer controls updates; graph construction controls differentiation.

7 / 8

Reconstruct a usable model

Implement Module before layers; preserve parameter identity through every forward call.

Check the 17-parameter count, numeric affine trace, and nested mode propagation.

Zero registered gradients with correct outputs suggest a detached .data copy.

8 / 8
←/→ or click edges to navigate · ? help · N notes · F fullscreen