crispr-kinetics-hpv16

Model weights for the paper "Deep Learning of CRISPR Fluorescence Kinetics for Ultrafast, Quantitative Viral Detection".

The model takes 15 fluorescence frames of one RPA-CRISPR/Cas12a reaction well and predicts the HPV16 concentration class (NC, 10 aM, 100 aM, 1 fM) and a log10 concentration.

It is an ensemble of two separately trained networks. Both apply the same CNN design to every frame (each network has its own weights); one then reads the frame features with an LSTM and the other with a 2-layer Transformer. The final output is the average of the two, each averaged over 4 flips.

Files

  • lstm/, transformer/: weights of the two branches, as model.safetensors and as the original PyTorch checkpoint best_model.pt
  • baseline_mean.npy: mean image of the NC wells in the training set, subtracted from every frame
  • modeling.py: model definitions
  • predict.py: preprocessing and inference
  • config.json: model settings
  • comparison/architectures/: the temporal architectures compared in the paper (see below)

Usage

pip install torch numpy pillow safetensors huggingface_hub
import sys
from huggingface_hub import snapshot_download

path = snapshot_download("shiyuxie/crispr-kinetics-hpv16")
sys.path.insert(0, path)
from predict import Ensemble

ens = Ensemble(path)
out = ens.predict_folder("ROI_time_series_xxx", roi=5)
print(out["label"], out["concentration_fM"], out["probs"])

Or from the command line:

python predict.py --folder ROI_time_series_xxx --roi 5

Input is frames A015 to A029 (150-290 s) of a well, 140x140 RGB. The files are named like A015 - 20250324_231500_roi_5.bmp. You can also pass 15 image paths directly to ens.predict().

10 fM samples were merged into the 1 fM class for training, so the model does not separate concentrations above 1 fM.

Results

The data were split by experimental run with seed 42: 60 runs for training, 16 for validation and 15 for testing (720 / 192 / 180 wells).

Accuracy MAE (log10)
Validation 96.9% (186/192)
Test 93.3% (168/180) 0.18
Test, LSTM branch only 91.7%
Test, Transformer branch only 88.9%

Test confusion matrix (rows are true class):

NC 10 aM 100 aM 1 fM
NC 36 0 0 0
10 aM 2 33 1 0
100 aM 0 0 36 0
1 fM 0 0 9 63

Comparison models

The temporal architectures compared in Fig. 2e and 2f all use the same CNN design and input as the main model and differ only in the temporal part. They were trained and tested on the same split as the main model. Two of them are the branches of the released ensemble; the other three are in comparison/architectures/, each with model.safetensors and a config.json.

Temporal model Folder Parameters Test accuracy
LSTM lstm/ 55,878 91.7%
Transformer, 2 layers, d = 48 transformer/ 81,750 88.9%
LSTM, mean + max pooling comparison/architectures/lstm_meanmax 54,629 87.2%
Transformer, 2 layers, d = 96 comparison/architectures/transformer_d96 203,718 85.6%
Transformer, 3 layers, d = 64 comparison/architectures/transformer_3l_d64 147,174 90.6%

Fig. 2e and 2f report the mean over repeated training runs, so the values there can differ slightly from the single models above.

from modeling import load_model
m = load_model(f"{path}/comparison/architectures/transformer_3l_d64")

The loaded model takes the same preprocessed input as the main model (predict.preprocess).

Other comparison methods (Fig. 2b and 2c)

Method Folder Test accuracy
Endpoint comparison/curve_methods/endpoint 71.1%
KS test comparison/curve_methods/ks_test 62.8%
Curve features + logistic regression comparison/curve_methods/curve_features_lr 79.4%
Slope comparison/curve_methods/slope 80.0%
CNN-GRU comparison/cnn_gru 85.0%
Single-frame CNN, 60 s comparison/single_frame_60s 33.3%
Single-frame CNN, 150 s comparison/single_frame_150s 56.7%
Single-frame CNN, 220 s comparison/single_frame_220s 66.7%
Single-frame CNN, 290 s comparison/single_frame_290s 68.9%

These methods were evaluated on a different random split of the same 91 runs than the main model. comparison/test_runs.json lists the test runs of both splits. For the CNN models the paper reports the mean over repeated training runs, so its values can differ slightly from the single models here. The 1D-CNN, LSTM and GRU models on the scalar curve were not kept and are not included.

The curve methods work on the mean intensity of frames A015โ€“A029:

import curve_methods as cm
curve = cm.curve_from_frames(frame_paths)
cm.CLASS_NAMES[cm.predict("slope", curve, cm.load("slope", path))]

CNN-GRU uses its own baseline_mean.npy in predict.preprocess. The single-frame models take one raw RGB frame:

import numpy as np, torch
from PIL import Image
m = load_model(f"{path}/comparison/single_frame_290s")
x = torch.from_numpy(np.asarray(Image.open(frame_A029).convert("RGB"), dtype=np.float32)).permute(2, 0, 1)[None]
reg, logits = m(x)

Limitations

This model is for research use only. It was trained on data from one imaging setup and one assay protocol. Results on other instruments or protocols may not hold without retraining.

Citation

Citation details will be added once the paper is published.

Downloads last month
6
Inference Providers NEW
This model isn't deployed by any Inference Provider. ๐Ÿ™‹ Ask for provider support

Space using shiyuxie/crispr-kinetics-hpv16 1