Model

A model optimized by fasterai, rebuilt from its spec and loaded strictly

Overview

An optimized model no longer has the shapes its factory builds: pruning changes channel counts, and those counts are the only thing standing between a checkpoint and a model that loads. FasterModel publishes both — the factory that builds the architecture, and the rebuild spec of the layers whose shapes changed.

Piece What it is Where it goes
source dotted path of the factory, torchvision.models.resnet18 config.json
source_kwargs what the factory is called with, e.g. {'num_classes': 10, 'weights': None} config.json
modules constructor arguments of every shape-carrying leaf, from spec_from config.json
weights the optimized weights, under the net. prefix model.safetensors

save_pretrained / from_pretrained come from PyTorchModelHubMixin, so a directory or a Hub repo id work the same way. Loading is always strict: a spec that disagrees with the weights raises instead of loading in part. wrap and from_pretrained both return the model in eval mode, so a forward pass reads the published BatchNorm statistics instead of the statistics of the batch it was given.


source

resolve

def resolve(
    source:str, # dotted path of a model factory, e.g. 'torchvision.models.resnet18'
)->Callable:

Import the model factory source points to


source

spec_from

def spec_from(
    model:nn.Module, # model whose optimized layers are recorded
)->dict:

Rebuild spec: the constructor arguments of every Conv2d, Linear and BatchNorm leaf, read off the live model


source

state_hash

def state_hash(
    obj:nn.Module | dict, # a model or a state dict
)->str:

sha256 over every state dict entry: key, shape, dtype and raw bytes


source

FasterModel

def FasterModel(
    source:str, # dotted path of the model factory
    source_kwargs:dict | None=None, # arguments the factory is called with
    modules:dict | None=None, # rebuild spec, as returned by `spec_from`
    recipe:dict | None=None, # the steps that produced the weights
    provenance:dict | None=None, # versions, commits, weights the source started from
):

A model optimized by fasterai: a source factory, the rebuild spec of its layers, and its weights


source

FasterModel.wrap

def wrap(
    model:nn.Module, # the optimized model to publish
    source:str, # dotted path of the model factory it came from
    source_kwargs:dict | None=None, # arguments the factory is called with
    recipe:dict | None=None, # the steps that produced the weights
    provenance:dict | None=None, # versions, commits, weights the source started from
)->"'FasterModel'":

Wrap an optimized model, reading its rebuild spec off its layers; returned in eval mode


source

load

def load(
    repo_id:str, # a Hub repo id, or a local artifact directory
    form:str='auto', # 'auto', or one of 'safetensors', 'torchscript', 'onnx'
    **kw
):

Load the form a repo publishes: a FasterModel, a TorchScript module, or the path of the ONNX file


Usage

Publish a model you just optimized:

from fastermodels import FasterModel

fm = FasterModel.wrap(pruned, 'torchvision.models.resnet18', {'num_classes': 10, 'weights': None},
                      recipe={'prune': 'ratio 0.3, local, round_to 8'})
fm.save_pretrained('artifact')            # config.json + model.safetensors
fm.push_to_hub('FasterAI-Labs/my-model')  # the same two files, on the Hub

Load back whatever a repo publishes, from a directory or from the Hub:

from fastermodels import load

model = load('FasterAI-Labs/my-model')    # safetensors, else TorchScript, else the ONNX path
load('artifact', form='torchscript')      # or name the form you want

A variant published in INT8 only has no model.safetensors, so load looks for model.safetensors, then model.torchscript.pt, then model.onnx, and raises naming the three when a repo has none of them. The first two come back ready to call; the ONNX comes back as a path, for the runtime of your choice.

When the repo does publish weights, FasterModel reads them directly:

fm = FasterModel.from_pretrained('artifact')
fm(x)                                     # delegates to fm.net, in eval mode
fm.recipe                                 # what produced these weights
state_hash(fm)                            # the same digest the producer published

source_kwargs never carries pretrained weights ('weights': None): loading an artifact downloads nothing but the artifact itself, and the weights the optimization started from are recorded in provenance.


See Also

  • Eval - the per-image harness the published numbers come from
  • Card - what the artifact says about itself
  • Gate - the conditions an artifact meets before publication
  • Measurement - one on-device measurement row of a published model

Tests live in nbs/tests/test_model.ipynb.