Instructions to use Taykhoom/CodonBERT with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use Taykhoom/CodonBERT with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("fill-mask", model="Taykhoom/CodonBERT", trust_remote_code=True)# Load model directly from transformers import AutoModelForMaskedLM model = AutoModelForMaskedLM.from_pretrained("Taykhoom/CodonBERT", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
Commit ·
ef33dba
0
Parent(s):
Initial CodonBERT Hugging Face port
Browse files- .gitattributes +35 -0
- README.md +239 -0
- config.json +26 -0
- model.safetensors +3 -0
- special_tokens_map.json +7 -0
- tokenization_codonbert.py +91 -0
- tokenizer_config.json +58 -0
- vocab.txt +69 -0
.gitattributes
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
*.7z filter=lfs diff=lfs merge=lfs -text
|
| 2 |
+
*.arrow filter=lfs diff=lfs merge=lfs -text
|
| 3 |
+
*.bin filter=lfs diff=lfs merge=lfs -text
|
| 4 |
+
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
| 5 |
+
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
| 6 |
+
*.ftz filter=lfs diff=lfs merge=lfs -text
|
| 7 |
+
*.gz filter=lfs diff=lfs merge=lfs -text
|
| 8 |
+
*.h5 filter=lfs diff=lfs merge=lfs -text
|
| 9 |
+
*.joblib filter=lfs diff=lfs merge=lfs -text
|
| 10 |
+
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
| 11 |
+
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
| 12 |
+
*.model filter=lfs diff=lfs merge=lfs -text
|
| 13 |
+
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
| 14 |
+
*.npy filter=lfs diff=lfs merge=lfs -text
|
| 15 |
+
*.npz filter=lfs diff=lfs merge=lfs -text
|
| 16 |
+
*.onnx filter=lfs diff=lfs merge=lfs -text
|
| 17 |
+
*.ot filter=lfs diff=lfs merge=lfs -text
|
| 18 |
+
*.parquet filter=lfs diff=lfs merge=lfs -text
|
| 19 |
+
*.pb filter=lfs diff=lfs merge=lfs -text
|
| 20 |
+
*.pickle filter=lfs diff=lfs merge=lfs -text
|
| 21 |
+
*.pkl filter=lfs diff=lfs merge=lfs -text
|
| 22 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
| 23 |
+
*.pth filter=lfs diff=lfs merge=lfs -text
|
| 24 |
+
*.rar filter=lfs diff=lfs merge=lfs -text
|
| 25 |
+
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
| 26 |
+
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
| 27 |
+
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
| 28 |
+
*.tar filter=lfs diff=lfs merge=lfs -text
|
| 29 |
+
*.tflite filter=lfs diff=lfs merge=lfs -text
|
| 30 |
+
*.tgz filter=lfs diff=lfs merge=lfs -text
|
| 31 |
+
*.wasm filter=lfs diff=lfs merge=lfs -text
|
| 32 |
+
*.xz filter=lfs diff=lfs merge=lfs -text
|
| 33 |
+
*.zip filter=lfs diff=lfs merge=lfs -text
|
| 34 |
+
*.zst filter=lfs diff=lfs merge=lfs -text
|
| 35 |
+
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
README.md
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
library_name: transformers
|
| 3 |
+
tags:
|
| 4 |
+
- RNA
|
| 5 |
+
- mRNA
|
| 6 |
+
- codon
|
| 7 |
+
- language-model
|
| 8 |
+
license: other
|
| 9 |
+
---
|
| 10 |
+
|
| 11 |
+
# CodonBERT
|
| 12 |
+
|
| 13 |
+
Minimal HuggingFace port of the **CodonBERT** checkpoint from
|
| 14 |
+
[CodonBERT](https://github.com/Sanofi-Public/CodonBERT) -- a BERT-based RNA
|
| 15 |
+
language model pretrained on codon-level representations of more than 10 million
|
| 16 |
+
mRNA coding sequences.
|
| 17 |
+
|
| 18 |
+
## Architecture
|
| 19 |
+
|
| 20 |
+
| Parameter | Value |
|
| 21 |
+
|---|---|
|
| 22 |
+
| Layers | 12 |
|
| 23 |
+
| Attention heads | 12 |
|
| 24 |
+
| Embedding dimension | 768 |
|
| 25 |
+
| FFN hidden dimension | 3072 (GELU) |
|
| 26 |
+
| Vocabulary size | 69 (5 special + 61 sense codons + 3 stop codons) |
|
| 27 |
+
| Positional encoding | Learned absolute |
|
| 28 |
+
| Normalization | LayerNorm (epsilon=1e-12) |
|
| 29 |
+
| Architecture | Standard post-LN BERT Transformer |
|
| 30 |
+
| Max sequence length | 1024 encoded tokens (up to 1022 codons / 3066 nt for one sequence) |
|
| 31 |
+
|
| 32 |
+
### Vocabulary
|
| 33 |
+
|
| 34 |
+
The tokenizer operates at the codon level. Unlike the original tokenizer, this port
|
| 35 |
+
accepts raw nucleotide strings and performs codon splitting automatically.
|
| 36 |
+
The 64 codons cover all combinations of {A, U, G, C}^3 in RNA space, including
|
| 37 |
+
the three stop codons.
|
| 38 |
+
Special tokens follow standard BERT convention: `[PAD]=0`, `[UNK]=1`,
|
| 39 |
+
`[CLS]=2`, `[SEP]=3`, `[MASK]=4`.
|
| 40 |
+
|
| 41 |
+
## Pretraining
|
| 42 |
+
|
| 43 |
+
- **Objective:** 15% masked language modeling (MLM) plus paired-sequence
|
| 44 |
+
taxonomy prediction (STP)
|
| 45 |
+
- **Data:** >10 million mRNA coding sequences from mammals, bacteria, human
|
| 46 |
+
viruses, and yeast
|
| 47 |
+
- **Source checkpoint:** `pytorch_model.bin` from the official
|
| 48 |
+
[Sanofi CodonBERT archive](https://cdn.prod.accelerator.sanofi/llm/CodonBERT.zip),
|
| 49 |
+
mirrored as [`lhallee/CodonBERT`](https://huggingface.co/lhallee/CodonBERT)
|
| 50 |
+
|
| 51 |
+
### Checkpoint selection
|
| 52 |
+
|
| 53 |
+
There is a single publicly released checkpoint from the original authors. The backbone
|
| 54 |
+
weights (`bert.*` prefix) and complete MLM prediction head are mapped directly.
|
| 55 |
+
Only the two-tensor STP/sequence-relationship head is discarded.
|
| 56 |
+
|
| 57 |
+
## Parity Verification
|
| 58 |
+
|
| 59 |
+
All verified on GPU with PyTorch 2.7.1 / CUDA 12.9:
|
| 60 |
+
|
| 61 |
+
- **Hidden states (eager):** all 13 levels match the original under
|
| 62 |
+
`torch.allclose(atol=1e-5, rtol=1e-5)` (observed max abs diff `1.15e-5`
|
| 63 |
+
on a padded three-sequence batch)
|
| 64 |
+
- **MLM logits and loss:** converted logits match original
|
| 65 |
+
`BertForPreTraining` logits under the same tolerance (observed max abs diff
|
| 66 |
+
`1.13e-5`; mixed `0`/`-100` label loss difference `2.87e-6`)
|
| 67 |
+
- **SDPA (evaluation):** final hidden states agree with eager FP32 to
|
| 68 |
+
`3.58e-6` max abs difference at non-padding positions
|
| 69 |
+
- **Flash attention 2 (evaluation):** verified against eager BF16 at
|
| 70 |
+
non-padding positions (all-layer differences up to `0.25`, expected BF16
|
| 71 |
+
accumulation across 12 layers)
|
| 72 |
+
|
| 73 |
+
## Related Models
|
| 74 |
+
|
| 75 |
+
See the full [CodonBERT collection](https://huggingface.co/collections/Taykhoom/codonbert).
|
| 76 |
+
|
| 77 |
+
| Model | Parameters | Notes |
|
| 78 |
+
|---|---:|---|
|
| 79 |
+
| **[CodonBERT](https://huggingface.co/Taykhoom/CodonBERT)** | 87.1M | This model |
|
| 80 |
+
|
| 81 |
+
## Usage
|
| 82 |
+
|
| 83 |
+
CodonBERT operates on CDS sequences. The tokenizer handles T->U conversion and codon
|
| 84 |
+
splitting automatically — pass raw nucleotide strings directly.
|
| 85 |
+
|
| 86 |
+
### Embedding generation
|
| 87 |
+
|
| 88 |
+
```python
|
| 89 |
+
import torch
|
| 90 |
+
from transformers import AutoTokenizer, AutoModel
|
| 91 |
+
|
| 92 |
+
tokenizer = AutoTokenizer.from_pretrained("Taykhoom/CodonBERT", trust_remote_code=True)
|
| 93 |
+
model = AutoModel.from_pretrained("Taykhoom/CodonBERT", trust_remote_code=True)
|
| 94 |
+
model.eval()
|
| 95 |
+
|
| 96 |
+
# Raw CDS nucleotide strings — T or U both accepted
|
| 97 |
+
cds_sequences = ["ATGAAAGGCCCTTAA", "ATGTTTGGG"]
|
| 98 |
+
|
| 99 |
+
enc = tokenizer(cds_sequences, return_tensors="pt", padding=True)
|
| 100 |
+
|
| 101 |
+
with torch.no_grad():
|
| 102 |
+
out = model(**enc)
|
| 103 |
+
|
| 104 |
+
cls_emb = out.last_hidden_state[:, 0, :] # (batch, 768) -- CLS token
|
| 105 |
+
content_mask = enc["attention_mask"].clone()
|
| 106 |
+
content_mask[:, 0] = 0 # exclude CLS
|
| 107 |
+
content_mask[torch.arange(content_mask.size(0)), enc["attention_mask"].sum(1) - 1] = 0
|
| 108 |
+
mean_emb = (out.last_hidden_state * content_mask.unsqueeze(-1)).sum(1) / \
|
| 109 |
+
content_mask.sum(1, keepdim=True) # mean over codons only
|
| 110 |
+
|
| 111 |
+
# Intermediate layers
|
| 112 |
+
out_all = model(**enc, output_hidden_states=True)
|
| 113 |
+
layer6_emb = out_all.hidden_states[6] # (batch, seq_len, 768)
|
| 114 |
+
```
|
| 115 |
+
|
| 116 |
+
### CDS-aware encoding (full mRNA input)
|
| 117 |
+
|
| 118 |
+
For full mRNA sequences where the CDS region must be extracted first:
|
| 119 |
+
|
| 120 |
+
```python
|
| 121 |
+
import numpy as np
|
| 122 |
+
|
| 123 |
+
# cds: binary array with 1 at the first nucleotide of each codon
|
| 124 |
+
enc, chunk_counts = tokenizer.batch_encode_with_cds(
|
| 125 |
+
mrna_sequences,
|
| 126 |
+
cds_tracks, # list of numpy arrays
|
| 127 |
+
return_tensors="pt",
|
| 128 |
+
padding=True,
|
| 129 |
+
)
|
| 130 |
+
with torch.no_grad():
|
| 131 |
+
out = model(**enc)
|
| 132 |
+
```
|
| 133 |
+
|
| 134 |
+
### Faster attention backends
|
| 135 |
+
|
| 136 |
+
```python
|
| 137 |
+
# Evaluation/inference only; use eager for training (see Implementation Notes).
|
| 138 |
+
model_sdpa = AutoModel.from_pretrained(
|
| 139 |
+
"Taykhoom/CodonBERT", trust_remote_code=True, attn_implementation="sdpa"
|
| 140 |
+
)
|
| 141 |
+
model_flash = AutoModel.from_pretrained(
|
| 142 |
+
"Taykhoom/CodonBERT", trust_remote_code=True,
|
| 143 |
+
attn_implementation="flash_attention_2", dtype=torch.bfloat16
|
| 144 |
+
)
|
| 145 |
+
```
|
| 146 |
+
|
| 147 |
+
### MLM logits
|
| 148 |
+
|
| 149 |
+
```python
|
| 150 |
+
from transformers import AutoModelForMaskedLM
|
| 151 |
+
|
| 152 |
+
model_mlm = AutoModelForMaskedLM.from_pretrained("Taykhoom/CodonBERT", trust_remote_code=True)
|
| 153 |
+
model_mlm.eval()
|
| 154 |
+
|
| 155 |
+
seq = "AUG [MASK] GGG"
|
| 156 |
+
enc = tokenizer(seq, return_tensors="pt")
|
| 157 |
+
with torch.no_grad():
|
| 158 |
+
logits = model_mlm(**enc).logits # (1, seq_len, 69)
|
| 159 |
+
```
|
| 160 |
+
|
| 161 |
+
The MLM prediction transform (dense + GELU + LayerNorm), decoder weight, and output
|
| 162 |
+
bias are all converted from the original checkpoint. The decoder tensor is initialized
|
| 163 |
+
exactly from the word embedding tensor. In this adapter it is a separate parameter,
|
| 164 |
+
not a runtime-tied alias; see the fine-tuning limitations below.
|
| 165 |
+
|
| 166 |
+
### Fine-tuning
|
| 167 |
+
|
| 168 |
+
For sequence-level tasks, use the CLS token embedding as input to a
|
| 169 |
+
classification/regression head. Train this checkpoint with the `eager` backend:
|
| 170 |
+
the current SDPA and Flash Attention 2 paths do not apply the configured `0.1`
|
| 171 |
+
attention-probability dropout during training.
|
| 172 |
+
|
| 173 |
+
The input embedding and MLM decoder start value-identical but are not storage-tied.
|
| 174 |
+
`tie_weights()` does not tie them, and `resize_token_embeddings()` leaves the decoder
|
| 175 |
+
at 69 outputs; vocabulary resizing is therefore unsupported. The model forward API
|
| 176 |
+
accepts `input_ids`, `attention_mask`, and `token_type_ids`, but not the stock BERT
|
| 177 |
+
`inputs_embeds`, `position_ids`, or `head_mask` arguments.
|
| 178 |
+
|
| 179 |
+
## Implementation Notes
|
| 180 |
+
|
| 181 |
+
Two key differences from the original CodonBERT release:
|
| 182 |
+
|
| 183 |
+
**1. Integrated codon tokenization.** The original repository requires users to
|
| 184 |
+
manually pre-process sequences into space-separated codons before passing them to
|
| 185 |
+
the tokenizer. This port ships `CodonBertTokenizer`, a `BertTokenizer` subclass
|
| 186 |
+
whose `_tokenize` method automatically normalizes sequences (T->U, uppercase) and
|
| 187 |
+
splits them into codon 3-mers. Users can pass raw nucleotide strings directly:
|
| 188 |
+
`tokenizer("AUGAAAGGG")` works without any pre-processing. A
|
| 189 |
+
`batch_encode_with_cds(sequences, cds_tracks)` method handles full mRNA input with
|
| 190 |
+
CDS extraction and codon-boundary-aligned chunking.
|
| 191 |
+
|
| 192 |
+
**2. SDPA and Flash Attention 2 support.** This port inherits from
|
| 193 |
+
[`Taykhoom/BERT-updated`](https://huggingface.co/Taykhoom/BERT-updated),
|
| 194 |
+
a minimal BERT re-implementation with all three backends (`eager`, `sdpa`,
|
| 195 |
+
`flash_attention_2`). Evaluation parity against the original eager implementation
|
| 196 |
+
is verified at every layer. For training, use eager as noted above. Eager attentions
|
| 197 |
+
requested in training mode are post-dropout tensors, so their rows do not sum to one.
|
| 198 |
+
Although the shared config accepts `hidden_act`, the backend always applies GELU;
|
| 199 |
+
this checkpoint is configured for GELU and is unaffected.
|
| 200 |
+
|
| 201 |
+
## Citation
|
| 202 |
+
|
| 203 |
+
```bibtex
|
| 204 |
+
@article{li2024_codonbert,
|
| 205 |
+
title = {{CodonBERT} large language model for {mRNA} vaccines},
|
| 206 |
+
author = {Li, Sizhen and Moayedpour, Saeed and Li, Ruijiang and Bailey, Michael and Riahi, Saleh and Kogler-Anele, Lorenzo and Miladi, Milad and Miner, Jacob and Pertuy, Fabien and Zheng, Dinghai and Wang, Jun and Balsubramani, Akshay and Tran, Khang and Zacharia, Minnie and Wu, Monica and Gu, Xiaobo and Clinton, Ryan and Asquith, Carla and Skaleski, Joseph and Boeglin, Lianne and Chivukula, Sudha and Dias, Anusha and Strugnell, Tod and Ulloa Montoya, Fernando and Agarwal, Vikram and Bar-Joseph, Ziv and Jager, Sven},
|
| 207 |
+
journal = {Genome Research},
|
| 208 |
+
volume = {34},
|
| 209 |
+
number = {7},
|
| 210 |
+
pages = {1027--1035},
|
| 211 |
+
year = {2024},
|
| 212 |
+
doi = {10.1101/gr.278870.123}
|
| 213 |
+
}
|
| 214 |
+
```
|
| 215 |
+
|
| 216 |
+
## Credits
|
| 217 |
+
|
| 218 |
+
Original model and code by Li et al. Source: [GitHub](https://github.com/Sanofi-Public/CodonBERT).
|
| 219 |
+
The HF conversion code was authored primarily by [Claude Code](https://claude.ai/code)
|
| 220 |
+
and reviewed manually by Taykhoom Dalal.
|
| 221 |
+
|
| 222 |
+
## License
|
| 223 |
+
|
| 224 |
+
Academic/non-commercial use only, following the original
|
| 225 |
+
[artifact license](https://github.com/Sanofi-Public/CodonBERT/blob/master/ARTIFACT_LICENSE.md):
|
| 226 |
+
|
| 227 |
+
Permission is hereby granted, free of charge, for academic research purposes only
|
| 228 |
+
and for non-commercial use only, to any person from an academic research or non-profit
|
| 229 |
+
organization obtaining a copy of these models, software, datasets and/or algorithms
|
| 230 |
+
(including, but not limited to, machine-learning model code, trained model weights,
|
| 231 |
+
inference-enabling code, training-enabling code, fine-tuning enabling code and other
|
| 232 |
+
elements) and/or associated documentation files (collectively the "Materials") to use,
|
| 233 |
+
copy, modify, or merge the Materials, subject to the following conditions: this IP
|
| 234 |
+
License Notice shall be included in all copies of the Materials or of substantial
|
| 235 |
+
portions of the Materials.
|
| 236 |
+
For purposes of this notice, "non-commercial use" excludes uses foreseeably resulting
|
| 237 |
+
in a commercial benefit or monetary gain. All other rights are reserved. The Materials
|
| 238 |
+
are provided "as is," without warranty of any kind, express or implied, including the
|
| 239 |
+
warranties of noninfringement.
|
config.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"architectures": [
|
| 3 |
+
"BertForMaskedLM"
|
| 4 |
+
],
|
| 5 |
+
"auto_map": {
|
| 6 |
+
"AutoConfig": "Taykhoom/BERT-updated--configuration_bert_updated.BertUpdatedConfig",
|
| 7 |
+
"AutoModel": "Taykhoom/BERT-updated--modeling_bert.BertModel",
|
| 8 |
+
"AutoModelForMaskedLM": "Taykhoom/BERT-updated--modeling_bert.BertForMaskedLM"
|
| 9 |
+
},
|
| 10 |
+
"attention_probs_dropout_prob": 0.1,
|
| 11 |
+
"hidden_act": "gelu",
|
| 12 |
+
"hidden_dropout_prob": 0.1,
|
| 13 |
+
"hidden_size": 768,
|
| 14 |
+
"initializer_range": 0.02,
|
| 15 |
+
"intermediate_size": 3072,
|
| 16 |
+
"layer_norm_eps": 1e-12,
|
| 17 |
+
"max_position_embeddings": 1024,
|
| 18 |
+
"model_type": "bert_updated",
|
| 19 |
+
"num_attention_heads": 12,
|
| 20 |
+
"num_hidden_layers": 12,
|
| 21 |
+
"pad_token_id": 0,
|
| 22 |
+
"type_vocab_size": 2,
|
| 23 |
+
"vocab_size": 69,
|
| 24 |
+
"transformers_version": "4.57.6",
|
| 25 |
+
"model_max_length": 1024
|
| 26 |
+
}
|
model.safetensors
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:534daf559ebc571a3158fed93fe140094f39c62eee74edc7bc319f66d6d89957
|
| 3 |
+
size 348554708
|
special_tokens_map.json
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cls_token": "[CLS]",
|
| 3 |
+
"mask_token": "[MASK]",
|
| 4 |
+
"pad_token": "[PAD]",
|
| 5 |
+
"sep_token": "[SEP]",
|
| 6 |
+
"unk_token": "[UNK]"
|
| 7 |
+
}
|
tokenization_codonbert.py
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import warnings
|
| 2 |
+
import numpy as np
|
| 3 |
+
from transformers import BertTokenizer
|
| 4 |
+
|
| 5 |
+
|
| 6 |
+
class CodonBertTokenizer(BertTokenizer):
|
| 7 |
+
"""BertTokenizer that auto-converts nucleotide sequences to codon-level tokens.
|
| 8 |
+
|
| 9 |
+
Raw nucleotide input is normalized (T->U, uppercase, whitespace stripped),
|
| 10 |
+
then split into non-overlapping 3-mer codons before vocab lookup. Trailing
|
| 11 |
+
1-2 nucleotides that do not form a complete codon are dropped.
|
| 12 |
+
|
| 13 |
+
eos_token is aliased to sep_token ("[SEP]") so that pooling code that
|
| 14 |
+
excludes both CLS and EOS/SEP positions works correctly.
|
| 15 |
+
|
| 16 |
+
Standard usage (raw nucleotides):
|
| 17 |
+
tokenizer("AUGAAAGGG")
|
| 18 |
+
tokenizer(["AUGAAAGGG", "AUGUUUCCC"], return_tensors="pt", padding=True)
|
| 19 |
+
|
| 20 |
+
CDS-aware usage (full mRNA + CDS track -> extract CDS, chunk, encode):
|
| 21 |
+
tokenizer.batch_encode_with_cds(
|
| 22 |
+
["NNNATGAAAGGGNN"],
|
| 23 |
+
cds=[np.array([0,0,0,1,0,0,1,0,0,1,0,0,0,0])],
|
| 24 |
+
return_tensors="pt",
|
| 25 |
+
padding=True,
|
| 26 |
+
)
|
| 27 |
+
|
| 28 |
+
Works with compare_minimal_vs_mm.py --use_cds out of the box.
|
| 29 |
+
"""
|
| 30 |
+
|
| 31 |
+
def __init__(self, *args, **kwargs):
|
| 32 |
+
kwargs.setdefault("eos_token", "[SEP]")
|
| 33 |
+
super().__init__(*args, **kwargs)
|
| 34 |
+
|
| 35 |
+
def _tokenize(self, text, split_special_tokens=False):
|
| 36 |
+
seq = "".join(text.split()).upper().replace("T", "U")
|
| 37 |
+
n = len(seq) - len(seq) % 3
|
| 38 |
+
return [seq[i:i + 3] for i in range(0, n, 3)]
|
| 39 |
+
|
| 40 |
+
@staticmethod
|
| 41 |
+
def _extract_cds(sequence, cds):
|
| 42 |
+
if sum(cds) == 0:
|
| 43 |
+
warnings.warn("No CDS found. Returning truncated sequence.")
|
| 44 |
+
n = len(sequence) - len(sequence) % 3
|
| 45 |
+
return sequence[:n]
|
| 46 |
+
first = int(np.argmax(cds == 1))
|
| 47 |
+
last = int(len(cds) - 1 - np.argmax(np.flip(cds) == 1)) + 2
|
| 48 |
+
proposed = sequence[first:last + 1]
|
| 49 |
+
if len(proposed) % 3 != 0:
|
| 50 |
+
warnings.warn("Irregular CDS. Returning truncated sequence.")
|
| 51 |
+
return proposed[:-(len(proposed) % 3)]
|
| 52 |
+
return proposed
|
| 53 |
+
|
| 54 |
+
def batch_encode_with_cds(self, sequences, cds_tracks, max_length=None, **kwargs):
|
| 55 |
+
"""Encode a batch of raw mRNA sequences using CDS-aware preprocessing.
|
| 56 |
+
|
| 57 |
+
Args:
|
| 58 |
+
sequences: List of raw nucleotide strings.
|
| 59 |
+
cds_tracks: List of numpy arrays (one per sequence). Non-zero values
|
| 60 |
+
mark the first nucleotide of each codon in the CDS region.
|
| 61 |
+
max_length: Max content codon-tokens per chunk (special tokens NOT
|
| 62 |
+
counted). Defaults to model_max_length - 2. This matches the
|
| 63 |
+
convention in compare_minimal_vs_mm.py where max_length is
|
| 64 |
+
already adjusted for special tokens.
|
| 65 |
+
**kwargs: Forwarded to batch_encode_plus (e.g. return_tensors, padding).
|
| 66 |
+
|
| 67 |
+
Returns:
|
| 68 |
+
(BatchEncoding, chunk_counts): chunk_counts[i] is the number of
|
| 69 |
+
chunks produced from sequence i.
|
| 70 |
+
"""
|
| 71 |
+
budget_codons = max_length or (self.model_max_length - 2)
|
| 72 |
+
budget_nt = budget_codons * 3
|
| 73 |
+
|
| 74 |
+
all_strings = []
|
| 75 |
+
chunk_counts = []
|
| 76 |
+
|
| 77 |
+
for seq, cds in zip(sequences, cds_tracks):
|
| 78 |
+
seq = seq.replace("T", "U").replace("t", "u").upper()
|
| 79 |
+
cds_seq = self._extract_cds(seq, np.asarray(cds))
|
| 80 |
+
n = len(cds_seq)
|
| 81 |
+
chunks = []
|
| 82 |
+
for i in range(0, max(n, 1), budget_nt):
|
| 83 |
+
chunk = cds_seq[i:i + budget_nt]
|
| 84 |
+
chunk = chunk[:len(chunk) - len(chunk) % 3]
|
| 85 |
+
if chunk:
|
| 86 |
+
chunks.append(chunk)
|
| 87 |
+
all_strings.extend(chunks or [""])
|
| 88 |
+
chunk_counts.append(len(chunks) or 1)
|
| 89 |
+
|
| 90 |
+
enc = self.batch_encode_plus(all_strings, **kwargs)
|
| 91 |
+
return enc, chunk_counts
|
tokenizer_config.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"added_tokens_decoder": {
|
| 3 |
+
"0": {
|
| 4 |
+
"content": "[PAD]",
|
| 5 |
+
"lstrip": false,
|
| 6 |
+
"normalized": false,
|
| 7 |
+
"rstrip": false,
|
| 8 |
+
"single_word": false,
|
| 9 |
+
"special": true
|
| 10 |
+
},
|
| 11 |
+
"1": {
|
| 12 |
+
"content": "[UNK]",
|
| 13 |
+
"lstrip": false,
|
| 14 |
+
"normalized": false,
|
| 15 |
+
"rstrip": false,
|
| 16 |
+
"single_word": false,
|
| 17 |
+
"special": true
|
| 18 |
+
},
|
| 19 |
+
"2": {
|
| 20 |
+
"content": "[CLS]",
|
| 21 |
+
"lstrip": false,
|
| 22 |
+
"normalized": false,
|
| 23 |
+
"rstrip": false,
|
| 24 |
+
"single_word": false,
|
| 25 |
+
"special": true
|
| 26 |
+
},
|
| 27 |
+
"3": {
|
| 28 |
+
"content": "[SEP]",
|
| 29 |
+
"lstrip": false,
|
| 30 |
+
"normalized": false,
|
| 31 |
+
"rstrip": false,
|
| 32 |
+
"single_word": false,
|
| 33 |
+
"special": true
|
| 34 |
+
},
|
| 35 |
+
"4": {
|
| 36 |
+
"content": "[MASK]",
|
| 37 |
+
"lstrip": false,
|
| 38 |
+
"normalized": false,
|
| 39 |
+
"rstrip": false,
|
| 40 |
+
"single_word": false,
|
| 41 |
+
"special": true
|
| 42 |
+
}
|
| 43 |
+
},
|
| 44 |
+
"cls_token": "[CLS]",
|
| 45 |
+
"do_basic_tokenize": true,
|
| 46 |
+
"do_lower_case": false,
|
| 47 |
+
"mask_token": "[MASK]",
|
| 48 |
+
"model_max_length": 1024,
|
| 49 |
+
"pad_token": "[PAD]",
|
| 50 |
+
"sep_token": "[SEP]",
|
| 51 |
+
"strip_accents": null,
|
| 52 |
+
"tokenize_chinese_chars": false,
|
| 53 |
+
"tokenizer_class": "CodonBertTokenizer",
|
| 54 |
+
"auto_map": {
|
| 55 |
+
"AutoTokenizer": ["tokenization_codonbert.CodonBertTokenizer", null]
|
| 56 |
+
},
|
| 57 |
+
"unk_token": "[UNK]"
|
| 58 |
+
}
|
vocab.txt
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[PAD]
|
| 2 |
+
[UNK]
|
| 3 |
+
[CLS]
|
| 4 |
+
[SEP]
|
| 5 |
+
[MASK]
|
| 6 |
+
AAA
|
| 7 |
+
AAU
|
| 8 |
+
AAG
|
| 9 |
+
AAC
|
| 10 |
+
AUA
|
| 11 |
+
AUU
|
| 12 |
+
AUG
|
| 13 |
+
AUC
|
| 14 |
+
AGA
|
| 15 |
+
AGU
|
| 16 |
+
AGG
|
| 17 |
+
AGC
|
| 18 |
+
ACA
|
| 19 |
+
ACU
|
| 20 |
+
ACG
|
| 21 |
+
ACC
|
| 22 |
+
UAA
|
| 23 |
+
UAU
|
| 24 |
+
UAG
|
| 25 |
+
UAC
|
| 26 |
+
UUA
|
| 27 |
+
UUU
|
| 28 |
+
UUG
|
| 29 |
+
UUC
|
| 30 |
+
UGA
|
| 31 |
+
UGU
|
| 32 |
+
UGG
|
| 33 |
+
UGC
|
| 34 |
+
UCA
|
| 35 |
+
UCU
|
| 36 |
+
UCG
|
| 37 |
+
UCC
|
| 38 |
+
GAA
|
| 39 |
+
GAU
|
| 40 |
+
GAG
|
| 41 |
+
GAC
|
| 42 |
+
GUA
|
| 43 |
+
GUU
|
| 44 |
+
GUG
|
| 45 |
+
GUC
|
| 46 |
+
GGA
|
| 47 |
+
GGU
|
| 48 |
+
GGG
|
| 49 |
+
GGC
|
| 50 |
+
GCA
|
| 51 |
+
GCU
|
| 52 |
+
GCG
|
| 53 |
+
GCC
|
| 54 |
+
CAA
|
| 55 |
+
CAU
|
| 56 |
+
CAG
|
| 57 |
+
CAC
|
| 58 |
+
CUA
|
| 59 |
+
CUU
|
| 60 |
+
CUG
|
| 61 |
+
CUC
|
| 62 |
+
CGA
|
| 63 |
+
CGU
|
| 64 |
+
CGG
|
| 65 |
+
CGC
|
| 66 |
+
CCA
|
| 67 |
+
CCU
|
| 68 |
+
CCG
|
| 69 |
+
CCC
|