protea-sparse-knn / README.md
XaxiPiruli's picture
Let the harness speak: drop the benchmark table from a preliminary artefact
2c6d616 verified
|
Raw
History Blame Contribute Delete
5.22 kB
---
license: unlicense
tags:
- protein
- gene-ontology
- protein-function-prediction
- sparse-encoder
- cafa
- lafa
library_name: pytorch
---
# protea-sparse-knn
Protein function prediction by nearest-neighbour Gene Ontology transfer,
performed in the space of a learned sparse encoder rather than in the raw
embedding space.
This repository holds the frozen artefacts a container needs to run the
method: the trained encoder and the reference bank. It is a LAFA
submission bundle, released so the evaluation can be reproduced.
## The idea
A protein language model places proteins near each other when their
sequences look alike. Function does not follow sequence that closely, and
the gap is what limits nearest-neighbour transfer.
This encoder is a single linear map from the 768-dimensional Ankh-base
embedding to a 2048-dimensional dictionary, keeping the 128 largest
components. It is trained so that the cosine between two proteins' codes
matches the information-content-weighted Lin semantic similarity of their
propagated GO closures, with hard negatives mined from embedding-near
neighbours. In other words, it learns a geometry in which distance means
functional similarity.
Held out on 4,000 proteins absent from the training pool, over 120,000
pairs, correlation against Lin semantic similarity:
| representation | Spearman |
| --- | --- |
| raw Ankh-base embedding | +0.168 |
| encoder, dense | +0.530 |
| encoder, top-128 (what ships here) | +0.467 |
The gain of the shipped code over the raw embedding is **+0.300**. Fitting
inside the earlier release instead moves it to +0.293, so the result does
not depend on which release it was fitted in. The figures are differences
rather than ratios on purpose: the baseline is small enough that the same
two runs read as +179 and +162 percent, a spread that is an artefact of
the denominator.
The encoder also removes most of the anisotropy of the raw space: mean
cosine between random pairs falls from 0.551 to 0.086.
## Contents
| file | what it is |
| --- | --- |
| `encoder.pt` | the trained encoder, 6.3 MB |
| `MANIFEST.json` | what it was fitted on |
| `VALIDATION.json` | the held-out measurement above |
| `codes_idx.npy` | dictionary positions of the kept components, `uint16` |
| `codes_val.npy` | their values, `float16` |
| `accessions.npy` | row order, mapping a code back to a protein |
| `donors.tsv.gz` | the annotations transferred by the neighbours |
| `BANK.json` | what the bank was built from |
| `EMBEDDING_RECIPE.json` | the backbone recipe the bank was built with |
`EMBEDDING_RECIPE.json` is not documentation. A consumer must embed its
queries with that exact recipe, or the queries and the bank end up in
different geometries and accuracy degrades without anything failing.
## Training and cutoff
Everything is fitted once and frozen. Nothing is refitted at inference.
| item | value |
| --- | --- |
| backbone | `ElnaggarLab/ankh-base`, last layer, mean pooled, L2-normalised, truncated at 2048 |
| annotations | GOA release 227, published 2025-09-04 |
| ontology | `releases/2025-07-22` |
| bank rows | 575,503 canonical proteins, over 487,237 distinct sequences |
| donor annotations | 5,880,402 over 557,071 proteins |
| encoder training pool | 60,000 proteins |
| dictionary | 2048, top 128 kept |
| seed | 42 |
The ontology is the last snapshot at or before the annotation release.
The training driver refuses to run if that ordering is violated, because
a later ontology would put terms that did not exist at the cutoff on the
label side of the objective.
The earlier release, GOA 226 of 2025-05-03, is reserved as the window for
choosing hyperparameters and is not used to fit what ships here.
## Running it
The container that consumes this bundle lives in the PROTEA repository
under `apps/lafa_sparse_knn`, with its bind-mount contract in
`METHOD_CARD.md`. Retrieval is exact brute force on the processor, and
the bank is held sparse, so the whole method fits in about 1.5 GB plus
the backbone.
## Two things a consumer should know
**The bank is keyed by protein, not by sequence.** 575,503 canonical
accessions resolve to 487,237 distinct sequences, so proteins sharing a
sequence appear as separate rows carrying their own annotations. They are
distinct donors, which is the intent, but they are also exact ties in
retrieval: a query matching a sequence held by five accessions fills five
neighbour slots with the same vector.
**Self-retrieval is the parity check.** Embedding a protein that is in
the bank returns that protein first, at cosine 0.99 or above (measured on
20 proteins: 19 return themselves and the twentieth returns an accession
sharing its exact sequence). If a consumer sees lower, its embedding
recipe has drifted from `EMBEDDING_RECIPE.json` and the results should
not be trusted.
## Scope
This is the retrieval core on its own. It carries no reranker, no
alignment features, no taxonomic prior and no per-aspect model. It is an
intermediate release of a system under active development, published so
the containerised inference path can be exercised end to end.
## Citation
Francisco Miguel Perez Canales. PROTEA: protein functional
embedding-based annotation.