Inspecting and loading models
Layer-by-layer summary
cu.tools.summary(model) # input (1, 3, 224, 224)
cu.tools.summary(model, input_size=(1, 1, 28, 28)) # MNIST-sized input
cu.tools.summary(learn) # a fastai Learner works too
Shows every layer’s output shape and parameter count (uses torchinfo, installed
with the package).
Input and output shape of one block
When you need the exact shape going into a block (to build a new head, or to feed the block on its own), ask the model instead of reading it off the table:
backbone = torchvision.models.efficientnet_b0().features
cu.tools.layer_shapes(backbone, backbone[2][0], input_size=(1, 3, 160, 160))
# 2.0 (MBConv): (1, 16, 80, 80) -> (1, 24, 40, 40)
s = cu.tools.layer_shapes(backbone, "2.0", (1, 3, 160, 160), verbose=False)
s.input, s.output # first input / first output
s.inputs # every positional input, e.g. [(1, 16, 80, 80)]
s.kwargs # tensors passed by keyword, e.g. {"mask": (1, 80, 80)}
cu.tools.layer_shapes(model, ["layer1", "layer2.0", "fc"]) # several at once
cu.tools.layer_shapes(learn, "0.4", x=xb) # fastai, real batch
The layer can be the module itself or its dotted name (as listed by
layer_names()). The model runs once in eval mode
without gradients, so BatchNorm statistics are not changed. A block that runs more
than once per pass (shared weights) reports its first call.
This replaces the usual hand-written hook:
inputs = []
hook = block.register_forward_pre_hook(lambda m, args: inputs.append(tuple(args[0].shape)))
with torch.no_grad():
backbone.eval()(torch.zeros(1, 3, 160, 160))
hook.remove()
Interactive graph with Netron
cu.tools.netron(model, input_size=(1, 1, 28, 28)) # drawn inside the cell output
cu.tools.netron(learn) # fastai Learner, (1, 3, 224, 224)
cu.tools.netron("/content/drive/MyDrive/model.onnx", height=600) # a saved file
cu.tools.stop_netron()
This one call replaces the usual Colab recipe of model.eval(), a dummy input on
the right device, torch.onnx.export, netron.start on a free port, and
google.colab.output.serve_kernel_port_as_iframe. Running it again for the same
model replaces the old viewer, so there are no “port in use” errors.
In-memory models are exported to ONNX by default, with the graph’s input and output
named input and output. format="torchscript" and format="export"
(torch.export) are also available. To keep the exported file, for example in
your run folder:
path = cu.tools.export_for_netron(model, run / "model.onnx", input_size=(1, 1, 28, 28))
cu.tools.netron(path)
Loading saved models
load_model() figures out the file type and always
returns a ready-to-use torch.nn.Module in eval mode, on the GPU when there is one.
You saved it with |
Load it with |
|---|---|
|
|
|
|
|
|
|
|
TorchScript or |
|
arch is the network the weights belong to: a model instance, a fastai
Learner, or a function that builds one (arch=MyNet).
learn = cu.models.load_model("export.pkl", learner=True) # the whole fastai Learner
model = cu.models.load_model("w.pth", arch=MyNet, device="cpu")
Warning
fastai .pkl exports and full PyTorch models are Python pickles: loading one
can run code. Only load files you or your course staff created. Plain weights
(state dicts) are always loaded safely.