Skip to main content

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.

Metadata

Release files for daicon 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for daicon 0.1.0
File Size Uploaded
daicon-0.1.0.tar.gz 848.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for daicon 0.1.0
File Interpreter ABI Platform
daicon-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 861.4 kB

Release files / daicon-0.1.0.tar.gz

Download URL daicon-0.1.0.tar.gz
Size 848.5 kB
Tags Source
SHA-256 checksum
How to use checksums
08aee2a1b4c1154c49961328207366ec551905bfff5ddc5f50684618f98b3c14
BLAKE2b-256 checksum
How to use checksums
4bc618fdfc6ca0cccfc56b5522fc6ffaa6dce7ddd5594f7fcd36d3f5c2d53a35
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 13, 2026.

Transparency log

Release files / daicon-0.1.0-py3-none-any.whl

Download URL daicon-0.1.0-py3-none-any.whl
Size 12.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
468a50e14dc53d1f2fa1665f3f65c31a3d3024a8740749c9ed46988dfe4b1dcd
BLAKE2b-256 checksum
How to use checksums
5ee0fbcb9c68cc592704c9356ccfe606e80edbc7ae3f7a43dff24d964ad52d21
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 13, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page