Skip to main content

inference

Model inference pipeline utilities.

Decomposes the monolithic initialise_model(data=...) flow into individually callable functions so that each concern (column configuration, dataloader creation, model init, inference) can be used and tested independently.

Module

Functions

build_column_config

def build_column_config(    image_prefix: str = 'Pixel Data',    selected_cols: Optional[list[str]] = None,    selected_cols_prefix: str | None = None,    schema_requirements: Any = 'empty',    batch_transforms: list[dict[str, typing.Any]] | None = None,    image_prefix_batch_transforms: list[dict[str, typing.Any]] | None = None,    auto_convert_grayscale_images: bool = True,)> DataStructure:

Build a DataStructure suitable for ophthalmology inference.

This is a thin wrapper around the DataStructure constructor with sensible defaults matching the GA Trial Bronze task YAML.

Arguments

  • image_prefix: Image column prefix (default "Pixel Data").
  • selected_cols: Explicit list of selected columns. Defaults to ["Columns", "Rows"] when None.
  • selected_cols_prefix: Prefix for selected columns (default same as image_prefix).
  • schema_requirements: Schema requirement level.
  • batch_transforms: Optional batch transforms list.
  • image_prefix_batch_transforms: Optional image-specific batch transforms.
  • auto_convert_grayscale_images: Convert grayscale to RGB (default True).

Returns A DataStructure instance.

create_inference_dataloader

def create_inference_dataloader(    datasource: FileSystemIterableSource,    schema: BitfountSchema,    datastructure: DataStructure,    batch_size: int | None = None,)> Any:

Create a test-only dataloader for inference, bypassing BitfountDataBunch.

This reproduces the subset of BitfountDataBunch.__init__ that is relevant for inference:

  1. datastructure.set_training_column_split_by_semantic_type(schema)
  2. data_factory.create_dataset(... data_split=TEST, splitter=_InferenceSplitter)
  3. data_factory.create_dataloader(dataset, batch_size)

No train/validation splits are created.

Arguments

  • datasource: The datasource to iterate over.
  • schema: A BitfountSchema (should already have features populated via BitfountSchema.add_dataframe_features).
  • datastructure: A DataStructure (from build_column_config).
  • batch_size: Batch size for the dataloader.

Returns A BitfountDataLoader wrapping the test dataset.

init_model_for_inference

def init_model_for_inference(model: Any)> None:

Initialise a model for inference without binding any data.

Calls model.initialise_model() with no datasource so that the model's internal create_model() and weight-loading logic runs, but no BitfountDataBunch or dataloaders are created.

After this call you can assign model.test_dl directly and run model._pl_trainer.test().

Arguments

  • model: A Bitfount model instance (already has weights loaded via deserialize).

run_inference

def run_inference(    model: Any,    datasource: FileSystemIterableSource,    schema: BitfountSchema,    datastructure: DataStructure,    batch_size: int | None = None,)> PredictReturnType:

End-to-end inference: init model, build dataloader, predict.

Composes init_model_for_inference, create_inference_dataloader, and the model's prediction machinery into a single call.

Arguments

  • model: A Bitfount model instance with weights loaded.
  • datasource: The datasource to run inference on.
  • schema: A populated BitfountSchema.
  • datastructure: A configured DataStructure.
  • batch_size: Batch size for inference.

Returns PredictReturnType (preds + keys).

Notes Some Hub models aggregate a whole forward batch into a single prediction (e.g. exam-level ophthalmology models). Run at a batch size

1, they emit fewer predictions than input records, tripping the "predictions vs keys" contract check. Since we cannot edit those models (they are fetched from the Hub), we run optimistically at the requested batch_size and, only if that contract fails, transparently retry the same chunk at one record per forward batch — the size at which no model can collapse per-record results. Well-behaved models never hit the retry, so they keep their throughput.