Skip to main content

Low-rank adapters for convolutional PyTorch models

Project description

daicon

PyPI Tests PyPI Downloads

Differential Adapters In CONvolutional neural networks.

daicon adds small trainable low-rank residual adapters to frozen PyTorch Conv1d and Linear layers. It was built for finetuning BPNet/Cherimoya-style models to improve differential accessibility, but the core injection API works with explicit module paths in ordinary PyTorch models too.

Installation

daicon is available through PyPI:

pip install daicon

Or, with uv:

uv add daicon

Quickstart

Use explicit module paths for general PyTorch models:

import torch
from daicon import adapter_parameters, inject_adapters

model = torch.nn.Sequential(
    torch.nn.Conv1d(4, 16, kernel_size=7, padding=3),
    torch.nn.ReLU(),
    torch.nn.Conv1d(16, 16, kernel_size=1),
)

config = inject_adapters(
    model,
    targets=["0", "2"],
    architecture=None,
)

optimizer = torch.optim.AdamW(adapter_parameters(model), lr=3e-4)

Use BPNet convenience shorthands when your model exposes BPNet-style fields:

from daicon import inject_adapters

config = inject_adapters(
    accessibility_model,
    targets="rconvs+heads",
)

BPNet shorthand names expand to explicit paths before injection:

Shorthand Paths
iconv iconv
rconvs rconvs.*
fconv fconv
linear linear
profile_only fconv
count_only linear
body_only iconv, rconvs.*
heads_only fconv, linear
all_conv iconv, rconvs.*, fconv
all iconv, rconvs.*, fconv, linear
rconvs+heads rconvs.*, fconv, linear

Use Cherimoya convenience shorthands when your model exposes Cherimoya-style fields named iconv, blocks, fconv, and linear:

from daicon import inject_adapters

config = inject_adapters(
    cherimoya_model,
    targets="all_postblock",
    architecture="cherimoya",
    block_rank=8,
)

Cherimoya block shorthands wrap whole blocks.* modules instead of replacing the layers inside each block. This keeps the frozen Cheri blocks intact while training small residual adapters around them.

Shorthand Paths Block adapter
heads_only fconv, linear none
all_postblock blocks.*, fconv, linear post-block bottleneck
late_postblock last 4 blocks.*, fconv, linear post-block bottleneck
early_postblock first 3 blocks.*, fconv, linear post-block bottleneck
mid_depthwise blocks.2 through blocks.5, fconv, linear parallel depthwise

Saving Adapters

Adapters are saved separately from base model weights:

from daicon import count_adapter_parameters, module_specs, save_adapter_bundle

manifest = {
    "adapter_config": config,
    "layer_specs": module_specs(accessibility_model),
    "trainable_params": count_adapter_parameters(accessibility_model),
}

save_adapter_bundle("celltype_f0.adapter.pt", accessibility_model, manifest)

Load them back into a matching base model:

from daicon import load_adapter_bundle

accessibility_model, manifest = load_adapter_bundle(
    accessibility_model,
    "celltype_f0.adapter.pt",
)

By default, bundle helpers expect adapters directly on the module you pass in. This matches the common post-training workflow of loading only a ChromBPNet accessibility module for inference or interpretation.

If you are working with a full ChromBPNet-style object and the adapters live under model.accessibility, pass adapter_root="accessibility":

save_adapter_bundle("celltype_f0.adapter.pt", model, manifest, adapter_root="accessibility")
model, manifest = load_adapter_bundle(
    model,
    "celltype_f0.adapter.pt",
    adapter_root="accessibility",
)

API

The main public functions are:

  • inject_adapters(module, targets, ...)
  • resolve_adapter_targets(targets, module=None, architecture="bpnet")
  • adapter_parameters(module)
  • adapter_state_dict(module)
  • save_adapter_bundle(path, model, manifest, adapter_root=None)
  • load_adapter_bundle(model, adapter_path, adapter_root=None)

Adapter wrappers:

  • LowRankConv1dAdapter
  • LowRankLinearAdapter
  • CheriPostBlockAdapter
  • CheriParallelDepthwiseAdapter

Injected adapters compute:

base(x) + scale * up(dropout(down(x)))

The up layer is zero-initialized, so injection is prediction-equivalent to the base model before training. Base layer parameters are frozen inside each adapter. Cherimoya post-block adapters remix frozen block outputs positionwise, while parallel depthwise adapters add a small dilated spatial branch at the block's native dilation.

Artifact Contract

An adapter bundle is a torch.save file containing:

{
    "manifest": {
        "format_version": 1,
        "adapter_config": {...},
        "layer_specs": {...},
        ...
    },
    "state_dict": {...},
}

The state dict contains only adapter branch weights, keyed by injected module path. Frozen base.* weights are intentionally excluded.

Notes

  • While the adapters were designed with bpnet-lite and cherimoya in mind, and injection code defaults have been written for these model architectures, daicon is kept intentionally light-weight/general and depends only on PyTorch.
  • Conv1d and Linear adapter defaults follow prior ChromBPNet/BPNet tuning: conv_rank=16, linear_rank=4, dropout=0, and alpha-style scaling with alpha=8, i.e. default conv_scale=8 / conv_rank and linear_scale=8 / linear_rank.
  • BPNet shorthands assume fields named iconv, rconvs, fconv, and linear.
  • Cherimoya shorthands assume fields named iconv, blocks, fconv, and linear; all_postblock is the recommended differential fine-tuning default, with block_rank=8, block_adapter="postblock", and block_scale=1 / block_rank when no explicit scale is provided.
  • The historical implementation handoff lives in notes/ADAPTER_HANDOFF.md.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

daicon-0.1.0.tar.gz (848.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

daicon-0.1.0-py3-none-any.whl (12.9 kB view details)

Uploaded Python 3

File details

Details for the file daicon-0.1.0.tar.gz.

File metadata

  • Download URL: daicon-0.1.0.tar.gz
  • Upload date:
  • Size: 848.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for daicon-0.1.0.tar.gz
Algorithm Hash digest
SHA256 08aee2a1b4c1154c49961328207366ec551905bfff5ddc5f50684618f98b3c14
MD5 1742fa780c2e232fe54198a923a4a11c
BLAKE2b-256 4bc618fdfc6ca0cccfc56b5522fc6ffaa6dce7ddd5594f7fcd36d3f5c2d53a35

See more details on using hashes here.

Provenance

The following attestation bundles were made for daicon-0.1.0.tar.gz:

Publisher: publish.yml on adamyhe/daicon

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file daicon-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: daicon-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 12.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for daicon-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 468a50e14dc53d1f2fa1665f3f65c31a3d3024a8740749c9ed46988dfe4b1dcd
MD5 62d2765eaf38d6887e1ecebee575522d
BLAKE2b-256 5ee0fbcb9c68cc592704c9356ccfe606e80edbc7ae3f7a43dff24d964ad52d21

See more details on using hashes here.

Provenance

The following attestation bundles were made for daicon-0.1.0-py3-none-any.whl:

Publisher: publish.yml on adamyhe/daicon

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page