lemon / README.md
Team-LEMON
Fix expected benchmark values to match actual reproducible results (seed=42)
39e808f
|
Raw
History Blame Contribute Delete
6.17 kB
---
license: mit
tags:
- protein
- biology
- sequence-encoder
- contrastive-learning
- lemon
---
# LEMON: Layered Extraction of Molecular Ordering from Nature
LEMON is a protein sequence encoder trained with hierarchical contrastive
learning for family and fold similarity search, using the ZEST tokenizer
(Zoned Encoding of Sequence Traits). Submitted anonymously for double-blind
peer review.
## Architecture
| Component | Details |
|---|---|
| **Encoder** | 24-layer transformer, 768-d, 12 heads, SwiGLU FFN (ff_mult=4), RoPE with linear scaling |
| **Pooling** | Learned-query multi-head attention aggregator → 768-d sequence vector |
| **Projector** | Bottleneck MLP (768 → 768 → 384-d), L2-normalised output |
| **Tokenizer** | ZEST 32K (Zoned Encoding of Sequence Traits) — greedy max-match trie over biochemically-substitutable amino-acid n-gram clusters |
| **Context** | 1,024 tokens (linear RoPE scaling for longer sequences) |
| **Dropout** | 0.04 |
**Parameter breakdown (203.72M total):**
| Module | Params |
|---|---|
| Core transformer | 194.52M |
| Attention aggregator | 2.95M |
| Profile expansion head | 2.41M |
| Global position embedding | 2.36M |
| Projector | 1.48M |
| **Total** | **203.72M** |
## Quickstart
```python
import torch
from huggingface_hub import snapshot_download
import sys, os
path = snapshot_download("Team-LEMON/lemon")
sys.path.insert(0, path)
from modeling_lemon import LemonEncoder
from tokenization_zest import ZESTTokenizer
tok = ZESTTokenizer.from_pretrained(path)
model = LemonEncoder.from_pretrained(
os.path.join(path, "model.safetensors"),
os.path.join(path, "config.json"),
)
model.eval()
seqs = ["MKTAYIAKQRQISFVKSHFSRQ", "ACDEFGHIKLMNPQRSTVWY"]
enc = tok.batch_encode_plus(seqs, max_length=512, padding=True)
with torch.no_grad():
emb = model.embed(enc["input_ids"], enc["attention_mask"]) # [2, 384]
print(emb.shape) # torch.Size([2, 384])
sim = model.similarity(emb[:1], emb[1:])
print("cosine-like similarity:", sim.item())
```
## Reproducing Table 1
The `eval_retrieval.py` script and all three benchmark datasets are bundled in this
repo. No external downloads required.
**Run all three datasets in one command:**
```python
from huggingface_hub import snapshot_download
path = snapshot_download("Team-LEMON/lemon")
```
```bash
cd /path/to/snapshot
python eval_retrieval.py # runs SCOPe + SCOP + CATH-S20
python eval_retrieval.py --scope # SCOPe only
python eval_retrieval.py --cath # CATH-S20 only
python eval_retrieval.py --scop # SCOP only
```
**Test-Time Augmentation (TTA) with Trie-Dropout:**
TTA improves retrieval by averaging embeddings from multiple stochastic tokenizations.
```bash
python eval_retrieval.py --dropout 0.45 --tta 5 # 5 stochastic passes, averaged
```
**TTA Gain (SCOPe, seed=42):**
| Level | Metric | Baseline | TTA (d=0.45, k=5) | Gain |
|-------|--------|----------|-------------------|------|
| fold | AUROC | 0.9025 | 0.9080 | +0.0055 |
| fold | mAP | 0.3067 | 0.3197 | +0.0130 |
| superfamily | AUROC | 0.9443 | 0.9519 | +0.0076 |
| superfamily | mAP | 0.4700 | 0.4803 | +0.0103 |
To reproduce:
```bash
# Baseline
python eval_retrieval.py --scope --seed 42
# With TTA
python eval_retrieval.py --scope --seed 42 --dropout 0.45 --tta 5
```
**Or from a Jupyter notebook:**
```python
import sys
from huggingface_hub import snapshot_download
path = snapshot_download("Team-LEMON/lemon")
sys.path.insert(0, path)
from eval_retrieval import run_benchmark, display_results
results = run_benchmark(repo=path, seed=42) # deterministic with seed=42
display_results(results)
# With TTA:
# results = run_benchmark(repo=path, seed=42, dropout=0.1, tta_passes=8)
```
**Expected output (seed=42, deterministic):**
| Dataset | Level | AUROC | mAP |
|----------|--------------|--------|--------|
| SCOPe | fold | 0.9025 | 0.3066 |
| SCOPe | superfamily | 0.9443 | 0.4700 |
| CATH-S20 | architecture | 0.8871 | 0.3128 |
| CATH-S20 | topology | 0.9580 | 0.5381 |
| SCOP | fold | 0.9062 | 0.2919 |
> Results are deterministic with `--seed 42` (default).
> CATH uses Architecture/Topology levels; SCOP/SCOPe uses Fold/Superfamily.
**Bundled dataset provenance:**
| File | Sequences | Original source |
|------|-----------|----------------|
| `data/scope_10_2.08.fa` | 7 117 | SCOPe 2.08, 10% seq-id — [scop.berkeley.edu](https://scop.berkeley.edu/downloads/scopeseq-2.08/) |
| `data/cath_s20.fa` | 15 043 | CATH v4.4.0 S20 — [cathdb.info](https://www.cathdb.info/wiki/doku/?id=data:index) |
| `data/cath_s20_labels.tsv` | 15 043 | CATH domain list v4.4.0 (S20 subset) — [cathdb.info](https://www.cathdb.info/wiki/doku/?id=data:index) |
| `data/scop175.fa` | 31 073 | SCOP 1.75 — [plm-zero-shot-remote-homology-evaluation](https://github.com/amoldwin/plm-zero-shot-remote-homology-evaluation) |
## Circular Permutation Detection (CIRPIN SCOPe40)
Zero-shot detection of circularly permuted protein pairs using cosine similarity of LEMON embeddings.
Benchmark: CIRPIN SCOPe40 — 18,127 pairs (1,967 positive CP pairs) from ASTRAL SCOPe 2.08 at 40% identity.
**Results (seed=42):**
| Configuration | AUROC | AUPRC | Accuracy |
|---------------|-------|-------|----------|
| Baseline | 0.7413 | 0.3035 | 0.8990 |
| TTA (d=0.45, k=5) | **0.7576** | **0.3066** | 0.8987 |
| Gain | +0.0163 | +0.0031 | - |
TTA improves CP detection by averaging embeddings over multiple stochastic tokenizations.
To reproduce:
```bash
# Baseline
python eval_circular_permutation.py --fasta data/cirpin/scope40.fa --pairs data/cirpin/pairs.tsv --seed 42
# With TTA
python eval_circular_permutation.py --fasta data/cirpin/scope40.fa --pairs data/cirpin/pairs.tsv --seed 42 --dropout 0.45 --tta 5
```
## Requirements
```
torch>=2.0
safetensors
huggingface_hub
```
## Notes
- Input sequences should be standard single-letter amino-acid strings.
- The tokenizer handles unknown characters via `<MASK>` token fallback.
- `model.embed()` returns L2-normalised embeddings; use dot product for
cosine similarity.
- `model.similarity()` applies a learned temperature scalar.