daicon
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:
LowRankConv1dAdapterLowRankLinearAdapterCheriPostBlockAdapterCheriParallelDepthwiseAdapter
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-liteandcherimoyain mind, and injection code defaults have been written for these model architectures,daiconis 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 withalpha=8, i.e. defaultconv_scale=8 / conv_rankandlinear_scale=8 / linear_rank. - BPNet shorthands assume fields named
iconv,rconvs,fconv, andlinear. - Cherimoya shorthands assume fields named
iconv,blocks,fconv, andlinear;all_postblockis the recommended differential fine-tuning default, withblock_rank=8,block_adapter="postblock", andblock_scale=1 / block_rankwhen 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)
| File | Size | Uploaded | |
|---|---|---|---|
| daicon-0.1.0.tar.gz | 848.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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 logRelease 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