Upload folder using huggingface_hub
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .gitattributes +3 -0
- .msc +0 -0
- .mv +1 -0
- LICENSE +21 -0
- README.md +283 -0
- configuration.json +2 -0
- data/fasta/few_proteins.fasta +6 -0
- data/fasta/some_proteins.fasta +30 -0
- data/inverse_folding/5YH2.cif +0 -0
- data/inverse_folding/5YH2.pdb +0 -0
- data/inverse_folding/5YH2_mutated_seqs.fasta +8 -0
- data/inverse_folding/example.json +0 -0
- data/variant_prediction/BLAT_ECOLX_Ranganathan2015.csv +0 -0
- data/variant_prediction/aggregated_rho.csv +17 -0
- data/variant_prediction/aggregated_rho_round3.csv +17 -0
- data/variant_prediction/rho_pp.csv +575 -0
- model/README.md +10 -0
- model/__init__.py +2 -0
- model/__pycache__/__init__.cpython-311.pyc +0 -0
- model/esm/__init__.py +13 -0
- model/esm/__pycache__/__init__.cpython-311.pyc +0 -0
- model/esm/__pycache__/esm1.cpython-311.pyc +0 -0
- model/esm/__pycache__/esm2.cpython-311.pyc +0 -0
- model/esm/__pycache__/msa_transformer.cpython-311.pyc +0 -0
- model/esm/__pycache__/pretrained.cpython-311.pyc +0 -0
- model/esm/__pycache__/version.cpython-311.pyc +0 -0
- model/esm/esm1.py +200 -0
- model/esm/esm2.py +152 -0
- model/esm/esmfold/__init__.py +0 -0
- model/esm/esmfold/v1/__init__.py +0 -0
- model/esm/esmfold/v1/categorical_mixture.py +43 -0
- model/esm/esmfold/v1/esmfold.py +364 -0
- model/esm/esmfold/v1/misc.py +309 -0
- model/esm/esmfold/v1/pretrained.py +197 -0
- model/esm/esmfold/v1/tri_self_attn_block.py +160 -0
- model/esm/esmfold/v1/trunk.py +245 -0
- model/esm/inverse_folding/__init__.py +8 -0
- model/esm/inverse_folding/features.py +352 -0
- model/esm/inverse_folding/gvp_encoder.py +56 -0
- model/esm/inverse_folding/gvp_modules.py +475 -0
- model/esm/inverse_folding/gvp_transformer.py +140 -0
- model/esm/inverse_folding/gvp_transformer_encoder.py +184 -0
- model/esm/inverse_folding/gvp_utils.py +68 -0
- model/esm/inverse_folding/multichain_util.py +152 -0
- model/esm/inverse_folding/transformer_decoder.py +228 -0
- model/esm/inverse_folding/transformer_layer.py +304 -0
- model/esm/inverse_folding/util.py +323 -0
- model/esm/msa_transformer.py +238 -0
- model/esm/pretrained.py +553 -0
- model/esm/version.py +6 -0
.gitattributes
CHANGED
|
@@ -33,3 +33,6 @@ saved_model/**/* 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
|
|
|
|
|
|
|
|
|
|
|
|
| 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
|
| 36 |
+
weight/esm-main/examples/inverse_folding/illustration.png filter=lfs diff=lfs merge=lfs -text
|
| 37 |
+
weight/esm-main/examples/lm-design/utils/ngram_stats/quadgram_seg.p filter=lfs diff=lfs merge=lfs -text
|
| 38 |
+
weight/esm-main/examples/lm-design/utils/ngram_stats/trigram_seg.p filter=lfs diff=lfs merge=lfs -text
|
.msc
ADDED
|
Binary file (46.3 kB). View file
|
|
|
.mv
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
Revision:master,CreatedAt:1784688787
|
LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) Meta Platforms, Inc. and affiliates.
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 6 |
+
of this software and associated documentation files (the "Software"), to deal
|
| 7 |
+
in the Software without restriction, including without limitation the rights
|
| 8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 9 |
+
copies of the Software, and to permit persons to whom the Software is
|
| 10 |
+
furnished to do so, subject to the following conditions:
|
| 11 |
+
|
| 12 |
+
The above copyright notice and this permission notice shall be included in all
|
| 13 |
+
copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 21 |
+
SOFTWARE.
|
README.md
ADDED
|
@@ -0,0 +1,283 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
license: mit
|
| 3 |
+
tasks:
|
| 4 |
+
- protein-structure-prediction
|
| 5 |
+
frameworks:
|
| 6 |
+
- pytorch
|
| 7 |
+
language:
|
| 8 |
+
- en
|
| 9 |
+
- zh
|
| 10 |
+
tags:
|
| 11 |
+
- OneScience
|
| 12 |
+
- Life Sciences
|
| 13 |
+
- Protein Language Model
|
| 14 |
+
- Protein Structure Prediction
|
| 15 |
+
- Variant Effect Prediction
|
| 16 |
+
- ESM
|
| 17 |
+
modelscope:
|
| 18 |
+
model: OneScience/ESM
|
| 19 |
+
data_path: data/
|
| 20 |
+
---
|
| 21 |
+
|
| 22 |
+
<p align="center">
|
| 23 |
+
<strong>
|
| 24 |
+
<span style="font-size: 30px;">ESM</span>
|
| 25 |
+
</strong>
|
| 26 |
+
</p>
|
| 27 |
+
|
| 28 |
+
# Model Introduction
|
| 29 |
+
|
| 30 |
+
ESM (Evolutionary Scale Modeling) is a family of protein language models released by Meta AI / FAIR. It can be used for protein sequence representation, structure prediction, variant effect assessment, and fixed-backbone sequence design.
|
| 31 |
+
|
| 32 |
+
Paper: Evolutionary-scale prediction of atomic-level protein structure with a language model
|
| 33 |
+
https://www.science.org/doi/10.1126/science.ade2574
|
| 34 |
+
|
| 35 |
+
# Model Description
|
| 36 |
+
|
| 37 |
+
This model package integrates PyTorch inference capabilities for ESM-1, ESM-2, MSA Transformer, ESMFold, ESM-1v, and ESM-IF1, and provides DCU runtime adaptation. The accompanying sample data is released with the ModelScope model package `OneScience/ESM`.
|
| 38 |
+
|
| 39 |
+
# Applicable Scenarios
|
| 40 |
+
|
| 41 |
+
| Scenario | Description |
|
| 42 |
+
| :---: | :--- |
|
| 43 |
+
| Protein sequence representation extraction | Input a FASTA file and output per-token, mean, BOS, or contact representations |
|
| 44 |
+
| Protein structure prediction | Input one or more amino acid sequences and output the corresponding PDB structure files |
|
| 45 |
+
| Variant effect scoring | Input a wild-type sequence and a DMS mutation table, and output mutation impact scores |
|
| 46 |
+
| Fixed-backbone sequence design | Input a PDB / CIF structure and chain ID, and sample candidate sequences satisfying backbone constraints |
|
| 47 |
+
| Structure-conditioned sequence scoring | Input a structure and candidate sequences, and compute conditional log-likelihood |
|
| 48 |
+
| ModelScope / OneCode runtime | After downloading the model project, quickly verify script connectivity in a biology-domain runtime environment |
|
| 49 |
+
|
| 50 |
+
|
| 51 |
+
# Usage Instructions
|
| 52 |
+
|
| 53 |
+
## 1. OneCode Usage
|
| 54 |
+
|
| 55 |
+
You can experience intelligent one-click AI4S programming through the OneCode online environment:
|
| 56 |
+
|
| 57 |
+
[Click to experience intelligent one-click AI4S programming](https://web-2069360198568017922-iaaj.ksai.scnet.cn:58043/home)
|
| 58 |
+
|
| 59 |
+
## 2. Manual Installation and Usage
|
| 60 |
+
|
| 61 |
+
**Hardware Requirements**
|
| 62 |
+
|
| 63 |
+
- GPU or DCU runtime is recommended.
|
| 64 |
+
- CPU can be used for import checks and small-configuration connectivity verification, but full training and inference are slow.
|
| 65 |
+
- DCU users need to install DTK in advance. DTK 25.04.2 or later is recommended, or the OneScience-recommended version matching the current cluster.
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
**Environment Check**
|
| 72 |
+
|
| 73 |
+
- NVIDIA GPU:
|
| 74 |
+
|
| 75 |
+
```bash
|
| 76 |
+
nvidia-smi
|
| 77 |
+
```
|
| 78 |
+
|
| 79 |
+
- Hygon DCU:
|
| 80 |
+
|
| 81 |
+
```bash
|
| 82 |
+
hy-smi
|
| 83 |
+
```
|
| 84 |
+
|
| 85 |
+
### Download the Model Package
|
| 86 |
+
|
| 87 |
+
```bash
|
| 88 |
+
modelscope download --model OneScience/ESM --local_dir ./ESM
|
| 89 |
+
cd ESM
|
| 90 |
+
```
|
| 91 |
+
|
| 92 |
+
This model package already contains a small amount of sample data that can be used directly for default workflow verification.
|
| 93 |
+
|
| 94 |
+
### Install the Runtime Environment
|
| 95 |
+
|
| 96 |
+
**DCU Environment**
|
| 97 |
+
|
| 98 |
+
```bash
|
| 99 |
+
# First activate DTK and Conda
|
| 100 |
+
conda create -n onescience311 python=3.11 -y
|
| 101 |
+
conda activate onescience311
|
| 102 |
+
# Supports uv installation
|
| 103 |
+
pip install onescience[bio-dcu] -i http://mirrors.onescience.ai:3141/pypi/simple/ --trusted-host mirrors.onescience.ai
|
| 104 |
+
```
|
| 105 |
+
|
| 106 |
+
```bash
|
| 107 |
+
# If libraries cannot be found, activate CUDA as shown below
|
| 108 |
+
source ${ROCM_PATH}/cuda/env.sh
|
| 109 |
+
export LD_LIBRARY_PATH="$CONDA_PREFIX/lib:$LD_LIBRARY_PATH"
|
| 110 |
+
export LD_LIBRARY_PATH="$CONDA_PREFIX/lib/python3.11/site-packages/fastpt/torch/lib:$LD_LIBRARY_PATH"
|
| 111 |
+
```
|
| 112 |
+
|
| 113 |
+
After installation, return to the model package directory:
|
| 114 |
+
|
| 115 |
+
```bash
|
| 116 |
+
cd ./ESM
|
| 117 |
+
```
|
| 118 |
+
|
| 119 |
+
### Training and Inference Data Introduction
|
| 120 |
+
|
| 121 |
+
The FASTA, PDB / CIF, and DMS data used by the ESM examples have been released with the [ModelScope model package OneScience/ESM](https://modelscope.cn/models/OneScience/ESM). After downloading the complete model package, they can be used directly from the `data/` directory. This model package does not include a training entry point; the data is used for example inference and workflow verification. You can also download only the data directory:
|
| 122 |
+
|
| 123 |
+
```bash
|
| 124 |
+
modelscope download --model OneScience/ESM ESM/data --local_dir ./data
|
| 125 |
+
```
|
| 126 |
+
### Training Weights
|
| 127 |
+
|
| 128 |
+
The repository includes multiple ESM weights under `weight/`, which can be selected for inference as needed.
|
| 129 |
+
|
| 130 |
+
### Prepare Weights
|
| 131 |
+
|
| 132 |
+
Place the required ESM weights in the following directory:
|
| 133 |
+
|
| 134 |
+
```text
|
| 135 |
+
weight/
|
| 136 |
+
checkpoints/
|
| 137 |
+
esm2_t6_8M_UR50D.pt
|
| 138 |
+
esmfold_3B_v1.pt
|
| 139 |
+
esm1v_t33_650M_UR90S_1.pt
|
| 140 |
+
esm_if1_gvp4_t16_142M_UR50.pt
|
| 141 |
+
...
|
| 142 |
+
```
|
| 143 |
+
|
| 144 |
+
If using a shared runtime directory, you can also specify the weight location through an environment variable:
|
| 145 |
+
|
| 146 |
+
```bash
|
| 147 |
+
export ESM_WEIGHT_DIR=/path/to/esm/weight
|
| 148 |
+
```
|
| 149 |
+
|
| 150 |
+
The default example reads:
|
| 151 |
+
|
| 152 |
+
- `weight/checkpoints/esm2_t6_8M_UR50D.pt`
|
| 153 |
+
|
| 154 |
+
The corresponding weights must be available for the ESMFold, ESM-1v, and ESM-IF1 examples.
|
| 155 |
+
|
| 156 |
+
### Default Example
|
| 157 |
+
|
| 158 |
+
```bash
|
| 159 |
+
bash scripts/infer.sh
|
| 160 |
+
```
|
| 161 |
+
|
| 162 |
+
The default example reads `data/fasta/few_proteins.fasta`, uses `esm2_t6_8M_UR50D.pt` to extract protein representations, and saves the results to `outputs/embeddings/`.
|
| 163 |
+
|
| 164 |
+
### Sequence Representation Extraction
|
| 165 |
+
|
| 166 |
+
```bash
|
| 167 |
+
python scripts/extract.py \
|
| 168 |
+
weight/checkpoints/esm2_t6_8M_UR50D.pt \
|
| 169 |
+
data/fasta/few_proteins.fasta \
|
| 170 |
+
outputs/embeddings \
|
| 171 |
+
--include mean per_tok \
|
| 172 |
+
--repr_layers 6
|
| 173 |
+
```
|
| 174 |
+
|
| 175 |
+
### ESMFold Structure Prediction
|
| 176 |
+
|
| 177 |
+
```bash
|
| 178 |
+
python scripts/fold.py \
|
| 179 |
+
-i data/fasta/few_proteins.fasta \
|
| 180 |
+
-o outputs/pdb \
|
| 181 |
+
--model-dir weight \
|
| 182 |
+
--cpu-only
|
| 183 |
+
```
|
| 184 |
+
|
| 185 |
+
The output directory will generate one or more `.pdb` files. For formal GPU / DCU inference, you can remove `--cpu-only` and set `--chunk-size` or `--max-tokens-per-batch` according to available memory.
|
| 186 |
+
|
| 187 |
+
You can also explicitly enable ESMFold through the default script:
|
| 188 |
+
|
| 189 |
+
```bash
|
| 190 |
+
RUN_ESMFOLD=1 bash scripts/infer.sh
|
| 191 |
+
```
|
| 192 |
+
|
| 193 |
+
### Inverse Folding Sequence Sampling
|
| 194 |
+
|
| 195 |
+
```bash
|
| 196 |
+
python scripts/inverse_folding/sample_sequences.py \
|
| 197 |
+
data/inverse_folding/5YH2.pdb \
|
| 198 |
+
--chain A \
|
| 199 |
+
--outpath outputs/sampled_seqs.fasta \
|
| 200 |
+
--num-samples 1 \
|
| 201 |
+
--nogpu
|
| 202 |
+
```
|
| 203 |
+
|
| 204 |
+
### Inverse Folding Sequence Scoring
|
| 205 |
+
|
| 206 |
+
```bash
|
| 207 |
+
python scripts/inverse_folding/score_log_likelihoods.py \
|
| 208 |
+
data/inverse_folding/5YH2.pdb \
|
| 209 |
+
data/inverse_folding/5YH2_mutated_seqs.fasta \
|
| 210 |
+
--chain A \
|
| 211 |
+
--outpath outputs/sequence_scores.csv \
|
| 212 |
+
--nogpu
|
| 213 |
+
```
|
| 214 |
+
|
| 215 |
+
### Variant Effect Prediction
|
| 216 |
+
|
| 217 |
+
Variant effect prediction requires providing a wild-type sequence matching the DMS mutation column:
|
| 218 |
+
|
| 219 |
+
```bash
|
| 220 |
+
python scripts/variant_prediction/predict.py \
|
| 221 |
+
--model-location esm1v_t33_650M_UR90S_1 \
|
| 222 |
+
--sequence "${ESM_VARIANT_SEQUENCE}" \
|
| 223 |
+
--dms-input data/variant_prediction/BLAT_ECOLX_Ranganathan2015.csv \
|
| 224 |
+
--mutation-col mutant \
|
| 225 |
+
--dms-output outputs/variant_prediction.csv \
|
| 226 |
+
--offset-idx 24 \
|
| 227 |
+
--scoring-strategy wt-marginals
|
| 228 |
+
```
|
| 229 |
+
|
| 230 |
+
# Data Format
|
| 231 |
+
|
| 232 |
+
Sample data is stored under `data/` by default:
|
| 233 |
+
|
| 234 |
+
```text
|
| 235 |
+
data/
|
| 236 |
+
fasta/
|
| 237 |
+
few_proteins.fasta
|
| 238 |
+
some_proteins.fasta
|
| 239 |
+
inverse_folding/
|
| 240 |
+
5YH2.pdb
|
| 241 |
+
5YH2.cif
|
| 242 |
+
5YH2_mutated_seqs.fasta
|
| 243 |
+
example.json
|
| 244 |
+
variant_prediction/
|
| 245 |
+
BLAT_ECOLX_Ranganathan2015.csv
|
| 246 |
+
rho_pp.csv
|
| 247 |
+
aggregated_rho.csv
|
| 248 |
+
aggregated_rho_round3.csv
|
| 249 |
+
```
|
| 250 |
+
|
| 251 |
+
Where:
|
| 252 |
+
|
| 253 |
+
- FASTA files are used for sequence representation extraction and structure prediction.
|
| 254 |
+
- PDB / CIF files are used for inverse folding sampling and structure-conditioned sequence scoring.
|
| 255 |
+
- The variant effect prediction CSV must contain a mutation column. The default example column name is `mutant`, and the mutation format is like `A123B`.
|
| 256 |
+
- Custom DMS data must ensure that the wild-type sequence provided by `--sequence` is consistent with the wild-type amino acids in the mutation column.
|
| 257 |
+
|
| 258 |
+
# Verification
|
| 259 |
+
|
| 260 |
+
Static import check:
|
| 261 |
+
|
| 262 |
+
```bash
|
| 263 |
+
python scripts/check_import_boundaries.py
|
| 264 |
+
```
|
| 265 |
+
|
| 266 |
+
Syntax check:
|
| 267 |
+
|
| 268 |
+
```bash
|
| 269 |
+
python -B -c "import ast, pathlib; [ast.parse(p.read_text(encoding='utf-8'), filename=str(p)) for root in ['model', 'scripts', 'tests'] for p in pathlib.Path(root).rglob('*.py')]"
|
| 270 |
+
```
|
| 271 |
+
|
| 272 |
+
# Official OneScience Information
|
| 273 |
+
|
| 274 |
+
| Platform | OneScience Main Repository | Skills Repository |
|
| 275 |
+
| --- | --- | --- |
|
| 276 |
+
| Gitee | https://gitee.com/onescience-ai/onescience | https://gitee.com/onescience-ai/oneskills |
|
| 277 |
+
| GitHub | https://github.com/onescience-ai/OneScience | https://github.com/onescience-ai/oneskills |
|
| 278 |
+
|
| 279 |
+
# Citations and License
|
| 280 |
+
|
| 281 |
+
- This repository is based on the ESM open-source model and provides DCU adaptation.
|
| 282 |
+
- ESM-related source code uses the MIT License; see `LICENSE`. For the terms of use for model weights and data, refer to the corresponding publisher's instructions.
|
| 283 |
+
- For scientific research, cite the corresponding original ESM paper according to the specific submodel. For ESM-2 / ESMFold, cite: [Evolutionary-scale prediction of atomic-level protein structure with a language model](https://www.science.org/doi/10.1126/science.ade2574).
|
configuration.json
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{"framework":"Pytorch","task":"other"}
|
| 2 |
+
|
data/fasta/few_proteins.fasta
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
>UniRef50_UPI0003108055
|
| 2 |
+
MPADAREYLESKHATRRFDRPAEVAGVVAFLLSDDTSFVIGAGYLVDGGYTALRAARGRLGPRRQAAPAVKLLPNTDSPR
|
| 3 |
+
>UniRef50_A0A223SCH7
|
| 4 |
+
MGPPRWWKGITGLAAVVHRADPEDKADLYAKMGLYLEYHPETRIVEARIKPRLHDVCESKVSEGGLEPPCP
|
| 5 |
+
>UniRef50_A0A090SUK6
|
| 6 |
+
MKTPEDRVFRATDEYSDFVMACRYKGNEREFVIASHDKLNEAQVETLTSYLSGEWFKKTYITGIMNDSDGVLSQHEEYGDEVFCQPLDELRVDRYIMMV
|
data/fasta/some_proteins.fasta
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
>UniRef50_A0A1E3NP16
|
| 2 |
+
AVIYYRFRSQKPDHIATIKFDGTGLTVFELKRDIILANNLLHSTDVDIVLYSTEDIQDTKSWGYQNGGSSSAGERELDDDNEVVPRSTTVLVRRTMTPKKNKGNVQRYVAGKPRLQVSGTNSVNKSISLGNNVGGTMNFGDAATNGDEDDMIKKMFSVQDEQWSQQQDVMATATRVDNFRTNVNEPVPEYYICYKCGEKGKHHIKNCPKNNDPNWEGVRVRKTTGIPKSHLKAIENPEDTIRDSNSSGNTTYMVNDEGKYVVAVADTKAWEKYQKTKKGESGGYLNGDVDVDDGELKDPETGKLWKSPVRIPCCNKIFSRKIIEDKLIDSDFTCPSCGKEQIYLDTLVADEELQAKVDEYVKNLSENKNNDGNSPKRRQVNPAGATANTSQLPQIPMMPMPPINMQMPPMNIGMPPFMPFMPMPGMNP
|
| 3 |
+
>UniRef50_UPI000836A30F
|
| 4 |
+
MTLRTLLALSILALAAAATVQARPGAPPCSPLGLKYQPGACEKWKREHPDVNPDGVVQTVTIVNNSSSVLGGYVTFWHANNEHTDVDLPGVKPGETWTANGSWTVGQAPYYLLYSSFQDSYGDPVTFYAVPISKYPALAKKLPPEPDNCQSNHFRMVFGDGPQYVYEQHSGAVVTGGQTDKNTLCQILGCPTGGSTAGGLNTQNRTTSRSAPQPVYFRSCDP
|
| 5 |
+
>UniRef50_A0A2G8L8Y3
|
| 6 |
+
MAQKRYEENLSPYAELFRSKLIEDFHLLESFDEHGKSDAPKYYSKDFEDPARQDKMMLENPHGLVKFQVYSRKEPGEHFMLVLILSNSIALGLQAEVSESDDPKFAGLKLALDIFDYCSLFLFMVEIILKWIDNFWSFWSDNWNIFDFAVTVGSFVPEIINFFAGDIGGSMVRVIVRNLRVFRILRSLKMVSRFRQVRLIALAIGKAFSAITFIMLLLFTFLYIFAITGIIFFDTYTRSERQDLKYKDSFRSLPRAMITLFQLFTLDQWYKLLNDMWKVMDSMIPLGYIILWICIGSFIFRNVFVGIMVNNFQSIRNDLFEEVKEQEAARQIIQDTEKFNEELSRQEKKLNANRRGTLYQSPTVQPPKPNQPQPSQLAGLDNSETDEQSVSQEDESNTDGQTSLSGTDSYDLLGESSDSLFRRSSDGMIDKDKLSTNWEKTVHDNLTLLTSTPSETLWPRDTLFRYFQLMESLMENLQERQDLQDLAYHSLLQIFDSFDTSA
|
| 7 |
+
>UniRef50_A0A1D5ZRM3
|
| 8 |
+
MPCVAHECHPRLPAANHCRSLSCLGTPAAGWSSGDDDREEDELDTKQVILNEMRNREMRKRSSRCSVDSPTLSGAFAWSFTPLHPRSSIEKVSCTEEEKEAASDSDNESEAFFSVKSFFTRSTSRAATVASSTDMDPPATWEGLRGCEGWPFGLCP
|
| 9 |
+
>UniRef50_UPI0003108055
|
| 10 |
+
MPADAREYLESKHATRRFDRPAEVAGVVAFLLSDDTSFVIGAGYLVDGGYTALRAARGRLGPRRQAAPAVKLLPNTDSPR
|
| 11 |
+
>UniRef50_A0A223SCH7
|
| 12 |
+
MGPPRWWKGITGLAAVVHRADPEDKADLYAKMGLYLEYHPETRIVEARIKPRLHDVCESKVSEGGLEPPCP
|
| 13 |
+
>UniRef50_A0A090SUK6
|
| 14 |
+
MKTPEDRVFRATDEYSDFVMACRYKGNEREFVIASHDKLNEAQVETLTSYLSGEWFKKTYITGIMNDSDGVLSQHEEYGDEVFCQPLDELRVDRYIMMV
|
| 15 |
+
>UniRef50_V4AGU2
|
| 16 |
+
MHLGSIYLMVVLLIYFAYTDDRKERENVDVINPEENLVQDDEQYVGDSTENIEKSGSEEEEEDKEAIEEEEDEEEELNYRYIPEPAQDIVDNGKKYIQVHCSFKQDESLIRHPSNCSRYFVCSYGVVEEMPVCDDGEVFSIQVSECVKKGSENDDCDKLPFDSPPEITRGTQPSLIWHPRHKSPRSQFRQPTTLQMKVPHIELESFTCSATGKVLSHHSENCAWYYNCSAHPDAVMQTFYSGFIMECPYPQLFSTETKQCEDFEDVKCGDRYEPKSPCDYRANHCHETSHCIPCWVRYASCLELPDGLNPWSELEWKPFFVECYKERTVFQGVCDKSAVFSPLTRACETPYSIPRQHGGWRPVCDGRRDGIYADEYGRCDIYYVCKGYIFTGFFRCEKGEMFNPVISICQKPEAVPYPCGDLEMPNICESSLNGYHLDMFGRCTHYFECKDQQLEGISMCPSGIFNPELQICESSRDQPKPCGNLTNLCTHKNDGFHSDENDCTKVFQCERGLTMTSYDCSGSVRTECDVCNTPTECNDKPNGLYPNLKEGVGYYYDCVRSQIQNHYKCDKEKGGPIFNPVKQRCFYPEDLCKEVFSLKIAW
|
| 17 |
+
>UniRef50_R5PKX9
|
| 18 |
+
MQGGEQDVFEHRQVREKVIALKNHADAAAQGAAEFERLSFEQDVAALDGFETDQAAQKRGFAAARRPENHRDFFVVKREVDAVENHSVAELLYETARFQNNVIGHFYAFHFFSRALAASDTGQHARK
|
| 19 |
+
>UniRef50_UPI0003674933
|
| 20 |
+
MKKKEDILNLEHTLLPWMGRTMKVLDYFIGDFLNLKGIELTKVQWILLKKLNEQNGQPQQNLAFLTNRDKASLARLITTMEKKKLVERIPSKIDGRINHIFITKHGCEILQKSAPVIEKVVGCIQEGISPEEIETVIKVMQKVNNNINRASN
|
| 21 |
+
>UniRef50_E9K9Y4
|
| 22 |
+
MADNVLMAYHIVHDPDERAKHVLNTKKLYKWRITEKTKGTPVVGNVALVQTQFAKRTPVMIYATKEVANDLSDLQPVKVFTNNRDQETVNQTFDDLMR
|
| 23 |
+
>UniRef50_A0A2C9LWN7
|
| 24 |
+
MGKITGLLFFLFTSVRVTPSMKNTVNDIYRVRKDVLTKYRNTEEYDLGQRKGPLKQMDTRETRTPYGHFNSDTAFISPKNILKATRPLAFHLGNLKNQTSPCSTWNLTVDCSYKSLDHIESSWFPSNTTVLLLNNNKLVTLHNETFAQLTNLTRLDLSSNDIRRIDAGAFQGLHNLQELNLHMHCCNFTDHYSLESVFAPLRNLRILNAMHNSDVGVLTYSYTFLTRLPLLQSLSIDFDLDTLYCGPEFNDLKNLTFLQFSGQVMYIDDRSFQNVAQLKNLSMDHLSNINNISHNAFKPLSNLKVLTMYHVLLYVQEILSLLEPFQGRNMTEITLDTTTRTLTQVNPTRNGILTNHDTKYLMNICLESFTLIDNRIFYIKPDAVQNIYTWKKCLMHLYIASNPIQGNNFALIRLFTLDNLKSFTFINMFRACHEFQPFPQSSPPATRNVASSSISSQNNHYQKDTTSNQQQMIRHSPFSPYLDMIDENPYQLNIPNYIFISPSLQYMNFQRLVMSQSFEYHFILVGAQNVTSLDISDSGFYRFNGLMEGVSAIKTLIISGNDVSVLSVSFFDTFVSLENFAISSCKLDRDFISLNSRRIFQNHTRLQELDISSNSLNYLSQNTFSYNNRLMWLNMSGNQFKDIPFDLTNTPELQFLDIRFNSLTTIDETTAQQMDHLVTKSGKLEILLEGNVLSCSCSDLSFMRWMRMTLVTFDQNGNFTCMNTDGERKYTLDYSNLDSLWRECWGSFFLYFALIMLCLYCIGVFAVFITMRNKNFIVSFFLQLFGGFKLHSRRDYPVGVYIGYSDKDYQFPCKELRSFIESSLKLKTFLIDRDLIASVDKASGIIEALNASWRILLVCSKSFLKEDDWSMFTMRSAIYTQTPANPARVVVLVHKDCLPLLPPALLSSVNDENICAVSEWAMNYEMMQMLTTRLH
|
| 25 |
+
>UniRef50_Q9REE6
|
| 26 |
+
MSLRGRELLTSEERLELVRIPEDISEQELGRNFTLSNFDLELIKNRRRDYNRLGFAVQLCVLRFPGWSLNDAEPIPKKVLQHLARQLHVDPDCFSLYSSREA
|
| 27 |
+
>UniRef50_A0A226D4M8
|
| 28 |
+
MQKVINFPIWRRYYFSECGNCNDFRPDGVKKVHPPQEKSRTMDDEILAAPEVTIPFEPSDPSEVVVNLISSEEEDDDDVIQIVEEKSVDKAERQRRRQKKKDLWAARKLQRNKGQNVPLQTAWQRGPRPQETSSFPTPPQQSGGAQQKPLSPILISTAGSPNTSGAPTPANVSQQPTPTPSFVHTTASTSTHPEISLNINSDLALLIRLGPDGRPILTRVENVEQNNTSTSTPTTTRKLPPAPPPPKISFDTQTGESLLNGELITRPIIDITTDSPPSITHAATVSPQTSRTSGPPTLSPISPPPRTTQSNPAHPPPRYEPRKSRHPPRDPLASSSSSSSSSPSPPPTSRARHTSSANIPPPLEPLFLNTTQLIHLIKTCRKCEKSFPTRCDGVIHQKKEHNRKHCPVCFLTLSRHGNTYKDHLNMYHALEGDKEMVVCPFCAVEHSFDGLYNHIGRSHLIPVESKGESEHEVIFSVAPSPQSNGHQTRSVTQGNTPPKNDTNSPPNLEKRRPGPASKTRKTTNDPVPSTSRTGLICHKYVPDVETPPSKAGRNFESRAGRNFESRNVYPPATNRLNPPRNKSPPRNKNLPRNKSPPRNKSLPRNKTPPPSSSRSSSSRSVSNNLRRKNPTPPPPTQPPPKKVAKPDEAGINEKIQAAIKAVNARVHIERSVHHPNNRSDREIPSTSRTVTSRHKVPTSKTSGNTSVRKDPSPPPPLQTPPKTTNLELSKVQKARIVEDVRSIVRDVRITRVLDDGEVPSTSRAVEEEKKKEEKKNETRARLPRSSRVGERSSGYFQMAEGIDFSPENPTPRSKDLKAIHISKLNLIYQQLKCYPDTSVIANVAKECGVEIPVVAKWFTKKHMEYCQKTQQRKRKRKPPELR
|
| 29 |
+
>UniRef50_UPI000B82D8F0
|
| 30 |
+
MGGLHLIELRNVNIEFDKKLIEDGTIKIYDGKITAIIGESGSGKTSLLYLLGLISSNHRYLYSFDDVTLDLSNDFEMSRIRKQKIGYIFQDNNLVENLTIFENIRLSATIAGINITDKEIKSYLEFVELGYIDSNHYPRKLSGGERQRVAIACALAKQPELILADEPTSALDTVNSEIIMGIFKKIAHKDKKKIVIATHNDRIYNEADVIYEIKNNKIQLVKGESSNESSKKEPEDYDNNVKLTPRFYFDYAIKTSRKGRFAKNLMIVLSAIAIAFSSVMYNFGDTFVKEQEKLMDAISDKEIFVVNMTAPLNTILDIDENLSIQDKDAELLRNISYVDTIYPYFEFRSIGYPLINETEASEGYIVVSKGQKEEKYTFAESKDNPYDKYVIIPYYPEQNLERRLKEKLSDESSDKVYISSQLAQLLGIENLKESVSLRVLTYVPIAQHETQMTVRPEGIVYEIDIDLSKVVELDLKIEGILDESVRNRYSNSGNNAIYVPYHKMQMILTQTQNSATIDTNLEYIEWRPSAFVVFAKSYNDVGLVIERVSSINPNFRAVSEYQDIESMNAIVKNTREIGLVIVIVILIIIFLLMSIIHMNHILDRKYEISLLKANGLTKIELTKLVSVESLRHVFLVSLISSVISLVVTKVMNLLFEEIA
|
data/inverse_folding/5YH2.cif
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
data/inverse_folding/5YH2.pdb
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
data/inverse_folding/5YH2_mutated_seqs.fasta
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
>mut_1
|
| 2 |
+
SVLQSLFEHPLYRTVLPDLTEEDTLFNLNAEIRLYPKAASESYPNWLRFHIGINRYELYSRHNPVIAALLRDLLSQKISSVGMKSGGTQLKLIMSFQNYGQALFKPMKQTREQETPPDFFYFSDFERHNAEIAAFHLDRILDFRRVPPVAGRLVNMTREIRDVTRDKKLWRTFFVSPANNICFYGECSYYCSTEHALCGKPDQIEGSLAAFLPDLALAKRKTWRNPWRRSYHKRKKAEWEVDPDYCDEVKQTPPYDRGTRLLDIMDMTIFDFLMGNMDRHHYETFEKFGNDTFIIHLDNGRGFGKHSHDEMSILVPLTQCCRVKRSTYLRLQLLAKEEYKLSSLMEESLLQDRLVPVLIKPHLEALDRRLRLVLKVLSDCVEKDGFSAVVENDLD
|
| 3 |
+
>mut_2
|
| 4 |
+
DVLQSLFEHPLYRTVLPDLTEEDTLFNLNAEIRLYPKAASESYPNWLRFHIGINRYELYSRHNPVIAALLRDLLSQKISSVGMKSGGTQLKLIMSFQNYGQALFKPMKQTREQETPPDFFYFSDFERHNAEIAAFHLDRILDFRRVPPVAGRLVNMTREIRDVTRDKKLWRTFFVSPANNICFYGECSYYCSTEHALCGKPDQIEGSLAAFLPDLALAKRKTWRNPWRRSYHKRKKAEWEVDPDYCDEVKQTPPYDRGTRLLDIMDMTIFDFLMGNMDRHHYETFEKFGNDTFIIHLDNGRGFGKHSHDEMSILVPLTQCCRVKRSTYLRLQLLAKEEYKLSSLMEESLLQDRLVPVLIKPHLEALDRRLRLVLKVLSDCVEKDGFSAVVENDLD
|
| 5 |
+
>mut_3
|
| 6 |
+
EVLQSLFEHPLYRTVLPDLTEEDTLFNLNAEIRLYPKAASESYPNWLRFHIGINRYELYSRHNPVIAALLRDLLSQKISSVGMKSGGTQLKLIMSFQNYGQALFKPMKQTREQETPPDFFYFSDFERHNAEIAAFHLDRILDFRRVPPVAGRLVNMTREIRDVTRDKKLWRTFFVSPANNICFYGECSYYCSTEHALCGKPDQIEGSLAAFLPDLALAKRKTWRNPWRRSYHKRKKAEWEVDPDYCDEVKQTPPYDRGTRLLDIMDMTIFDFLMGNMDRHHYETFEKFGNDTFIIHLDNGRGFGKHSHDEMSILVPLTQCCRVKRSTYLRLQLLAKEEYKLSSLMEESLLQDRLVPVLIKPHLEALDRRLRLVLKVLSDCVEKDGFSAVVENDLD
|
| 7 |
+
>mut_4
|
| 8 |
+
VVLQSLFEHPLYRTVLPDLTEEDTLFNLNAEIRLYPKAASESYPNWLRFHIGINRYELYSRHNPVIAALLRDLLSQKISSVGMKSGGTQLKLIMSFQNYGQALFKPMKQTREQETPPDFFYFSDFERHNAEIAAFHLDRILDFRRVPPVAGRLVNMTREIRDVTRDKKLWRTFFVSPANNICFYGECSYYCSTEHALCGKPDQIEGSLAAFLPDLALAKRKTWRNPWRRSYHKRKKAEWEVDPDYCDEVKQTPPYDRGTRLLDIMDMTIFDFLMGNMDRHHYETFEKFGNDTFIIHLDNGRGFGKHSHDEMSILVPLTQCCRVKRSTYLRLQLLAKEEYKLSSLMEESLLQDRLVPVLIKPHLEALDRRLRLVLKVLSDCVEKDGFSAVVENDLD
|
data/inverse_folding/example.json
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
data/variant_prediction/BLAT_ECOLX_Ranganathan2015.csv
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
data/variant_prediction/aggregated_rho.csv
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
,valid,valid,valid,full,full,full,test,test,test
|
| 2 |
+
,rho,rho_boot_mean,rho_boot_std,rho,rho_boot_mean,rho_boot_std,rho,rho_boot_mean,rho_boot_std
|
| 3 |
+
prediction_name,,,,,,,,,
|
| 4 |
+
DeepSequence (published),0.5602602238441781,0.5612750863332869,0.011985038405770958,0.5136039187155506,0.512778392574446,0.017143498537203965,0.4985534977063157,0.4971342978135294,0.01880751793444042
|
| 5 |
+
DeepSequence (published) - single,0.5430017493589612,0.5443701641109099,0.012423838414787655,0.5020580499120493,0.5011407877592315,0.017404933590781577,0.4888504049291744,0.4871958276457871,0.01901173848626349
|
| 6 |
+
DeepSequence (replicated),0.5635921424785667,0.5646995390005713,0.01208513622243054,0.5201346211408833,0.5192886065212002,0.01673076687983822,0.5061160658706628,0.5046399186246291,0.018229357414485857
|
| 7 |
+
ESM-1b,0.5666981361139574,0.5676141841913277,0.012025131590764206,0.4585307340241866,0.45722552072809847,0.019420008294609183,0.42363802367264763,0.42161627444963734,0.021805452392623693
|
| 8 |
+
ESM-1v (+further training),0.5979754992703865,0.5985949225433556,0.011700006848349927,0.5382829634571142,0.5368211143294155,0.01685153619316537,0.5190273067431552,0.516894079421693,0.018513319852783258
|
| 9 |
+
ESM-1v (zero shot),0.593067646900253,0.5941859676949833,0.012216511625608212,0.5089550689778174,0.5077512066859666,0.01778501791633543,0.48182197932541876,0.47986902571531576,0.019581310268182918
|
| 10 |
+
EVMutation (published),0.5490624796568302,0.5497402994229479,0.012972877244416833,0.508419480578392,0.5068193077204962,0.017724141740786323,0.49530883571437995,0.4929738265261569,0.01925680770735712
|
| 11 |
+
EVMutation (replicated),0.5512073418060958,0.5516069925840847,0.012682710408380227,0.5112223872556211,0.509417510409684,0.01815069563293862,0.49832401481998395,0.4958080000308451,0.019914561834409074
|
| 12 |
+
MSA Transformer,0.5987868160929384,0.5996093743584658,0.011619082338376548,0.5422875260142875,0.5414621273787668,0.016736474302820666,0.5240619485695612,0.5227049509337023,0.01838724590425425
|
| 13 |
+
PSSM,0.4633509799617207,0.46414678680632565,0.013608999290250463,0.4604575410937561,0.45896520887271747,0.018669177520973506,0.45952417371699333,0.4572937321199404,0.020301493079271263
|
| 14 |
+
ProtBERT-BFD,0.5166978551105863,0.5173010932587435,0.0135134115364477,0.42751993235504165,0.4278749478751994,0.020253227983813266,0.39875286049841424,0.39902780420308837,0.022427362321673118
|
| 15 |
+
TAPE,0.16039305189488504,0.16335386054336812,0.015534139865906533,0.17144437052454356,0.1748040435344602,0.023020918331052527,0.17500931201798176,0.1784976509509415,0.025436008158518972
|
| 16 |
+
UniRep,0.17009503694214162,0.1687392944334104,0.018385140300946963,0.15554362973563243,0.15406970922460442,0.022971233340804673,0.15084962741095204,0.14933758496369925,0.024450618192371674
|
| 17 |
+
gt,1.0,1.0,0.0,1.0,1.0,0.0,1.0,1.0,0.0
|
data/variant_prediction/aggregated_rho_round3.csv
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
,valid,valid,valid,full,full,full,test,test,test
|
| 2 |
+
,rho,rho_boot_mean,rho_boot_std,rho,rho_boot_mean,rho_boot_std,rho,rho_boot_mean,rho_boot_std
|
| 3 |
+
prediction_name,,,,,,,,,
|
| 4 |
+
DeepSequence (published),0.56,0.561,0.012,0.514,0.513,0.017,0.499,0.497,0.019
|
| 5 |
+
DeepSequence (published) - single,0.543,0.544,0.012,0.502,0.501,0.017,0.489,0.487,0.019
|
| 6 |
+
DeepSequence (replicated),0.564,0.565,0.012,0.52,0.519,0.017,0.506,0.505,0.018
|
| 7 |
+
ESM-1b,0.567,0.568,0.012,0.459,0.457,0.019,0.424,0.422,0.022
|
| 8 |
+
ESM-1v (+further training),0.598,0.599,0.012,0.538,0.537,0.017,0.519,0.517,0.019
|
| 9 |
+
ESM-1v (zero shot),0.593,0.594,0.012,0.509,0.508,0.018,0.482,0.48,0.02
|
| 10 |
+
EVMutation (published),0.549,0.55,0.013,0.508,0.507,0.018,0.495,0.493,0.019
|
| 11 |
+
EVMutation (replicated),0.551,0.552,0.013,0.511,0.509,0.018,0.498,0.496,0.02
|
| 12 |
+
MSA Transformer,0.599,0.6,0.012,0.542,0.541,0.017,0.524,0.523,0.018
|
| 13 |
+
PSSM,0.463,0.464,0.014,0.46,0.459,0.019,0.46,0.457,0.02
|
| 14 |
+
ProtBERT-BFD,0.517,0.517,0.014,0.428,0.428,0.02,0.399,0.399,0.022
|
| 15 |
+
TAPE,0.16,0.163,0.016,0.171,0.175,0.023,0.175,0.178,0.025
|
| 16 |
+
UniRep,0.17,0.169,0.018,0.156,0.154,0.023,0.151,0.149,0.024
|
| 17 |
+
gt,1.0,1.0,0.0,1.0,1.0,0.0,1.0,1.0,0.0
|
data/variant_prediction/rho_pp.csv
ADDED
|
@@ -0,0 +1,575 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
,protein_name,prediction_name,rho,rho_boot_mean,rho_boot_std
|
| 2 |
+
112,BLAT_ECOLX_Ranganathan2015,gt,1.0,1.0,0.0
|
| 3 |
+
113,BLAT_ECOLX_Ranganathan2015,MSA Transformer,0.7734667485457659,0.7738027379896001,0.005810229642357195
|
| 4 |
+
114,BLAT_ECOLX_Ranganathan2015,PSSM,0.614150958806157,0.6140369220507402,0.00914005554519492
|
| 5 |
+
115,BLAT_ECOLX_Ranganathan2015,EVMutation (published),0.7176707275279989,0.7184384489293669,0.005172838583114061
|
| 6 |
+
116,BLAT_ECOLX_Ranganathan2015,DeepSequence (published) - single,0.755008978954388,0.7561275888133361,0.006397359248039358
|
| 7 |
+
117,BLAT_ECOLX_Ranganathan2015,DeepSequence (published),0.7755001128993768,0.7754839719498734,0.0059058513297401
|
| 8 |
+
118,BLAT_ECOLX_Ranganathan2015,ESM-1v (zero shot),0.7251281855227297,0.7252663698494137,0.005817208726713974
|
| 9 |
+
119,BLAT_ECOLX_Ranganathan2015,ESM-1v (+further training),0.7713005999939375,0.7711664330412893,0.005154671622503008
|
| 10 |
+
120,BLAT_ECOLX_Ranganathan2015,DeepSequence (replicated),0.7907734920246668,0.7896796440415632,0.004950863463811736
|
| 11 |
+
121,BLAT_ECOLX_Ranganathan2015,EVMutation (replicated),0.7409416788010579,0.7414034481390834,0.004511986638702662
|
| 12 |
+
122,BLAT_ECOLX_Ranganathan2015,ProtBERT-BFD,0.5066624675266317,0.5086811085713664,0.008432655997093638
|
| 13 |
+
123,BLAT_ECOLX_Ranganathan2015,TAPE,0.1437575573041793,0.14718890398398213,0.00854664176422607
|
| 14 |
+
124,BLAT_ECOLX_Ranganathan2015,UniRep,0.03205236543975054,0.03109080054090812,0.01290097463153492
|
| 15 |
+
125,BLAT_ECOLX_Ranganathan2015,ESM-1b,0.7244733058050135,0.7244715086369378,0.0054093172279529814
|
| 16 |
+
322,PABP_YEAST_Fields2013-doubles,gt,1.0,1.0,0.0
|
| 17 |
+
323,PABP_YEAST_Fields2013-doubles,MSA Transformer,0.7092749798819215,0.7083666356138891,0.0028152329308467395
|
| 18 |
+
324,PABP_YEAST_Fields2013-doubles,PSSM,0.5022876340276876,0.5009430131340434,0.003914000389196363
|
| 19 |
+
325,PABP_YEAST_Fields2013-doubles,EVMutation (published),0.6334326213147348,0.6319953143501386,0.0031257311261953294
|
| 20 |
+
326,PABP_YEAST_Fields2013-doubles,DeepSequence (published) - single,0.697950719553739,0.6969873459722575,0.002722620907521595
|
| 21 |
+
327,PABP_YEAST_Fields2013-doubles,DeepSequence (published),0.7135955622146342,0.7126803646172054,0.0026005801571960326
|
| 22 |
+
328,PABP_YEAST_Fields2013-doubles,ESM-1v (zero shot),0.6808954491918657,0.6802766119879265,0.003337373999951867
|
| 23 |
+
329,PABP_YEAST_Fields2013-doubles,ESM-1v (+further training),0.6724484972163407,0.6715887930967597,0.003131790856684628
|
| 24 |
+
330,PABP_YEAST_Fields2013-doubles,DeepSequence (replicated),0.6690002200834452,0.6682783362133506,0.002924928420789724
|
| 25 |
+
331,PABP_YEAST_Fields2013-doubles,EVMutation (replicated),0.6370081500864611,0.6365136199984236,0.0033115051939607903
|
| 26 |
+
332,PABP_YEAST_Fields2013-doubles,ProtBERT-BFD,0.7018606830370693,0.7013726492421438,0.0029126542395483735
|
| 27 |
+
333,PABP_YEAST_Fields2013-doubles,TAPE,0.08509310570891564,0.0848841242307348,0.0055652064474624435
|
| 28 |
+
334,PABP_YEAST_Fields2013-doubles,UniRep,0.25423830212504706,0.2528601717205464,0.005044020233400653
|
| 29 |
+
335,PABP_YEAST_Fields2013-doubles,ESM-1b,0.6989229474973527,0.6986292605564589,0.0033935909980897867
|
| 30 |
+
0,AMIE_PSEAE_Whitehead,gt,1.0,1.0,0.0
|
| 31 |
+
1,AMIE_PSEAE_Whitehead,MSA Transformer,0.6078201305487886,0.6074995010322104,0.006655174664199262
|
| 32 |
+
2,AMIE_PSEAE_Whitehead,PSSM,0.3851814980540226,0.3857114471207458,0.01419582618409421
|
| 33 |
+
3,AMIE_PSEAE_Whitehead,EVMutation (published),0.5482672326862741,0.5494300599441264,0.009296902066198478
|
| 34 |
+
4,AMIE_PSEAE_Whitehead,DeepSequence (published) - single,0.6192004998182683,0.6235042563787871,0.009786304100603813
|
| 35 |
+
5,AMIE_PSEAE_Whitehead,DeepSequence (published),0.64337902253515,0.6466208891535095,0.008118407538893896
|
| 36 |
+
6,AMIE_PSEAE_Whitehead,ESM-1v (zero shot),0.6666021525370552,0.6679182566255217,0.008613681679123195
|
| 37 |
+
7,AMIE_PSEAE_Whitehead,ESM-1v (+further training),0.671863659978349,0.6738279065439714,0.008391215501243852
|
| 38 |
+
8,AMIE_PSEAE_Whitehead,DeepSequence (replicated),0.6459861864504847,0.6488672280630794,0.007018822987447003
|
| 39 |
+
9,AMIE_PSEAE_Whitehead,EVMutation (replicated),0.5609325769621947,0.561649692444916,0.008422893320380829
|
| 40 |
+
10,AMIE_PSEAE_Whitehead,ProtBERT-BFD,0.6338505619537509,0.6354477176484321,0.009554450012056636
|
| 41 |
+
11,AMIE_PSEAE_Whitehead,TAPE,0.10859786063312615,0.11076584881696006,0.015015379880043802
|
| 42 |
+
12,AMIE_PSEAE_Whitehead,UniRep,0.07739084999605612,0.073724376050283,0.01240093912413262
|
| 43 |
+
13,AMIE_PSEAE_Whitehead,ESM-1b,0.5853972837117107,0.5836827247268739,0.009689198977483172
|
| 44 |
+
476,TIM_SULSO_b0,gt,1.0,1.0,0.0
|
| 45 |
+
477,TIM_SULSO_b0,MSA Transformer,0.652792451949853,0.6557516749540702,0.01600526744858049
|
| 46 |
+
478,TIM_SULSO_b0,PSSM,0.5593694164359105,0.566935653048683,0.01690630663394768
|
| 47 |
+
479,TIM_SULSO_b0,EVMutation (published),0.586140631338893,0.5919185710638765,0.01641131140995354
|
| 48 |
+
480,TIM_SULSO_b0,DeepSequence (published) - single,0.5440966818223795,0.5487337742437185,0.015747346163591917
|
| 49 |
+
481,TIM_SULSO_b0,DeepSequence (published),0.5505948722659953,0.5565402351008099,0.014555638377778407
|
| 50 |
+
482,TIM_SULSO_b0,ESM-1v (zero shot),0.6424600791408842,0.647621332390191,0.016028029413886244
|
| 51 |
+
483,TIM_SULSO_b0,ESM-1v (+further training),0.6528241665901272,0.6555645155980578,0.015379852940306115
|
| 52 |
+
484,TIM_SULSO_b0,DeepSequence (replicated),0.58320310154665,0.5889306881826475,0.015779505439458753
|
| 53 |
+
485,TIM_SULSO_b0,EVMutation (replicated),0.5887928613337577,0.5940831887831108,0.016569303240529226
|
| 54 |
+
486,TIM_SULSO_b0,ProtBERT-BFD,0.6317983649729998,0.6345885687258263,0.01602936969330677
|
| 55 |
+
487,TIM_SULSO_b0,TAPE,0.5532247068671533,0.5587646824504885,0.019898766536311598
|
| 56 |
+
488,TIM_SULSO_b0,UniRep,0.16614520326579557,0.17309558518510257,0.03137269514815842
|
| 57 |
+
489,TIM_SULSO_b0,ESM-1b,0.6237553534772002,0.6315291160092146,0.015666927222771784
|
| 58 |
+
266,KKA2_KLEPN_Mikkelsen2014,gt,1.0,1.0,0.0
|
| 59 |
+
267,KKA2_KLEPN_Mikkelsen2014,MSA Transformer,0.6483744764229661,0.6501362354726463,0.008392887010519141
|
| 60 |
+
268,KKA2_KLEPN_Mikkelsen2014,PSSM,0.33148417825671017,0.3321644636508253,0.00954461359833698
|
| 61 |
+
269,KKA2_KLEPN_Mikkelsen2014,EVMutation (published),0.6040252893227205,0.6046576561680694,0.007611417821309178
|
| 62 |
+
270,KKA2_KLEPN_Mikkelsen2014,DeepSequence (published) - single,0.6428015918045534,0.646183322009227,0.006466715772852643
|
| 63 |
+
271,KKA2_KLEPN_Mikkelsen2014,DeepSequence (published),0.6622233077856657,0.6647874075249056,0.007006878882782913
|
| 64 |
+
272,KKA2_KLEPN_Mikkelsen2014,ESM-1v (zero shot),0.627837107524989,0.6303585274093482,0.008597860670353218
|
| 65 |
+
273,KKA2_KLEPN_Mikkelsen2014,ESM-1v (+further training),0.6540013975518588,0.6568513820339432,0.008249320892729436
|
| 66 |
+
274,KKA2_KLEPN_Mikkelsen2014,DeepSequence (replicated),0.6708322568508106,0.6736802365189244,0.007635987315614941
|
| 67 |
+
275,KKA2_KLEPN_Mikkelsen2014,EVMutation (replicated),0.6078971023630376,0.6084473779526628,0.009849549243896777
|
| 68 |
+
276,KKA2_KLEPN_Mikkelsen2014,ProtBERT-BFD,0.5441498820889966,0.5461574522717653,0.011666264975033773
|
| 69 |
+
277,KKA2_KLEPN_Mikkelsen2014,TAPE,0.19644765859472593,0.19660401466689767,0.013538150129702716
|
| 70 |
+
278,KKA2_KLEPN_Mikkelsen2014,UniRep,0.24229449050660715,0.2442377698228683,0.014857522651962994
|
| 71 |
+
279,KKA2_KLEPN_Mikkelsen2014,ESM-1b,0.5796639591499797,0.5828984127122095,0.009462666946528803
|
| 72 |
+
182,DLG4_RAT_Ranganathan2012,gt,1.0,1.0,0.0
|
| 73 |
+
183,DLG4_RAT_Ranganathan2012,MSA Transformer,0.5106330149144778,0.5128948633920939,0.020360553500470727
|
| 74 |
+
184,DLG4_RAT_Ranganathan2012,PSSM,0.4603978833849677,0.4625263978112141,0.023120281422982173
|
| 75 |
+
185,DLG4_RAT_Ranganathan2012,EVMutation (published),0.5352653453343902,0.539345546690929,0.02299279306281621
|
| 76 |
+
186,DLG4_RAT_Ranganathan2012,DeepSequence (published) - single,0.5918364209116883,0.5957477584911891,0.01995659395689766
|
| 77 |
+
187,DLG4_RAT_Ranganathan2012,DeepSequence (published),0.6036625648098791,0.6070883056488765,0.020478051115311577
|
| 78 |
+
188,DLG4_RAT_Ranganathan2012,ESM-1v (zero shot),0.5939968225123472,0.596847197984075,0.017630058333348964
|
| 79 |
+
189,DLG4_RAT_Ranganathan2012,ESM-1v (+further training),0.5682242782581113,0.5694370162367897,0.018958485435275826
|
| 80 |
+
190,DLG4_RAT_Ranganathan2012,DeepSequence (replicated),0.5765783481552431,0.5780455229510647,0.020809463738300338
|
| 81 |
+
191,DLG4_RAT_Ranganathan2012,EVMutation (replicated),0.5241180720329418,0.5261248836538202,0.02186178951891566
|
| 82 |
+
192,DLG4_RAT_Ranganathan2012,ProtBERT-BFD,0.5595215663542064,0.5614010576594576,0.01854665905518769
|
| 83 |
+
193,DLG4_RAT_Ranganathan2012,TAPE,0.013351052100670802,0.023584538183512672,0.014457178947554198
|
| 84 |
+
194,DLG4_RAT_Ranganathan2012,UniRep,0.3016230099651694,0.29971140046709394,0.027613438646412317
|
| 85 |
+
195,DLG4_RAT_Ranganathan2012,ESM-1b,0.5275305911412679,0.5302881928240022,0.01742943283364256
|
| 86 |
+
532,UBC9_HUMAN_Roth2017,gt,1.0,1.0,0.0
|
| 87 |
+
533,UBC9_HUMAN_Roth2017,MSA Transformer,0.5257424624114496,0.5264407612968436,0.016782723059713636
|
| 88 |
+
534,UBC9_HUMAN_Roth2017,PSSM,0.4252037519097337,0.42647455982971144,0.01848680680775899
|
| 89 |
+
535,UBC9_HUMAN_Roth2017,EVMutation (published),0.509842177492847,0.5077129136778502,0.015575205557209867
|
| 90 |
+
536,UBC9_HUMAN_Roth2017,DeepSequence (published) - single,0.5301569663083602,0.5321597182510774,0.017474789730172
|
| 91 |
+
537,UBC9_HUMAN_Roth2017,DeepSequence (published),0.5451981164854786,0.5458299698225401,0.01779569747351641
|
| 92 |
+
538,UBC9_HUMAN_Roth2017,ESM-1v (zero shot),0.5278002974052306,0.5289273564517684,0.0174313365381068
|
| 93 |
+
539,UBC9_HUMAN_Roth2017,ESM-1v (+further training),0.530438889646823,0.5308418048769536,0.016194450129423676
|
| 94 |
+
540,UBC9_HUMAN_Roth2017,DeepSequence (replicated),0.564757773228155,0.566254233293921,0.01584492457358362
|
| 95 |
+
541,UBC9_HUMAN_Roth2017,EVMutation (replicated),0.5197625999541963,0.5169223464706466,0.015797268774811208
|
| 96 |
+
542,UBC9_HUMAN_Roth2017,ProtBERT-BFD,0.4566745629330005,0.4597664455496374,0.01695356254093292
|
| 97 |
+
543,UBC9_HUMAN_Roth2017,TAPE,0.2663201366958923,0.2655109350197859,0.020940445702932447
|
| 98 |
+
544,UBC9_HUMAN_Roth2017,UniRep,0.027526620911384754,0.032226022213806015,0.0170540626567071
|
| 99 |
+
545,UBC9_HUMAN_Roth2017,ESM-1b,0.42880952407240114,0.4257117461019339,0.016052256587648167
|
| 100 |
+
56,BG505_env_Bloom2018,gt,1.0,1.0,0.0
|
| 101 |
+
57,BG505_env_Bloom2018,MSA Transformer,0.5171538292833168,0.5171496622518762,0.006910262108734762
|
| 102 |
+
58,BG505_env_Bloom2018,PSSM,0.4805043665958063,0.47934729964627765,0.006403736305762083
|
| 103 |
+
59,BG505_env_Bloom2018,EVMutation (published),0.4088382668800448,0.4081773036708733,0.005327774682093342
|
| 104 |
+
60,BG505_env_Bloom2018,DeepSequence (published) - single,0.17427055696697,0.17391089639228693,0.007096603606133151
|
| 105 |
+
61,BG505_env_Bloom2018,DeepSequence (published),0.17901824140808725,0.17897151771830583,0.007361446332203004
|
| 106 |
+
62,BG505_env_Bloom2018,ESM-1v (zero shot),0.5263381402665136,0.5258084748455352,0.007358753329943184
|
| 107 |
+
63,BG505_env_Bloom2018,ESM-1v (+further training),0.5320285787368926,0.5326341655547056,0.006038819273548771
|
| 108 |
+
64,BG505_env_Bloom2018,DeepSequence (replicated),0.12964060496065777,0.12952804062160664,0.009474191082563171
|
| 109 |
+
65,BG505_env_Bloom2018,EVMutation (replicated),0.4183486299186111,0.41871016990435506,0.006336285035457084
|
| 110 |
+
66,BG505_env_Bloom2018,ProtBERT-BFD,0.325305964247549,0.32240107597741696,0.007706083919970625
|
| 111 |
+
67,BG505_env_Bloom2018,TAPE,0.028456890112386356,0.03179954870869962,0.006177994317554592
|
| 112 |
+
68,BG505_env_Bloom2018,UniRep,0.20075668930719107,0.20277486226220803,0.008814544928765732
|
| 113 |
+
69,BG505_env_Bloom2018,ESM-1b,0.46213634322466174,0.4615123969304536,0.007864462687152629
|
| 114 |
+
462,SUMO1_HUMAN_Roth2017,gt,1.0,1.0,0.0
|
| 115 |
+
463,SUMO1_HUMAN_Roth2017,MSA Transformer,0.5159144148964154,0.5204033887826773,0.016144534346014247
|
| 116 |
+
464,SUMO1_HUMAN_Roth2017,PSSM,0.5068653918333971,0.5116066608485563,0.014073225487584034
|
| 117 |
+
465,SUMO1_HUMAN_Roth2017,EVMutation (published),0.3943527527312187,0.39862273161443174,0.0218398217088854
|
| 118 |
+
466,SUMO1_HUMAN_Roth2017,DeepSequence (published) - single,0.4546171147375774,0.4563868817701918,0.018789136591575727
|
| 119 |
+
467,SUMO1_HUMAN_Roth2017,DeepSequence (published),0.4817132258726107,0.48324298006415234,0.01745562156694833
|
| 120 |
+
468,SUMO1_HUMAN_Roth2017,ESM-1v (zero shot),0.4891908408067041,0.4902530587936492,0.02001929801145162
|
| 121 |
+
469,SUMO1_HUMAN_Roth2017,ESM-1v (+further training),0.4870961371636435,0.48754122676040595,0.017288489612331478
|
| 122 |
+
470,SUMO1_HUMAN_Roth2017,DeepSequence (replicated),0.4779470243180796,0.479960524595585,0.020147523090706877
|
| 123 |
+
471,SUMO1_HUMAN_Roth2017,EVMutation (replicated),0.39100280963861933,0.3956383413944518,0.022045400156456525
|
| 124 |
+
472,SUMO1_HUMAN_Roth2017,ProtBERT-BFD,0.4707613294700864,0.4702076997635277,0.020510642797657852
|
| 125 |
+
473,SUMO1_HUMAN_Roth2017,TAPE,0.15068074140877044,0.14631769856923166,0.02417823419968644
|
| 126 |
+
474,SUMO1_HUMAN_Roth2017,UniRep,0.08697581842056104,0.06864759400267187,0.02922305952665209
|
| 127 |
+
475,SUMO1_HUMAN_Roth2017,ESM-1b,0.4208939554865267,0.4235043067669399,0.019117696248176413
|
| 128 |
+
196,GAL4_YEAST_Shendure2015,gt,1.0,1.0,0.0
|
| 129 |
+
197,GAL4_YEAST_Shendure2015,MSA Transformer,0.5266956520744294,0.5236482827987523,0.016313958672329276
|
| 130 |
+
198,GAL4_YEAST_Shendure2015,PSSM,0.368064720312814,0.36172145092245883,0.020305140527647172
|
| 131 |
+
199,GAL4_YEAST_Shendure2015,EVMutation (published),0.5527897519391798,0.5471044481198163,0.02237497642639291
|
| 132 |
+
200,GAL4_YEAST_Shendure2015,DeepSequence (published) - single,0.42007796271168657,0.41396009878702655,0.019800914070488684
|
| 133 |
+
201,GAL4_YEAST_Shendure2015,DeepSequence (published),0.44771721216490296,0.44150522173269036,0.018572211283338934
|
| 134 |
+
202,GAL4_YEAST_Shendure2015,ESM-1v (zero shot),0.45042739409421084,0.4485824906124051,0.01733151555320306
|
| 135 |
+
203,GAL4_YEAST_Shendure2015,ESM-1v (+further training),0.4395287875677813,0.43649598169067916,0.018212972219452478
|
| 136 |
+
204,GAL4_YEAST_Shendure2015,DeepSequence (replicated),0.5272024171674746,0.5237709355239704,0.016265152112029255
|
| 137 |
+
205,GAL4_YEAST_Shendure2015,EVMutation (replicated),0.523268936970079,0.5165768570993756,0.01812112296069153
|
| 138 |
+
206,GAL4_YEAST_Shendure2015,ProtBERT-BFD,0.3363931685215737,0.33298715717786215,0.022821772133688727
|
| 139 |
+
207,GAL4_YEAST_Shendure2015,TAPE,0.05800080952303017,0.06811831080338804,0.02702340073359099
|
| 140 |
+
208,GAL4_YEAST_Shendure2015,UniRep,0.3119470194838534,0.3090243620686157,0.024570145461742788
|
| 141 |
+
209,GAL4_YEAST_Shendure2015,ESM-1b,0.615398097573459,0.6139141766482525,0.01616576617819578
|
| 142 |
+
84,BLAT_ECOLX_Ostermeier2014,gt,1.0,1.0,0.0
|
| 143 |
+
85,BLAT_ECOLX_Ostermeier2014,MSA Transformer,0.7774725340080285,0.7772991120484407,0.00583115239464695
|
| 144 |
+
86,BLAT_ECOLX_Ostermeier2014,PSSM,0.6266355490550037,0.6249558545704365,0.010963908722361101
|
| 145 |
+
87,BLAT_ECOLX_Ostermeier2014,EVMutation (published),0.7253493163946709,0.7259111779130355,0.007055247161974134
|
| 146 |
+
88,BLAT_ECOLX_Ostermeier2014,DeepSequence (published) - single,0.7573575626515066,0.7574787327674316,0.0052410410467141665
|
| 147 |
+
89,BLAT_ECOLX_Ostermeier2014,DeepSequence (published),0.7780042111143465,0.7782069969302521,0.004849028422585635
|
| 148 |
+
90,BLAT_ECOLX_Ostermeier2014,ESM-1v (zero shot),0.7233628349192526,0.7225479424696009,0.006683971493639809
|
| 149 |
+
91,BLAT_ECOLX_Ostermeier2014,ESM-1v (+further training),0.7730745420327815,0.7726874168606355,0.0065547231293585735
|
| 150 |
+
92,BLAT_ECOLX_Ostermeier2014,DeepSequence (replicated),0.7927294372907648,0.7925690818705499,0.005021676073847794
|
| 151 |
+
93,BLAT_ECOLX_Ostermeier2014,EVMutation (replicated),0.747447811602467,0.7485714564837528,0.0071001482782374
|
| 152 |
+
94,BLAT_ECOLX_Ostermeier2014,ProtBERT-BFD,0.4821130792800116,0.47870446935550176,0.010356473470947562
|
| 153 |
+
95,BLAT_ECOLX_Ostermeier2014,TAPE,0.14731886213718737,0.1477711259950593,0.015163340123327854
|
| 154 |
+
96,BLAT_ECOLX_Ostermeier2014,UniRep,0.03889602482478667,0.040737324507109665,0.01611318153937308
|
| 155 |
+
97,BLAT_ECOLX_Ostermeier2014,ESM-1b,0.7251755113400309,0.7251084679688187,0.007010136942265081
|
| 156 |
+
126,BLAT_ECOLX_Tenaillon2013,gt,1.0,1.0,0.0
|
| 157 |
+
127,BLAT_ECOLX_Tenaillon2013,MSA Transformer,0.758747218907931,0.7560608794742473,0.014270208324360757
|
| 158 |
+
128,BLAT_ECOLX_Tenaillon2013,PSSM,0.5914509988018589,0.584550802834145,0.019364487874982444
|
| 159 |
+
129,BLAT_ECOLX_Tenaillon2013,EVMutation (published),0.6976808741924794,0.6939730281305263,0.017209064919944853
|
| 160 |
+
130,BLAT_ECOLX_Tenaillon2013,DeepSequence (published) - single,0.7351880319385844,0.734362047270455,0.014525091995200967
|
| 161 |
+
131,BLAT_ECOLX_Tenaillon2013,DeepSequence (published),0.7543453371693124,0.7522080258926729,0.012721106563380765
|
| 162 |
+
132,BLAT_ECOLX_Tenaillon2013,ESM-1v (zero shot),0.705631894277465,0.6997739614439058,0.019936391958892526
|
| 163 |
+
133,BLAT_ECOLX_Tenaillon2013,ESM-1v (+further training),0.7468651561611359,0.7420410512131015,0.018012297742261523
|
| 164 |
+
134,BLAT_ECOLX_Tenaillon2013,DeepSequence (replicated),0.7636633966742921,0.7615069456529638,0.012651819062077643
|
| 165 |
+
135,BLAT_ECOLX_Tenaillon2013,EVMutation (replicated),0.7188975120768561,0.7181426689915423,0.015603675185522175
|
| 166 |
+
136,BLAT_ECOLX_Tenaillon2013,ProtBERT-BFD,0.5849974717911389,0.5759011621581035,0.02142157252628116
|
| 167 |
+
137,BLAT_ECOLX_Tenaillon2013,TAPE,0.12293837281461435,0.12415027252537572,0.02966599757403504
|
| 168 |
+
138,BLAT_ECOLX_Tenaillon2013,UniRep,0.018139031023161226,0.026517625360817247,0.022618042553652993
|
| 169 |
+
139,BLAT_ECOLX_Tenaillon2013,ESM-1b,0.7054857406191637,0.6998800269911201,0.021248434713645674
|
| 170 |
+
294,MTH3_HAEAESTABILIZED_Tawfik2015,gt,1.0,1.0,0.0
|
| 171 |
+
295,MTH3_HAEAESTABILIZED_Tawfik2015,MSA Transformer,0.6835339164997478,0.6812589032616372,0.015535718954003042
|
| 172 |
+
296,MTH3_HAEAESTABILIZED_Tawfik2015,PSSM,0.4416134495623428,0.44246894551424826,0.020085764953621237
|
| 173 |
+
297,MTH3_HAEAESTABILIZED_Tawfik2015,EVMutation (published),0.6941903664027441,0.692016316213505,0.013094374915061331
|
| 174 |
+
298,MTH3_HAEAESTABILIZED_Tawfik2015,DeepSequence (published) - single,0.7101794101084092,0.7063260455653937,0.01326393690807996
|
| 175 |
+
299,MTH3_HAEAESTABILIZED_Tawfik2015,DeepSequence (published),0.7267412245284101,0.7233050341503924,0.011532195128181771
|
| 176 |
+
300,MTH3_HAEAESTABILIZED_Tawfik2015,ESM-1v (zero shot),0.7028328471487627,0.6988674105054747,0.01389621848758316
|
| 177 |
+
301,MTH3_HAEAESTABILIZED_Tawfik2015,ESM-1v (+further training),0.710444924607402,0.7058556345404041,0.013349806491214776
|
| 178 |
+
302,MTH3_HAEAESTABILIZED_Tawfik2015,DeepSequence (replicated),0.7319377341571671,0.7284289432359438,0.011025526727213455
|
| 179 |
+
303,MTH3_HAEAESTABILIZED_Tawfik2015,EVMutation (replicated),0.6881944596927662,0.6851918594602512,0.014875805426091208
|
| 180 |
+
304,MTH3_HAEAESTABILIZED_Tawfik2015,ProtBERT-BFD,0.6227906481890101,0.6226488635471868,0.01368447324595496
|
| 181 |
+
305,MTH3_HAEAESTABILIZED_Tawfik2015,TAPE,0.28986222371790993,0.29059002837311587,0.02293939359468894
|
| 182 |
+
306,MTH3_HAEAESTABILIZED_Tawfik2015,UniRep,0.21256210891011498,0.20623088209322155,0.016982274395708104
|
| 183 |
+
307,MTH3_HAEAESTABILIZED_Tawfik2015,ESM-1b,0.6013150928569109,0.6001765775002926,0.016765716391031985
|
| 184 |
+
336,PABP_YEAST_Fields2013-singles,gt,1.0,1.0,0.0
|
| 185 |
+
337,PABP_YEAST_Fields2013-singles,MSA Transformer,0.6686627777483488,0.6635711675242917,0.016177764258807882
|
| 186 |
+
338,PABP_YEAST_Fields2013-singles,PSSM,0.42896284951548524,0.4291061605053958,0.02141741884779835
|
| 187 |
+
339,PABP_YEAST_Fields2013-singles,EVMutation (published),0.6013962392775869,0.5997811886851577,0.01156645100836508
|
| 188 |
+
340,PABP_YEAST_Fields2013-singles,DeepSequence (published) - single,0.6812656818721897,0.6786988061064501,0.015497646686186226
|
| 189 |
+
341,PABP_YEAST_Fields2013-singles,DeepSequence (published),0.6879032274975242,0.6849609026248084,0.013722212867231664
|
| 190 |
+
342,PABP_YEAST_Fields2013-singles,ESM-1v (zero shot),0.6658159648503742,0.6617537305293117,0.015156538272710452
|
| 191 |
+
343,PABP_YEAST_Fields2013-singles,ESM-1v (+further training),0.6465056114571746,0.6403467410293169,0.015004313697387745
|
| 192 |
+
344,PABP_YEAST_Fields2013-singles,DeepSequence (replicated),0.621237612823598,0.6166697742075684,0.015117873200550663
|
| 193 |
+
345,PABP_YEAST_Fields2013-singles,EVMutation (replicated),0.6004126589511687,0.5972505301682013,0.014433400233151502
|
| 194 |
+
346,PABP_YEAST_Fields2013-singles,ProtBERT-BFD,0.6590004474532792,0.6522426172055227,0.01761240430158242
|
| 195 |
+
347,PABP_YEAST_Fields2013-singles,TAPE,0.08173774797871515,0.07580827883401792,0.02537818685979441
|
| 196 |
+
348,PABP_YEAST_Fields2013-singles,UniRep,0.3524666785583584,0.3507280735011912,0.0214696561284629
|
| 197 |
+
349,PABP_YEAST_Fields2013-singles,ESM-1b,0.6826492897030101,0.6776229323965959,0.014065470938740474
|
| 198 |
+
378,POL_HV1N5-CA_Ndungu2014,gt,1.0,1.0,0.0
|
| 199 |
+
379,POL_HV1N5-CA_Ndungu2014,MSA Transformer,0.8910953880622985,0.8715091885859015,0.04404390170038043
|
| 200 |
+
380,POL_HV1N5-CA_Ndungu2014,PSSM,0.8027669847951657,0.7648376227138198,0.07156434462986615
|
| 201 |
+
381,POL_HV1N5-CA_Ndungu2014,EVMutation (published),0.814063406437493,0.770542797914026,0.07799856588047756
|
| 202 |
+
382,POL_HV1N5-CA_Ndungu2014,DeepSequence (published) - single,0.8237975570016259,0.79822473995615,0.059914597251614195
|
| 203 |
+
383,POL_HV1N5-CA_Ndungu2014,DeepSequence (published),0.8152651534207193,0.7889600095175417,0.06617658502045558
|
| 204 |
+
384,POL_HV1N5-CA_Ndungu2014,ESM-1v (zero shot),0.6512266902103299,0.6238138829808892,0.07766375006901825
|
| 205 |
+
385,POL_HV1N5-CA_Ndungu2014,ESM-1v (+further training),0.815024804024074,0.7869525208215408,0.05466301623393627
|
| 206 |
+
386,POL_HV1N5-CA_Ndungu2014,DeepSequence (replicated),0.820552840146915,0.7966023557532389,0.05723243614263114
|
| 207 |
+
387,POL_HV1N5-CA_Ndungu2014,EVMutation (replicated),0.8211537136385281,0.7735182879439364,0.08095098085359952
|
| 208 |
+
388,POL_HV1N5-CA_Ndungu2014,ProtBERT-BFD,0.38179501657099424,0.42193301482635154,0.14774279685397848
|
| 209 |
+
389,POL_HV1N5-CA_Ndungu2014,TAPE,0.3483864504373032,0.4104118824597043,0.1470038347598428
|
| 210 |
+
390,POL_HV1N5-CA_Ndungu2014,UniRep,0.4639945102236729,0.40093126150106306,0.16524010823471783
|
| 211 |
+
391,POL_HV1N5-CA_Ndungu2014,ESM-1b,0.5957059795852749,0.5731935627996381,0.13224460706985164
|
| 212 |
+
364,POLG_HCVJF_Sun2014,gt,1.0,1.0,0.0
|
| 213 |
+
365,POLG_HCVJF_Sun2014,MSA Transformer,0.6677478668298926,0.670497369164695,0.017151824473903992
|
| 214 |
+
366,POLG_HCVJF_Sun2014,PSSM,0.6494520970500091,0.6472164109404976,0.01636183923822566
|
| 215 |
+
367,POLG_HCVJF_Sun2014,EVMutation (published),0.5865270173010575,0.5896466823313951,0.019303754939295415
|
| 216 |
+
368,POLG_HCVJF_Sun2014,DeepSequence (published) - single,0.39251206867133814,0.39508591794495096,0.020227604662347038
|
| 217 |
+
369,POLG_HCVJF_Sun2014,DeepSequence (published),0.3713820411310244,0.3795469161150128,0.023014839527838928
|
| 218 |
+
370,POLG_HCVJF_Sun2014,ESM-1v (zero shot),0.6340055756536588,0.6335374345199196,0.01764641035648572
|
| 219 |
+
371,POLG_HCVJF_Sun2014,ESM-1v (+further training),0.5652424039602515,0.5708409099578081,0.020101066917986344
|
| 220 |
+
372,POLG_HCVJF_Sun2014,DeepSequence (replicated),0.46165721811412747,0.46807649417617975,0.022195221779086654
|
| 221 |
+
373,POLG_HCVJF_Sun2014,EVMutation (replicated),0.5825890447985209,0.5852998202243922,0.022749622221884737
|
| 222 |
+
374,POLG_HCVJF_Sun2014,ProtBERT-BFD,0.08677957966093554,0.07770559640019087,0.018629212118296944
|
| 223 |
+
375,POLG_HCVJF_Sun2014,TAPE,0.05680250795137183,0.04875383206148289,0.02707444904306108
|
| 224 |
+
376,POLG_HCVJF_Sun2014,UniRep,0.023755477003752395,0.018385016483602818,0.018204300138877978
|
| 225 |
+
377,POLG_HCVJF_Sun2014,ESM-1b,0.14790101977036282,0.1451007380223277,0.018527745632610403
|
| 226 |
+
308,P84126_THETH_b0,gt,1.0,1.0,0.0
|
| 227 |
+
309,P84126_THETH_b0,MSA Transformer,0.5799265252107147,0.5738614544298895,0.016977861401835232
|
| 228 |
+
310,P84126_THETH_b0,PSSM,0.5059938805045767,0.497875302076657,0.017450898377151254
|
| 229 |
+
311,P84126_THETH_b0,EVMutation (published),0.5762676414938405,0.5713927693726344,0.015545247017306097
|
| 230 |
+
312,P84126_THETH_b0,DeepSequence (published) - single,0.5267205050047176,0.5248192557448691,0.018977964279615622
|
| 231 |
+
313,P84126_THETH_b0,DeepSequence (published),0.5877949812163814,0.5848736179704858,0.015886804363744445
|
| 232 |
+
314,P84126_THETH_b0,ESM-1v (zero shot),0.5870635090422014,0.5811455597687403,0.01549045031439649
|
| 233 |
+
315,P84126_THETH_b0,ESM-1v (+further training),0.5790524141907541,0.572625780593036,0.014736663161466617
|
| 234 |
+
316,P84126_THETH_b0,DeepSequence (replicated),0.6038248556337414,0.602211740801349,0.013767217833566922
|
| 235 |
+
317,P84126_THETH_b0,EVMutation (replicated),0.5700921855537731,0.5640773353834833,0.016516084944527984
|
| 236 |
+
318,P84126_THETH_b0,ProtBERT-BFD,0.5721041244229742,0.5675746516094956,0.016572893593986743
|
| 237 |
+
319,P84126_THETH_b0,TAPE,0.530841865819399,0.524876249458913,0.02120781628171545
|
| 238 |
+
320,P84126_THETH_b0,UniRep,0.2274910400298911,0.22961913248092042,0.020560804448588488
|
| 239 |
+
321,P84126_THETH_b0,ESM-1b,0.5700277792841302,0.5653475783194437,0.014015440292458613
|
| 240 |
+
238,HSP82_YEAST_Bolon2016,gt,1.0,1.0,0.0
|
| 241 |
+
239,HSP82_YEAST_Bolon2016,MSA Transformer,0.48917822587769644,0.4911252194110343,0.010638436729624378
|
| 242 |
+
240,HSP82_YEAST_Bolon2016,PSSM,0.5080494707835187,0.5081989816141457,0.011630856503356157
|
| 243 |
+
241,HSP82_YEAST_Bolon2016,EVMutation (published),0.49012823437511943,0.4936437806547088,0.009824172602805919
|
| 244 |
+
242,HSP82_YEAST_Bolon2016,DeepSequence (published) - single,0.5292966677834544,0.529631038805717,0.010670673995645957
|
| 245 |
+
243,HSP82_YEAST_Bolon2016,DeepSequence (published),0.5345178740223454,0.5359585453318252,0.010405888846639616
|
| 246 |
+
244,HSP82_YEAST_Bolon2016,ESM-1v (zero shot),0.5770032224447383,0.5794593692641861,0.011071932164493134
|
| 247 |
+
245,HSP82_YEAST_Bolon2016,ESM-1v (+further training),0.5582427433705837,0.5611201932811588,0.011556274778765427
|
| 248 |
+
246,HSP82_YEAST_Bolon2016,DeepSequence (replicated),0.5447815098744462,0.5468478860295007,0.009190852805604763
|
| 249 |
+
247,HSP82_YEAST_Bolon2016,EVMutation (replicated),0.4813174874985635,0.4833921506539731,0.010641726788141665
|
| 250 |
+
248,HSP82_YEAST_Bolon2016,ProtBERT-BFD,0.5020206378059789,0.5038884666599158,0.010495246599296015
|
| 251 |
+
249,HSP82_YEAST_Bolon2016,TAPE,0.11898211650679438,0.11418591489599068,0.0095283384478768
|
| 252 |
+
250,HSP82_YEAST_Bolon2016,UniRep,0.28031483895837656,0.27995048255516847,0.016433158282085403
|
| 253 |
+
251,HSP82_YEAST_Bolon2016,ESM-1b,0.5364678889354202,0.5369383571750992,0.012361055325265038
|
| 254 |
+
518,TPMT_HUMAN_Fowler2018,gt,1.0,1.0,0.0
|
| 255 |
+
519,TPMT_HUMAN_Fowler2018,MSA Transformer,0.5424668178781977,0.540549584398611,0.0130129824539858
|
| 256 |
+
520,TPMT_HUMAN_Fowler2018,PSSM,0.48146126611262924,0.4789555004656866,0.01619133485423122
|
| 257 |
+
521,TPMT_HUMAN_Fowler2018,EVMutation (published),0.5243737765811296,0.5211293318961853,0.013677282837478894
|
| 258 |
+
522,TPMT_HUMAN_Fowler2018,DeepSequence (published) - single,0.5616767945109112,0.5601851812367447,0.014098853189084848
|
| 259 |
+
523,TPMT_HUMAN_Fowler2018,DeepSequence (published),0.57189769074549,0.5692094068525796,0.014271609738516988
|
| 260 |
+
524,TPMT_HUMAN_Fowler2018,ESM-1v (zero shot),0.5746177224716744,0.5733456843246085,0.013161147755010085
|
| 261 |
+
525,TPMT_HUMAN_Fowler2018,ESM-1v (+further training),0.5667144426739071,0.5643404804061067,0.012156963082272723
|
| 262 |
+
526,TPMT_HUMAN_Fowler2018,DeepSequence (replicated),0.5734186713594054,0.5725136899852928,0.01380924904516693
|
| 263 |
+
527,TPMT_HUMAN_Fowler2018,EVMutation (replicated),0.5415452371370989,0.5367554768824575,0.014285595575941081
|
| 264 |
+
528,TPMT_HUMAN_Fowler2018,ProtBERT-BFD,0.5755683713471709,0.5740036007868525,0.011781062164033955
|
| 265 |
+
529,TPMT_HUMAN_Fowler2018,TAPE,0.21528496910537398,0.2163150200476124,0.01671186684925183
|
| 266 |
+
530,TPMT_HUMAN_Fowler2018,UniRep,0.24493123064838648,0.2429991773585667,0.01737637750092445
|
| 267 |
+
531,TPMT_HUMAN_Fowler2018,ESM-1b,0.585864822736713,0.5831594511762555,0.012841359293495367
|
| 268 |
+
252,IF1_ECOLI_Kishony,gt,1.0,1.0,0.0
|
| 269 |
+
253,IF1_ECOLI_Kishony,MSA Transformer,0.5374285372059321,0.5379972559155065,0.020194737882211888
|
| 270 |
+
254,IF1_ECOLI_Kishony,PSSM,0.5052167418774901,0.5069241815649538,0.021074640419288252
|
| 271 |
+
255,IF1_ECOLI_Kishony,EVMutation (published),0.5003046508987051,0.5003352234717605,0.022143569265813394
|
| 272 |
+
256,IF1_ECOLI_Kishony,DeepSequence (published) - single,0.5239331603676252,0.5269853910903933,0.019737341732545446
|
| 273 |
+
257,IF1_ECOLI_Kishony,DeepSequence (published),0.5232098971780704,0.5263086088632558,0.019848792789945318
|
| 274 |
+
258,IF1_ECOLI_Kishony,ESM-1v (zero shot),0.5489484528277484,0.5487290835018946,0.018090689195472447
|
| 275 |
+
259,IF1_ECOLI_Kishony,ESM-1v (+further training),0.5619784833217806,0.5609262853368223,0.01759996229002091
|
| 276 |
+
260,IF1_ECOLI_Kishony,DeepSequence (replicated),0.5371602219910716,0.5377419211137229,0.016834767452949526
|
| 277 |
+
261,IF1_ECOLI_Kishony,EVMutation (replicated),0.49106963416130595,0.487364241499556,0.02231862948055046
|
| 278 |
+
262,IF1_ECOLI_Kishony,ProtBERT-BFD,0.49640551530348803,0.49572596972809546,0.021526763193477596
|
| 279 |
+
263,IF1_ECOLI_Kishony,TAPE,0.3330415186026132,0.3329560370901763,0.025365922197565095
|
| 280 |
+
264,IF1_ECOLI_Kishony,UniRep,0.11711947357011687,0.11208310104103972,0.02358345571859419
|
| 281 |
+
265,IF1_ECOLI_Kishony,ESM-1b,0.548626388294071,0.5492417382232484,0.020649586745340585
|
| 282 |
+
154,BRCA1_HUMAN_RING,gt,1.0,1.0,0.0
|
| 283 |
+
155,BRCA1_HUMAN_RING,MSA Transformer,0.5193005569644538,0.5203285046503858,0.041166837523028924
|
| 284 |
+
156,BRCA1_HUMAN_RING,PSSM,0.5634130110253781,0.5581058154928551,0.04362682737121433
|
| 285 |
+
157,BRCA1_HUMAN_RING,EVMutation (published),0.4739893403358574,0.4727346993937392,0.036203681195866866
|
| 286 |
+
158,BRCA1_HUMAN_RING,DeepSequence (published) - single,0.5543323620928434,0.5511807082846618,0.039417214029845105
|
| 287 |
+
159,BRCA1_HUMAN_RING,DeepSequence (published),0.5617365720006955,0.5591185452387899,0.03842959531538541
|
| 288 |
+
160,BRCA1_HUMAN_RING,ESM-1v (zero shot),0.5415424138323831,0.5341119058002446,0.03653613513934021
|
| 289 |
+
161,BRCA1_HUMAN_RING,ESM-1v (+further training),0.5550269189493816,0.5537267190735496,0.03937349908877672
|
| 290 |
+
162,BRCA1_HUMAN_RING,DeepSequence (replicated),0.5658118851058472,0.5627698357833636,0.037505350857757684
|
| 291 |
+
163,BRCA1_HUMAN_RING,EVMutation (replicated),0.46724701283596226,0.46596752209015424,0.04012929367216169
|
| 292 |
+
164,BRCA1_HUMAN_RING,ProtBERT-BFD,0.47507688987212,0.4713003309113355,0.03734723419650255
|
| 293 |
+
165,BRCA1_HUMAN_RING,TAPE,0.32511391092165925,0.3259918359586091,0.05215348292668556
|
| 294 |
+
166,BRCA1_HUMAN_RING,UniRep,0.4574870950916383,0.466226203934293,0.029045683651907416
|
| 295 |
+
167,BRCA1_HUMAN_RING,ESM-1b,0.5729860249285059,0.5672443289637067,0.030337589962057807
|
| 296 |
+
98,BLAT_ECOLX_Palzkill2012,gt,1.0,1.0,0.0
|
| 297 |
+
99,BLAT_ECOLX_Palzkill2012,MSA Transformer,0.5790109592895919,0.576559464262669,0.00813860157556571
|
| 298 |
+
100,BLAT_ECOLX_Palzkill2012,PSSM,0.43541874109113293,0.4346912136467994,0.011525932575641511
|
| 299 |
+
101,BLAT_ECOLX_Palzkill2012,EVMutation (published),0.5035045285112302,0.5015670440233889,0.011387370179059404
|
| 300 |
+
102,BLAT_ECOLX_Palzkill2012,DeepSequence (published) - single,0.5387135089739988,0.5368824370193662,0.011450482383497546
|
| 301 |
+
103,BLAT_ECOLX_Palzkill2012,DeepSequence (published),0.555680249906377,0.5539233663406711,0.009685510491284273
|
| 302 |
+
104,BLAT_ECOLX_Palzkill2012,ESM-1v (zero shot),0.5394874702645197,0.5391023570614875,0.01072036011365782
|
| 303 |
+
105,BLAT_ECOLX_Palzkill2012,ESM-1v (+further training),0.5672174721013816,0.5661011431263104,0.010297339893877539
|
| 304 |
+
106,BLAT_ECOLX_Palzkill2012,DeepSequence (replicated),0.5665462527968158,0.5646253670538975,0.00957133565445041
|
| 305 |
+
107,BLAT_ECOLX_Palzkill2012,EVMutation (replicated),0.5174199245259459,0.5144044189835617,0.010884656508769686
|
| 306 |
+
108,BLAT_ECOLX_Palzkill2012,ProtBERT-BFD,0.413553141253597,0.4108322854585459,0.009768034882433663
|
| 307 |
+
109,BLAT_ECOLX_Palzkill2012,TAPE,0.06707069584638124,0.06961505855709685,0.01069869285554942
|
| 308 |
+
110,BLAT_ECOLX_Palzkill2012,UniRep,0.0166580631994596,0.02360053325843217,0.01073550650340384
|
| 309 |
+
111,BLAT_ECOLX_Palzkill2012,ESM-1b,0.54626199827611,0.5450469362296847,0.010574502773225362
|
| 310 |
+
210,HG_FLU_Bloom2016,gt,1.0,1.0,0.0
|
| 311 |
+
211,HG_FLU_Bloom2016,MSA Transformer,0.4807847197470188,0.48133913444729065,0.007238779061281368
|
| 312 |
+
212,HG_FLU_Bloom2016,PSSM,0.467255239211276,0.4658023016610004,0.007807096034181624
|
| 313 |
+
213,HG_FLU_Bloom2016,EVMutation (published),0.45827659972583357,0.45804886604872685,0.008079452114456188
|
| 314 |
+
214,HG_FLU_Bloom2016,DeepSequence (published) - single,0.38185154496925244,0.3815243480167388,0.009700262344961326
|
| 315 |
+
215,HG_FLU_Bloom2016,DeepSequence (published),0.408559044093847,0.4088655809693629,0.007996666160114359
|
| 316 |
+
216,HG_FLU_Bloom2016,ESM-1v (zero shot),0.5377581449296356,0.5381755966315286,0.00849950538034111
|
| 317 |
+
217,HG_FLU_Bloom2016,ESM-1v (+further training),0.508004961821385,0.50881255466271,0.008423294599454892
|
| 318 |
+
218,HG_FLU_Bloom2016,DeepSequence (replicated),0.425338497638415,0.425397348539834,0.007829596385814108
|
| 319 |
+
219,HG_FLU_Bloom2016,EVMutation (replicated),0.4745801474914726,0.4740523393070549,0.00772632329264063
|
| 320 |
+
220,HG_FLU_Bloom2016,ProtBERT-BFD,0.01216830054805121,0.014371682213071179,0.008595363873197908
|
| 321 |
+
221,HG_FLU_Bloom2016,TAPE,0.011506602346493722,0.011595399204682536,0.006272208060584064
|
| 322 |
+
222,HG_FLU_Bloom2016,UniRep,0.11238855588872076,0.11416182055768724,0.009338414613763222
|
| 323 |
+
223,HG_FLU_Bloom2016,ESM-1b,0.13466161180017006,0.13615942676936274,0.010191230998347687
|
| 324 |
+
224,HIS7_YEAST_Kondrashov2017,gt,1.0,1.0,0.0
|
| 325 |
+
225,HIS7_YEAST_Kondrashov2017,MSA Transformer,0.30171610633916407,0.301852298319144,0.0012676098127205092
|
| 326 |
+
226,HIS7_YEAST_Kondrashov2017,PSSM,0.46025981696434587,0.4602850849857719,0.0008742604182146493
|
| 327 |
+
227,HIS7_YEAST_Kondrashov2017,EVMutation (published),0.5865226545066141,0.5868249726401576,0.0008233711922239475
|
| 328 |
+
228,HIS7_YEAST_Kondrashov2017,DeepSequence (published) - single,0.4924067186635951,0.49266995692585214,0.0009319735566991191
|
| 329 |
+
229,HIS7_YEAST_Kondrashov2017,DeepSequence (published),0.539985999849893,0.540227447923642,0.0008648831057151851
|
| 330 |
+
230,HIS7_YEAST_Kondrashov2017,ESM-1v (zero shot),0.529358182381123,0.5295580913555231,0.0007957702421518582
|
| 331 |
+
231,HIS7_YEAST_Kondrashov2017,ESM-1v (+further training),0.5600853174526501,0.5602849321317114,0.0008034030458959766
|
| 332 |
+
232,HIS7_YEAST_Kondrashov2017,DeepSequence (replicated),0.5771729957674867,0.5774905109783149,0.0007170541729409019
|
| 333 |
+
233,HIS7_YEAST_Kondrashov2017,EVMutation (replicated),0.5839282060088532,0.5842957417091784,0.0008208185316044222
|
| 334 |
+
234,HIS7_YEAST_Kondrashov2017,ProtBERT-BFD,0.5529258544618092,0.5529676964174914,0.0007360080980740549
|
| 335 |
+
235,HIS7_YEAST_Kondrashov2017,TAPE,0.1014260339205887,0.101752697842131,0.0014218010200125605
|
| 336 |
+
236,HIS7_YEAST_Kondrashov2017,UniRep,0.1815849109979771,0.18158251774490938,0.0014496180282351032
|
| 337 |
+
237,HIS7_YEAST_Kondrashov2017,ESM-1b,0.5000466702129686,0.5002672548811231,0.0008300778727114249
|
| 338 |
+
70,BG_STRSQ_hmmerbit,gt,1.0,1.0,0.0
|
| 339 |
+
71,BG_STRSQ_hmmerbit,MSA Transformer,0.6555958579973886,0.659326801766521,0.00913574784080978
|
| 340 |
+
72,BG_STRSQ_hmmerbit,PSSM,0.5431285035494208,0.5491891696554254,0.01382628634556949
|
| 341 |
+
73,BG_STRSQ_hmmerbit,EVMutation (published),0.6297133475442988,0.6326270443670063,0.006525349201880503
|
| 342 |
+
74,BG_STRSQ_hmmerbit,DeepSequence (published) - single,0.6663981684713202,0.667051777591926,0.008814659279799686
|
| 343 |
+
75,BG_STRSQ_hmmerbit,DeepSequence (published),0.671353366524517,0.6721885348190513,0.009076474761061238
|
| 344 |
+
76,BG_STRSQ_hmmerbit,ESM-1v (zero shot),0.528482255049547,0.5356316829302887,0.013445455516506805
|
| 345 |
+
77,BG_STRSQ_hmmerbit,ESM-1v (+further training),0.6516055107633002,0.6555062061803748,0.009214695345811378
|
| 346 |
+
78,BG_STRSQ_hmmerbit,DeepSequence (replicated),0.6751486915624705,0.6760984429469532,0.009352478062896172
|
| 347 |
+
79,BG_STRSQ_hmmerbit,EVMutation (replicated),0.6403197196758124,0.6434637152906157,0.007241339119188467
|
| 348 |
+
80,BG_STRSQ_hmmerbit,ProtBERT-BFD,0.6365069784319516,0.6396483776091306,0.007811080769658407
|
| 349 |
+
81,BG_STRSQ_hmmerbit,TAPE,0.43294588799591494,0.44008364687109375,0.01682011773736568
|
| 350 |
+
82,BG_STRSQ_hmmerbit,UniRep,0.19989240659304872,0.20517404401460504,0.014963964273707563
|
| 351 |
+
83,BG_STRSQ_hmmerbit,ESM-1b,0.6009580023829318,0.6080513205167206,0.013233900564372743
|
| 352 |
+
546,UBE4B_MOUSE_Klevit2013-singles,gt,1.0,1.0,0.0
|
| 353 |
+
547,UBE4B_MOUSE_Klevit2013-singles,MSA Transformer,0.49832943520981005,0.49905990983648263,0.03105986611446269
|
| 354 |
+
548,UBE4B_MOUSE_Klevit2013-singles,PSSM,0.48860473816872396,0.49337529571134364,0.031233090528237636
|
| 355 |
+
549,UBE4B_MOUSE_Klevit2013-singles,EVMutation (published),0.4906841388190489,0.49199509841786193,0.03340124290266937
|
| 356 |
+
550,UBE4B_MOUSE_Klevit2013-singles,DeepSequence (published) - single,0.5312205433544338,0.5329703058977546,0.029417950250717785
|
| 357 |
+
551,UBE4B_MOUSE_Klevit2013-singles,DeepSequence (published),0.5395815016518124,0.5430445683834082,0.02805620658685915
|
| 358 |
+
552,UBE4B_MOUSE_Klevit2013-singles,ESM-1v (zero shot),0.5220724759142595,0.5231561587068752,0.024550717856015463
|
| 359 |
+
553,UBE4B_MOUSE_Klevit2013-singles,ESM-1v (+further training),0.5218576853965179,0.5198018293944963,0.029197148702440747
|
| 360 |
+
554,UBE4B_MOUSE_Klevit2013-singles,DeepSequence (replicated),0.5223215278319518,0.5271163507848048,0.02943995962728437
|
| 361 |
+
555,UBE4B_MOUSE_Klevit2013-singles,EVMutation (replicated),0.4846034274372467,0.48559313231244233,0.035130463278636635
|
| 362 |
+
556,UBE4B_MOUSE_Klevit2013-singles,ProtBERT-BFD,0.5185431412393127,0.5236656965174686,0.028751086492193833
|
| 363 |
+
557,UBE4B_MOUSE_Klevit2013-singles,TAPE,0.01730835573288986,0.03524679123603523,0.02987730394986271
|
| 364 |
+
558,UBE4B_MOUSE_Klevit2013-singles,UniRep,0.10151869130428068,0.09383999274532392,0.03556604553816262
|
| 365 |
+
559,UBE4B_MOUSE_Klevit2013-singles,ESM-1b,0.4877718340726251,0.48675329873590983,0.03538514294193213
|
| 366 |
+
14,B3VI55_LIPSTSTABLE,gt,1.0,1.0,0.0
|
| 367 |
+
15,B3VI55_LIPSTSTABLE,MSA Transformer,0.5251005167937696,0.5275545723143799,0.009041770337910218
|
| 368 |
+
16,B3VI55_LIPSTSTABLE,PSSM,0.33176316087515695,0.3329724203391258,0.011406640278605069
|
| 369 |
+
17,B3VI55_LIPSTSTABLE,EVMutation (published),0.43366434910484786,0.43528511611104986,0.010773070057405095
|
| 370 |
+
18,B3VI55_LIPSTSTABLE,DeepSequence (published) - single,0.4747977554498681,0.4764432728845286,0.00955452160837742
|
| 371 |
+
19,B3VI55_LIPSTSTABLE,DeepSequence (published),0.48780043789141697,0.489281157459712,0.008995219832666802
|
| 372 |
+
20,B3VI55_LIPSTSTABLE,ESM-1v (zero shot),0.5144594346026741,0.516476518473857,0.009568231035205155
|
| 373 |
+
21,B3VI55_LIPSTSTABLE,ESM-1v (+further training),0.5408988777571562,0.5429418957469877,0.008374931117004644
|
| 374 |
+
22,B3VI55_LIPSTSTABLE,DeepSequence (replicated),0.5108241872870117,0.511210509948324,0.008885420291063774
|
| 375 |
+
23,B3VI55_LIPSTSTABLE,EVMutation (replicated),0.45220927299548147,0.45292929103074864,0.01073069192782447
|
| 376 |
+
24,B3VI55_LIPSTSTABLE,ProtBERT-BFD,0.3909053736573994,0.39106874014118553,0.010538767559809602
|
| 377 |
+
25,B3VI55_LIPSTSTABLE,TAPE,0.1114444287805763,0.1120507952365121,0.012548143306758398
|
| 378 |
+
26,B3VI55_LIPSTSTABLE,UniRep,0.1050036846541006,0.10502881984575867,0.013417162356959514
|
| 379 |
+
27,B3VI55_LIPSTSTABLE,ESM-1b,0.4153440056253525,0.4178700751301828,0.011532303943529923
|
| 380 |
+
42,BF520_env_Bloom2018,gt,1.0,1.0,0.0
|
| 381 |
+
43,BF520_env_Bloom2018,MSA Transformer,0.53045503362033,0.528360683768996,0.007312684938262093
|
| 382 |
+
44,BF520_env_Bloom2018,PSSM,0.48128944926535605,0.47846350663914833,0.007277527859925501
|
| 383 |
+
45,BF520_env_Bloom2018,EVMutation (published),0.3961853129701546,0.3926921454653422,0.00906487418575762
|
| 384 |
+
46,BF520_env_Bloom2018,DeepSequence (published) - single,0.0033350478364570987,0.009194378034284379,0.008689823275268422
|
| 385 |
+
47,BF520_env_Bloom2018,DeepSequence (published),0.0029335219050744344,0.008967370879028378,0.005401668464782235
|
| 386 |
+
48,BF520_env_Bloom2018,ESM-1v (zero shot),0.5137302974636209,0.5110743977804137,0.006968499056122589
|
| 387 |
+
49,BF520_env_Bloom2018,ESM-1v (+further training),0.5260276733897689,0.524307610096477,0.006318717908534139
|
| 388 |
+
50,BF520_env_Bloom2018,DeepSequence (replicated),0.03940344835961486,0.03571128763490593,0.010040975563315926
|
| 389 |
+
51,BF520_env_Bloom2018,EVMutation (replicated),0.41701008243014626,0.4131323889976084,0.009699036294956902
|
| 390 |
+
52,BF520_env_Bloom2018,ProtBERT-BFD,0.35920295750142894,0.356294565641996,0.008888654031775356
|
| 391 |
+
53,BF520_env_Bloom2018,TAPE,0.03296454518403542,0.03347884384026924,0.010604055757164086
|
| 392 |
+
54,BF520_env_Bloom2018,UniRep,0.19509435241603182,0.19534025730349494,0.008044823411980718
|
| 393 |
+
55,BF520_env_Bloom2018,ESM-1b,0.4644044299599039,0.4621942590259476,0.0072479072681551
|
| 394 |
+
490,TIM_THEMA_b0,gt,1.0,1.0,0.0
|
| 395 |
+
491,TIM_THEMA_b0,MSA Transformer,0.476641570693168,0.4772084109762894,0.021262538481700146
|
| 396 |
+
492,TIM_THEMA_b0,PSSM,0.3987702061334132,0.39949709692713725,0.022351322419246027
|
| 397 |
+
493,TIM_THEMA_b0,EVMutation (published),0.43189426495468003,0.4320501737162544,0.023786620230565422
|
| 398 |
+
494,TIM_THEMA_b0,DeepSequence (published) - single,0.4429769169797119,0.4459763974635589,0.023367347171715933
|
| 399 |
+
495,TIM_THEMA_b0,DeepSequence (published),0.43793312514525096,0.43932643176681746,0.02400129226573652
|
| 400 |
+
496,TIM_THEMA_b0,ESM-1v (zero shot),0.5026024874119385,0.5028606317050863,0.0196194686907316
|
| 401 |
+
497,TIM_THEMA_b0,ESM-1v (+further training),0.49669513157740486,0.49715001129465347,0.021252079717001313
|
| 402 |
+
498,TIM_THEMA_b0,DeepSequence (replicated),0.4065555906798227,0.4088509392059708,0.02383945792859995
|
| 403 |
+
499,TIM_THEMA_b0,EVMutation (replicated),0.4372508700326144,0.43818153131258974,0.022249944638541977
|
| 404 |
+
500,TIM_THEMA_b0,ProtBERT-BFD,0.5030640016728883,0.505061273209954,0.02004593130312488
|
| 405 |
+
501,TIM_THEMA_b0,TAPE,0.426213240694561,0.42842760017164616,0.025447870266352153
|
| 406 |
+
502,TIM_THEMA_b0,UniRep,0.15476155586059467,0.14652965312897737,0.02996974334997726
|
| 407 |
+
503,TIM_THEMA_b0,ESM-1b,0.45916689313021203,0.45909489666370673,0.021672817044030984
|
| 408 |
+
560,YAP1_HUMAN_Fields2012-singles,gt,1.0,1.0,0.0
|
| 409 |
+
561,YAP1_HUMAN_Fields2012-singles,MSA Transformer,0.5887070642875368,0.5706519861099527,0.040386258549904866
|
| 410 |
+
562,YAP1_HUMAN_Fields2012-singles,PSSM,0.5690684565019047,0.5451477752262303,0.04238593338136975
|
| 411 |
+
563,YAP1_HUMAN_Fields2012-singles,EVMutation (published),0.5844091425595583,0.5694702589374069,0.03313034558652812
|
| 412 |
+
564,YAP1_HUMAN_Fields2012-singles,DeepSequence (published) - single,0.6529398136915281,0.6360722049001328,0.032593234109222484
|
| 413 |
+
565,YAP1_HUMAN_Fields2012-singles,DeepSequence (published),0.6456339137145388,0.6294381645066613,0.03481028251531764
|
| 414 |
+
566,YAP1_HUMAN_Fields2012-singles,ESM-1v (zero shot),0.493433729941941,0.48010349687654763,0.03994836553901359
|
| 415 |
+
567,YAP1_HUMAN_Fields2012-singles,ESM-1v (+further training),0.6376365184641369,0.623715503200643,0.03529100768352496
|
| 416 |
+
568,YAP1_HUMAN_Fields2012-singles,DeepSequence (replicated),0.6447076152922595,0.6272717205426198,0.033734031749303436
|
| 417 |
+
569,YAP1_HUMAN_Fields2012-singles,EVMutation (replicated),0.557456385066247,0.543521991089175,0.035472281995781466
|
| 418 |
+
570,YAP1_HUMAN_Fields2012-singles,ProtBERT-BFD,0.5482997903990557,0.5417356076069597,0.03807717806310085
|
| 419 |
+
571,YAP1_HUMAN_Fields2012-singles,TAPE,0.14957625858401177,0.1801038227952158,0.05696901517750361
|
| 420 |
+
572,YAP1_HUMAN_Fields2012-singles,UniRep,0.029127721955503238,0.05432100409858017,0.03754188708662973
|
| 421 |
+
573,YAP1_HUMAN_Fields2012-singles,ESM-1b,0.49074132050160213,0.47904274853673057,0.033063480562130175
|
| 422 |
+
140,BRCA1_HUMAN_BRCT,gt,1.0,1.0,0.0
|
| 423 |
+
141,BRCA1_HUMAN_BRCT,MSA Transformer,0.5928951868322753,0.5960239232158157,0.024771243739877567
|
| 424 |
+
142,BRCA1_HUMAN_BRCT,PSSM,0.45174214496735526,0.4661431870435194,0.02242218107567778
|
| 425 |
+
143,BRCA1_HUMAN_BRCT,EVMutation (published),0.575430631741363,0.5736725403805653,0.02241134787829384
|
| 426 |
+
144,BRCA1_HUMAN_BRCT,DeepSequence (published) - single,0.56817101100728,0.5677360233280984,0.023388317280203356
|
| 427 |
+
145,BRCA1_HUMAN_BRCT,DeepSequence (published),0.5887397586618573,0.5891289275127845,0.025473578386602996
|
| 428 |
+
146,BRCA1_HUMAN_BRCT,ESM-1v (zero shot),0.43099744949022667,0.43820237951190066,0.026042969300316396
|
| 429 |
+
147,BRCA1_HUMAN_BRCT,ESM-1v (+further training),0.5902839735003296,0.5924129041526023,0.022139044593609002
|
| 430 |
+
148,BRCA1_HUMAN_BRCT,DeepSequence (replicated),0.6048855640279864,0.6073185827311438,0.022386535818213062
|
| 431 |
+
149,BRCA1_HUMAN_BRCT,EVMutation (replicated),0.5943999321364778,0.5914745443226089,0.021113952368322746
|
| 432 |
+
150,BRCA1_HUMAN_BRCT,ProtBERT-BFD,0.3807653003587669,0.38891615029062426,0.025074152619186402
|
| 433 |
+
151,BRCA1_HUMAN_BRCT,TAPE,0.05185305485548559,0.06300777252497933,0.028006890598497248
|
| 434 |
+
152,BRCA1_HUMAN_BRCT,UniRep,0.001009857244270908,0.024731061663019048,0.015154925933309927
|
| 435 |
+
153,BRCA1_HUMAN_BRCT,ESM-1b,0.5015315617812091,0.5064634555923619,0.023953542534915467
|
| 436 |
+
392,PTEN_HUMAN_Fowler2018,gt,1.0,1.0,0.0
|
| 437 |
+
393,PTEN_HUMAN_Fowler2018,MSA Transformer,0.47723620402030725,0.4753707747929236,0.02041283060478458
|
| 438 |
+
394,PTEN_HUMAN_Fowler2018,PSSM,0.4856705789707024,0.48540163299274086,0.01456452062108191
|
| 439 |
+
395,PTEN_HUMAN_Fowler2018,EVMutation (published),0.4719118285668927,0.471271072166362,0.0171946566182038
|
| 440 |
+
396,PTEN_HUMAN_Fowler2018,DeepSequence (published) - single,0.3920133344336003,0.38858890670495655,0.021275758912234644
|
| 441 |
+
397,PTEN_HUMAN_Fowler2018,DeepSequence (published),0.41987506342546416,0.4166267407337688,0.02048001735899819
|
| 442 |
+
398,PTEN_HUMAN_Fowler2018,ESM-1v (zero shot),0.4229117460619157,0.4216791615081128,0.022889108923404226
|
| 443 |
+
399,PTEN_HUMAN_Fowler2018,ESM-1v (+further training),0.39745119841802773,0.3945916752986646,0.021297362107723237
|
| 444 |
+
400,PTEN_HUMAN_Fowler2018,DeepSequence (replicated),0.4305140142957644,0.4275242282868633,0.019725711174546957
|
| 445 |
+
401,PTEN_HUMAN_Fowler2018,EVMutation (replicated),0.4562780374489617,0.4570343049276496,0.017322527192949605
|
| 446 |
+
402,PTEN_HUMAN_Fowler2018,ProtBERT-BFD,0.33431387346212144,0.33179215244793264,0.020748503501032432
|
| 447 |
+
403,PTEN_HUMAN_Fowler2018,TAPE,0.0815737781117076,0.07995492505287519,0.010503276183057134
|
| 448 |
+
404,PTEN_HUMAN_Fowler2018,UniRep,0.12983006902884325,0.12588348859114926,0.014127656261654718
|
| 449 |
+
405,PTEN_HUMAN_Fowler2018,ESM-1b,0.4531834407900847,0.4504022413646627,0.019849910120253392
|
| 450 |
+
406,RASH_HUMAN_Kuriyan,gt,1.0,1.0,0.0
|
| 451 |
+
407,RASH_HUMAN_Kuriyan,MSA Transformer,0.4803453272496495,0.47796060028078263,0.017296002593559925
|
| 452 |
+
408,RASH_HUMAN_Kuriyan,PSSM,0.45403466334542103,0.45183098094027907,0.01787397783493158
|
| 453 |
+
409,RASH_HUMAN_Kuriyan,EVMutation (published),0.426341747437809,0.4229653964620471,0.01796419071897713
|
| 454 |
+
410,RASH_HUMAN_Kuriyan,DeepSequence (published) - single,0.4728843219749578,0.468646862737559,0.01795985229559378
|
| 455 |
+
411,RASH_HUMAN_Kuriyan,DeepSequence (published),0.46630499110930534,0.4614459892414701,0.01844189066007253
|
| 456 |
+
412,RASH_HUMAN_Kuriyan,ESM-1v (zero shot),0.40727875438677086,0.40514547710795606,0.019133507919327063
|
| 457 |
+
413,RASH_HUMAN_Kuriyan,ESM-1v (+further training),0.4147935141888191,0.4135324566538796,0.019219555375441195
|
| 458 |
+
414,RASH_HUMAN_Kuriyan,DeepSequence (replicated),0.4718463706052156,0.4693887363231767,0.01665373741632862
|
| 459 |
+
415,RASH_HUMAN_Kuriyan,EVMutation (replicated),0.41905311471869217,0.4152533339275954,0.0186456211620091
|
| 460 |
+
416,RASH_HUMAN_Kuriyan,ProtBERT-BFD,0.3754077679946978,0.37224319469530265,0.020828472200020876
|
| 461 |
+
417,RASH_HUMAN_Kuriyan,TAPE,0.3410037149796282,0.33821305583243977,0.02006172500654845
|
| 462 |
+
418,RASH_HUMAN_Kuriyan,UniRep,0.28316890117187576,0.2804521504745546,0.016931648162857683
|
| 463 |
+
419,RASH_HUMAN_Kuriyan,ESM-1b,0.34359820576597994,0.3393198546702645,0.02233342505800977
|
| 464 |
+
420,RL401_YEAST_Bolon2013,gt,1.0,1.0,0.0
|
| 465 |
+
421,RL401_YEAST_Bolon2013,MSA Transformer,0.5393318004129806,0.539097206955352,0.021107284547232343
|
| 466 |
+
422,RL401_YEAST_Bolon2013,PSSM,0.4115446821389685,0.4029967757216066,0.02694607790699914
|
| 467 |
+
423,RL401_YEAST_Bolon2013,EVMutation (published),0.45052851516991577,0.44375165687449697,0.020730159359455567
|
| 468 |
+
424,RL401_YEAST_Bolon2013,DeepSequence (published) - single,0.4749118165434772,0.4687082939023236,0.02394781384346245
|
| 469 |
+
425,RL401_YEAST_Bolon2013,DeepSequence (published),0.4891069305943915,0.4832628867355531,0.020837235335480923
|
| 470 |
+
426,RL401_YEAST_Bolon2013,ESM-1v (zero shot),0.3780305382545389,0.3758572950839938,0.024438101597142162
|
| 471 |
+
427,RL401_YEAST_Bolon2013,ESM-1v (+further training),0.36982341765304827,0.36644542392899027,0.02407282307497699
|
| 472 |
+
428,RL401_YEAST_Bolon2013,DeepSequence (replicated),0.4875479135136087,0.48185494209379953,0.0224889402600134
|
| 473 |
+
429,RL401_YEAST_Bolon2013,EVMutation (replicated),0.4649054471564614,0.45886647149033805,0.023302945044134975
|
| 474 |
+
430,RL401_YEAST_Bolon2013,ProtBERT-BFD,0.39888508524198757,0.39548316549478596,0.024888924809883948
|
| 475 |
+
431,RL401_YEAST_Bolon2013,TAPE,0.14136362276356793,0.1330418322501083,0.03239530659402373
|
| 476 |
+
432,RL401_YEAST_Bolon2013,UniRep,0.11132107785812106,0.10371964011546289,0.027489697230632073
|
| 477 |
+
433,RL401_YEAST_Bolon2013,ESM-1b,0.24192958338903614,0.24085320243486236,0.026555927080409752
|
| 478 |
+
504,TPK1_HUMAN_Roth2017,gt,1.0,1.0,0.0
|
| 479 |
+
505,TPK1_HUMAN_Roth2017,MSA Transformer,0.3415408511396077,0.33848473630002246,0.021212292675018753
|
| 480 |
+
506,TPK1_HUMAN_Roth2017,PSSM,0.22072657020579714,0.2217644870830699,0.02369863818079656
|
| 481 |
+
507,TPK1_HUMAN_Roth2017,EVMutation (published),0.2469522178641623,0.24730841435573284,0.01871959166700927
|
| 482 |
+
508,TPK1_HUMAN_Roth2017,DeepSequence (published) - single,0.2575167904390149,0.2558063144550207,0.02055476962559519
|
| 483 |
+
509,TPK1_HUMAN_Roth2017,DeepSequence (published),0.25614519361128574,0.2543757481978049,0.021967216506252808
|
| 484 |
+
510,TPK1_HUMAN_Roth2017,ESM-1v (zero shot),0.33312805710397364,0.327155968484034,0.019777338079982523
|
| 485 |
+
511,TPK1_HUMAN_Roth2017,ESM-1v (+further training),0.3317814621900089,0.3260704249321161,0.020979034647608977
|
| 486 |
+
512,TPK1_HUMAN_Roth2017,DeepSequence (replicated),0.254473186445843,0.2514295290110877,0.02177016005083741
|
| 487 |
+
513,TPK1_HUMAN_Roth2017,EVMutation (replicated),0.23867041174072273,0.23850268855356252,0.019193703578397097
|
| 488 |
+
514,TPK1_HUMAN_Roth2017,ProtBERT-BFD,0.24102052288064413,0.2413615342747228,0.021738163307345192
|
| 489 |
+
515,TPK1_HUMAN_Roth2017,TAPE,0.08255844412157543,0.08001237804591124,0.014507842152561057
|
| 490 |
+
516,TPK1_HUMAN_Roth2017,UniRep,0.03311972123416161,0.03305706490328286,0.021578991252520243
|
| 491 |
+
517,TPK1_HUMAN_Roth2017,ESM-1b,0.31345297835126973,0.3093139122995233,0.01991362706272715
|
| 492 |
+
448,RL401_YEAST_Fraser2016,gt,1.0,1.0,0.0
|
| 493 |
+
449,RL401_YEAST_Fraser2016,MSA Transformer,0.47482528061086265,0.4755124342582121,0.022569966034399314
|
| 494 |
+
450,RL401_YEAST_Fraser2016,PSSM,0.3774016009912691,0.3773571687306486,0.015993333803246766
|
| 495 |
+
451,RL401_YEAST_Fraser2016,EVMutation (published),0.40924774479083326,0.414388594923377,0.023024753763437884
|
| 496 |
+
452,RL401_YEAST_Fraser2016,DeepSequence (published) - single,0.4318166476420829,0.4331294439053056,0.01910722980495821
|
| 497 |
+
453,RL401_YEAST_Fraser2016,DeepSequence (published),0.4461365210878178,0.44899827665090486,0.019914780607228476
|
| 498 |
+
454,RL401_YEAST_Fraser2016,ESM-1v (zero shot),0.32760495384990906,0.3291822704728004,0.02640133685107885
|
| 499 |
+
455,RL401_YEAST_Fraser2016,ESM-1v (+further training),0.32990765588855403,0.3301471135676151,0.027322775648250797
|
| 500 |
+
456,RL401_YEAST_Fraser2016,DeepSequence (replicated),0.4347770704966268,0.44167537164330406,0.017646832557385868
|
| 501 |
+
457,RL401_YEAST_Fraser2016,EVMutation (replicated),0.4137359503211986,0.42342848446020753,0.023604416626258205
|
| 502 |
+
458,RL401_YEAST_Fraser2016,ProtBERT-BFD,0.352256182908315,0.35488121411289225,0.026464030488060585
|
| 503 |
+
459,RL401_YEAST_Fraser2016,TAPE,0.11246047580054895,0.11267381281460156,0.029451868723884767
|
| 504 |
+
460,RL401_YEAST_Fraser2016,UniRep,0.09228239837675453,0.0855139650342207,0.02787982622396566
|
| 505 |
+
461,RL401_YEAST_Fraser2016,ESM-1b,0.20980461592629226,0.21406696973008782,0.028067024964270798
|
| 506 |
+
168,CALM1_HUMAN_Roth2017,gt,1.0,1.0,0.0
|
| 507 |
+
169,CALM1_HUMAN_Roth2017,MSA Transformer,0.23711821254687918,0.23943485564742276,0.03113662255833698
|
| 508 |
+
170,CALM1_HUMAN_Roth2017,PSSM,0.1940025702015548,0.19913438415655305,0.02630867989950736
|
| 509 |
+
171,CALM1_HUMAN_Roth2017,EVMutation (published),0.23244288732891077,0.23757839644300488,0.02612586314740137
|
| 510 |
+
172,CALM1_HUMAN_Roth2017,DeepSequence (published) - single,0.22492618953594645,0.22906576202846649,0.030735041631348013
|
| 511 |
+
173,CALM1_HUMAN_Roth2017,DeepSequence (published),0.22789905079105036,0.22969671581656934,0.029946806999461846
|
| 512 |
+
174,CALM1_HUMAN_Roth2017,ESM-1v (zero shot),0.2617141623664426,0.2652270689648074,0.025228781176764935
|
| 513 |
+
175,CALM1_HUMAN_Roth2017,ESM-1v (+further training),0.2721918164887156,0.2732936184582442,0.027420080243011954
|
| 514 |
+
176,CALM1_HUMAN_Roth2017,DeepSequence (replicated),0.23307246773532486,0.23633457440270692,0.029771707595051294
|
| 515 |
+
177,CALM1_HUMAN_Roth2017,EVMutation (replicated),0.23487698274177318,0.24137564501443426,0.02702788568104191
|
| 516 |
+
178,CALM1_HUMAN_Roth2017,ProtBERT-BFD,0.29084218774026066,0.2918048272665779,0.027753008367247246
|
| 517 |
+
179,CALM1_HUMAN_Roth2017,TAPE,0.12219793057831531,0.12415304964391952,0.019957547541863924
|
| 518 |
+
180,CALM1_HUMAN_Roth2017,UniRep,0.07689880828775296,0.08034276883486069,0.028587576009811506
|
| 519 |
+
181,CALM1_HUMAN_Roth2017,ESM-1b,0.24496865240057522,0.2451996389337371,0.02464309631183189
|
| 520 |
+
434,RL401_YEAST_Bolon2014,gt,1.0,1.0,0.0
|
| 521 |
+
435,RL401_YEAST_Bolon2014,MSA Transformer,0.473016586760016,0.4787538735227928,0.01635240282545988
|
| 522 |
+
436,RL401_YEAST_Bolon2014,PSSM,0.4689225734723619,0.4737125791144366,0.018513489042818982
|
| 523 |
+
437,RL401_YEAST_Bolon2014,EVMutation (published),0.39726026462632547,0.40239056557397346,0.0228080866519743
|
| 524 |
+
438,RL401_YEAST_Bolon2014,DeepSequence (published) - single,0.4295635873940029,0.4359091171923386,0.020125832508895207
|
| 525 |
+
439,RL401_YEAST_Bolon2014,DeepSequence (published),0.4226902253289641,0.4296887661396075,0.02042130768745852
|
| 526 |
+
440,RL401_YEAST_Bolon2014,ESM-1v (zero shot),0.2555902509515176,0.26273723347289263,0.023433435512064758
|
| 527 |
+
441,RL401_YEAST_Bolon2014,ESM-1v (+further training),0.30819485583382966,0.3149369605358795,0.022303272256952115
|
| 528 |
+
442,RL401_YEAST_Bolon2014,DeepSequence (replicated),0.4208601802656798,0.427057708121087,0.022928982939476122
|
| 529 |
+
443,RL401_YEAST_Bolon2014,EVMutation (replicated),0.3795164863252923,0.38353041172591634,0.022737389271498636
|
| 530 |
+
444,RL401_YEAST_Bolon2014,ProtBERT-BFD,0.3305475177656725,0.33333306438483723,0.024066951141161263
|
| 531 |
+
445,RL401_YEAST_Bolon2014,TAPE,0.27031483697506303,0.2748860791185031,0.023958009305355937
|
| 532 |
+
446,RL401_YEAST_Bolon2014,UniRep,0.16611039235432376,0.16134631003484823,0.029548951247265007
|
| 533 |
+
447,RL401_YEAST_Bolon2014,ESM-1b,0.18258453677698241,0.18424186541936532,0.02190939840845001
|
| 534 |
+
28,B3VI55_LIPST_Whitehead2015,gt,1.0,1.0,0.0
|
| 535 |
+
29,B3VI55_LIPST_Whitehead2015,MSA Transformer,0.25670663558953755,0.2568287164790948,0.014303617378529112
|
| 536 |
+
30,B3VI55_LIPST_Whitehead2015,PSSM,0.17356487805783094,0.17229178651491212,0.014476649812023814
|
| 537 |
+
31,B3VI55_LIPST_Whitehead2015,EVMutation (published),0.22415909454397737,0.22201195664151258,0.015151263735652506
|
| 538 |
+
32,B3VI55_LIPST_Whitehead2015,DeepSequence (published) - single,0.2314762900256378,0.23010900979180499,0.015350637015825532
|
| 539 |
+
33,B3VI55_LIPST_Whitehead2015,DeepSequence (published),0.2314408826509719,0.23018066970458023,0.015030815308284325
|
| 540 |
+
34,B3VI55_LIPST_Whitehead2015,ESM-1v (zero shot),0.2361417829414803,0.235599751959246,0.01380734986895981
|
| 541 |
+
35,B3VI55_LIPST_Whitehead2015,ESM-1v (+further training),0.2424504346933426,0.24107272979662708,0.013833009304666605
|
| 542 |
+
36,B3VI55_LIPST_Whitehead2015,DeepSequence (replicated),0.24479443697061962,0.2433108240939475,0.015917153531149808
|
| 543 |
+
37,B3VI55_LIPST_Whitehead2015,EVMutation (replicated),0.2251732484740546,0.2236926065862732,0.015150897486335867
|
| 544 |
+
38,B3VI55_LIPST_Whitehead2015,ProtBERT-BFD,0.22029752268681757,0.22189350964142437,0.012296008345577645
|
| 545 |
+
39,B3VI55_LIPST_Whitehead2015,TAPE,0.03217727698102332,0.033398754623545045,0.014930614521878988
|
| 546 |
+
40,B3VI55_LIPST_Whitehead2015,UniRep,0.052410727620420754,0.051318677282283995,0.012063912744717856
|
| 547 |
+
41,B3VI55_LIPST_Whitehead2015,ESM-1b,0.21414102345131894,0.21411325444647447,0.01376144270479094
|
| 548 |
+
280,MK01_HUMAN_Johannessen,gt,1.0,1.0,0.0
|
| 549 |
+
281,MK01_HUMAN_Johannessen,MSA Transformer,0.21600719562316348,0.21324362844208555,0.010869477909858859
|
| 550 |
+
282,MK01_HUMAN_Johannessen,PSSM,0.24003601283569995,0.23781768411144993,0.012873462567914572
|
| 551 |
+
283,MK01_HUMAN_Johannessen,EVMutation (published),0.2411806504637287,0.23555029839403527,0.014919109500043859
|
| 552 |
+
284,MK01_HUMAN_Johannessen,DeepSequence (published) - single,0.21622583201496393,0.2118857875656635,0.01330985778159382
|
| 553 |
+
285,MK01_HUMAN_Johannessen,DeepSequence (published),0.2262833888426422,0.2222242751773241,0.013845563303298817
|
| 554 |
+
286,MK01_HUMAN_Johannessen,ESM-1v (zero shot),0.18610638097061274,0.1807887324699657,0.011421581908870595
|
| 555 |
+
287,MK01_HUMAN_Johannessen,ESM-1v (+further training),0.1711612951379414,0.1656998628430867,0.011097399419126037
|
| 556 |
+
288,MK01_HUMAN_Johannessen,DeepSequence (replicated),0.2262833888426422,0.2222242751773241,0.013845563303298817
|
| 557 |
+
289,MK01_HUMAN_Johannessen,EVMutation (replicated),0.2411806504637287,0.23555029839403527,0.014919109500043859
|
| 558 |
+
290,MK01_HUMAN_Johannessen,ProtBERT-BFD,0.03761357865712906,0.032009850323277314,0.013532258402167076
|
| 559 |
+
291,MK01_HUMAN_Johannessen,TAPE,0.24566726233768266,0.2425196910807727,0.014722071012130074
|
| 560 |
+
292,MK01_HUMAN_Johannessen,UniRep,0.16466166691457634,0.15865978272069822,0.012603347408739064
|
| 561 |
+
293,MK01_HUMAN_Johannessen,ESM-1b,0.020968477238634434,0.014843912213619878,0.011595884022987897
|
| 562 |
+
350,PA_FLU_Sun2015,gt,1.0,1.0,0.0
|
| 563 |
+
351,PA_FLU_Sun2015,MSA Transformer,0.40499549570010246,0.4071708283839041,0.020127599355418007
|
| 564 |
+
352,PA_FLU_Sun2015,PSSM,0.4870284991956425,0.48503558622411713,0.017254863079323307
|
| 565 |
+
353,PA_FLU_Sun2015,EVMutation (published),0.4799931222249091,0.47963201439188896,0.017318908492685997
|
| 566 |
+
354,PA_FLU_Sun2015,DeepSequence (published) - single,0.47395691140007384,0.47172219190050396,0.017516562617318692
|
| 567 |
+
355,PA_FLU_Sun2015,DeepSequence (published),0.4782770520849889,0.4776150037730753,0.01692698104707
|
| 568 |
+
356,PA_FLU_Sun2015,ESM-1v (zero shot),0.10354167707274801,0.10113956150869738,0.014997098538970815
|
| 569 |
+
357,PA_FLU_Sun2015,ESM-1v (+further training),0.5736052915722709,0.5754278729569327,0.011947354137920797
|
| 570 |
+
358,PA_FLU_Sun2015,DeepSequence (replicated),0.49574925840401,0.49600755923376527,0.014212454786638254
|
| 571 |
+
359,PA_FLU_Sun2015,EVMutation (replicated),0.5055094042813111,0.5062333117389017,0.014772450707935335
|
| 572 |
+
360,PA_FLU_Sun2015,ProtBERT-BFD,0.025567814891833348,0.028868599359005404,0.017475521452476987
|
| 573 |
+
361,PA_FLU_Sun2015,TAPE,0.023351679974442957,0.02740069503679209,0.01716926448528921
|
| 574 |
+
362,PA_FLU_Sun2015,UniRep,0.03233737793643953,0.030453300705534824,0.023348423732335796
|
| 575 |
+
363,PA_FLU_Sun2015,ESM-1b,0.0350533539652243,0.03379222480788328,0.01958723862748923
|
model/README.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Local Model Source
|
| 2 |
+
|
| 3 |
+
This directory contains OneScience `models` sources that ESM imports directly.
|
| 4 |
+
|
| 5 |
+
- `esm/`: local copy of `onescience.models.esm`
|
| 6 |
+
- `openfold/`: local copy of `onescience.models.openfold`, required by ESMFold
|
| 7 |
+
- `protenix/layer_norm/`: optional fused layer norm dependency used by OpenFold when `LAYERNORM_TYPE=fast_layernorm`
|
| 8 |
+
|
| 9 |
+
Other OneScience namespaces such as `onescience.datapipes`, `onescience.modules`, and `onescience.utils` are intentionally imported from the installed OneScience environment.
|
| 10 |
+
|
model/__init__.py
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Local model packages copied from OneScience for the standalone ESM project."""
|
| 2 |
+
|
model/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (269 Bytes). View file
|
|
|
model/esm/__init__.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) Facebook, Inc. and its affiliates.
|
| 2 |
+
#
|
| 3 |
+
# This source code is licensed under the MIT license found in the
|
| 4 |
+
# LICENSE file in the root directory of this source tree.
|
| 5 |
+
|
| 6 |
+
from onescience.datapipes import esm as data # noqa
|
| 7 |
+
from onescience.datapipes.esm import Alphabet, BatchConverter, FastaBatchedDataset # noqa
|
| 8 |
+
|
| 9 |
+
from .version import version as __version__ # noqa
|
| 10 |
+
from .esm1 import ProteinBertModel # noqa
|
| 11 |
+
from .esm2 import ESM2 # noqa
|
| 12 |
+
from .msa_transformer import MSATransformer #noqa
|
| 13 |
+
from . import pretrained # noqa
|
model/esm/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (689 Bytes). View file
|
|
|
model/esm/__pycache__/esm1.cpython-311.pyc
ADDED
|
Binary file (10.1 kB). View file
|
|
|
model/esm/__pycache__/esm2.cpython-311.pyc
ADDED
|
Binary file (6.71 kB). View file
|
|
|
model/esm/__pycache__/msa_transformer.cpython-311.pyc
ADDED
|
Binary file (10.3 kB). View file
|
|
|
model/esm/__pycache__/pretrained.cpython-311.pyc
ADDED
|
Binary file (29.9 kB). View file
|
|
|
model/esm/__pycache__/version.cpython-311.pyc
ADDED
|
Binary file (201 Bytes). View file
|
|
|
model/esm/esm1.py
ADDED
|
@@ -0,0 +1,200 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
| 2 |
+
#
|
| 3 |
+
# This source code is licensed under the MIT license found in the
|
| 4 |
+
# LICENSE file in the root directory of this source tree.
|
| 5 |
+
|
| 6 |
+
import math
|
| 7 |
+
|
| 8 |
+
import torch
|
| 9 |
+
import torch.nn as nn
|
| 10 |
+
import torch.nn.functional as F
|
| 11 |
+
|
| 12 |
+
from onescience.modules.esm import (
|
| 13 |
+
TransformerLayer,
|
| 14 |
+
LearnedPositionalEmbedding,
|
| 15 |
+
SinusoidalPositionalEmbedding,
|
| 16 |
+
RobertaLMHead,
|
| 17 |
+
ESM1bLayerNorm,
|
| 18 |
+
ContactPredictionHead,
|
| 19 |
+
)
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
class ProteinBertModel(nn.Module):
|
| 23 |
+
@classmethod
|
| 24 |
+
def add_args(cls, parser):
|
| 25 |
+
parser.add_argument(
|
| 26 |
+
"--num_layers", default=36, type=int, metavar="N", help="number of layers"
|
| 27 |
+
)
|
| 28 |
+
parser.add_argument(
|
| 29 |
+
"--embed_dim", default=1280, type=int, metavar="N", help="embedding dimension"
|
| 30 |
+
)
|
| 31 |
+
parser.add_argument(
|
| 32 |
+
"--logit_bias", action="store_true", help="whether to apply bias to logits"
|
| 33 |
+
)
|
| 34 |
+
parser.add_argument(
|
| 35 |
+
"--ffn_embed_dim",
|
| 36 |
+
default=5120,
|
| 37 |
+
type=int,
|
| 38 |
+
metavar="N",
|
| 39 |
+
help="embedding dimension for FFN",
|
| 40 |
+
)
|
| 41 |
+
parser.add_argument(
|
| 42 |
+
"--attention_heads",
|
| 43 |
+
default=20,
|
| 44 |
+
type=int,
|
| 45 |
+
metavar="N",
|
| 46 |
+
help="number of attention heads",
|
| 47 |
+
)
|
| 48 |
+
|
| 49 |
+
def __init__(self, args, alphabet):
|
| 50 |
+
super().__init__()
|
| 51 |
+
self.args = args
|
| 52 |
+
self.alphabet_size = len(alphabet)
|
| 53 |
+
self.padding_idx = alphabet.padding_idx
|
| 54 |
+
self.mask_idx = alphabet.mask_idx
|
| 55 |
+
self.cls_idx = alphabet.cls_idx
|
| 56 |
+
self.eos_idx = alphabet.eos_idx
|
| 57 |
+
self.prepend_bos = alphabet.prepend_bos
|
| 58 |
+
self.append_eos = alphabet.append_eos
|
| 59 |
+
self.emb_layer_norm_before = getattr(self.args, "emb_layer_norm_before", False)
|
| 60 |
+
if self.args.arch == "roberta_large":
|
| 61 |
+
self.model_version = "ESM-1b"
|
| 62 |
+
self._init_submodules_esm1b()
|
| 63 |
+
else:
|
| 64 |
+
self.model_version = "ESM-1"
|
| 65 |
+
self._init_submodules_esm1()
|
| 66 |
+
|
| 67 |
+
def _init_submodules_common(self):
|
| 68 |
+
self.embed_tokens = nn.Embedding(
|
| 69 |
+
self.alphabet_size, self.args.embed_dim, padding_idx=self.padding_idx
|
| 70 |
+
)
|
| 71 |
+
self.layers = nn.ModuleList(
|
| 72 |
+
[
|
| 73 |
+
TransformerLayer(
|
| 74 |
+
self.args.embed_dim,
|
| 75 |
+
self.args.ffn_embed_dim,
|
| 76 |
+
self.args.attention_heads,
|
| 77 |
+
add_bias_kv=(self.model_version != "ESM-1b"),
|
| 78 |
+
use_esm1b_layer_norm=(self.model_version == "ESM-1b"),
|
| 79 |
+
)
|
| 80 |
+
for _ in range(self.args.layers)
|
| 81 |
+
]
|
| 82 |
+
)
|
| 83 |
+
|
| 84 |
+
self.contact_head = ContactPredictionHead(
|
| 85 |
+
self.args.layers * self.args.attention_heads,
|
| 86 |
+
self.prepend_bos,
|
| 87 |
+
self.append_eos,
|
| 88 |
+
eos_idx=self.eos_idx,
|
| 89 |
+
)
|
| 90 |
+
|
| 91 |
+
def _init_submodules_esm1b(self):
|
| 92 |
+
self._init_submodules_common()
|
| 93 |
+
self.embed_scale = 1
|
| 94 |
+
self.embed_positions = LearnedPositionalEmbedding(
|
| 95 |
+
self.args.max_positions, self.args.embed_dim, self.padding_idx
|
| 96 |
+
)
|
| 97 |
+
self.emb_layer_norm_before = (
|
| 98 |
+
ESM1bLayerNorm(self.args.embed_dim) if self.emb_layer_norm_before else None
|
| 99 |
+
)
|
| 100 |
+
self.emb_layer_norm_after = ESM1bLayerNorm(self.args.embed_dim)
|
| 101 |
+
self.lm_head = RobertaLMHead(
|
| 102 |
+
embed_dim=self.args.embed_dim,
|
| 103 |
+
output_dim=self.alphabet_size,
|
| 104 |
+
weight=self.embed_tokens.weight,
|
| 105 |
+
)
|
| 106 |
+
|
| 107 |
+
def _init_submodules_esm1(self):
|
| 108 |
+
self._init_submodules_common()
|
| 109 |
+
self.embed_scale = math.sqrt(self.args.embed_dim)
|
| 110 |
+
self.embed_positions = SinusoidalPositionalEmbedding(self.args.embed_dim, self.padding_idx)
|
| 111 |
+
self.embed_out = nn.Parameter(torch.zeros((self.alphabet_size, self.args.embed_dim)))
|
| 112 |
+
self.embed_out_bias = None
|
| 113 |
+
if self.args.final_bias:
|
| 114 |
+
self.embed_out_bias = nn.Parameter(torch.zeros(self.alphabet_size))
|
| 115 |
+
|
| 116 |
+
def forward(self, tokens, repr_layers=[], need_head_weights=False, return_contacts=False):
|
| 117 |
+
if return_contacts:
|
| 118 |
+
need_head_weights = True
|
| 119 |
+
|
| 120 |
+
assert tokens.ndim == 2
|
| 121 |
+
padding_mask = tokens.eq(self.padding_idx) # B, T
|
| 122 |
+
|
| 123 |
+
x = self.embed_scale * self.embed_tokens(tokens)
|
| 124 |
+
|
| 125 |
+
if getattr(self.args, "token_dropout", False):
|
| 126 |
+
x.masked_fill_((tokens == self.mask_idx).unsqueeze(-1), 0.0)
|
| 127 |
+
# x: B x T x C
|
| 128 |
+
mask_ratio_train = 0.15 * 0.8
|
| 129 |
+
src_lengths = (~padding_mask).sum(-1)
|
| 130 |
+
mask_ratio_observed = (tokens == self.mask_idx).sum(-1).float() / src_lengths
|
| 131 |
+
x = x * (1 - mask_ratio_train) / (1 - mask_ratio_observed)[:, None, None]
|
| 132 |
+
|
| 133 |
+
x = x + self.embed_positions(tokens)
|
| 134 |
+
|
| 135 |
+
if self.model_version == "ESM-1b":
|
| 136 |
+
if self.emb_layer_norm_before:
|
| 137 |
+
x = self.emb_layer_norm_before(x)
|
| 138 |
+
if padding_mask is not None:
|
| 139 |
+
x = x * (1 - padding_mask.unsqueeze(-1).type_as(x))
|
| 140 |
+
|
| 141 |
+
repr_layers = set(repr_layers)
|
| 142 |
+
hidden_representations = {}
|
| 143 |
+
if 0 in repr_layers:
|
| 144 |
+
hidden_representations[0] = x
|
| 145 |
+
|
| 146 |
+
if need_head_weights:
|
| 147 |
+
attn_weights = []
|
| 148 |
+
|
| 149 |
+
# (B, T, E) => (T, B, E)
|
| 150 |
+
x = x.transpose(0, 1)
|
| 151 |
+
|
| 152 |
+
if not padding_mask.any():
|
| 153 |
+
padding_mask = None
|
| 154 |
+
|
| 155 |
+
for layer_idx, layer in enumerate(self.layers):
|
| 156 |
+
x, attn = layer(
|
| 157 |
+
x, self_attn_padding_mask=padding_mask, need_head_weights=need_head_weights
|
| 158 |
+
)
|
| 159 |
+
if (layer_idx + 1) in repr_layers:
|
| 160 |
+
hidden_representations[layer_idx + 1] = x.transpose(0, 1)
|
| 161 |
+
if need_head_weights:
|
| 162 |
+
# (H, B, T, T) => (B, H, T, T)
|
| 163 |
+
attn_weights.append(attn.transpose(1, 0))
|
| 164 |
+
|
| 165 |
+
if self.model_version == "ESM-1b":
|
| 166 |
+
x = self.emb_layer_norm_after(x)
|
| 167 |
+
x = x.transpose(0, 1) # (T, B, E) => (B, T, E)
|
| 168 |
+
|
| 169 |
+
# last hidden representation should have layer norm applied
|
| 170 |
+
if (layer_idx + 1) in repr_layers:
|
| 171 |
+
hidden_representations[layer_idx + 1] = x
|
| 172 |
+
x = self.lm_head(x)
|
| 173 |
+
else:
|
| 174 |
+
x = F.linear(x, self.embed_out, bias=self.embed_out_bias)
|
| 175 |
+
x = x.transpose(0, 1) # (T, B, E) => (B, T, E)
|
| 176 |
+
|
| 177 |
+
result = {"logits": x, "representations": hidden_representations}
|
| 178 |
+
if need_head_weights:
|
| 179 |
+
# attentions: B x L x H x T x T
|
| 180 |
+
attentions = torch.stack(attn_weights, 1)
|
| 181 |
+
if self.model_version == "ESM-1":
|
| 182 |
+
# ESM-1 models have an additional null-token for attention, which we remove
|
| 183 |
+
attentions = attentions[..., :-1]
|
| 184 |
+
if padding_mask is not None:
|
| 185 |
+
attention_mask = 1 - padding_mask.type_as(attentions)
|
| 186 |
+
attention_mask = attention_mask.unsqueeze(1) * attention_mask.unsqueeze(2)
|
| 187 |
+
attentions = attentions * attention_mask[:, None, None, :, :]
|
| 188 |
+
result["attentions"] = attentions
|
| 189 |
+
if return_contacts:
|
| 190 |
+
contacts = self.contact_head(tokens, attentions)
|
| 191 |
+
result["contacts"] = contacts
|
| 192 |
+
|
| 193 |
+
return result
|
| 194 |
+
|
| 195 |
+
def predict_contacts(self, tokens):
|
| 196 |
+
return self(tokens, return_contacts=True)["contacts"]
|
| 197 |
+
|
| 198 |
+
@property
|
| 199 |
+
def num_layers(self):
|
| 200 |
+
return self.args.layers
|
model/esm/esm2.py
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
| 2 |
+
#
|
| 3 |
+
# This source code is licensed under the MIT license found in the
|
| 4 |
+
# LICENSE file in the root directory of this source tree.
|
| 5 |
+
|
| 6 |
+
from typing import Union
|
| 7 |
+
import torch
|
| 8 |
+
import torch.nn as nn
|
| 9 |
+
|
| 10 |
+
from onescience.datapipes.esm import Alphabet
|
| 11 |
+
from onescience.modules.esm import (
|
| 12 |
+
ContactPredictionHead,
|
| 13 |
+
ESM1bLayerNorm,
|
| 14 |
+
RobertaLMHead,
|
| 15 |
+
TransformerLayer,
|
| 16 |
+
)
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
class ESM2(nn.Module):
|
| 20 |
+
def __init__(
|
| 21 |
+
self,
|
| 22 |
+
num_layers: int = 33,
|
| 23 |
+
embed_dim: int = 1280,
|
| 24 |
+
attention_heads: int = 20,
|
| 25 |
+
alphabet: Union[Alphabet, str] = "ESM-1b",
|
| 26 |
+
token_dropout: bool = True,
|
| 27 |
+
):
|
| 28 |
+
super().__init__()
|
| 29 |
+
self.num_layers = num_layers
|
| 30 |
+
self.embed_dim = embed_dim
|
| 31 |
+
self.attention_heads = attention_heads
|
| 32 |
+
if not isinstance(alphabet, Alphabet):
|
| 33 |
+
alphabet = Alphabet.from_architecture(alphabet)
|
| 34 |
+
self.alphabet = alphabet
|
| 35 |
+
self.alphabet_size = len(alphabet)
|
| 36 |
+
self.padding_idx = alphabet.padding_idx
|
| 37 |
+
self.mask_idx = alphabet.mask_idx
|
| 38 |
+
self.cls_idx = alphabet.cls_idx
|
| 39 |
+
self.eos_idx = alphabet.eos_idx
|
| 40 |
+
self.prepend_bos = alphabet.prepend_bos
|
| 41 |
+
self.append_eos = alphabet.append_eos
|
| 42 |
+
self.token_dropout = token_dropout
|
| 43 |
+
|
| 44 |
+
self._init_submodules()
|
| 45 |
+
|
| 46 |
+
def _init_submodules(self):
|
| 47 |
+
self.embed_scale = 1
|
| 48 |
+
self.embed_tokens = nn.Embedding(
|
| 49 |
+
self.alphabet_size,
|
| 50 |
+
self.embed_dim,
|
| 51 |
+
padding_idx=self.padding_idx,
|
| 52 |
+
)
|
| 53 |
+
|
| 54 |
+
self.layers = nn.ModuleList(
|
| 55 |
+
[
|
| 56 |
+
TransformerLayer(
|
| 57 |
+
self.embed_dim,
|
| 58 |
+
4 * self.embed_dim,
|
| 59 |
+
self.attention_heads,
|
| 60 |
+
add_bias_kv=False,
|
| 61 |
+
use_esm1b_layer_norm=True,
|
| 62 |
+
use_rotary_embeddings=True,
|
| 63 |
+
)
|
| 64 |
+
for _ in range(self.num_layers)
|
| 65 |
+
]
|
| 66 |
+
)
|
| 67 |
+
|
| 68 |
+
self.contact_head = ContactPredictionHead(
|
| 69 |
+
self.num_layers * self.attention_heads,
|
| 70 |
+
self.prepend_bos,
|
| 71 |
+
self.append_eos,
|
| 72 |
+
eos_idx=self.eos_idx,
|
| 73 |
+
)
|
| 74 |
+
self.emb_layer_norm_after = ESM1bLayerNorm(self.embed_dim)
|
| 75 |
+
|
| 76 |
+
self.lm_head = RobertaLMHead(
|
| 77 |
+
embed_dim=self.embed_dim,
|
| 78 |
+
output_dim=self.alphabet_size,
|
| 79 |
+
weight=self.embed_tokens.weight,
|
| 80 |
+
)
|
| 81 |
+
|
| 82 |
+
def forward(self, tokens, repr_layers=[], need_head_weights=False, return_contacts=False):
|
| 83 |
+
if return_contacts:
|
| 84 |
+
need_head_weights = True
|
| 85 |
+
|
| 86 |
+
assert tokens.ndim == 2
|
| 87 |
+
padding_mask = tokens.eq(self.padding_idx) # B, T
|
| 88 |
+
|
| 89 |
+
x = self.embed_scale * self.embed_tokens(tokens)
|
| 90 |
+
|
| 91 |
+
if self.token_dropout:
|
| 92 |
+
x.masked_fill_((tokens == self.mask_idx).unsqueeze(-1), 0.0)
|
| 93 |
+
# x: B x T x C
|
| 94 |
+
mask_ratio_train = 0.15 * 0.8
|
| 95 |
+
src_lengths = (~padding_mask).sum(-1)
|
| 96 |
+
mask_ratio_observed = (tokens == self.mask_idx).sum(-1).to(x.dtype) / src_lengths
|
| 97 |
+
x = x * (1 - mask_ratio_train) / (1 - mask_ratio_observed)[:, None, None]
|
| 98 |
+
|
| 99 |
+
if padding_mask is not None:
|
| 100 |
+
x = x * (1 - padding_mask.unsqueeze(-1).type_as(x))
|
| 101 |
+
|
| 102 |
+
repr_layers = set(repr_layers)
|
| 103 |
+
hidden_representations = {}
|
| 104 |
+
if 0 in repr_layers:
|
| 105 |
+
hidden_representations[0] = x
|
| 106 |
+
|
| 107 |
+
if need_head_weights:
|
| 108 |
+
attn_weights = []
|
| 109 |
+
|
| 110 |
+
# (B, T, E) => (T, B, E)
|
| 111 |
+
x = x.transpose(0, 1)
|
| 112 |
+
|
| 113 |
+
if not padding_mask.any():
|
| 114 |
+
padding_mask = None
|
| 115 |
+
|
| 116 |
+
for layer_idx, layer in enumerate(self.layers):
|
| 117 |
+
x, attn = layer(
|
| 118 |
+
x,
|
| 119 |
+
self_attn_padding_mask=padding_mask,
|
| 120 |
+
need_head_weights=need_head_weights,
|
| 121 |
+
)
|
| 122 |
+
if (layer_idx + 1) in repr_layers:
|
| 123 |
+
hidden_representations[layer_idx + 1] = x.transpose(0, 1)
|
| 124 |
+
if need_head_weights:
|
| 125 |
+
# (H, B, T, T) => (B, H, T, T)
|
| 126 |
+
attn_weights.append(attn.transpose(1, 0))
|
| 127 |
+
|
| 128 |
+
x = self.emb_layer_norm_after(x)
|
| 129 |
+
x = x.transpose(0, 1) # (T, B, E) => (B, T, E)
|
| 130 |
+
|
| 131 |
+
# last hidden representation should have layer norm applied
|
| 132 |
+
if (layer_idx + 1) in repr_layers:
|
| 133 |
+
hidden_representations[layer_idx + 1] = x
|
| 134 |
+
x = self.lm_head(x)
|
| 135 |
+
|
| 136 |
+
result = {"logits": x, "representations": hidden_representations}
|
| 137 |
+
if need_head_weights:
|
| 138 |
+
# attentions: B x L x H x T x T
|
| 139 |
+
attentions = torch.stack(attn_weights, 1)
|
| 140 |
+
if padding_mask is not None:
|
| 141 |
+
attention_mask = 1 - padding_mask.type_as(attentions)
|
| 142 |
+
attention_mask = attention_mask.unsqueeze(1) * attention_mask.unsqueeze(2)
|
| 143 |
+
attentions = attentions * attention_mask[:, None, None, :, :]
|
| 144 |
+
result["attentions"] = attentions
|
| 145 |
+
if return_contacts:
|
| 146 |
+
contacts = self.contact_head(tokens, attentions)
|
| 147 |
+
result["contacts"] = contacts
|
| 148 |
+
|
| 149 |
+
return result
|
| 150 |
+
|
| 151 |
+
def predict_contacts(self, tokens):
|
| 152 |
+
return self(tokens, return_contacts=True)["contacts"]
|
model/esm/esmfold/__init__.py
ADDED
|
File without changes
|
model/esm/esmfold/v1/__init__.py
ADDED
|
File without changes
|
model/esm/esmfold/v1/categorical_mixture.py
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
| 2 |
+
#
|
| 3 |
+
# This source code is licensed under the MIT license found in the
|
| 4 |
+
# LICENSE file in the root directory of this source tree.
|
| 5 |
+
import torch
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
class CategoricalMixture:
|
| 9 |
+
def __init__(self, param, bins=50, start=0, end=1):
|
| 10 |
+
# All tensors are of shape ..., bins.
|
| 11 |
+
self.logits = param
|
| 12 |
+
bins = torch.linspace(
|
| 13 |
+
start, end, bins + 1, device=self.logits.device, dtype=self.logits.dtype
|
| 14 |
+
)
|
| 15 |
+
self.v_bins = (bins[:-1] + bins[1:]) / 2
|
| 16 |
+
|
| 17 |
+
def log_prob(self, true):
|
| 18 |
+
# Shapes are:
|
| 19 |
+
# self.probs: ... x bins
|
| 20 |
+
# true : ...
|
| 21 |
+
true_index = (
|
| 22 |
+
(
|
| 23 |
+
true.unsqueeze(-1)
|
| 24 |
+
- self.v_bins[
|
| 25 |
+
[
|
| 26 |
+
None,
|
| 27 |
+
]
|
| 28 |
+
* true.ndim
|
| 29 |
+
]
|
| 30 |
+
)
|
| 31 |
+
.abs()
|
| 32 |
+
.argmin(-1)
|
| 33 |
+
)
|
| 34 |
+
nll = self.logits.log_softmax(-1)
|
| 35 |
+
return torch.take_along_dim(nll, true_index.unsqueeze(-1), dim=-1).squeeze(-1)
|
| 36 |
+
|
| 37 |
+
def mean(self):
|
| 38 |
+
return (self.logits.softmax(-1) @ self.v_bins.unsqueeze(1)).squeeze(-1)
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
def categorical_lddt(logits, bins=50):
|
| 42 |
+
# Logits are ..., 37, bins.
|
| 43 |
+
return CategoricalMixture(logits, bins=bins).mean()
|
model/esm/esmfold/v1/esmfold.py
ADDED
|
@@ -0,0 +1,364 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
| 2 |
+
#
|
| 3 |
+
# This source code is licensed under the MIT license found in the
|
| 4 |
+
# LICENSE file in the root directory of this source tree.
|
| 5 |
+
import typing as T
|
| 6 |
+
from dataclasses import dataclass, field
|
| 7 |
+
from functools import partial
|
| 8 |
+
|
| 9 |
+
import torch
|
| 10 |
+
import torch.nn as nn
|
| 11 |
+
from torch import nn
|
| 12 |
+
from torch.nn import LayerNorm
|
| 13 |
+
|
| 14 |
+
import model.esm as esm
|
| 15 |
+
from model.esm import Alphabet
|
| 16 |
+
from model.esm.esmfold.v1.categorical_mixture import categorical_lddt
|
| 17 |
+
from model.esm.esmfold.v1.misc import (
|
| 18 |
+
batch_encode_sequences,
|
| 19 |
+
collate_dense_tensors,
|
| 20 |
+
output_to_pdb,
|
| 21 |
+
)
|
| 22 |
+
from model.esm.esmfold.v1.trunk import FoldingTrunk, FoldingTrunkConfig
|
| 23 |
+
from onescience.datapipes.openfold.data_transforms import make_atom14_masks
|
| 24 |
+
from onescience.utils.openfold.np import residue_constants
|
| 25 |
+
from onescience.utils.openfold.loss import compute_predicted_aligned_error, compute_tm
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
@dataclass
|
| 29 |
+
class ESMFoldConfig:
|
| 30 |
+
trunk: T.Any = field(default_factory=FoldingTrunkConfig)
|
| 31 |
+
lddt_head_hid_dim: int = 128
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
load_fn = esm.pretrained.load_model_and_alphabet
|
| 35 |
+
esm_registry = {
|
| 36 |
+
"esm2_8M": partial(load_fn, "esm2_t6_8M_UR50D_500K"),
|
| 37 |
+
"esm2_8M_270K": esm.pretrained.esm2_t6_8M_UR50D,
|
| 38 |
+
"esm2_35M": partial(load_fn, "esm2_t12_35M_UR50D_500K"),
|
| 39 |
+
"esm2_35M_270K": esm.pretrained.esm2_t12_35M_UR50D,
|
| 40 |
+
"esm2_150M": partial(load_fn, "esm2_t30_150M_UR50D_500K"),
|
| 41 |
+
"esm2_150M_270K": partial(load_fn, "esm2_t30_150M_UR50D_270K"),
|
| 42 |
+
"esm2_650M": esm.pretrained.esm2_t33_650M_UR50D,
|
| 43 |
+
"esm2_650M_270K": partial(load_fn, "esm2_t33_650M_270K_UR50D"),
|
| 44 |
+
"esm2_3B": esm.pretrained.esm2_t36_3B_UR50D,
|
| 45 |
+
"esm2_3B_270K": partial(load_fn, "esm2_t36_3B_UR50D_500K"),
|
| 46 |
+
"esm2_15B": esm.pretrained.esm2_t48_15B_UR50D,
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
class ESMFold(nn.Module):
|
| 51 |
+
def __init__(self, esmfold_config=None, **kwargs):
|
| 52 |
+
super().__init__()
|
| 53 |
+
|
| 54 |
+
self.cfg = esmfold_config if esmfold_config else ESMFoldConfig(**kwargs)
|
| 55 |
+
cfg = self.cfg
|
| 56 |
+
|
| 57 |
+
self.distogram_bins = 64
|
| 58 |
+
|
| 59 |
+
self.esm, self.esm_dict = esm_registry.get(cfg.esm_type)()
|
| 60 |
+
|
| 61 |
+
self.esm.requires_grad_(False)
|
| 62 |
+
self.esm.half()
|
| 63 |
+
|
| 64 |
+
self.esm_feats = self.esm.embed_dim
|
| 65 |
+
self.esm_attns = self.esm.num_layers * self.esm.attention_heads
|
| 66 |
+
self.register_buffer("af2_to_esm", ESMFold._af2_to_esm(self.esm_dict))
|
| 67 |
+
self.esm_s_combine = nn.Parameter(torch.zeros(self.esm.num_layers + 1))
|
| 68 |
+
|
| 69 |
+
c_s = cfg.trunk.sequence_state_dim
|
| 70 |
+
c_z = cfg.trunk.pairwise_state_dim
|
| 71 |
+
|
| 72 |
+
self.esm_s_mlp = nn.Sequential(
|
| 73 |
+
LayerNorm(self.esm_feats),
|
| 74 |
+
nn.Linear(self.esm_feats, c_s),
|
| 75 |
+
nn.ReLU(),
|
| 76 |
+
nn.Linear(c_s, c_s),
|
| 77 |
+
)
|
| 78 |
+
if cfg.use_esm_attn_map:
|
| 79 |
+
self.esm_z_mlp = nn.Sequential(
|
| 80 |
+
LayerNorm(self.esm_attns),
|
| 81 |
+
nn.Linear(self.esm_attns, c_z),
|
| 82 |
+
nn.ReLU(),
|
| 83 |
+
nn.Linear(c_z, c_z),
|
| 84 |
+
)
|
| 85 |
+
|
| 86 |
+
# 0 is padding, N is unknown residues, N + 1 is mask.
|
| 87 |
+
self.n_tokens_embed = residue_constants.restype_num + 3
|
| 88 |
+
self.pad_idx = 0
|
| 89 |
+
self.unk_idx = self.n_tokens_embed - 2
|
| 90 |
+
self.mask_idx = self.n_tokens_embed - 1
|
| 91 |
+
self.embedding = nn.Embedding(self.n_tokens_embed, c_s, padding_idx=0)
|
| 92 |
+
|
| 93 |
+
self.trunk = FoldingTrunk(**cfg.trunk)
|
| 94 |
+
|
| 95 |
+
self.distogram_head = nn.Linear(c_z, self.distogram_bins)
|
| 96 |
+
self.ptm_head = nn.Linear(c_z, self.distogram_bins)
|
| 97 |
+
self.lm_head = nn.Linear(c_s, self.n_tokens_embed)
|
| 98 |
+
self.lddt_bins = 50
|
| 99 |
+
self.lddt_head = nn.Sequential(
|
| 100 |
+
nn.LayerNorm(cfg.trunk.structure_module.c_s),
|
| 101 |
+
nn.Linear(cfg.trunk.structure_module.c_s, cfg.lddt_head_hid_dim),
|
| 102 |
+
nn.Linear(cfg.lddt_head_hid_dim, cfg.lddt_head_hid_dim),
|
| 103 |
+
nn.Linear(cfg.lddt_head_hid_dim, 37 * self.lddt_bins),
|
| 104 |
+
)
|
| 105 |
+
|
| 106 |
+
@staticmethod
|
| 107 |
+
def _af2_to_esm(d: Alphabet):
|
| 108 |
+
# Remember that t is shifted from residue_constants by 1 (0 is padding).
|
| 109 |
+
esm_reorder = [d.padding_idx] + [
|
| 110 |
+
d.get_idx(v) for v in residue_constants.restypes_with_x
|
| 111 |
+
]
|
| 112 |
+
return torch.tensor(esm_reorder)
|
| 113 |
+
|
| 114 |
+
def _af2_idx_to_esm_idx(self, aa, mask):
|
| 115 |
+
aa = (aa + 1).masked_fill(mask != 1, 0)
|
| 116 |
+
return self.af2_to_esm[aa]
|
| 117 |
+
|
| 118 |
+
def _compute_language_model_representations(
|
| 119 |
+
self, esmaa: torch.Tensor
|
| 120 |
+
) -> torch.Tensor:
|
| 121 |
+
"""Adds bos/eos tokens for the language model, since the structure module doesn't use these."""
|
| 122 |
+
batch_size = esmaa.size(0)
|
| 123 |
+
|
| 124 |
+
bosi, eosi = self.esm_dict.cls_idx, self.esm_dict.eos_idx
|
| 125 |
+
bos = esmaa.new_full((batch_size, 1), bosi)
|
| 126 |
+
eos = esmaa.new_full((batch_size, 1), self.esm_dict.padding_idx)
|
| 127 |
+
esmaa = torch.cat([bos, esmaa, eos], dim=1)
|
| 128 |
+
# Use the first padding index as eos during inference.
|
| 129 |
+
esmaa[range(batch_size), (esmaa != 1).sum(1)] = eosi
|
| 130 |
+
|
| 131 |
+
res = self.esm(
|
| 132 |
+
esmaa,
|
| 133 |
+
repr_layers=range(self.esm.num_layers + 1),
|
| 134 |
+
need_head_weights=self.cfg.use_esm_attn_map,
|
| 135 |
+
)
|
| 136 |
+
esm_s = torch.stack(
|
| 137 |
+
[v for _, v in sorted(res["representations"].items())], dim=2
|
| 138 |
+
)
|
| 139 |
+
esm_s = esm_s[:, 1:-1] # B, L, nLayers, C
|
| 140 |
+
esm_z = (
|
| 141 |
+
res["attentions"].permute(0, 4, 3, 1, 2).flatten(3, 4)[:, 1:-1, 1:-1, :]
|
| 142 |
+
if self.cfg.use_esm_attn_map
|
| 143 |
+
else None
|
| 144 |
+
)
|
| 145 |
+
return esm_s, esm_z
|
| 146 |
+
|
| 147 |
+
def _mask_inputs_to_esm(self, esmaa, pattern):
|
| 148 |
+
new_esmaa = esmaa.clone()
|
| 149 |
+
new_esmaa[pattern == 1] = self.esm_dict.mask_idx
|
| 150 |
+
return new_esmaa
|
| 151 |
+
|
| 152 |
+
def forward(
|
| 153 |
+
self,
|
| 154 |
+
aa: torch.Tensor,
|
| 155 |
+
mask: T.Optional[torch.Tensor] = None,
|
| 156 |
+
residx: T.Optional[torch.Tensor] = None,
|
| 157 |
+
masking_pattern: T.Optional[torch.Tensor] = None,
|
| 158 |
+
num_recycles: T.Optional[int] = None,
|
| 159 |
+
):
|
| 160 |
+
"""Runs a forward pass given input tokens. Use `model.infer` to
|
| 161 |
+
run inference from a sequence.
|
| 162 |
+
|
| 163 |
+
Args:
|
| 164 |
+
aa (torch.Tensor): Tensor containing indices corresponding to amino acids. Indices match
|
| 165 |
+
onescience.utils.openfold.np.residue_constants.restype_order_with_x.
|
| 166 |
+
mask (torch.Tensor): Binary tensor with 1 meaning position is unmasked and 0 meaning position is masked.
|
| 167 |
+
residx (torch.Tensor): Residue indices of amino acids. Will assume contiguous if not provided.
|
| 168 |
+
masking_pattern (torch.Tensor): Optional masking to pass to the input. Binary tensor of the same size
|
| 169 |
+
as `aa`. Positions with 1 will be masked. ESMFold sometimes produces different samples when
|
| 170 |
+
different masks are provided.
|
| 171 |
+
num_recycles (int): How many recycle iterations to perform. If None, defaults to training max
|
| 172 |
+
recycles, which is 3.
|
| 173 |
+
"""
|
| 174 |
+
|
| 175 |
+
if mask is None:
|
| 176 |
+
mask = torch.ones_like(aa)
|
| 177 |
+
|
| 178 |
+
B = aa.shape[0]
|
| 179 |
+
L = aa.shape[1]
|
| 180 |
+
device = aa.device
|
| 181 |
+
|
| 182 |
+
if residx is None:
|
| 183 |
+
residx = torch.arange(L, device=device).expand_as(aa)
|
| 184 |
+
|
| 185 |
+
# === ESM ===
|
| 186 |
+
esmaa = self._af2_idx_to_esm_idx(aa, mask)
|
| 187 |
+
|
| 188 |
+
if masking_pattern is not None:
|
| 189 |
+
esmaa = self._mask_inputs_to_esm(esmaa, masking_pattern)
|
| 190 |
+
|
| 191 |
+
esm_s, esm_z = self._compute_language_model_representations(esmaa)
|
| 192 |
+
|
| 193 |
+
# Convert esm_s to the precision used by the trunk and
|
| 194 |
+
# the structure module. These tensors may be a lower precision if, for example,
|
| 195 |
+
# we're running the language model in fp16 precision.
|
| 196 |
+
esm_s = esm_s.to(self.esm_s_combine.dtype)
|
| 197 |
+
esm_s = esm_s.detach()
|
| 198 |
+
|
| 199 |
+
# === preprocessing ===
|
| 200 |
+
esm_s = (self.esm_s_combine.softmax(0).unsqueeze(0) @ esm_s).squeeze(2)
|
| 201 |
+
|
| 202 |
+
s_s_0 = self.esm_s_mlp(esm_s)
|
| 203 |
+
if self.cfg.use_esm_attn_map:
|
| 204 |
+
esm_z = esm_z.to(self.esm_s_combine.dtype)
|
| 205 |
+
esm_z = esm_z.detach()
|
| 206 |
+
s_z_0 = self.esm_z_mlp(esm_z)
|
| 207 |
+
else:
|
| 208 |
+
s_z_0 = s_s_0.new_zeros(B, L, L, self.cfg.trunk.pairwise_state_dim)
|
| 209 |
+
|
| 210 |
+
s_s_0 += self.embedding(aa)
|
| 211 |
+
|
| 212 |
+
structure: dict = self.trunk(
|
| 213 |
+
s_s_0, s_z_0, aa, residx, mask, no_recycles=num_recycles
|
| 214 |
+
)
|
| 215 |
+
# Documenting what we expect:
|
| 216 |
+
structure = {
|
| 217 |
+
k: v
|
| 218 |
+
for k, v in structure.items()
|
| 219 |
+
if k
|
| 220 |
+
in [
|
| 221 |
+
"s_z",
|
| 222 |
+
"s_s",
|
| 223 |
+
"frames",
|
| 224 |
+
"sidechain_frames",
|
| 225 |
+
"unnormalized_angles",
|
| 226 |
+
"angles",
|
| 227 |
+
"positions",
|
| 228 |
+
"states",
|
| 229 |
+
]
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
disto_logits = self.distogram_head(structure["s_z"])
|
| 233 |
+
disto_logits = (disto_logits + disto_logits.transpose(1, 2)) / 2
|
| 234 |
+
structure["distogram_logits"] = disto_logits
|
| 235 |
+
|
| 236 |
+
lm_logits = self.lm_head(structure["s_s"])
|
| 237 |
+
structure["lm_logits"] = lm_logits
|
| 238 |
+
|
| 239 |
+
structure["aatype"] = aa
|
| 240 |
+
make_atom14_masks(structure)
|
| 241 |
+
|
| 242 |
+
for k in [
|
| 243 |
+
"atom14_atom_exists",
|
| 244 |
+
"atom37_atom_exists",
|
| 245 |
+
]:
|
| 246 |
+
structure[k] *= mask.unsqueeze(-1)
|
| 247 |
+
structure["residue_index"] = residx
|
| 248 |
+
|
| 249 |
+
lddt_head = self.lddt_head(structure["states"]).reshape(
|
| 250 |
+
structure["states"].shape[0], B, L, -1, self.lddt_bins
|
| 251 |
+
)
|
| 252 |
+
structure["lddt_head"] = lddt_head
|
| 253 |
+
plddt = categorical_lddt(lddt_head[-1], bins=self.lddt_bins)
|
| 254 |
+
structure["plddt"] = (
|
| 255 |
+
100 * plddt
|
| 256 |
+
) # we predict plDDT between 0 and 1, scale to be between 0 and 100.
|
| 257 |
+
|
| 258 |
+
ptm_logits = self.ptm_head(structure["s_z"])
|
| 259 |
+
|
| 260 |
+
seqlen = mask.type(torch.int64).sum(1)
|
| 261 |
+
structure["ptm_logits"] = ptm_logits
|
| 262 |
+
structure["ptm"] = torch.stack(
|
| 263 |
+
[
|
| 264 |
+
compute_tm(
|
| 265 |
+
batch_ptm_logits[None, :sl, :sl],
|
| 266 |
+
max_bins=31,
|
| 267 |
+
no_bins=self.distogram_bins,
|
| 268 |
+
)
|
| 269 |
+
for batch_ptm_logits, sl in zip(ptm_logits, seqlen)
|
| 270 |
+
]
|
| 271 |
+
)
|
| 272 |
+
structure.update(
|
| 273 |
+
compute_predicted_aligned_error(
|
| 274 |
+
ptm_logits, max_bin=31, no_bins=self.distogram_bins
|
| 275 |
+
)
|
| 276 |
+
)
|
| 277 |
+
|
| 278 |
+
return structure
|
| 279 |
+
|
| 280 |
+
@torch.no_grad()
|
| 281 |
+
def infer(
|
| 282 |
+
self,
|
| 283 |
+
sequences: T.Union[str, T.List[str]],
|
| 284 |
+
residx=None,
|
| 285 |
+
masking_pattern: T.Optional[torch.Tensor] = None,
|
| 286 |
+
num_recycles: T.Optional[int] = None,
|
| 287 |
+
residue_index_offset: T.Optional[int] = 512,
|
| 288 |
+
chain_linker: T.Optional[str] = "G" * 25,
|
| 289 |
+
):
|
| 290 |
+
"""Runs a forward pass given input sequences.
|
| 291 |
+
|
| 292 |
+
Args:
|
| 293 |
+
sequences (Union[str, List[str]]): A list of sequences to make predictions for. Multimers can also be passed in,
|
| 294 |
+
each chain should be separated by a ':' token (e.g. "<chain1>:<chain2>:<chain3>").
|
| 295 |
+
residx (torch.Tensor): Residue indices of amino acids. Will assume contiguous if not provided.
|
| 296 |
+
masking_pattern (torch.Tensor): Optional masking to pass to the input. Binary tensor of the same size
|
| 297 |
+
as `aa`. Positions with 1 will be masked. ESMFold sometimes produces different samples when
|
| 298 |
+
different masks are provided.
|
| 299 |
+
num_recycles (int): How many recycle iterations to perform. If None, defaults to training max
|
| 300 |
+
recycles (cfg.trunk.max_recycles), which is 4.
|
| 301 |
+
residue_index_offset (int): Residue index separation between chains if predicting a multimer. Has no effect on
|
| 302 |
+
single chain predictions. Default: 512.
|
| 303 |
+
chain_linker (str): Linker to use between chains if predicting a multimer. Has no effect on single chain
|
| 304 |
+
predictions. Default: length-25 poly-G ("G" * 25).
|
| 305 |
+
"""
|
| 306 |
+
if isinstance(sequences, str):
|
| 307 |
+
sequences = [sequences]
|
| 308 |
+
|
| 309 |
+
aatype, mask, _residx, linker_mask, chain_index = batch_encode_sequences(
|
| 310 |
+
sequences, residue_index_offset, chain_linker
|
| 311 |
+
)
|
| 312 |
+
|
| 313 |
+
if residx is None:
|
| 314 |
+
residx = _residx
|
| 315 |
+
elif not isinstance(residx, torch.Tensor):
|
| 316 |
+
residx = collate_dense_tensors(residx)
|
| 317 |
+
|
| 318 |
+
aatype, mask, residx, linker_mask = map(
|
| 319 |
+
lambda x: x.to(self.device), (aatype, mask, residx, linker_mask)
|
| 320 |
+
)
|
| 321 |
+
|
| 322 |
+
output = self.forward(
|
| 323 |
+
aatype,
|
| 324 |
+
mask=mask,
|
| 325 |
+
residx=residx,
|
| 326 |
+
masking_pattern=masking_pattern,
|
| 327 |
+
num_recycles=num_recycles,
|
| 328 |
+
)
|
| 329 |
+
|
| 330 |
+
output["atom37_atom_exists"] = output[
|
| 331 |
+
"atom37_atom_exists"
|
| 332 |
+
] * linker_mask.unsqueeze(2)
|
| 333 |
+
|
| 334 |
+
output["mean_plddt"] = (output["plddt"] * output["atom37_atom_exists"]).sum(
|
| 335 |
+
dim=(1, 2)
|
| 336 |
+
) / output["atom37_atom_exists"].sum(dim=(1, 2))
|
| 337 |
+
output["chain_index"] = chain_index
|
| 338 |
+
|
| 339 |
+
return output
|
| 340 |
+
|
| 341 |
+
def output_to_pdb(self, output: T.Dict) -> T.List[str]:
|
| 342 |
+
"""Returns the pbd (file) string from the model given the model output."""
|
| 343 |
+
return output_to_pdb(output)
|
| 344 |
+
|
| 345 |
+
def infer_pdbs(self, seqs: T.List[str], *args, **kwargs) -> T.List[str]:
|
| 346 |
+
"""Returns list of pdb (files) strings from the model given a list of input sequences."""
|
| 347 |
+
output = self.infer(seqs, *args, **kwargs)
|
| 348 |
+
return self.output_to_pdb(output)
|
| 349 |
+
|
| 350 |
+
def infer_pdb(self, sequence: str, *args, **kwargs) -> str:
|
| 351 |
+
"""Returns the pdb (file) string from the model given an input sequence."""
|
| 352 |
+
return self.infer_pdbs([sequence], *args, **kwargs)[0]
|
| 353 |
+
|
| 354 |
+
def set_chunk_size(self, chunk_size: T.Optional[int]):
|
| 355 |
+
# This parameter means the axial attention will be computed
|
| 356 |
+
# in a chunked manner. This should make the memory used more or less O(L) instead of O(L^2).
|
| 357 |
+
# It's equivalent to running a for loop over chunks of the dimension we're iterative over,
|
| 358 |
+
# where the chunk_size is the size of the chunks, so 128 would mean to parse 128-lengthed chunks.
|
| 359 |
+
# Setting the value to None will return to default behavior, disable chunking.
|
| 360 |
+
self.trunk.set_chunk_size(chunk_size)
|
| 361 |
+
|
| 362 |
+
@property
|
| 363 |
+
def device(self):
|
| 364 |
+
return self.esm_s_combine.device
|
model/esm/esmfold/v1/misc.py
ADDED
|
@@ -0,0 +1,309 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
| 2 |
+
#
|
| 3 |
+
# This source code is licensed under the MIT license found in the
|
| 4 |
+
# LICENSE file in the root directory of this source tree.
|
| 5 |
+
import typing as T
|
| 6 |
+
|
| 7 |
+
import numpy as np
|
| 8 |
+
import torch
|
| 9 |
+
import torch.nn.functional as F
|
| 10 |
+
from einops import rearrange, repeat
|
| 11 |
+
from torch import nn
|
| 12 |
+
from onescience.utils.openfold.np import residue_constants
|
| 13 |
+
from onescience.utils.openfold.np.protein import Protein as OFProtein
|
| 14 |
+
from onescience.utils.openfold.np.protein import to_pdb
|
| 15 |
+
from onescience.utils.openfold.feats import atom14_to_atom37
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
def encode_sequence(
|
| 19 |
+
seq: str,
|
| 20 |
+
residue_index_offset: T.Optional[int] = 512,
|
| 21 |
+
chain_linker: T.Optional[str] = "G" * 25,
|
| 22 |
+
) -> T.Tuple[torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor]:
|
| 23 |
+
if chain_linker is None:
|
| 24 |
+
chain_linker = ""
|
| 25 |
+
if residue_index_offset is None:
|
| 26 |
+
residue_index_offset = 0
|
| 27 |
+
|
| 28 |
+
chains = seq.split(":")
|
| 29 |
+
seq = chain_linker.join(chains)
|
| 30 |
+
|
| 31 |
+
unk_idx = residue_constants.restype_order_with_x["X"]
|
| 32 |
+
encoded = torch.tensor(
|
| 33 |
+
[residue_constants.restype_order_with_x.get(aa, unk_idx) for aa in seq]
|
| 34 |
+
)
|
| 35 |
+
residx = torch.arange(len(encoded))
|
| 36 |
+
|
| 37 |
+
if residue_index_offset > 0:
|
| 38 |
+
start = 0
|
| 39 |
+
for i, chain in enumerate(chains):
|
| 40 |
+
residx[start : start + len(chain) + len(chain_linker)] += (
|
| 41 |
+
i * residue_index_offset
|
| 42 |
+
)
|
| 43 |
+
start += len(chain) + len(chain_linker)
|
| 44 |
+
|
| 45 |
+
linker_mask = torch.ones_like(encoded, dtype=torch.float32)
|
| 46 |
+
chain_index = []
|
| 47 |
+
offset = 0
|
| 48 |
+
for i, chain in enumerate(chains):
|
| 49 |
+
if i > 0:
|
| 50 |
+
chain_index.extend([i - 1] * len(chain_linker))
|
| 51 |
+
chain_index.extend([i] * len(chain))
|
| 52 |
+
offset += len(chain)
|
| 53 |
+
linker_mask[offset : offset + len(chain_linker)] = 0
|
| 54 |
+
offset += len(chain_linker)
|
| 55 |
+
|
| 56 |
+
chain_index = torch.tensor(chain_index, dtype=torch.int64)
|
| 57 |
+
|
| 58 |
+
return encoded, residx, linker_mask, chain_index
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
def batch_encode_sequences(
|
| 62 |
+
sequences: T.Sequence[str],
|
| 63 |
+
residue_index_offset: T.Optional[int] = 512,
|
| 64 |
+
chain_linker: T.Optional[str] = "G" * 25,
|
| 65 |
+
) -> T.Tuple[torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor]:
|
| 66 |
+
|
| 67 |
+
aatype_list = []
|
| 68 |
+
residx_list = []
|
| 69 |
+
linker_mask_list = []
|
| 70 |
+
chain_index_list = []
|
| 71 |
+
for seq in sequences:
|
| 72 |
+
aatype_seq, residx_seq, linker_mask_seq, chain_index_seq = encode_sequence(
|
| 73 |
+
seq,
|
| 74 |
+
residue_index_offset=residue_index_offset,
|
| 75 |
+
chain_linker=chain_linker,
|
| 76 |
+
)
|
| 77 |
+
aatype_list.append(aatype_seq)
|
| 78 |
+
residx_list.append(residx_seq)
|
| 79 |
+
linker_mask_list.append(linker_mask_seq)
|
| 80 |
+
chain_index_list.append(chain_index_seq)
|
| 81 |
+
|
| 82 |
+
aatype = collate_dense_tensors(aatype_list)
|
| 83 |
+
mask = collate_dense_tensors(
|
| 84 |
+
[aatype.new_ones(len(aatype_seq)) for aatype_seq in aatype_list]
|
| 85 |
+
)
|
| 86 |
+
residx = collate_dense_tensors(residx_list)
|
| 87 |
+
linker_mask = collate_dense_tensors(linker_mask_list)
|
| 88 |
+
chain_index_list = collate_dense_tensors(chain_index_list, -1)
|
| 89 |
+
|
| 90 |
+
return aatype, mask, residx, linker_mask, chain_index_list
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
def output_to_pdb(output: T.Dict) -> T.List[str]:
|
| 94 |
+
"""Returns the pbd (file) string from the model given the model output."""
|
| 95 |
+
# atom14_to_atom37 must be called first, as it fails on latest numpy if the
|
| 96 |
+
# input is a numpy array. It will work if the input is a torch tensor.
|
| 97 |
+
final_atom_positions = atom14_to_atom37(output["positions"][-1], output)
|
| 98 |
+
output = {k: v.to("cpu").numpy() for k, v in output.items()}
|
| 99 |
+
final_atom_positions = final_atom_positions.cpu().numpy()
|
| 100 |
+
final_atom_mask = output["atom37_atom_exists"]
|
| 101 |
+
pdbs = []
|
| 102 |
+
for i in range(output["aatype"].shape[0]):
|
| 103 |
+
aa = output["aatype"][i]
|
| 104 |
+
pred_pos = final_atom_positions[i]
|
| 105 |
+
mask = final_atom_mask[i]
|
| 106 |
+
resid = output["residue_index"][i] + 1
|
| 107 |
+
pred = OFProtein(
|
| 108 |
+
aatype=aa,
|
| 109 |
+
atom_positions=pred_pos,
|
| 110 |
+
atom_mask=mask,
|
| 111 |
+
residue_index=resid,
|
| 112 |
+
b_factors=output["plddt"][i],
|
| 113 |
+
chain_index=output["chain_index"][i] if "chain_index" in output else None,
|
| 114 |
+
)
|
| 115 |
+
pdbs.append(to_pdb(pred))
|
| 116 |
+
return pdbs
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
def collate_dense_tensors(
|
| 120 |
+
samples: T.List[torch.Tensor], pad_v: float = 0
|
| 121 |
+
) -> torch.Tensor:
|
| 122 |
+
"""
|
| 123 |
+
Takes a list of tensors with the following dimensions:
|
| 124 |
+
[(d_11, ..., d_1K),
|
| 125 |
+
(d_21, ..., d_2K),
|
| 126 |
+
...,
|
| 127 |
+
(d_N1, ..., d_NK)]
|
| 128 |
+
and stack + pads them into a single tensor of:
|
| 129 |
+
(N, max_i=1,N { d_i1 }, ..., max_i=1,N {diK})
|
| 130 |
+
"""
|
| 131 |
+
if len(samples) == 0:
|
| 132 |
+
return torch.Tensor()
|
| 133 |
+
if len(set(x.dim() for x in samples)) != 1:
|
| 134 |
+
raise RuntimeError(
|
| 135 |
+
f"Samples has varying dimensions: {[x.dim() for x in samples]}"
|
| 136 |
+
)
|
| 137 |
+
(device,) = tuple(set(x.device for x in samples)) # assumes all on same device
|
| 138 |
+
max_shape = [max(lst) for lst in zip(*[x.shape for x in samples])]
|
| 139 |
+
result = torch.empty(
|
| 140 |
+
len(samples), *max_shape, dtype=samples[0].dtype, device=device
|
| 141 |
+
)
|
| 142 |
+
result.fill_(pad_v)
|
| 143 |
+
for i in range(len(samples)):
|
| 144 |
+
result_i = result[i]
|
| 145 |
+
t = samples[i]
|
| 146 |
+
result_i[tuple(slice(0, k) for k in t.shape)] = t
|
| 147 |
+
return result
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
class Attention(nn.Module):
|
| 151 |
+
def __init__(self, embed_dim, num_heads, head_width, gated=False):
|
| 152 |
+
super().__init__()
|
| 153 |
+
assert embed_dim == num_heads * head_width
|
| 154 |
+
|
| 155 |
+
self.embed_dim = embed_dim
|
| 156 |
+
self.num_heads = num_heads
|
| 157 |
+
self.head_width = head_width
|
| 158 |
+
|
| 159 |
+
self.proj = nn.Linear(embed_dim, embed_dim * 3, bias=False)
|
| 160 |
+
self.o_proj = nn.Linear(embed_dim, embed_dim, bias=True)
|
| 161 |
+
self.gated = gated
|
| 162 |
+
if gated:
|
| 163 |
+
self.g_proj = nn.Linear(embed_dim, embed_dim)
|
| 164 |
+
torch.nn.init.zeros_(self.g_proj.weight)
|
| 165 |
+
torch.nn.init.ones_(self.g_proj.bias)
|
| 166 |
+
|
| 167 |
+
self.rescale_factor = self.head_width**-0.5
|
| 168 |
+
|
| 169 |
+
torch.nn.init.zeros_(self.o_proj.bias)
|
| 170 |
+
|
| 171 |
+
def forward(self, x, mask=None, bias=None, indices=None):
|
| 172 |
+
"""
|
| 173 |
+
Basic self attention with optional mask and external pairwise bias.
|
| 174 |
+
To handle sequences of different lengths, use mask.
|
| 175 |
+
|
| 176 |
+
Inputs:
|
| 177 |
+
x: batch of input sequneces (.. x L x C)
|
| 178 |
+
mask: batch of boolean masks where 1=valid, 0=padding position (.. x L_k). optional.
|
| 179 |
+
bias: batch of scalar pairwise attention biases (.. x Lq x Lk x num_heads). optional.
|
| 180 |
+
|
| 181 |
+
Outputs:
|
| 182 |
+
sequence projection (B x L x embed_dim), attention maps (B x L x L x num_heads)
|
| 183 |
+
"""
|
| 184 |
+
|
| 185 |
+
t = rearrange(self.proj(x), "... l (h c) -> ... h l c", h=self.num_heads)
|
| 186 |
+
q, k, v = t.chunk(3, dim=-1)
|
| 187 |
+
|
| 188 |
+
q = self.rescale_factor * q
|
| 189 |
+
a = torch.einsum("...qc,...kc->...qk", q, k)
|
| 190 |
+
|
| 191 |
+
# Add external attention bias.
|
| 192 |
+
if bias is not None:
|
| 193 |
+
a = a + rearrange(bias, "... lq lk h -> ... h lq lk")
|
| 194 |
+
|
| 195 |
+
# Do not attend to padding tokens.
|
| 196 |
+
if mask is not None:
|
| 197 |
+
mask = repeat(
|
| 198 |
+
mask, "... lk -> ... h lq lk", h=self.num_heads, lq=q.shape[-2]
|
| 199 |
+
)
|
| 200 |
+
a = a.masked_fill(mask == False, -np.inf)
|
| 201 |
+
|
| 202 |
+
a = F.softmax(a, dim=-1)
|
| 203 |
+
|
| 204 |
+
y = torch.einsum("...hqk,...hkc->...qhc", a, v)
|
| 205 |
+
y = rearrange(y, "... h c -> ... (h c)", h=self.num_heads)
|
| 206 |
+
|
| 207 |
+
if self.gated:
|
| 208 |
+
y = self.g_proj(x).sigmoid() * y
|
| 209 |
+
y = self.o_proj(y)
|
| 210 |
+
|
| 211 |
+
return y, rearrange(a, "... lq lk h -> ... h lq lk")
|
| 212 |
+
|
| 213 |
+
|
| 214 |
+
class Dropout(nn.Module):
|
| 215 |
+
"""
|
| 216 |
+
Implementation of dropout with the ability to share the dropout mask
|
| 217 |
+
along a particular dimension.
|
| 218 |
+
"""
|
| 219 |
+
|
| 220 |
+
def __init__(self, r: float, batch_dim: T.Union[int, T.List[int]]):
|
| 221 |
+
super(Dropout, self).__init__()
|
| 222 |
+
|
| 223 |
+
self.r = r
|
| 224 |
+
if type(batch_dim) == int:
|
| 225 |
+
batch_dim = [batch_dim]
|
| 226 |
+
self.batch_dim = batch_dim
|
| 227 |
+
self.dropout = nn.Dropout(self.r)
|
| 228 |
+
|
| 229 |
+
def forward(self, x: torch.Tensor) -> torch.Tensor:
|
| 230 |
+
shape = list(x.shape)
|
| 231 |
+
if self.batch_dim is not None:
|
| 232 |
+
for bd in self.batch_dim:
|
| 233 |
+
shape[bd] = 1
|
| 234 |
+
return x * self.dropout(x.new_ones(shape))
|
| 235 |
+
|
| 236 |
+
|
| 237 |
+
class SequenceToPair(nn.Module):
|
| 238 |
+
def __init__(self, sequence_state_dim, inner_dim, pairwise_state_dim):
|
| 239 |
+
super().__init__()
|
| 240 |
+
|
| 241 |
+
self.layernorm = nn.LayerNorm(sequence_state_dim)
|
| 242 |
+
self.proj = nn.Linear(sequence_state_dim, inner_dim * 2, bias=True)
|
| 243 |
+
self.o_proj = nn.Linear(2 * inner_dim, pairwise_state_dim, bias=True)
|
| 244 |
+
|
| 245 |
+
torch.nn.init.zeros_(self.proj.bias)
|
| 246 |
+
torch.nn.init.zeros_(self.o_proj.bias)
|
| 247 |
+
|
| 248 |
+
def forward(self, sequence_state):
|
| 249 |
+
"""
|
| 250 |
+
Inputs:
|
| 251 |
+
sequence_state: B x L x sequence_state_dim
|
| 252 |
+
|
| 253 |
+
Output:
|
| 254 |
+
pairwise_state: B x L x L x pairwise_state_dim
|
| 255 |
+
|
| 256 |
+
Intermediate state:
|
| 257 |
+
B x L x L x 2*inner_dim
|
| 258 |
+
"""
|
| 259 |
+
|
| 260 |
+
assert len(sequence_state.shape) == 3
|
| 261 |
+
|
| 262 |
+
s = self.layernorm(sequence_state)
|
| 263 |
+
s = self.proj(s)
|
| 264 |
+
q, k = s.chunk(2, dim=-1)
|
| 265 |
+
|
| 266 |
+
prod = q[:, None, :, :] * k[:, :, None, :]
|
| 267 |
+
diff = q[:, None, :, :] - k[:, :, None, :]
|
| 268 |
+
|
| 269 |
+
x = torch.cat([prod, diff], dim=-1)
|
| 270 |
+
x = self.o_proj(x)
|
| 271 |
+
|
| 272 |
+
return x
|
| 273 |
+
|
| 274 |
+
|
| 275 |
+
class PairToSequence(nn.Module):
|
| 276 |
+
def __init__(self, pairwise_state_dim, num_heads):
|
| 277 |
+
super().__init__()
|
| 278 |
+
|
| 279 |
+
self.layernorm = nn.LayerNorm(pairwise_state_dim)
|
| 280 |
+
self.linear = nn.Linear(pairwise_state_dim, num_heads, bias=False)
|
| 281 |
+
|
| 282 |
+
def forward(self, pairwise_state):
|
| 283 |
+
"""
|
| 284 |
+
Inputs:
|
| 285 |
+
pairwise_state: B x L x L x pairwise_state_dim
|
| 286 |
+
|
| 287 |
+
Output:
|
| 288 |
+
pairwise_bias: B x L x L x num_heads
|
| 289 |
+
"""
|
| 290 |
+
assert len(pairwise_state.shape) == 4
|
| 291 |
+
z = self.layernorm(pairwise_state)
|
| 292 |
+
pairwise_bias = self.linear(z)
|
| 293 |
+
return pairwise_bias
|
| 294 |
+
|
| 295 |
+
|
| 296 |
+
class ResidueMLP(nn.Module):
|
| 297 |
+
def __init__(self, embed_dim, inner_dim, norm=nn.LayerNorm, dropout=0):
|
| 298 |
+
super().__init__()
|
| 299 |
+
|
| 300 |
+
self.mlp = nn.Sequential(
|
| 301 |
+
norm(embed_dim),
|
| 302 |
+
nn.Linear(embed_dim, inner_dim),
|
| 303 |
+
nn.ReLU(),
|
| 304 |
+
nn.Linear(inner_dim, embed_dim),
|
| 305 |
+
nn.Dropout(dropout),
|
| 306 |
+
)
|
| 307 |
+
|
| 308 |
+
def forward(self, x):
|
| 309 |
+
return x + self.mlp(x)
|
model/esm/esmfold/v1/pretrained.py
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
| 2 |
+
|
| 3 |
+
# This source code is licensed under the MIT license found in the
|
| 4 |
+
# LICENSE file in the root directory of this source tree.
|
| 5 |
+
|
| 6 |
+
from pathlib import Path
|
| 7 |
+
|
| 8 |
+
import torch
|
| 9 |
+
|
| 10 |
+
from model.esm.esmfold.v1.esmfold import ESMFold
|
| 11 |
+
|
| 12 |
+
def _upgrade_state_dict(model_state):
|
| 13 |
+
"""Map legacy ESMFold checkpoint keys to the current OpenFold modules."""
|
| 14 |
+
point_projection_prefixes = (
|
| 15 |
+
"trunk.structure_module.ipa.linear_q_points",
|
| 16 |
+
"trunk.structure_module.ipa.linear_kv_points",
|
| 17 |
+
"trunk.structure_module.ipa.linear_k_points",
|
| 18 |
+
"trunk.structure_module.ipa.linear_v_points",
|
| 19 |
+
)
|
| 20 |
+
for prefix in point_projection_prefixes:
|
| 21 |
+
for suffix in ("weight", "bias"):
|
| 22 |
+
old_key = f"{prefix}.{suffix}"
|
| 23 |
+
new_key = f"{prefix}.linear.{suffix}"
|
| 24 |
+
if old_key in model_state and new_key not in model_state:
|
| 25 |
+
model_state[new_key] = model_state.pop(old_key)
|
| 26 |
+
return model_state
|
| 27 |
+
|
| 28 |
+
def _load_model(model_name):
|
| 29 |
+
if model_name.endswith(".pt"): # local, treat as filepath
|
| 30 |
+
model_path = Path(model_name)
|
| 31 |
+
model_data = torch.load(str(model_path), map_location="cpu")
|
| 32 |
+
else: # load from hub
|
| 33 |
+
url = f"https://dl.fbaipublicfiles.com/fair-esm/models/{model_name}.pt"
|
| 34 |
+
model_data = torch.hub.load_state_dict_from_url(url, progress=False, map_location="cpu")
|
| 35 |
+
|
| 36 |
+
cfg = model_data["cfg"]["model"]
|
| 37 |
+
model_state = _upgrade_state_dict(model_data["model"])
|
| 38 |
+
# model_state = model_data["model"]
|
| 39 |
+
model = ESMFold(esmfold_config=cfg)
|
| 40 |
+
|
| 41 |
+
expected_keys = set(model.state_dict().keys())
|
| 42 |
+
found_keys = set(model_state.keys())
|
| 43 |
+
|
| 44 |
+
missing_essential_keys = []
|
| 45 |
+
for missing_key in expected_keys - found_keys:
|
| 46 |
+
if not missing_key.startswith("esm."):
|
| 47 |
+
missing_essential_keys.append(missing_key)
|
| 48 |
+
|
| 49 |
+
if missing_essential_keys:
|
| 50 |
+
raise RuntimeError(f"Keys '{', '.join(missing_essential_keys)}' are missing.")
|
| 51 |
+
|
| 52 |
+
model.load_state_dict(model_state, strict=False)
|
| 53 |
+
|
| 54 |
+
return model
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
def esmfold_v0():
|
| 58 |
+
"""
|
| 59 |
+
ESMFold v0 model with 3B ESM-2, 48 folding blocks.
|
| 60 |
+
This version was used for the paper (Lin et al, 2022). It was trained
|
| 61 |
+
on all PDB chains until 2020-05, to ensure temporal holdout with CASP14
|
| 62 |
+
and the CAMEO validation and test set reported there.
|
| 63 |
+
"""
|
| 64 |
+
return _load_model("esmfold_3B_v0")
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
def esmfold_v1():
|
| 68 |
+
"""
|
| 69 |
+
ESMFold v1 model using 3B ESM-2, 48 folding blocks.
|
| 70 |
+
ESMFold provides fast high accuracy atomic level structure prediction
|
| 71 |
+
directly from the individual sequence of a protein. ESMFold uses the ESM2
|
| 72 |
+
protein language model to extract meaningful representations from the
|
| 73 |
+
protein sequence.
|
| 74 |
+
"""
|
| 75 |
+
return _load_model("esmfold_3B_v1")
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
def esmfold_structure_module_only_8M():
|
| 79 |
+
"""
|
| 80 |
+
ESMFold baseline model using 8M ESM-2, 0 folding blocks.
|
| 81 |
+
ESM-2 here is trained out to 500K updates.
|
| 82 |
+
This is a model designed to test the capabilities of the language model
|
| 83 |
+
when ablated for number of parameters in the language model.
|
| 84 |
+
See table S1 in (Lin et al, 2022).
|
| 85 |
+
"""
|
| 86 |
+
return _load_model("esmfold_structure_module_only_8M")
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
def esmfold_structure_module_only_8M_270K():
|
| 90 |
+
"""
|
| 91 |
+
ESMFold baseline model using 8M ESM-2, 0 folding blocks.
|
| 92 |
+
ESM-2 here is trained out to 270K updates.
|
| 93 |
+
This is a model designed to test the capabilities of the language model
|
| 94 |
+
when ablated for number of parameters in the language model.
|
| 95 |
+
See table S1 in (Lin et al, 2022).
|
| 96 |
+
"""
|
| 97 |
+
return _load_model("esmfold_structure_module_only_8M_270K")
|
| 98 |
+
|
| 99 |
+
|
| 100 |
+
def esmfold_structure_module_only_35M():
|
| 101 |
+
"""
|
| 102 |
+
ESMFold baseline model using 35M ESM-2, 0 folding blocks.
|
| 103 |
+
ESM-2 here is trained out to 500K updates.
|
| 104 |
+
This is a model designed to test the capabilities of the language model
|
| 105 |
+
when ablated for number of parameters in the language model.
|
| 106 |
+
See table S1 in (Lin et al, 2022).
|
| 107 |
+
"""
|
| 108 |
+
return _load_model("esmfold_structure_module_only_35M")
|
| 109 |
+
|
| 110 |
+
|
| 111 |
+
def esmfold_structure_module_only_35M_270K():
|
| 112 |
+
"""
|
| 113 |
+
ESMFold baseline model using 35M ESM-2, 0 folding blocks.
|
| 114 |
+
ESM-2 here is trained out to 270K updates.
|
| 115 |
+
This is a model designed to test the capabilities of the language model
|
| 116 |
+
when ablated for number of parameters in the language model.
|
| 117 |
+
See table S1 in (Lin et al, 2022).
|
| 118 |
+
"""
|
| 119 |
+
return _load_model("esmfold_structure_module_only_35M_270K")
|
| 120 |
+
|
| 121 |
+
|
| 122 |
+
def esmfold_structure_module_only_150M():
|
| 123 |
+
"""
|
| 124 |
+
ESMFold baseline model using 150M ESM-2, 0 folding blocks.
|
| 125 |
+
ESM-2 here is trained out to 500K updates.
|
| 126 |
+
This is a model designed to test the capabilities of the language model
|
| 127 |
+
when ablated for number of parameters in the language model.
|
| 128 |
+
See table S1 in (Lin et al, 2022).
|
| 129 |
+
"""
|
| 130 |
+
return _load_model("esmfold_structure_module_only_150M")
|
| 131 |
+
|
| 132 |
+
|
| 133 |
+
def esmfold_structure_module_only_150M_270K():
|
| 134 |
+
"""
|
| 135 |
+
ESMFold baseline model using 150M ESM-2, 0 folding blocks.
|
| 136 |
+
ESM-2 here is trained out to 270K updates.
|
| 137 |
+
This is a model designed to test the capabilities of the language model
|
| 138 |
+
when ablated for number of parameters in the language model.
|
| 139 |
+
See table S1 in (Lin et al, 2022).
|
| 140 |
+
"""
|
| 141 |
+
return _load_model("esmfold_structure_module_only_150M_270K")
|
| 142 |
+
|
| 143 |
+
|
| 144 |
+
def esmfold_structure_module_only_650M():
|
| 145 |
+
"""
|
| 146 |
+
ESMFold baseline model using 650M ESM-2, 0 folding blocks.
|
| 147 |
+
ESM-2 here is trained out to 500K updates.
|
| 148 |
+
This is a model designed to test the capabilities of the language model
|
| 149 |
+
when ablated for number of parameters in the language model.
|
| 150 |
+
See table S1 in (Lin et al, 2022).
|
| 151 |
+
"""
|
| 152 |
+
return _load_model("esmfold_structure_module_only_650M")
|
| 153 |
+
|
| 154 |
+
|
| 155 |
+
def esmfold_structure_module_only_650M_270K():
|
| 156 |
+
"""
|
| 157 |
+
ESMFold baseline model using 650M ESM-2, 0 folding blocks.
|
| 158 |
+
ESM-2 here is trained out to 270K updates.
|
| 159 |
+
This is a model designed to test the capabilities of the language model
|
| 160 |
+
when ablated for number of parameters in the language model.
|
| 161 |
+
See table S1 in (Lin et al, 2022).
|
| 162 |
+
"""
|
| 163 |
+
return _load_model("esmfold_structure_module_only_650M_270K")
|
| 164 |
+
|
| 165 |
+
|
| 166 |
+
def esmfold_structure_module_only_3B():
|
| 167 |
+
"""
|
| 168 |
+
ESMFold baseline model using 3B ESM-2, 0 folding blocks.
|
| 169 |
+
ESM-2 here is trained out to 500K updates.
|
| 170 |
+
This is a model designed to test the capabilities of the language model
|
| 171 |
+
when ablated for number of parameters in the language model.
|
| 172 |
+
See table S1 in (Lin et al, 2022).
|
| 173 |
+
"""
|
| 174 |
+
return _load_model("esmfold_structure_module_only_3B")
|
| 175 |
+
|
| 176 |
+
|
| 177 |
+
def esmfold_structure_module_only_3B_270K():
|
| 178 |
+
"""
|
| 179 |
+
ESMFold baseline model using 3B ESM-2, 0 folding blocks.
|
| 180 |
+
ESM-2 here is trained out to 270K updates.
|
| 181 |
+
This is a model designed to test the capabilities of the language model
|
| 182 |
+
when ablated for number of parameters in the language model.
|
| 183 |
+
See table S1 in (Lin et al, 2022).
|
| 184 |
+
"""
|
| 185 |
+
return _load_model("esmfold_structure_module_only_3B_270K")
|
| 186 |
+
|
| 187 |
+
|
| 188 |
+
def esmfold_structure_module_only_15B():
|
| 189 |
+
"""
|
| 190 |
+
ESMFold baseline model using 15B ESM-2, 0 folding blocks.
|
| 191 |
+
ESM-2 here is trained out to 270K updates.
|
| 192 |
+
The 15B parameter ESM-2 was not trained out to 500K updates
|
| 193 |
+
This is a model designed to test the capabilities of the language model
|
| 194 |
+
when ablated for number of parameters in the language model.
|
| 195 |
+
See table S1 in (Lin et al, 2022).
|
| 196 |
+
"""
|
| 197 |
+
return _load_model("esmfold_structure_module_only_15B")
|
model/esm/esmfold/v1/tri_self_attn_block.py
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
| 2 |
+
#
|
| 3 |
+
# This source code is licensed under the MIT license found in the
|
| 4 |
+
# LICENSE file in the root directory of this source tree.
|
| 5 |
+
import torch
|
| 6 |
+
from model.openfold.triangular_attention import (
|
| 7 |
+
TriangleAttentionEndingNode,
|
| 8 |
+
TriangleAttentionStartingNode,
|
| 9 |
+
)
|
| 10 |
+
from model.openfold.triangular_multiplicative_update import (
|
| 11 |
+
TriangleMultiplicationIncoming,
|
| 12 |
+
TriangleMultiplicationOutgoing,
|
| 13 |
+
)
|
| 14 |
+
from torch import nn
|
| 15 |
+
|
| 16 |
+
from model.esm.esmfold.v1.misc import (
|
| 17 |
+
Attention,
|
| 18 |
+
Dropout,
|
| 19 |
+
PairToSequence,
|
| 20 |
+
ResidueMLP,
|
| 21 |
+
SequenceToPair,
|
| 22 |
+
)
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
class TriangularSelfAttentionBlock(nn.Module):
|
| 26 |
+
def __init__(
|
| 27 |
+
self,
|
| 28 |
+
sequence_state_dim,
|
| 29 |
+
pairwise_state_dim,
|
| 30 |
+
sequence_head_width,
|
| 31 |
+
pairwise_head_width,
|
| 32 |
+
dropout=0,
|
| 33 |
+
**__kwargs,
|
| 34 |
+
):
|
| 35 |
+
super().__init__()
|
| 36 |
+
|
| 37 |
+
assert sequence_state_dim % sequence_head_width == 0
|
| 38 |
+
assert pairwise_state_dim % pairwise_head_width == 0
|
| 39 |
+
sequence_num_heads = sequence_state_dim // sequence_head_width
|
| 40 |
+
pairwise_num_heads = pairwise_state_dim // pairwise_head_width
|
| 41 |
+
assert sequence_state_dim == sequence_num_heads * sequence_head_width
|
| 42 |
+
assert pairwise_state_dim == pairwise_num_heads * pairwise_head_width
|
| 43 |
+
assert pairwise_state_dim % 2 == 0
|
| 44 |
+
|
| 45 |
+
self.sequence_state_dim = sequence_state_dim
|
| 46 |
+
self.pairwise_state_dim = pairwise_state_dim
|
| 47 |
+
|
| 48 |
+
self.layernorm_1 = nn.LayerNorm(sequence_state_dim)
|
| 49 |
+
|
| 50 |
+
self.sequence_to_pair = SequenceToPair(
|
| 51 |
+
sequence_state_dim, pairwise_state_dim // 2, pairwise_state_dim
|
| 52 |
+
)
|
| 53 |
+
self.pair_to_sequence = PairToSequence(pairwise_state_dim, sequence_num_heads)
|
| 54 |
+
|
| 55 |
+
self.seq_attention = Attention(
|
| 56 |
+
sequence_state_dim, sequence_num_heads, sequence_head_width, gated=True
|
| 57 |
+
)
|
| 58 |
+
self.tri_mul_out = TriangleMultiplicationOutgoing(
|
| 59 |
+
pairwise_state_dim,
|
| 60 |
+
pairwise_state_dim,
|
| 61 |
+
)
|
| 62 |
+
self.tri_mul_in = TriangleMultiplicationIncoming(
|
| 63 |
+
pairwise_state_dim,
|
| 64 |
+
pairwise_state_dim,
|
| 65 |
+
)
|
| 66 |
+
self.tri_att_start = TriangleAttentionStartingNode(
|
| 67 |
+
pairwise_state_dim,
|
| 68 |
+
pairwise_head_width,
|
| 69 |
+
pairwise_num_heads,
|
| 70 |
+
inf=1e9,
|
| 71 |
+
) # type: ignore
|
| 72 |
+
self.tri_att_end = TriangleAttentionEndingNode(
|
| 73 |
+
pairwise_state_dim,
|
| 74 |
+
pairwise_head_width,
|
| 75 |
+
pairwise_num_heads,
|
| 76 |
+
inf=1e9,
|
| 77 |
+
) # type: ignore
|
| 78 |
+
|
| 79 |
+
self.mlp_seq = ResidueMLP(sequence_state_dim, 4 * sequence_state_dim, dropout=dropout)
|
| 80 |
+
self.mlp_pair = ResidueMLP(pairwise_state_dim, 4 * pairwise_state_dim, dropout=dropout)
|
| 81 |
+
|
| 82 |
+
assert dropout < 0.4
|
| 83 |
+
self.drop = nn.Dropout(dropout)
|
| 84 |
+
self.row_drop = Dropout(dropout * 2, 2)
|
| 85 |
+
self.col_drop = Dropout(dropout * 2, 1)
|
| 86 |
+
|
| 87 |
+
torch.nn.init.zeros_(self.tri_mul_in.linear_z.weight)
|
| 88 |
+
torch.nn.init.zeros_(self.tri_mul_in.linear_z.bias)
|
| 89 |
+
torch.nn.init.zeros_(self.tri_mul_out.linear_z.weight)
|
| 90 |
+
torch.nn.init.zeros_(self.tri_mul_out.linear_z.bias)
|
| 91 |
+
torch.nn.init.zeros_(self.tri_att_start.mha.linear_o.weight)
|
| 92 |
+
torch.nn.init.zeros_(self.tri_att_start.mha.linear_o.bias)
|
| 93 |
+
torch.nn.init.zeros_(self.tri_att_end.mha.linear_o.weight)
|
| 94 |
+
torch.nn.init.zeros_(self.tri_att_end.mha.linear_o.bias)
|
| 95 |
+
|
| 96 |
+
torch.nn.init.zeros_(self.sequence_to_pair.o_proj.weight)
|
| 97 |
+
torch.nn.init.zeros_(self.sequence_to_pair.o_proj.bias)
|
| 98 |
+
torch.nn.init.zeros_(self.pair_to_sequence.linear.weight)
|
| 99 |
+
torch.nn.init.zeros_(self.seq_attention.o_proj.weight)
|
| 100 |
+
torch.nn.init.zeros_(self.seq_attention.o_proj.bias)
|
| 101 |
+
torch.nn.init.zeros_(self.mlp_seq.mlp[-2].weight)
|
| 102 |
+
torch.nn.init.zeros_(self.mlp_seq.mlp[-2].bias)
|
| 103 |
+
torch.nn.init.zeros_(self.mlp_pair.mlp[-2].weight)
|
| 104 |
+
torch.nn.init.zeros_(self.mlp_pair.mlp[-2].bias)
|
| 105 |
+
|
| 106 |
+
def forward(self, sequence_state, pairwise_state, mask=None, chunk_size=None, **__kwargs):
|
| 107 |
+
"""
|
| 108 |
+
Inputs:
|
| 109 |
+
sequence_state: B x L x sequence_state_dim
|
| 110 |
+
pairwise_state: B x L x L x pairwise_state_dim
|
| 111 |
+
mask: B x L boolean tensor of valid positions
|
| 112 |
+
|
| 113 |
+
Output:
|
| 114 |
+
sequence_state: B x L x sequence_state_dim
|
| 115 |
+
pairwise_state: B x L x L x pairwise_state_dim
|
| 116 |
+
"""
|
| 117 |
+
assert len(sequence_state.shape) == 3
|
| 118 |
+
assert len(pairwise_state.shape) == 4
|
| 119 |
+
if mask is not None:
|
| 120 |
+
assert len(mask.shape) == 2
|
| 121 |
+
|
| 122 |
+
batch_dim, seq_dim, sequence_state_dim = sequence_state.shape
|
| 123 |
+
pairwise_state_dim = pairwise_state.shape[3]
|
| 124 |
+
assert sequence_state_dim == self.sequence_state_dim
|
| 125 |
+
assert pairwise_state_dim == self.pairwise_state_dim
|
| 126 |
+
assert batch_dim == pairwise_state.shape[0]
|
| 127 |
+
assert seq_dim == pairwise_state.shape[1]
|
| 128 |
+
assert seq_dim == pairwise_state.shape[2]
|
| 129 |
+
|
| 130 |
+
# Update sequence state
|
| 131 |
+
bias = self.pair_to_sequence(pairwise_state)
|
| 132 |
+
|
| 133 |
+
# Self attention with bias + mlp.
|
| 134 |
+
y = self.layernorm_1(sequence_state)
|
| 135 |
+
y, _ = self.seq_attention(y, mask=mask, bias=bias)
|
| 136 |
+
sequence_state = sequence_state + self.drop(y)
|
| 137 |
+
sequence_state = self.mlp_seq(sequence_state)
|
| 138 |
+
|
| 139 |
+
# Update pairwise state
|
| 140 |
+
pairwise_state = pairwise_state + self.sequence_to_pair(sequence_state)
|
| 141 |
+
|
| 142 |
+
# Axial attention with triangular bias.
|
| 143 |
+
tri_mask = mask.unsqueeze(2) * mask.unsqueeze(1) if mask is not None else None
|
| 144 |
+
pairwise_state = pairwise_state + self.row_drop(
|
| 145 |
+
self.tri_mul_out(pairwise_state, mask=tri_mask)
|
| 146 |
+
)
|
| 147 |
+
pairwise_state = pairwise_state + self.col_drop(
|
| 148 |
+
self.tri_mul_in(pairwise_state, mask=tri_mask)
|
| 149 |
+
)
|
| 150 |
+
pairwise_state = pairwise_state + self.row_drop(
|
| 151 |
+
self.tri_att_start(pairwise_state, mask=tri_mask, chunk_size=chunk_size)
|
| 152 |
+
)
|
| 153 |
+
pairwise_state = pairwise_state + self.col_drop(
|
| 154 |
+
self.tri_att_end(pairwise_state, mask=tri_mask, chunk_size=chunk_size)
|
| 155 |
+
)
|
| 156 |
+
|
| 157 |
+
# MLP over pairs.
|
| 158 |
+
pairwise_state = self.mlp_pair(pairwise_state)
|
| 159 |
+
|
| 160 |
+
return sequence_state, pairwise_state
|
model/esm/esmfold/v1/trunk.py
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
| 2 |
+
#
|
| 3 |
+
# This source code is licensed under the MIT license found in the
|
| 4 |
+
# LICENSE file in the root directory of this source tree.
|
| 5 |
+
import typing as T
|
| 6 |
+
from contextlib import ExitStack
|
| 7 |
+
# from dataclasses import dataclass
|
| 8 |
+
from dataclasses import dataclass, field
|
| 9 |
+
|
| 10 |
+
import torch
|
| 11 |
+
import torch.nn as nn
|
| 12 |
+
from model.openfold.structure_module import StructureModule
|
| 13 |
+
|
| 14 |
+
from model.esm.esmfold.v1.tri_self_attn_block import TriangularSelfAttentionBlock
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
@dataclass
|
| 18 |
+
class StructureModuleConfig:
|
| 19 |
+
c_s: int = 384
|
| 20 |
+
c_z: int = 128
|
| 21 |
+
c_ipa: int = 16
|
| 22 |
+
c_resnet: int = 128
|
| 23 |
+
no_heads_ipa: int = 12
|
| 24 |
+
no_qk_points: int = 4
|
| 25 |
+
no_v_points: int = 8
|
| 26 |
+
dropout_rate: float = 0.1
|
| 27 |
+
no_blocks: int = 8
|
| 28 |
+
no_transition_layers: int = 1
|
| 29 |
+
no_resnet_blocks: int = 2
|
| 30 |
+
no_angles: int = 7
|
| 31 |
+
trans_scale_factor: int = 10
|
| 32 |
+
epsilon: float = 1e-8
|
| 33 |
+
inf: float = 1e5
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
@dataclass
|
| 37 |
+
class FoldingTrunkConfig:
|
| 38 |
+
_name: str = "FoldingTrunkConfig"
|
| 39 |
+
num_blocks: int = 48
|
| 40 |
+
sequence_state_dim: int = 1024
|
| 41 |
+
pairwise_state_dim: int = 128
|
| 42 |
+
sequence_head_width: int = 32
|
| 43 |
+
pairwise_head_width: int = 32
|
| 44 |
+
position_bins: int = 32
|
| 45 |
+
dropout: float = 0
|
| 46 |
+
layer_drop: float = 0
|
| 47 |
+
cpu_grad_checkpoint: bool = False
|
| 48 |
+
|
| 49 |
+
max_recycles: int = 4
|
| 50 |
+
chunk_size: T.Optional[int] = None
|
| 51 |
+
|
| 52 |
+
# structure_module: StructureModuleConfig = StructureModuleConfig()
|
| 53 |
+
structure_module: StructureModuleConfig = field(default_factory=StructureModuleConfig)
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def get_axial_mask(mask):
|
| 57 |
+
"""
|
| 58 |
+
Helper to convert B x L mask of valid positions to axial mask used
|
| 59 |
+
in row column attentions.
|
| 60 |
+
|
| 61 |
+
Input:
|
| 62 |
+
mask: B x L tensor of booleans
|
| 63 |
+
|
| 64 |
+
Output:
|
| 65 |
+
mask: B x L x L tensor of booleans
|
| 66 |
+
"""
|
| 67 |
+
|
| 68 |
+
if mask is None:
|
| 69 |
+
return None
|
| 70 |
+
assert len(mask.shape) == 2
|
| 71 |
+
batch_dim, seq_dim = mask.shape
|
| 72 |
+
m = mask.unsqueeze(1).expand(batch_dim, seq_dim, seq_dim)
|
| 73 |
+
m = m.reshape(batch_dim * seq_dim, seq_dim)
|
| 74 |
+
return m
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
class RelativePosition(nn.Module):
|
| 78 |
+
def __init__(self, bins, pairwise_state_dim):
|
| 79 |
+
super().__init__()
|
| 80 |
+
self.bins = bins
|
| 81 |
+
|
| 82 |
+
# Note an additional offset is used so that the 0th position
|
| 83 |
+
# is reserved for masked pairs.
|
| 84 |
+
self.embedding = torch.nn.Embedding(2 * bins + 2, pairwise_state_dim)
|
| 85 |
+
|
| 86 |
+
def forward(self, residue_index, mask=None):
|
| 87 |
+
"""
|
| 88 |
+
Input:
|
| 89 |
+
residue_index: B x L tensor of indices (dytpe=torch.long)
|
| 90 |
+
mask: B x L tensor of booleans
|
| 91 |
+
|
| 92 |
+
Output:
|
| 93 |
+
pairwise_state: B x L x L x pairwise_state_dim tensor of embeddings
|
| 94 |
+
"""
|
| 95 |
+
|
| 96 |
+
assert residue_index.dtype == torch.long
|
| 97 |
+
if mask is not None:
|
| 98 |
+
assert residue_index.shape == mask.shape
|
| 99 |
+
|
| 100 |
+
diff = residue_index[:, None, :] - residue_index[:, :, None]
|
| 101 |
+
diff = diff.clamp(-self.bins, self.bins)
|
| 102 |
+
diff = diff + self.bins + 1 # Add 1 to adjust for padding index.
|
| 103 |
+
|
| 104 |
+
if mask is not None:
|
| 105 |
+
mask = mask[:, None, :] * mask[:, :, None]
|
| 106 |
+
diff[mask == False] = 0
|
| 107 |
+
|
| 108 |
+
output = self.embedding(diff)
|
| 109 |
+
return output
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
class FoldingTrunk(nn.Module):
|
| 113 |
+
def __init__(self, **kwargs):
|
| 114 |
+
super().__init__()
|
| 115 |
+
self.cfg = FoldingTrunkConfig(**kwargs)
|
| 116 |
+
assert self.cfg.max_recycles > 0
|
| 117 |
+
|
| 118 |
+
c_s = self.cfg.sequence_state_dim
|
| 119 |
+
c_z = self.cfg.pairwise_state_dim
|
| 120 |
+
|
| 121 |
+
assert c_s % self.cfg.sequence_head_width == 0
|
| 122 |
+
assert c_z % self.cfg.pairwise_head_width == 0
|
| 123 |
+
block = TriangularSelfAttentionBlock
|
| 124 |
+
|
| 125 |
+
self.pairwise_positional_embedding = RelativePosition(self.cfg.position_bins, c_z)
|
| 126 |
+
|
| 127 |
+
self.blocks = nn.ModuleList(
|
| 128 |
+
[
|
| 129 |
+
block(
|
| 130 |
+
sequence_state_dim=c_s,
|
| 131 |
+
pairwise_state_dim=c_z,
|
| 132 |
+
sequence_head_width=self.cfg.sequence_head_width,
|
| 133 |
+
pairwise_head_width=self.cfg.pairwise_head_width,
|
| 134 |
+
dropout=self.cfg.dropout,
|
| 135 |
+
)
|
| 136 |
+
for i in range(self.cfg.num_blocks)
|
| 137 |
+
]
|
| 138 |
+
)
|
| 139 |
+
|
| 140 |
+
self.recycle_bins = 15
|
| 141 |
+
self.recycle_s_norm = nn.LayerNorm(c_s)
|
| 142 |
+
self.recycle_z_norm = nn.LayerNorm(c_z)
|
| 143 |
+
self.recycle_disto = nn.Embedding(self.recycle_bins, c_z)
|
| 144 |
+
self.recycle_disto.weight[0].detach().zero_()
|
| 145 |
+
|
| 146 |
+
self.structure_module = StructureModule(**self.cfg.structure_module) # type: ignore
|
| 147 |
+
self.trunk2sm_s = nn.Linear(c_s, self.structure_module.c_s)
|
| 148 |
+
self.trunk2sm_z = nn.Linear(c_z, self.structure_module.c_z)
|
| 149 |
+
|
| 150 |
+
self.chunk_size = self.cfg.chunk_size
|
| 151 |
+
|
| 152 |
+
def set_chunk_size(self, chunk_size):
|
| 153 |
+
# This parameter means the axial attention will be computed
|
| 154 |
+
# in a chunked manner. This should make the memory used more or less O(L) instead of O(L^2).
|
| 155 |
+
# It's equivalent to running a for loop over chunks of the dimension we're iterative over,
|
| 156 |
+
# where the chunk_size is the size of the chunks, so 128 would mean to parse 128-lengthed chunks.
|
| 157 |
+
self.chunk_size = chunk_size
|
| 158 |
+
|
| 159 |
+
def forward(self, seq_feats, pair_feats, true_aa, residx, mask, no_recycles: T.Optional[int] = None):
|
| 160 |
+
"""
|
| 161 |
+
Inputs:
|
| 162 |
+
seq_feats: B x L x C tensor of sequence features
|
| 163 |
+
pair_feats: B x L x L x C tensor of pair features
|
| 164 |
+
residx: B x L long tensor giving the position in the sequence
|
| 165 |
+
mask: B x L boolean tensor indicating valid residues
|
| 166 |
+
|
| 167 |
+
Output:
|
| 168 |
+
predicted_structure: B x L x (num_atoms_per_residue * 3) tensor wrapped in a Coordinates object
|
| 169 |
+
"""
|
| 170 |
+
|
| 171 |
+
device = seq_feats.device
|
| 172 |
+
s_s_0 = seq_feats
|
| 173 |
+
s_z_0 = pair_feats
|
| 174 |
+
|
| 175 |
+
if no_recycles is None:
|
| 176 |
+
no_recycles = self.cfg.max_recycles
|
| 177 |
+
else:
|
| 178 |
+
assert no_recycles >= 0, "Number of recycles must not be negative."
|
| 179 |
+
no_recycles += 1 # First 'recycle' is just the standard forward pass through the model.
|
| 180 |
+
|
| 181 |
+
def trunk_iter(s, z, residx, mask):
|
| 182 |
+
z = z + self.pairwise_positional_embedding(residx, mask=mask)
|
| 183 |
+
|
| 184 |
+
for block in self.blocks:
|
| 185 |
+
s, z = block(s, z, mask=mask, residue_index=residx, chunk_size=self.chunk_size)
|
| 186 |
+
return s, z
|
| 187 |
+
|
| 188 |
+
s_s = s_s_0
|
| 189 |
+
s_z = s_z_0
|
| 190 |
+
recycle_s = torch.zeros_like(s_s)
|
| 191 |
+
recycle_z = torch.zeros_like(s_z)
|
| 192 |
+
recycle_bins = torch.zeros(*s_z.shape[:-1], device=device, dtype=torch.int64)
|
| 193 |
+
|
| 194 |
+
assert no_recycles > 0
|
| 195 |
+
for recycle_idx in range(no_recycles):
|
| 196 |
+
with ExitStack() if recycle_idx == no_recycles - 1 else torch.no_grad():
|
| 197 |
+
# === Recycling ===
|
| 198 |
+
recycle_s = self.recycle_s_norm(recycle_s.detach())
|
| 199 |
+
recycle_z = self.recycle_z_norm(recycle_z.detach())
|
| 200 |
+
recycle_z += self.recycle_disto(recycle_bins.detach())
|
| 201 |
+
|
| 202 |
+
s_s, s_z = trunk_iter(s_s_0 + recycle_s, s_z_0 + recycle_z, residx, mask)
|
| 203 |
+
|
| 204 |
+
# === Structure module ===
|
| 205 |
+
structure = self.structure_module(
|
| 206 |
+
{"single": self.trunk2sm_s(s_s), "pair": self.trunk2sm_z(s_z)},
|
| 207 |
+
true_aa,
|
| 208 |
+
mask.float(),
|
| 209 |
+
)
|
| 210 |
+
|
| 211 |
+
recycle_s = s_s
|
| 212 |
+
recycle_z = s_z
|
| 213 |
+
# Distogram needs the N, CA, C coordinates, and bin constants same as alphafold.
|
| 214 |
+
recycle_bins = FoldingTrunk.distogram(
|
| 215 |
+
structure["positions"][-1][:, :, :3],
|
| 216 |
+
3.375,
|
| 217 |
+
21.375,
|
| 218 |
+
self.recycle_bins,
|
| 219 |
+
)
|
| 220 |
+
|
| 221 |
+
assert isinstance(structure, dict) # type: ignore
|
| 222 |
+
structure["s_s"] = s_s
|
| 223 |
+
structure["s_z"] = s_z
|
| 224 |
+
|
| 225 |
+
return structure
|
| 226 |
+
|
| 227 |
+
@staticmethod
|
| 228 |
+
def distogram(coords, min_bin, max_bin, num_bins):
|
| 229 |
+
# Coords are [... L x 3 x 3], where it's [N, CA, C] x 3 coordinates.
|
| 230 |
+
boundaries = torch.linspace(
|
| 231 |
+
min_bin,
|
| 232 |
+
max_bin,
|
| 233 |
+
num_bins - 1,
|
| 234 |
+
device=coords.device,
|
| 235 |
+
)
|
| 236 |
+
boundaries = boundaries**2
|
| 237 |
+
N, CA, C = [x.squeeze(-2) for x in coords.chunk(3, dim=-2)]
|
| 238 |
+
# Infer CB coordinates.
|
| 239 |
+
b = CA - N
|
| 240 |
+
c = C - CA
|
| 241 |
+
a = b.cross(c, dim=-1)
|
| 242 |
+
CB = -0.58273431 * a + 0.56802827 * b - 0.54067466 * c + CA
|
| 243 |
+
dists = (CB[..., None, :, :] - CB[..., :, None, :]).pow(2).sum(dim=-1, keepdims=True)
|
| 244 |
+
bins = torch.sum(dists > boundaries, dim=-1) # [..., L, L]
|
| 245 |
+
return bins
|
model/esm/inverse_folding/__init__.py
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) Facebook, Inc. and its affiliates.
|
| 2 |
+
#
|
| 3 |
+
# This source code is licensed under the MIT license found in the
|
| 4 |
+
# LICENSE file in the root directory of this source tree.
|
| 5 |
+
|
| 6 |
+
from . import gvp_transformer
|
| 7 |
+
from . import util
|
| 8 |
+
from . import multichain_util
|
model/esm/inverse_folding/features.py
ADDED
|
@@ -0,0 +1,352 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
| 2 |
+
#
|
| 3 |
+
# This source code is licensed under the MIT license found in the
|
| 4 |
+
# LICENSE file in the root directory of this source tree.
|
| 5 |
+
#
|
| 6 |
+
# Portions of this file were adapted from the open source code for the following
|
| 7 |
+
# two papers:
|
| 8 |
+
#
|
| 9 |
+
# Ingraham, J., Garg, V., Barzilay, R., & Jaakkola, T. (2019). Generative
|
| 10 |
+
# models for graph-based protein design. Advances in Neural Information
|
| 11 |
+
# Processing Systems, 32.
|
| 12 |
+
#
|
| 13 |
+
# Jing, B., Eismann, S., Suriana, P., Townshend, R. J. L., & Dror, R. (2020).
|
| 14 |
+
# Learning from Protein Structure with Geometric Vector Perceptrons. In
|
| 15 |
+
# International Conference on Learning Representations.
|
| 16 |
+
#
|
| 17 |
+
# MIT License
|
| 18 |
+
#
|
| 19 |
+
# Copyright (c) 2020 Bowen Jing, Stephan Eismann, Patricia Suriana, Raphael Townshend, Ron Dror
|
| 20 |
+
#
|
| 21 |
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 22 |
+
# of this software and associated documentation files (the "Software"), to deal
|
| 23 |
+
# in the Software without restriction, including without limitation the rights
|
| 24 |
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 25 |
+
# copies of the Software, and to permit persons to whom the Software is
|
| 26 |
+
# furnished to do so, subject to the following conditions:
|
| 27 |
+
#
|
| 28 |
+
# The above copyright notice and this permission notice shall be included in all
|
| 29 |
+
# copies or substantial portions of the Software.
|
| 30 |
+
#
|
| 31 |
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 32 |
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 33 |
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 34 |
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 35 |
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 36 |
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 37 |
+
# SOFTWARE.
|
| 38 |
+
#
|
| 39 |
+
# ================================================================
|
| 40 |
+
# The below license applies to the portions of the code (parts of
|
| 41 |
+
# src/datasets.py and src/models.py) adapted from Ingraham, et al.
|
| 42 |
+
# ================================================================
|
| 43 |
+
#
|
| 44 |
+
# MIT License
|
| 45 |
+
#
|
| 46 |
+
# Copyright (c) 2019 John Ingraham, Vikas Garg, Regina Barzilay, Tommi Jaakkola
|
| 47 |
+
#
|
| 48 |
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 49 |
+
# of this software and associated documentation files (the "Software"), to deal
|
| 50 |
+
# in the Software without restriction, including without limitation the rights
|
| 51 |
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 52 |
+
# copies of the Software, and to permit persons to whom the Software is
|
| 53 |
+
# furnished to do so, subject to the following conditions:
|
| 54 |
+
#
|
| 55 |
+
# The above copyright notice and this permission notice shall be included in all
|
| 56 |
+
# copies or substantial portions of the Software.
|
| 57 |
+
#
|
| 58 |
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 59 |
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 60 |
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 61 |
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 62 |
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 63 |
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 64 |
+
# SOFTWARE.
|
| 65 |
+
|
| 66 |
+
import math
|
| 67 |
+
import numpy as np
|
| 68 |
+
import torch
|
| 69 |
+
import torch.nn as nn
|
| 70 |
+
import torch.nn.functional as F
|
| 71 |
+
|
| 72 |
+
from .gvp_utils import flatten_graph
|
| 73 |
+
from .gvp_modules import GVP, LayerNorm
|
| 74 |
+
from .util import normalize, norm, nan_to_num, rbf
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
class GVPInputFeaturizer(nn.Module):
|
| 78 |
+
|
| 79 |
+
@staticmethod
|
| 80 |
+
def get_node_features(coords, coord_mask, with_coord_mask=True):
|
| 81 |
+
# scalar features
|
| 82 |
+
node_scalar_features = GVPInputFeaturizer._dihedrals(coords)
|
| 83 |
+
if with_coord_mask:
|
| 84 |
+
node_scalar_features = torch.cat([
|
| 85 |
+
node_scalar_features,
|
| 86 |
+
coord_mask.float().unsqueeze(-1)
|
| 87 |
+
], dim=-1)
|
| 88 |
+
# vector features
|
| 89 |
+
X_ca = coords[:, :, 1]
|
| 90 |
+
orientations = GVPInputFeaturizer._orientations(X_ca)
|
| 91 |
+
sidechains = GVPInputFeaturizer._sidechains(coords)
|
| 92 |
+
node_vector_features = torch.cat([orientations, sidechains.unsqueeze(-2)], dim=-2)
|
| 93 |
+
return node_scalar_features, node_vector_features
|
| 94 |
+
|
| 95 |
+
@staticmethod
|
| 96 |
+
def _orientations(X):
|
| 97 |
+
forward = normalize(X[:, 1:] - X[:, :-1])
|
| 98 |
+
backward = normalize(X[:, :-1] - X[:, 1:])
|
| 99 |
+
forward = F.pad(forward, [0, 0, 0, 1])
|
| 100 |
+
backward = F.pad(backward, [0, 0, 1, 0])
|
| 101 |
+
return torch.cat([forward.unsqueeze(-2), backward.unsqueeze(-2)], -2)
|
| 102 |
+
|
| 103 |
+
@staticmethod
|
| 104 |
+
def _sidechains(X):
|
| 105 |
+
n, origin, c = X[:, :, 0], X[:, :, 1], X[:, :, 2]
|
| 106 |
+
c, n = normalize(c - origin), normalize(n - origin)
|
| 107 |
+
bisector = normalize(c + n)
|
| 108 |
+
perp = normalize(torch.cross(c, n, dim=-1))
|
| 109 |
+
vec = -bisector * math.sqrt(1 / 3) - perp * math.sqrt(2 / 3)
|
| 110 |
+
return vec
|
| 111 |
+
|
| 112 |
+
@staticmethod
|
| 113 |
+
def _dihedrals(X, eps=1e-7):
|
| 114 |
+
X = torch.flatten(X[:, :, :3], 1, 2)
|
| 115 |
+
bsz = X.shape[0]
|
| 116 |
+
dX = X[:, 1:] - X[:, :-1]
|
| 117 |
+
U = normalize(dX, dim=-1)
|
| 118 |
+
u_2 = U[:, :-2]
|
| 119 |
+
u_1 = U[:, 1:-1]
|
| 120 |
+
u_0 = U[:, 2:]
|
| 121 |
+
|
| 122 |
+
# Backbone normals
|
| 123 |
+
n_2 = normalize(torch.cross(u_2, u_1, dim=-1), dim=-1)
|
| 124 |
+
n_1 = normalize(torch.cross(u_1, u_0, dim=-1), dim=-1)
|
| 125 |
+
|
| 126 |
+
# Angle between normals
|
| 127 |
+
cosD = torch.sum(n_2 * n_1, -1)
|
| 128 |
+
cosD = torch.clamp(cosD, -1 + eps, 1 - eps)
|
| 129 |
+
D = torch.sign(torch.sum(u_2 * n_1, -1)) * torch.acos(cosD)
|
| 130 |
+
|
| 131 |
+
# This scheme will remove phi[0], psi[-1], omega[-1]
|
| 132 |
+
D = F.pad(D, [1, 2])
|
| 133 |
+
D = torch.reshape(D, [bsz, -1, 3])
|
| 134 |
+
# Lift angle representations to the circle
|
| 135 |
+
D_features = torch.cat([torch.cos(D), torch.sin(D)], -1)
|
| 136 |
+
return D_features
|
| 137 |
+
|
| 138 |
+
@staticmethod
|
| 139 |
+
def _positional_embeddings(edge_index,
|
| 140 |
+
num_embeddings=None,
|
| 141 |
+
num_positional_embeddings=16,
|
| 142 |
+
period_range=[2, 1000]):
|
| 143 |
+
# From https://github.com/jingraham/neurips19-graph-protein-design
|
| 144 |
+
num_embeddings = num_embeddings or num_positional_embeddings
|
| 145 |
+
d = edge_index[0] - edge_index[1]
|
| 146 |
+
|
| 147 |
+
frequency = torch.exp(
|
| 148 |
+
torch.arange(0, num_embeddings, 2, dtype=torch.float32,
|
| 149 |
+
device=edge_index.device)
|
| 150 |
+
* -(np.log(10000.0) / num_embeddings)
|
| 151 |
+
)
|
| 152 |
+
angles = d.unsqueeze(-1) * frequency
|
| 153 |
+
E = torch.cat((torch.cos(angles), torch.sin(angles)), -1)
|
| 154 |
+
return E
|
| 155 |
+
|
| 156 |
+
@staticmethod
|
| 157 |
+
def _dist(X, coord_mask, padding_mask, top_k_neighbors, eps=1e-8):
|
| 158 |
+
""" Pairwise euclidean distances """
|
| 159 |
+
bsz, maxlen = X.size(0), X.size(1)
|
| 160 |
+
coord_mask_2D = torch.unsqueeze(coord_mask,1) * torch.unsqueeze(coord_mask,2)
|
| 161 |
+
residue_mask = ~padding_mask
|
| 162 |
+
residue_mask_2D = torch.unsqueeze(residue_mask,1) * torch.unsqueeze(residue_mask,2)
|
| 163 |
+
dX = torch.unsqueeze(X,1) - torch.unsqueeze(X,2)
|
| 164 |
+
D = coord_mask_2D * norm(dX, dim=-1)
|
| 165 |
+
|
| 166 |
+
# sorting preference: first those with coords, then among the residues that
|
| 167 |
+
# exist but are masked use distance in sequence as tie breaker, and then the
|
| 168 |
+
# residues that came from padding are last
|
| 169 |
+
seqpos = torch.arange(maxlen, device=X.device)
|
| 170 |
+
Dseq = torch.abs(seqpos.unsqueeze(1) - seqpos.unsqueeze(0)).repeat(bsz, 1, 1)
|
| 171 |
+
D_adjust = nan_to_num(D) + (~coord_mask_2D) * (1e8 + Dseq*1e6) + (
|
| 172 |
+
~residue_mask_2D) * (1e10)
|
| 173 |
+
|
| 174 |
+
if top_k_neighbors == -1:
|
| 175 |
+
D_neighbors = D_adjust
|
| 176 |
+
E_idx = seqpos.repeat(
|
| 177 |
+
*D_neighbors.shape[:-1], 1)
|
| 178 |
+
else:
|
| 179 |
+
# Identify k nearest neighbors (including self)
|
| 180 |
+
k = min(top_k_neighbors, X.size(1))
|
| 181 |
+
D_neighbors, E_idx = torch.topk(D_adjust, k, dim=-1, largest=False)
|
| 182 |
+
|
| 183 |
+
coord_mask_neighbors = (D_neighbors < 5e7)
|
| 184 |
+
residue_mask_neighbors = (D_neighbors < 5e9)
|
| 185 |
+
return D_neighbors, E_idx, coord_mask_neighbors, residue_mask_neighbors
|
| 186 |
+
|
| 187 |
+
|
| 188 |
+
class Normalize(nn.Module):
|
| 189 |
+
def __init__(self, features, epsilon=1e-6):
|
| 190 |
+
super(Normalize, self).__init__()
|
| 191 |
+
self.gain = nn.Parameter(torch.ones(features))
|
| 192 |
+
self.bias = nn.Parameter(torch.zeros(features))
|
| 193 |
+
self.epsilon = epsilon
|
| 194 |
+
|
| 195 |
+
def forward(self, x, dim=-1):
|
| 196 |
+
mu = x.mean(dim, keepdim=True)
|
| 197 |
+
sigma = torch.sqrt(x.var(dim, keepdim=True) + self.epsilon)
|
| 198 |
+
gain = self.gain
|
| 199 |
+
bias = self.bias
|
| 200 |
+
# Reshape
|
| 201 |
+
if dim != -1:
|
| 202 |
+
shape = [1] * len(mu.size())
|
| 203 |
+
shape[dim] = self.gain.size()[0]
|
| 204 |
+
gain = gain.view(shape)
|
| 205 |
+
bias = bias.view(shape)
|
| 206 |
+
return gain * (x - mu) / (sigma + self.epsilon) + bias
|
| 207 |
+
|
| 208 |
+
|
| 209 |
+
class DihedralFeatures(nn.Module):
|
| 210 |
+
def __init__(self, node_embed_dim):
|
| 211 |
+
""" Embed dihedral angle features. """
|
| 212 |
+
super(DihedralFeatures, self).__init__()
|
| 213 |
+
# 3 dihedral angles; sin and cos of each angle
|
| 214 |
+
node_in = 6
|
| 215 |
+
# Normalization and embedding
|
| 216 |
+
self.node_embedding = nn.Linear(node_in, node_embed_dim, bias=True)
|
| 217 |
+
self.norm_nodes = Normalize(node_embed_dim)
|
| 218 |
+
|
| 219 |
+
def forward(self, X):
|
| 220 |
+
""" Featurize coordinates as an attributed graph """
|
| 221 |
+
V = self._dihedrals(X)
|
| 222 |
+
V = self.node_embedding(V)
|
| 223 |
+
V = self.norm_nodes(V)
|
| 224 |
+
return V
|
| 225 |
+
|
| 226 |
+
@staticmethod
|
| 227 |
+
def _dihedrals(X, eps=1e-7, return_angles=False):
|
| 228 |
+
# First 3 coordinates are N, CA, C
|
| 229 |
+
X = X[:,:,:3,:].reshape(X.shape[0], 3*X.shape[1], 3)
|
| 230 |
+
|
| 231 |
+
# Shifted slices of unit vectors
|
| 232 |
+
dX = X[:,1:,:] - X[:,:-1,:]
|
| 233 |
+
U = F.normalize(dX, dim=-1)
|
| 234 |
+
u_2 = U[:,:-2,:]
|
| 235 |
+
u_1 = U[:,1:-1,:]
|
| 236 |
+
u_0 = U[:,2:,:]
|
| 237 |
+
# Backbone normals
|
| 238 |
+
n_2 = F.normalize(torch.cross(u_2, u_1, dim=-1), dim=-1)
|
| 239 |
+
n_1 = F.normalize(torch.cross(u_1, u_0, dim=-1), dim=-1)
|
| 240 |
+
|
| 241 |
+
# Angle between normals
|
| 242 |
+
cosD = (n_2 * n_1).sum(-1)
|
| 243 |
+
cosD = torch.clamp(cosD, -1+eps, 1-eps)
|
| 244 |
+
D = torch.sign((u_2 * n_1).sum(-1)) * torch.acos(cosD)
|
| 245 |
+
|
| 246 |
+
# This scheme will remove phi[0], psi[-1], omega[-1]
|
| 247 |
+
D = F.pad(D, (1,2), 'constant', 0)
|
| 248 |
+
D = D.view((D.size(0), int(D.size(1)/3), 3))
|
| 249 |
+
phi, psi, omega = torch.unbind(D,-1)
|
| 250 |
+
|
| 251 |
+
if return_angles:
|
| 252 |
+
return phi, psi, omega
|
| 253 |
+
|
| 254 |
+
# Lift angle representations to the circle
|
| 255 |
+
D_features = torch.cat((torch.cos(D), torch.sin(D)), 2)
|
| 256 |
+
return D_features
|
| 257 |
+
|
| 258 |
+
|
| 259 |
+
class GVPGraphEmbedding(GVPInputFeaturizer):
|
| 260 |
+
|
| 261 |
+
def __init__(self, args):
|
| 262 |
+
super().__init__()
|
| 263 |
+
self.top_k_neighbors = args.top_k_neighbors
|
| 264 |
+
self.num_positional_embeddings = 16
|
| 265 |
+
self.remove_edges_without_coords = True
|
| 266 |
+
node_input_dim = (7, 3)
|
| 267 |
+
edge_input_dim = (34, 1)
|
| 268 |
+
node_hidden_dim = (args.node_hidden_dim_scalar,
|
| 269 |
+
args.node_hidden_dim_vector)
|
| 270 |
+
edge_hidden_dim = (args.edge_hidden_dim_scalar,
|
| 271 |
+
args.edge_hidden_dim_vector)
|
| 272 |
+
self.embed_node = nn.Sequential(
|
| 273 |
+
GVP(node_input_dim, node_hidden_dim, activations=(None, None)),
|
| 274 |
+
LayerNorm(node_hidden_dim, eps=1e-4)
|
| 275 |
+
)
|
| 276 |
+
self.embed_edge = nn.Sequential(
|
| 277 |
+
GVP(edge_input_dim, edge_hidden_dim, activations=(None, None)),
|
| 278 |
+
LayerNorm(edge_hidden_dim, eps=1e-4)
|
| 279 |
+
)
|
| 280 |
+
self.embed_confidence = nn.Linear(16, args.node_hidden_dim_scalar)
|
| 281 |
+
|
| 282 |
+
def forward(self, coords, coord_mask, padding_mask, confidence):
|
| 283 |
+
with torch.no_grad():
|
| 284 |
+
node_features = self.get_node_features(coords, coord_mask)
|
| 285 |
+
edge_features, edge_index = self.get_edge_features(
|
| 286 |
+
coords, coord_mask, padding_mask)
|
| 287 |
+
node_embeddings_scalar, node_embeddings_vector = self.embed_node(node_features)
|
| 288 |
+
edge_embeddings = self.embed_edge(edge_features)
|
| 289 |
+
|
| 290 |
+
rbf_rep = rbf(confidence, 0., 1.)
|
| 291 |
+
node_embeddings = (
|
| 292 |
+
node_embeddings_scalar + self.embed_confidence(rbf_rep),
|
| 293 |
+
node_embeddings_vector
|
| 294 |
+
)
|
| 295 |
+
|
| 296 |
+
node_embeddings, edge_embeddings, edge_index = flatten_graph(
|
| 297 |
+
node_embeddings, edge_embeddings, edge_index)
|
| 298 |
+
return node_embeddings, edge_embeddings, edge_index
|
| 299 |
+
|
| 300 |
+
def get_edge_features(self, coords, coord_mask, padding_mask):
|
| 301 |
+
X_ca = coords[:, :, 1]
|
| 302 |
+
# Get distances to the top k neighbors
|
| 303 |
+
E_dist, E_idx, E_coord_mask, E_residue_mask = GVPInputFeaturizer._dist(
|
| 304 |
+
X_ca, coord_mask, padding_mask, self.top_k_neighbors)
|
| 305 |
+
# Flatten the graph to be batch size 1 for torch_geometric package
|
| 306 |
+
dest = E_idx
|
| 307 |
+
B, L, k = E_idx.shape[:3]
|
| 308 |
+
src = torch.arange(L, device=E_idx.device).view([1, L, 1]).expand(B, L, k)
|
| 309 |
+
# After flattening, [2, B, E]
|
| 310 |
+
edge_index = torch.stack([src, dest], dim=0).flatten(2, 3)
|
| 311 |
+
# After flattening, [B, E]
|
| 312 |
+
E_dist = E_dist.flatten(1, 2)
|
| 313 |
+
E_coord_mask = E_coord_mask.flatten(1, 2).unsqueeze(-1)
|
| 314 |
+
E_residue_mask = E_residue_mask.flatten(1, 2)
|
| 315 |
+
# Calculate relative positional embeddings and distance RBF
|
| 316 |
+
pos_embeddings = GVPInputFeaturizer._positional_embeddings(
|
| 317 |
+
edge_index,
|
| 318 |
+
num_positional_embeddings=self.num_positional_embeddings,
|
| 319 |
+
)
|
| 320 |
+
D_rbf = rbf(E_dist, 0., 20.)
|
| 321 |
+
# Calculate relative orientation
|
| 322 |
+
X_src = X_ca.unsqueeze(2).expand(-1, -1, k, -1).flatten(1, 2)
|
| 323 |
+
X_dest = torch.gather(
|
| 324 |
+
X_ca,
|
| 325 |
+
1,
|
| 326 |
+
edge_index[1, :, :].unsqueeze(-1).expand([B, L*k, 3])
|
| 327 |
+
)
|
| 328 |
+
coord_mask_src = coord_mask.unsqueeze(2).expand(-1, -1, k).flatten(1, 2)
|
| 329 |
+
coord_mask_dest = torch.gather(
|
| 330 |
+
coord_mask,
|
| 331 |
+
1,
|
| 332 |
+
edge_index[1, :, :].expand([B, L*k])
|
| 333 |
+
)
|
| 334 |
+
E_vectors = X_src - X_dest
|
| 335 |
+
# For the ones without coordinates, substitute in the average vector
|
| 336 |
+
E_vector_mean = torch.sum(E_vectors * E_coord_mask, dim=1,
|
| 337 |
+
keepdims=True) / torch.sum(E_coord_mask, dim=1, keepdims=True)
|
| 338 |
+
E_vectors = E_vectors * E_coord_mask + E_vector_mean * ~(E_coord_mask)
|
| 339 |
+
# Normalize and remove nans
|
| 340 |
+
edge_s = torch.cat([D_rbf, pos_embeddings], dim=-1)
|
| 341 |
+
edge_v = normalize(E_vectors).unsqueeze(-2)
|
| 342 |
+
edge_s, edge_v = map(nan_to_num, (edge_s, edge_v))
|
| 343 |
+
# Also add indications of whether the coordinates are present
|
| 344 |
+
edge_s = torch.cat([
|
| 345 |
+
edge_s,
|
| 346 |
+
(~coord_mask_src).float().unsqueeze(-1),
|
| 347 |
+
(~coord_mask_dest).float().unsqueeze(-1),
|
| 348 |
+
], dim=-1)
|
| 349 |
+
edge_index[:, ~E_residue_mask] = -1
|
| 350 |
+
if self.remove_edges_without_coords:
|
| 351 |
+
edge_index[:, ~E_coord_mask.squeeze(-1)] = -1
|
| 352 |
+
return (edge_s, edge_v), edge_index.transpose(0, 1)
|
model/esm/inverse_folding/gvp_encoder.py
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
| 2 |
+
#
|
| 3 |
+
# This source code is licensed under the MIT license found in the
|
| 4 |
+
# LICENSE file in the root directory of this source tree.
|
| 5 |
+
|
| 6 |
+
from argparse import Namespace
|
| 7 |
+
|
| 8 |
+
import torch
|
| 9 |
+
import torch.nn as nn
|
| 10 |
+
import torch.nn.functional as F
|
| 11 |
+
|
| 12 |
+
from .features import GVPGraphEmbedding
|
| 13 |
+
from .gvp_modules import GVPConvLayer, LayerNorm
|
| 14 |
+
from .gvp_utils import unflatten_graph
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
class GVPEncoder(nn.Module):
|
| 19 |
+
|
| 20 |
+
def __init__(self, args):
|
| 21 |
+
super().__init__()
|
| 22 |
+
self.args = args
|
| 23 |
+
self.embed_graph = GVPGraphEmbedding(args)
|
| 24 |
+
|
| 25 |
+
node_hidden_dim = (args.node_hidden_dim_scalar,
|
| 26 |
+
args.node_hidden_dim_vector)
|
| 27 |
+
edge_hidden_dim = (args.edge_hidden_dim_scalar,
|
| 28 |
+
args.edge_hidden_dim_vector)
|
| 29 |
+
|
| 30 |
+
conv_activations = (F.relu, torch.sigmoid)
|
| 31 |
+
self.encoder_layers = nn.ModuleList(
|
| 32 |
+
GVPConvLayer(
|
| 33 |
+
node_hidden_dim,
|
| 34 |
+
edge_hidden_dim,
|
| 35 |
+
drop_rate=args.dropout,
|
| 36 |
+
vector_gate=True,
|
| 37 |
+
attention_heads=0,
|
| 38 |
+
n_message=3,
|
| 39 |
+
conv_activations=conv_activations,
|
| 40 |
+
n_edge_gvps=0,
|
| 41 |
+
eps=1e-4,
|
| 42 |
+
layernorm=True,
|
| 43 |
+
)
|
| 44 |
+
for i in range(args.num_encoder_layers)
|
| 45 |
+
)
|
| 46 |
+
|
| 47 |
+
def forward(self, coords, coord_mask, padding_mask, confidence):
|
| 48 |
+
node_embeddings, edge_embeddings, edge_index = self.embed_graph(
|
| 49 |
+
coords, coord_mask, padding_mask, confidence)
|
| 50 |
+
|
| 51 |
+
for i, layer in enumerate(self.encoder_layers):
|
| 52 |
+
node_embeddings, edge_embeddings = layer(node_embeddings,
|
| 53 |
+
edge_index, edge_embeddings)
|
| 54 |
+
|
| 55 |
+
node_embeddings = unflatten_graph(node_embeddings, coords.shape[0])
|
| 56 |
+
return node_embeddings
|
model/esm/inverse_folding/gvp_modules.py
ADDED
|
@@ -0,0 +1,475 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Contents of this file are from the open source code for
|
| 2 |
+
#
|
| 3 |
+
# Jing, B., Eismann, S., Suriana, P., Townshend, R. J. L., & Dror, R. (2020).
|
| 4 |
+
# Learning from Protein Structure with Geometric Vector Perceptrons. In
|
| 5 |
+
# International Conference on Learning Representations.
|
| 6 |
+
#
|
| 7 |
+
# MIT License
|
| 8 |
+
#
|
| 9 |
+
# Copyright (c) 2020 Bowen Jing, Stephan Eismann, Patricia Suriana, Raphael Townshend, Ron Dror
|
| 10 |
+
#
|
| 11 |
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 12 |
+
# of this software and associated documentation files (the "Software"), to deal
|
| 13 |
+
# in the Software without restriction, including without limitation the rights
|
| 14 |
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 15 |
+
# copies of the Software, and to permit persons to whom the Software is
|
| 16 |
+
# furnished to do so, subject to the following conditions:
|
| 17 |
+
#
|
| 18 |
+
# The above copyright notice and this permission notice shall be included in all
|
| 19 |
+
# copies or substantial portions of the Software.
|
| 20 |
+
#
|
| 21 |
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 22 |
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 23 |
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 24 |
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 25 |
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 26 |
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 27 |
+
# SOFTWARE.
|
| 28 |
+
|
| 29 |
+
import typing as T
|
| 30 |
+
import torch
|
| 31 |
+
from torch import nn
|
| 32 |
+
import torch.nn.functional as F
|
| 33 |
+
from torch_geometric.nn import MessagePassing
|
| 34 |
+
|
| 35 |
+
def tuple_size(tp):
|
| 36 |
+
return tuple([0 if a is None else a.size() for a in tp])
|
| 37 |
+
|
| 38 |
+
def tuple_sum(tp1, tp2):
|
| 39 |
+
s1, v1 = tp1
|
| 40 |
+
s2, v2 = tp2
|
| 41 |
+
if v2 is None and v2 is None:
|
| 42 |
+
return (s1 + s2, None)
|
| 43 |
+
return (s1 + s2, v1 + v2)
|
| 44 |
+
|
| 45 |
+
def tuple_cat(*args, dim=-1):
|
| 46 |
+
'''
|
| 47 |
+
Concatenates any number of tuples (s, V) elementwise.
|
| 48 |
+
|
| 49 |
+
:param dim: dimension along which to concatenate when viewed
|
| 50 |
+
as the `dim` index for the scalar-channel tensors.
|
| 51 |
+
This means that `dim=-1` will be applied as
|
| 52 |
+
`dim=-2` for the vector-channel tensors.
|
| 53 |
+
'''
|
| 54 |
+
dim %= len(args[0][0].shape)
|
| 55 |
+
s_args, v_args = list(zip(*args))
|
| 56 |
+
return torch.cat(s_args, dim=dim), torch.cat(v_args, dim=dim)
|
| 57 |
+
|
| 58 |
+
def tuple_index(x, idx):
|
| 59 |
+
'''
|
| 60 |
+
Indexes into a tuple (s, V) along the first dimension.
|
| 61 |
+
|
| 62 |
+
:param idx: any object which can be used to index into a `torch.Tensor`
|
| 63 |
+
'''
|
| 64 |
+
return x[0][idx], x[1][idx]
|
| 65 |
+
|
| 66 |
+
def randn(n, dims, device="cpu"):
|
| 67 |
+
'''
|
| 68 |
+
Returns random tuples (s, V) drawn elementwise from a normal distribution.
|
| 69 |
+
|
| 70 |
+
:param n: number of data points
|
| 71 |
+
:param dims: tuple of dimensions (n_scalar, n_vector)
|
| 72 |
+
|
| 73 |
+
:return: (s, V) with s.shape = (n, n_scalar) and
|
| 74 |
+
V.shape = (n, n_vector, 3)
|
| 75 |
+
'''
|
| 76 |
+
return torch.randn(n, dims[0], device=device), \
|
| 77 |
+
torch.randn(n, dims[1], 3, device=device)
|
| 78 |
+
|
| 79 |
+
def _norm_no_nan(x, axis=-1, keepdims=False, eps=1e-8, sqrt=True):
|
| 80 |
+
'''
|
| 81 |
+
L2 norm of tensor clamped above a minimum value `eps`.
|
| 82 |
+
|
| 83 |
+
:param sqrt: if `False`, returns the square of the L2 norm
|
| 84 |
+
'''
|
| 85 |
+
# clamp is slow
|
| 86 |
+
# out = torch.clamp(torch.sum(torch.square(x), axis, keepdims), min=eps)
|
| 87 |
+
out = torch.sum(torch.square(x), axis, keepdims) + eps
|
| 88 |
+
return torch.sqrt(out) if sqrt else out
|
| 89 |
+
|
| 90 |
+
def _split(x, nv):
|
| 91 |
+
'''
|
| 92 |
+
Splits a merged representation of (s, V) back into a tuple.
|
| 93 |
+
Should be used only with `_merge(s, V)` and only if the tuple
|
| 94 |
+
representation cannot be used.
|
| 95 |
+
|
| 96 |
+
:param x: the `torch.Tensor` returned from `_merge`
|
| 97 |
+
:param nv: the number of vector channels in the input to `_merge`
|
| 98 |
+
'''
|
| 99 |
+
v = torch.reshape(x[..., -3*nv:], x.shape[:-1] + (nv, 3))
|
| 100 |
+
s = x[..., :-3*nv]
|
| 101 |
+
return s, v
|
| 102 |
+
|
| 103 |
+
def _merge(s, v):
|
| 104 |
+
'''
|
| 105 |
+
Merges a tuple (s, V) into a single `torch.Tensor`, where the
|
| 106 |
+
vector channels are flattened and appended to the scalar channels.
|
| 107 |
+
Should be used only if the tuple representation cannot be used.
|
| 108 |
+
Use `_split(x, nv)` to reverse.
|
| 109 |
+
'''
|
| 110 |
+
v = torch.reshape(v, v.shape[:-2] + (3*v.shape[-2],))
|
| 111 |
+
return torch.cat([s, v], -1)
|
| 112 |
+
|
| 113 |
+
class GVP(nn.Module):
|
| 114 |
+
'''
|
| 115 |
+
Geometric Vector Perceptron. See manuscript and README.md
|
| 116 |
+
for more details.
|
| 117 |
+
|
| 118 |
+
:param in_dims: tuple (n_scalar, n_vector)
|
| 119 |
+
:param out_dims: tuple (n_scalar, n_vector)
|
| 120 |
+
:param h_dim: intermediate number of vector channels, optional
|
| 121 |
+
:param activations: tuple of functions (scalar_act, vector_act)
|
| 122 |
+
:param tuple_io: whether to keep accepting tuple inputs and outputs when vi
|
| 123 |
+
or vo = 0
|
| 124 |
+
'''
|
| 125 |
+
def __init__(self, in_dims, out_dims, h_dim=None, vector_gate=False,
|
| 126 |
+
activations=(F.relu, torch.sigmoid), tuple_io=True,
|
| 127 |
+
eps=1e-8):
|
| 128 |
+
super(GVP, self).__init__()
|
| 129 |
+
self.si, self.vi = in_dims
|
| 130 |
+
self.so, self.vo = out_dims
|
| 131 |
+
self.tuple_io = tuple_io
|
| 132 |
+
if self.vi:
|
| 133 |
+
self.h_dim = h_dim or max(self.vi, self.vo)
|
| 134 |
+
self.wh = nn.Linear(self.vi, self.h_dim, bias=False)
|
| 135 |
+
self.ws = nn.Linear(self.h_dim + self.si, self.so)
|
| 136 |
+
if self.vo:
|
| 137 |
+
self.wv = nn.Linear(self.h_dim, self.vo, bias=False)
|
| 138 |
+
if vector_gate:
|
| 139 |
+
self.wg = nn.Linear(self.so, self.vo)
|
| 140 |
+
else:
|
| 141 |
+
self.ws = nn.Linear(self.si, self.so)
|
| 142 |
+
|
| 143 |
+
self.vector_gate = vector_gate
|
| 144 |
+
self.scalar_act, self.vector_act = activations
|
| 145 |
+
self.eps = eps
|
| 146 |
+
|
| 147 |
+
def forward(self, x):
|
| 148 |
+
'''
|
| 149 |
+
:param x: tuple (s, V) of `torch.Tensor`,
|
| 150 |
+
or (if vectors_in is 0), a single `torch.Tensor`
|
| 151 |
+
:return: tuple (s, V) of `torch.Tensor`,
|
| 152 |
+
or (if vectors_out is 0), a single `torch.Tensor`
|
| 153 |
+
'''
|
| 154 |
+
if self.vi:
|
| 155 |
+
s, v = x
|
| 156 |
+
v = torch.transpose(v, -1, -2)
|
| 157 |
+
vh = self.wh(v)
|
| 158 |
+
vn = _norm_no_nan(vh, axis=-2, eps=self.eps)
|
| 159 |
+
s = self.ws(torch.cat([s, vn], -1))
|
| 160 |
+
if self.scalar_act:
|
| 161 |
+
s = self.scalar_act(s)
|
| 162 |
+
if self.vo:
|
| 163 |
+
v = self.wv(vh)
|
| 164 |
+
v = torch.transpose(v, -1, -2)
|
| 165 |
+
if self.vector_gate:
|
| 166 |
+
g = self.wg(s).unsqueeze(-1)
|
| 167 |
+
else:
|
| 168 |
+
g = _norm_no_nan(v, axis=-1, keepdims=True, eps=self.eps)
|
| 169 |
+
if self.vector_act:
|
| 170 |
+
g = self.vector_act(g)
|
| 171 |
+
v = v * g
|
| 172 |
+
else:
|
| 173 |
+
if self.tuple_io:
|
| 174 |
+
assert x[1] is None
|
| 175 |
+
x = x[0]
|
| 176 |
+
s = self.ws(x)
|
| 177 |
+
if self.scalar_act:
|
| 178 |
+
s = self.scalar_act(s)
|
| 179 |
+
if self.vo:
|
| 180 |
+
v = torch.zeros(list(s.shape)[:-1] + [self.vo, 3],
|
| 181 |
+
device=s.device)
|
| 182 |
+
|
| 183 |
+
if self.vo:
|
| 184 |
+
return (s, v)
|
| 185 |
+
elif self.tuple_io:
|
| 186 |
+
return (s, None)
|
| 187 |
+
else:
|
| 188 |
+
return s
|
| 189 |
+
|
| 190 |
+
|
| 191 |
+
class _VDropout(nn.Module):
|
| 192 |
+
'''
|
| 193 |
+
Vector channel dropout where the elements of each
|
| 194 |
+
vector channel are dropped together.
|
| 195 |
+
'''
|
| 196 |
+
def __init__(self, drop_rate):
|
| 197 |
+
super(_VDropout, self).__init__()
|
| 198 |
+
self.drop_rate = drop_rate
|
| 199 |
+
|
| 200 |
+
def forward(self, x):
|
| 201 |
+
'''
|
| 202 |
+
:param x: `torch.Tensor` corresponding to vector channels
|
| 203 |
+
'''
|
| 204 |
+
if x is None:
|
| 205 |
+
return None
|
| 206 |
+
device = x.device
|
| 207 |
+
if not self.training:
|
| 208 |
+
return x
|
| 209 |
+
mask = torch.bernoulli(
|
| 210 |
+
(1 - self.drop_rate) * torch.ones(x.shape[:-1], device=device)
|
| 211 |
+
).unsqueeze(-1)
|
| 212 |
+
x = mask * x / (1 - self.drop_rate)
|
| 213 |
+
return x
|
| 214 |
+
|
| 215 |
+
class Dropout(nn.Module):
|
| 216 |
+
'''
|
| 217 |
+
Combined dropout for tuples (s, V).
|
| 218 |
+
Takes tuples (s, V) as input and as output.
|
| 219 |
+
'''
|
| 220 |
+
def __init__(self, drop_rate):
|
| 221 |
+
super(Dropout, self).__init__()
|
| 222 |
+
self.sdropout = nn.Dropout(drop_rate)
|
| 223 |
+
self.vdropout = _VDropout(drop_rate)
|
| 224 |
+
|
| 225 |
+
def forward(self, x):
|
| 226 |
+
'''
|
| 227 |
+
:param x: tuple (s, V) of `torch.Tensor`,
|
| 228 |
+
or single `torch.Tensor`
|
| 229 |
+
(will be assumed to be scalar channels)
|
| 230 |
+
'''
|
| 231 |
+
if type(x) is torch.Tensor:
|
| 232 |
+
return self.sdropout(x)
|
| 233 |
+
s, v = x
|
| 234 |
+
return self.sdropout(s), self.vdropout(v)
|
| 235 |
+
|
| 236 |
+
class LayerNorm(nn.Module):
|
| 237 |
+
'''
|
| 238 |
+
Combined LayerNorm for tuples (s, V).
|
| 239 |
+
Takes tuples (s, V) as input and as output.
|
| 240 |
+
'''
|
| 241 |
+
def __init__(self, dims, tuple_io=True, eps=1e-8):
|
| 242 |
+
super(LayerNorm, self).__init__()
|
| 243 |
+
self.tuple_io = tuple_io
|
| 244 |
+
self.s, self.v = dims
|
| 245 |
+
self.scalar_norm = nn.LayerNorm(self.s)
|
| 246 |
+
self.eps = eps
|
| 247 |
+
|
| 248 |
+
def forward(self, x):
|
| 249 |
+
'''
|
| 250 |
+
:param x: tuple (s, V) of `torch.Tensor`,
|
| 251 |
+
or single `torch.Tensor`
|
| 252 |
+
(will be assumed to be scalar channels)
|
| 253 |
+
'''
|
| 254 |
+
if not self.v:
|
| 255 |
+
if self.tuple_io:
|
| 256 |
+
return self.scalar_norm(x[0]), None
|
| 257 |
+
return self.scalar_norm(x)
|
| 258 |
+
s, v = x
|
| 259 |
+
vn = _norm_no_nan(v, axis=-1, keepdims=True, sqrt=False, eps=self.eps)
|
| 260 |
+
nonzero_mask = (vn > 2 * self.eps)
|
| 261 |
+
vn = torch.sum(vn * nonzero_mask, dim=-2, keepdim=True
|
| 262 |
+
) / (self.eps + torch.sum(nonzero_mask, dim=-2, keepdim=True))
|
| 263 |
+
vn = torch.sqrt(vn + self.eps)
|
| 264 |
+
v = nonzero_mask * (v / vn)
|
| 265 |
+
return self.scalar_norm(s), v
|
| 266 |
+
|
| 267 |
+
class GVPConv(MessagePassing):
|
| 268 |
+
'''
|
| 269 |
+
Graph convolution / message passing with Geometric Vector Perceptrons.
|
| 270 |
+
Takes in a graph with node and edge embeddings,
|
| 271 |
+
and returns new node embeddings.
|
| 272 |
+
|
| 273 |
+
This does NOT do residual updates and pointwise feedforward layers
|
| 274 |
+
---see `GVPConvLayer`.
|
| 275 |
+
|
| 276 |
+
:param in_dims: input node embedding dimensions (n_scalar, n_vector)
|
| 277 |
+
:param out_dims: output node embedding dimensions (n_scalar, n_vector)
|
| 278 |
+
:param edge_dims: input edge embedding dimensions (n_scalar, n_vector)
|
| 279 |
+
:param n_layers: number of GVPs in the message function
|
| 280 |
+
:param module_list: preconstructed message function, overrides n_layers
|
| 281 |
+
:param aggr: should be "add" if some incoming edges are masked, as in
|
| 282 |
+
a masked autoregressive decoder architecture
|
| 283 |
+
'''
|
| 284 |
+
def __init__(self, in_dims, out_dims, edge_dims, n_layers=3,
|
| 285 |
+
vector_gate=False, module_list=None, aggr="mean", eps=1e-8,
|
| 286 |
+
activations=(F.relu, torch.sigmoid)):
|
| 287 |
+
super(GVPConv, self).__init__(aggr=aggr)
|
| 288 |
+
self.eps = eps
|
| 289 |
+
self.si, self.vi = in_dims
|
| 290 |
+
self.so, self.vo = out_dims
|
| 291 |
+
self.se, self.ve = edge_dims
|
| 292 |
+
|
| 293 |
+
module_list = module_list or []
|
| 294 |
+
if not module_list:
|
| 295 |
+
if n_layers == 1:
|
| 296 |
+
module_list.append(
|
| 297 |
+
GVP((2*self.si + self.se, 2*self.vi + self.ve),
|
| 298 |
+
(self.so, self.vo), activations=(None, None)))
|
| 299 |
+
else:
|
| 300 |
+
module_list.append(
|
| 301 |
+
GVP((2*self.si + self.se, 2*self.vi + self.ve), out_dims,
|
| 302 |
+
vector_gate=vector_gate, activations=activations)
|
| 303 |
+
)
|
| 304 |
+
for i in range(n_layers - 2):
|
| 305 |
+
module_list.append(GVP(out_dims, out_dims,
|
| 306 |
+
vector_gate=vector_gate))
|
| 307 |
+
module_list.append(GVP(out_dims, out_dims,
|
| 308 |
+
activations=(None, None)))
|
| 309 |
+
self.message_func = nn.Sequential(*module_list)
|
| 310 |
+
|
| 311 |
+
def forward(self, x, edge_index, edge_attr):
|
| 312 |
+
'''
|
| 313 |
+
:param x: tuple (s, V) of `torch.Tensor`
|
| 314 |
+
:param edge_index: array of shape [2, n_edges]
|
| 315 |
+
:param edge_attr: tuple (s, V) of `torch.Tensor`
|
| 316 |
+
'''
|
| 317 |
+
x_s, x_v = x
|
| 318 |
+
message = self.propagate(edge_index,
|
| 319 |
+
s=x_s, v=x_v.reshape(x_v.shape[0], 3*x_v.shape[1]),
|
| 320 |
+
edge_attr=edge_attr)
|
| 321 |
+
return _split(message, self.vo)
|
| 322 |
+
|
| 323 |
+
def message(self, s_i, v_i, s_j, v_j, edge_attr):
|
| 324 |
+
v_j = v_j.view(v_j.shape[0], v_j.shape[1]//3, 3)
|
| 325 |
+
v_i = v_i.view(v_i.shape[0], v_i.shape[1]//3, 3)
|
| 326 |
+
message = tuple_cat((s_j, v_j), edge_attr, (s_i, v_i))
|
| 327 |
+
message = self.message_func(message)
|
| 328 |
+
return _merge(*message)
|
| 329 |
+
|
| 330 |
+
|
| 331 |
+
class GVPConvLayer(nn.Module):
|
| 332 |
+
'''
|
| 333 |
+
Full graph convolution / message passing layer with
|
| 334 |
+
Geometric Vector Perceptrons. Residually updates node embeddings with
|
| 335 |
+
aggregated incoming messages, applies a pointwise feedforward
|
| 336 |
+
network to node embeddings, and returns updated node embeddings.
|
| 337 |
+
|
| 338 |
+
To only compute the aggregated messages, see `GVPConv`.
|
| 339 |
+
|
| 340 |
+
:param node_dims: node embedding dimensions (n_scalar, n_vector)
|
| 341 |
+
:param edge_dims: input edge embedding dimensions (n_scalar, n_vector)
|
| 342 |
+
:param n_message: number of GVPs to use in message function
|
| 343 |
+
:param n_feedforward: number of GVPs to use in feedforward function
|
| 344 |
+
:param drop_rate: drop probability in all dropout layers
|
| 345 |
+
:param autoregressive: if `True`, this `GVPConvLayer` will be used
|
| 346 |
+
with a different set of input node embeddings for messages
|
| 347 |
+
where src >= dst
|
| 348 |
+
'''
|
| 349 |
+
def __init__(self, node_dims, edge_dims, vector_gate=False,
|
| 350 |
+
n_message=3, n_feedforward=2, drop_rate=.1,
|
| 351 |
+
autoregressive=False, attention_heads=0,
|
| 352 |
+
conv_activations=(F.relu, torch.sigmoid),
|
| 353 |
+
n_edge_gvps=0, layernorm=True, eps=1e-8):
|
| 354 |
+
|
| 355 |
+
super(GVPConvLayer, self).__init__()
|
| 356 |
+
if attention_heads == 0:
|
| 357 |
+
self.conv = GVPConv(
|
| 358 |
+
node_dims, node_dims, edge_dims, n_layers=n_message,
|
| 359 |
+
vector_gate=vector_gate,
|
| 360 |
+
aggr="add" if autoregressive else "mean",
|
| 361 |
+
activations=conv_activations,
|
| 362 |
+
eps=eps,
|
| 363 |
+
)
|
| 364 |
+
else:
|
| 365 |
+
raise NotImplementedError
|
| 366 |
+
if layernorm:
|
| 367 |
+
self.norm = nn.ModuleList([LayerNorm(node_dims, eps=eps) for _ in range(2)])
|
| 368 |
+
else:
|
| 369 |
+
self.norm = nn.ModuleList([nn.Identity() for _ in range(2)])
|
| 370 |
+
self.dropout = nn.ModuleList([Dropout(drop_rate) for _ in range(2)])
|
| 371 |
+
|
| 372 |
+
ff_func = []
|
| 373 |
+
if n_feedforward == 1:
|
| 374 |
+
ff_func.append(GVP(node_dims, node_dims, activations=(None, None)))
|
| 375 |
+
else:
|
| 376 |
+
hid_dims = 4*node_dims[0], 2*node_dims[1]
|
| 377 |
+
ff_func.append(GVP(node_dims, hid_dims, vector_gate=vector_gate))
|
| 378 |
+
for i in range(n_feedforward-2):
|
| 379 |
+
ff_func.append(GVP(hid_dims, hid_dims, vector_gate=vector_gate))
|
| 380 |
+
ff_func.append(GVP(hid_dims, node_dims, activations=(None, None)))
|
| 381 |
+
self.ff_func = nn.Sequential(*ff_func)
|
| 382 |
+
|
| 383 |
+
self.edge_message_func = None
|
| 384 |
+
if n_edge_gvps > 0:
|
| 385 |
+
si, vi = node_dims
|
| 386 |
+
se, ve = edge_dims
|
| 387 |
+
module_list = [
|
| 388 |
+
GVP((2*si + se, 2*vi + ve), edge_dims, vector_gate=vector_gate)
|
| 389 |
+
]
|
| 390 |
+
for i in range(n_edge_gvps - 2):
|
| 391 |
+
module_list.append(GVP(edge_dims, edge_dims,
|
| 392 |
+
vector_gate=vector_gate))
|
| 393 |
+
if n_edge_gvps > 1:
|
| 394 |
+
module_list.append(GVP(edge_dims, edge_dims,
|
| 395 |
+
activations=(None, None)))
|
| 396 |
+
self.edge_message_func = nn.Sequential(*module_list)
|
| 397 |
+
if layernorm:
|
| 398 |
+
self.edge_norm = LayerNorm(edge_dims, eps=eps)
|
| 399 |
+
else:
|
| 400 |
+
self.edge_norm = nn.Identity()
|
| 401 |
+
self.edge_dropout = Dropout(drop_rate)
|
| 402 |
+
|
| 403 |
+
def forward(self, x, edge_index, edge_attr,
|
| 404 |
+
autoregressive_x=None, node_mask=None):
|
| 405 |
+
'''
|
| 406 |
+
:param x: tuple (s, V) of `torch.Tensor`
|
| 407 |
+
:param edge_index: array of shape [2, n_edges]
|
| 408 |
+
:param edge_attr: tuple (s, V) of `torch.Tensor`
|
| 409 |
+
:param autoregressive_x: tuple (s, V) of `torch.Tensor`.
|
| 410 |
+
If not `None`, will be used as srcqq node embeddings
|
| 411 |
+
for forming messages where src >= dst. The corrent node
|
| 412 |
+
embeddings `x` will still be the base of the update and the
|
| 413 |
+
pointwise feedforward.
|
| 414 |
+
:param node_mask: array of type `bool` to index into the first
|
| 415 |
+
dim of node embeddings (s, V). If not `None`, only
|
| 416 |
+
these nodes will be updated.
|
| 417 |
+
'''
|
| 418 |
+
if self.edge_message_func:
|
| 419 |
+
src, dst = edge_index
|
| 420 |
+
if autoregressive_x is None:
|
| 421 |
+
x_src = x[0][src], x[1][src]
|
| 422 |
+
else:
|
| 423 |
+
mask = (src < dst).unsqueeze(-1)
|
| 424 |
+
x_src = (
|
| 425 |
+
torch.where(mask, x[0][src], autoregressive_x[0][src]),
|
| 426 |
+
torch.where(mask.unsqueeze(-1), x[1][src],
|
| 427 |
+
autoregressive_x[1][src])
|
| 428 |
+
)
|
| 429 |
+
x_dst = x[0][dst], x[1][dst]
|
| 430 |
+
x_edge = (
|
| 431 |
+
torch.cat([x_src[0], edge_attr[0], x_dst[0]], dim=-1),
|
| 432 |
+
torch.cat([x_src[1], edge_attr[1], x_dst[1]], dim=-2)
|
| 433 |
+
)
|
| 434 |
+
edge_attr_dh = self.edge_message_func(x_edge)
|
| 435 |
+
edge_attr = self.edge_norm(tuple_sum(edge_attr,
|
| 436 |
+
self.edge_dropout(edge_attr_dh)))
|
| 437 |
+
|
| 438 |
+
if autoregressive_x is not None:
|
| 439 |
+
# Guarding this import here to remove the dependency on torch_scatter, since this isn't used
|
| 440 |
+
# in ESM-IF1
|
| 441 |
+
from torch_scatter import scatter_add
|
| 442 |
+
src, dst = edge_index
|
| 443 |
+
mask = src < dst
|
| 444 |
+
edge_index_forward = edge_index[:, mask]
|
| 445 |
+
edge_index_backward = edge_index[:, ~mask]
|
| 446 |
+
edge_attr_forward = tuple_index(edge_attr, mask)
|
| 447 |
+
edge_attr_backward = tuple_index(edge_attr, ~mask)
|
| 448 |
+
|
| 449 |
+
dh = tuple_sum(
|
| 450 |
+
self.conv(x, edge_index_forward, edge_attr_forward),
|
| 451 |
+
self.conv(autoregressive_x, edge_index_backward, edge_attr_backward)
|
| 452 |
+
)
|
| 453 |
+
|
| 454 |
+
count = scatter_add(torch.ones_like(dst), dst,
|
| 455 |
+
dim_size=dh[0].size(0)).clamp(min=1).unsqueeze(-1)
|
| 456 |
+
|
| 457 |
+
dh = dh[0] / count, dh[1] / count.unsqueeze(-1)
|
| 458 |
+
|
| 459 |
+
else:
|
| 460 |
+
dh = self.conv(x, edge_index, edge_attr)
|
| 461 |
+
|
| 462 |
+
if node_mask is not None:
|
| 463 |
+
x_ = x
|
| 464 |
+
x, dh = tuple_index(x, node_mask), tuple_index(dh, node_mask)
|
| 465 |
+
|
| 466 |
+
x = self.norm[0](tuple_sum(x, self.dropout[0](dh)))
|
| 467 |
+
|
| 468 |
+
dh = self.ff_func(x)
|
| 469 |
+
x = self.norm[1](tuple_sum(x, self.dropout[1](dh)))
|
| 470 |
+
|
| 471 |
+
if node_mask is not None:
|
| 472 |
+
x_[0][node_mask], x_[1][node_mask] = x[0], x[1]
|
| 473 |
+
x = x_
|
| 474 |
+
|
| 475 |
+
return x, edge_attr
|
model/esm/inverse_folding/gvp_transformer.py
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
| 2 |
+
#
|
| 3 |
+
# This source code is licensed under the MIT license found in the
|
| 4 |
+
# LICENSE file in the root directory of this source tree.
|
| 5 |
+
|
| 6 |
+
import argparse
|
| 7 |
+
from typing import Any, Dict, List, Optional, Tuple, NamedTuple
|
| 8 |
+
import torch
|
| 9 |
+
from torch import nn
|
| 10 |
+
from torch import Tensor
|
| 11 |
+
import torch.nn.functional as F
|
| 12 |
+
from scipy.spatial import transform
|
| 13 |
+
|
| 14 |
+
from onescience.datapipes.esm import Alphabet
|
| 15 |
+
|
| 16 |
+
from .features import DihedralFeatures
|
| 17 |
+
from .gvp_encoder import GVPEncoder
|
| 18 |
+
from .gvp_utils import unflatten_graph
|
| 19 |
+
from .gvp_transformer_encoder import GVPTransformerEncoder
|
| 20 |
+
from .transformer_decoder import TransformerDecoder
|
| 21 |
+
from .util import rotate, CoordBatchConverter
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
class GVPTransformerModel(nn.Module):
|
| 25 |
+
"""
|
| 26 |
+
GVP-Transformer inverse folding model.
|
| 27 |
+
|
| 28 |
+
Architecture: Geometric GVP-GNN as initial layers, followed by
|
| 29 |
+
sequence-to-sequence Transformer encoder and decoder.
|
| 30 |
+
"""
|
| 31 |
+
|
| 32 |
+
def __init__(self, args, alphabet):
|
| 33 |
+
super().__init__()
|
| 34 |
+
encoder_embed_tokens = self.build_embedding(
|
| 35 |
+
args, alphabet, args.encoder_embed_dim,
|
| 36 |
+
)
|
| 37 |
+
decoder_embed_tokens = self.build_embedding(
|
| 38 |
+
args, alphabet, args.decoder_embed_dim,
|
| 39 |
+
)
|
| 40 |
+
encoder = self.build_encoder(args, alphabet, encoder_embed_tokens)
|
| 41 |
+
decoder = self.build_decoder(args, alphabet, decoder_embed_tokens)
|
| 42 |
+
self.args = args
|
| 43 |
+
self.encoder = encoder
|
| 44 |
+
self.decoder = decoder
|
| 45 |
+
|
| 46 |
+
@classmethod
|
| 47 |
+
def build_encoder(cls, args, src_dict, embed_tokens):
|
| 48 |
+
encoder = GVPTransformerEncoder(args, src_dict, embed_tokens)
|
| 49 |
+
return encoder
|
| 50 |
+
|
| 51 |
+
@classmethod
|
| 52 |
+
def build_decoder(cls, args, tgt_dict, embed_tokens):
|
| 53 |
+
decoder = TransformerDecoder(
|
| 54 |
+
args,
|
| 55 |
+
tgt_dict,
|
| 56 |
+
embed_tokens,
|
| 57 |
+
)
|
| 58 |
+
return decoder
|
| 59 |
+
|
| 60 |
+
@classmethod
|
| 61 |
+
def build_embedding(cls, args, dictionary, embed_dim):
|
| 62 |
+
num_embeddings = len(dictionary)
|
| 63 |
+
padding_idx = dictionary.padding_idx
|
| 64 |
+
emb = nn.Embedding(num_embeddings, embed_dim, padding_idx)
|
| 65 |
+
nn.init.normal_(emb.weight, mean=0, std=embed_dim ** -0.5)
|
| 66 |
+
nn.init.constant_(emb.weight[padding_idx], 0)
|
| 67 |
+
return emb
|
| 68 |
+
|
| 69 |
+
def forward(
|
| 70 |
+
self,
|
| 71 |
+
coords,
|
| 72 |
+
padding_mask,
|
| 73 |
+
confidence,
|
| 74 |
+
prev_output_tokens,
|
| 75 |
+
return_all_hiddens: bool = False,
|
| 76 |
+
features_only: bool = False,
|
| 77 |
+
):
|
| 78 |
+
encoder_out = self.encoder(coords, padding_mask, confidence,
|
| 79 |
+
return_all_hiddens=return_all_hiddens)
|
| 80 |
+
logits, extra = self.decoder(
|
| 81 |
+
prev_output_tokens,
|
| 82 |
+
encoder_out=encoder_out,
|
| 83 |
+
features_only=features_only,
|
| 84 |
+
return_all_hiddens=return_all_hiddens,
|
| 85 |
+
)
|
| 86 |
+
return logits, extra
|
| 87 |
+
|
| 88 |
+
def sample(self, coords, partial_seq=None, temperature=1.0, confidence=None, device=None):
|
| 89 |
+
"""
|
| 90 |
+
Samples sequences based on multinomial sampling (no beam search).
|
| 91 |
+
|
| 92 |
+
Args:
|
| 93 |
+
coords: L x 3 x 3 list representing one backbone
|
| 94 |
+
partial_seq: Optional, partial sequence with mask tokens if part of
|
| 95 |
+
the sequence is known
|
| 96 |
+
temperature: sampling temperature, use low temperature for higher
|
| 97 |
+
sequence recovery and high temperature for higher diversity
|
| 98 |
+
confidence: optional length L list of confidence scores for coordinates
|
| 99 |
+
"""
|
| 100 |
+
L = len(coords)
|
| 101 |
+
# Convert to batch format
|
| 102 |
+
batch_converter = CoordBatchConverter(self.decoder.dictionary)
|
| 103 |
+
batch_coords, confidence, _, _, padding_mask = (
|
| 104 |
+
batch_converter([(coords, confidence, None)], device=device)
|
| 105 |
+
)
|
| 106 |
+
|
| 107 |
+
# Start with prepend token
|
| 108 |
+
mask_idx = self.decoder.dictionary.get_idx('<mask>')
|
| 109 |
+
sampled_tokens = torch.full((1, 1+L), mask_idx, dtype=int)
|
| 110 |
+
sampled_tokens[0, 0] = self.decoder.dictionary.get_idx('<cath>')
|
| 111 |
+
if partial_seq is not None:
|
| 112 |
+
for i, c in enumerate(partial_seq):
|
| 113 |
+
sampled_tokens[0, i+1] = self.decoder.dictionary.get_idx(c)
|
| 114 |
+
|
| 115 |
+
# Save incremental states for faster sampling
|
| 116 |
+
incremental_state = dict()
|
| 117 |
+
|
| 118 |
+
# Run encoder only once
|
| 119 |
+
encoder_out = self.encoder(batch_coords, padding_mask, confidence)
|
| 120 |
+
|
| 121 |
+
# Make sure all tensors are on the same device if a GPU is present
|
| 122 |
+
if device:
|
| 123 |
+
sampled_tokens = sampled_tokens.to(device)
|
| 124 |
+
|
| 125 |
+
# Decode one token at a time
|
| 126 |
+
for i in range(1, L+1):
|
| 127 |
+
logits, _ = self.decoder(
|
| 128 |
+
sampled_tokens[:, :i],
|
| 129 |
+
encoder_out,
|
| 130 |
+
incremental_state=incremental_state,
|
| 131 |
+
)
|
| 132 |
+
logits = logits[0].transpose(0, 1)
|
| 133 |
+
logits /= temperature
|
| 134 |
+
probs = F.softmax(logits, dim=-1)
|
| 135 |
+
if sampled_tokens[0, i] == mask_idx:
|
| 136 |
+
sampled_tokens[:, i] = torch.multinomial(probs, 1).squeeze(-1)
|
| 137 |
+
sampled_seq = sampled_tokens[0, 1:]
|
| 138 |
+
|
| 139 |
+
# Convert back to string via lookup
|
| 140 |
+
return ''.join([self.decoder.dictionary.get_tok(a) for a in sampled_seq])
|
model/esm/inverse_folding/gvp_transformer_encoder.py
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
| 2 |
+
#
|
| 3 |
+
# Contents of this file were adapted from the open source fairseq repository.
|
| 4 |
+
#
|
| 5 |
+
# This source code is licensed under the MIT license found in the
|
| 6 |
+
# LICENSE file in the root directory of this source tree.
|
| 7 |
+
|
| 8 |
+
import argparse
|
| 9 |
+
import math
|
| 10 |
+
from typing import Dict, List, Optional
|
| 11 |
+
|
| 12 |
+
import torch
|
| 13 |
+
import torch.nn as nn
|
| 14 |
+
from torch import Tensor
|
| 15 |
+
|
| 16 |
+
from onescience.modules.esm import SinusoidalPositionalEmbedding
|
| 17 |
+
from .features import GVPInputFeaturizer, DihedralFeatures
|
| 18 |
+
from .gvp_encoder import GVPEncoder
|
| 19 |
+
from .transformer_layer import TransformerEncoderLayer
|
| 20 |
+
from .util import nan_to_num, get_rotation_frames, rotate, rbf
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
class GVPTransformerEncoder(nn.Module):
|
| 24 |
+
"""
|
| 25 |
+
Transformer encoder consisting of *args.encoder.layers* layers. Each layer
|
| 26 |
+
is a :class:`TransformerEncoderLayer`.
|
| 27 |
+
|
| 28 |
+
Args:
|
| 29 |
+
args (argparse.Namespace): parsed command-line arguments
|
| 30 |
+
dictionary (~fairseq.data.Dictionary): encoding dictionary
|
| 31 |
+
embed_tokens (torch.nn.Embedding): input embedding
|
| 32 |
+
"""
|
| 33 |
+
|
| 34 |
+
def __init__(self, args, dictionary, embed_tokens):
|
| 35 |
+
super().__init__()
|
| 36 |
+
self.args = args
|
| 37 |
+
self.dictionary = dictionary
|
| 38 |
+
|
| 39 |
+
self.dropout_module = nn.Dropout(args.dropout)
|
| 40 |
+
|
| 41 |
+
embed_dim = embed_tokens.embedding_dim
|
| 42 |
+
self.padding_idx = embed_tokens.padding_idx
|
| 43 |
+
|
| 44 |
+
self.embed_tokens = embed_tokens
|
| 45 |
+
self.embed_scale = math.sqrt(embed_dim)
|
| 46 |
+
self.embed_positions = SinusoidalPositionalEmbedding(
|
| 47 |
+
embed_dim,
|
| 48 |
+
self.padding_idx,
|
| 49 |
+
)
|
| 50 |
+
self.embed_gvp_input_features = nn.Linear(15, embed_dim)
|
| 51 |
+
self.embed_confidence = nn.Linear(16, embed_dim)
|
| 52 |
+
self.embed_dihedrals = DihedralFeatures(embed_dim)
|
| 53 |
+
|
| 54 |
+
gvp_args = argparse.Namespace()
|
| 55 |
+
for k, v in vars(args).items():
|
| 56 |
+
if k.startswith("gvp_"):
|
| 57 |
+
setattr(gvp_args, k[4:], v)
|
| 58 |
+
self.gvp_encoder = GVPEncoder(gvp_args)
|
| 59 |
+
gvp_out_dim = gvp_args.node_hidden_dim_scalar + (3 *
|
| 60 |
+
gvp_args.node_hidden_dim_vector)
|
| 61 |
+
self.embed_gvp_output = nn.Linear(gvp_out_dim, embed_dim)
|
| 62 |
+
|
| 63 |
+
self.layers = nn.ModuleList([])
|
| 64 |
+
self.layers.extend(
|
| 65 |
+
[self.build_encoder_layer(args) for i in range(args.encoder_layers)]
|
| 66 |
+
)
|
| 67 |
+
self.num_layers = len(self.layers)
|
| 68 |
+
self.layer_norm = nn.LayerNorm(embed_dim)
|
| 69 |
+
|
| 70 |
+
def build_encoder_layer(self, args):
|
| 71 |
+
return TransformerEncoderLayer(args)
|
| 72 |
+
|
| 73 |
+
def forward_embedding(self, coords, padding_mask, confidence):
|
| 74 |
+
"""
|
| 75 |
+
Args:
|
| 76 |
+
coords: N, CA, C backbone coordinates in shape length x 3 (atoms) x 3
|
| 77 |
+
padding_mask: boolean Tensor (true for padding) of shape length
|
| 78 |
+
confidence: confidence scores between 0 and 1 of shape length
|
| 79 |
+
"""
|
| 80 |
+
components = dict()
|
| 81 |
+
coord_mask = torch.all(torch.all(torch.isfinite(coords), dim=-1), dim=-1)
|
| 82 |
+
coords = nan_to_num(coords)
|
| 83 |
+
mask_tokens = (
|
| 84 |
+
padding_mask * self.dictionary.padding_idx +
|
| 85 |
+
~padding_mask * self.dictionary.get_idx("<mask>")
|
| 86 |
+
)
|
| 87 |
+
components["tokens"] = self.embed_tokens(mask_tokens) * self.embed_scale
|
| 88 |
+
components["diherals"] = self.embed_dihedrals(coords)
|
| 89 |
+
|
| 90 |
+
# GVP encoder
|
| 91 |
+
gvp_out_scalars, gvp_out_vectors = self.gvp_encoder(coords,
|
| 92 |
+
coord_mask, padding_mask, confidence)
|
| 93 |
+
R = get_rotation_frames(coords)
|
| 94 |
+
# Rotate to local rotation frame for rotation-invariance
|
| 95 |
+
gvp_out_features = torch.cat([
|
| 96 |
+
gvp_out_scalars,
|
| 97 |
+
rotate(gvp_out_vectors, R.transpose(-2, -1)).flatten(-2, -1),
|
| 98 |
+
], dim=-1)
|
| 99 |
+
components["gvp_out"] = self.embed_gvp_output(gvp_out_features)
|
| 100 |
+
|
| 101 |
+
components["confidence"] = self.embed_confidence(
|
| 102 |
+
rbf(confidence, 0., 1.))
|
| 103 |
+
|
| 104 |
+
# In addition to GVP encoder outputs, also directly embed GVP input node
|
| 105 |
+
# features to the Transformer
|
| 106 |
+
scalar_features, vector_features = GVPInputFeaturizer.get_node_features(
|
| 107 |
+
coords, coord_mask, with_coord_mask=False)
|
| 108 |
+
features = torch.cat([
|
| 109 |
+
scalar_features,
|
| 110 |
+
rotate(vector_features, R.transpose(-2, -1)).flatten(-2, -1),
|
| 111 |
+
], dim=-1)
|
| 112 |
+
components["gvp_input_features"] = self.embed_gvp_input_features(features)
|
| 113 |
+
|
| 114 |
+
embed = sum(components.values())
|
| 115 |
+
# for k, v in components.items():
|
| 116 |
+
# print(k, torch.mean(v, dim=(0,1)), torch.std(v, dim=(0,1)))
|
| 117 |
+
|
| 118 |
+
x = embed
|
| 119 |
+
x = x + self.embed_positions(mask_tokens)
|
| 120 |
+
x = self.dropout_module(x)
|
| 121 |
+
return x, components
|
| 122 |
+
|
| 123 |
+
def forward(
|
| 124 |
+
self,
|
| 125 |
+
coords,
|
| 126 |
+
encoder_padding_mask,
|
| 127 |
+
confidence,
|
| 128 |
+
return_all_hiddens: bool = False,
|
| 129 |
+
):
|
| 130 |
+
"""
|
| 131 |
+
Args:
|
| 132 |
+
coords (Tensor): backbone coordinates
|
| 133 |
+
shape batch_size x num_residues x num_atoms (3 for N, CA, C) x 3
|
| 134 |
+
encoder_padding_mask (ByteTensor): the positions of
|
| 135 |
+
padding elements of shape `(batch_size x num_residues)`
|
| 136 |
+
confidence (Tensor): the confidence score of shape (batch_size x
|
| 137 |
+
num_residues). The value is between 0. and 1. for each residue
|
| 138 |
+
coordinate, or -1. if no coordinate is given
|
| 139 |
+
return_all_hiddens (bool, optional): also return all of the
|
| 140 |
+
intermediate hidden states (default: False).
|
| 141 |
+
|
| 142 |
+
Returns:
|
| 143 |
+
dict:
|
| 144 |
+
- **encoder_out** (Tensor): the last encoder layer's output of
|
| 145 |
+
shape `(num_residues, batch_size, embed_dim)`
|
| 146 |
+
- **encoder_padding_mask** (ByteTensor): the positions of
|
| 147 |
+
padding elements of shape `(batch_size, num_residues)`
|
| 148 |
+
- **encoder_embedding** (Tensor): the (scaled) embedding lookup
|
| 149 |
+
of shape `(batch_size, num_residues, embed_dim)`
|
| 150 |
+
- **encoder_states** (List[Tensor]): all intermediate
|
| 151 |
+
hidden states of shape `(num_residues, batch_size, embed_dim)`.
|
| 152 |
+
Only populated if *return_all_hiddens* is True.
|
| 153 |
+
"""
|
| 154 |
+
x, encoder_embedding = self.forward_embedding(coords,
|
| 155 |
+
encoder_padding_mask, confidence)
|
| 156 |
+
# account for padding while computing the representation
|
| 157 |
+
x = x * (1 - encoder_padding_mask.unsqueeze(-1).type_as(x))
|
| 158 |
+
|
| 159 |
+
# B x T x C -> T x B x C
|
| 160 |
+
x = x.transpose(0, 1)
|
| 161 |
+
|
| 162 |
+
encoder_states = []
|
| 163 |
+
|
| 164 |
+
if return_all_hiddens:
|
| 165 |
+
encoder_states.append(x)
|
| 166 |
+
|
| 167 |
+
# encoder layers
|
| 168 |
+
for layer in self.layers:
|
| 169 |
+
x = layer(
|
| 170 |
+
x, encoder_padding_mask=encoder_padding_mask
|
| 171 |
+
)
|
| 172 |
+
if return_all_hiddens:
|
| 173 |
+
assert encoder_states is not None
|
| 174 |
+
encoder_states.append(x)
|
| 175 |
+
|
| 176 |
+
if self.layer_norm is not None:
|
| 177 |
+
x = self.layer_norm(x)
|
| 178 |
+
|
| 179 |
+
return {
|
| 180 |
+
"encoder_out": [x], # T x B x C
|
| 181 |
+
"encoder_padding_mask": [encoder_padding_mask], # B x T
|
| 182 |
+
"encoder_embedding": [encoder_embedding], # dictionary
|
| 183 |
+
"encoder_states": encoder_states, # List[T x B x C]
|
| 184 |
+
}
|
model/esm/inverse_folding/gvp_utils.py
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
| 2 |
+
#
|
| 3 |
+
# This source code is licensed under the MIT license found in the
|
| 4 |
+
# LICENSE file in the root directory of this source tree.
|
| 5 |
+
|
| 6 |
+
import torch
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
def flatten_graph(node_embeddings, edge_embeddings, edge_index):
|
| 10 |
+
"""
|
| 11 |
+
Flattens the graph into a batch size one (with disconnected subgraphs for
|
| 12 |
+
each example) to be compatible with pytorch-geometric package.
|
| 13 |
+
Args:
|
| 14 |
+
node_embeddings: node embeddings in tuple form (scalar, vector)
|
| 15 |
+
- scalar: shape batch size x nodes x node_embed_dim
|
| 16 |
+
- vector: shape batch size x nodes x node_embed_dim x 3
|
| 17 |
+
edge_embeddings: edge embeddings of in tuple form (scalar, vector)
|
| 18 |
+
- scalar: shape batch size x edges x edge_embed_dim
|
| 19 |
+
- vector: shape batch size x edges x edge_embed_dim x 3
|
| 20 |
+
edge_index: shape batch_size x 2 (source node and target node) x edges
|
| 21 |
+
Returns:
|
| 22 |
+
node_embeddings: node embeddings in tuple form (scalar, vector)
|
| 23 |
+
- scalar: shape batch total_nodes x node_embed_dim
|
| 24 |
+
- vector: shape batch total_nodes x node_embed_dim x 3
|
| 25 |
+
edge_embeddings: edge embeddings of in tuple form (scalar, vector)
|
| 26 |
+
- scalar: shape batch total_edges x edge_embed_dim
|
| 27 |
+
- vector: shape batch total_edges x edge_embed_dim x 3
|
| 28 |
+
edge_index: shape 2 x total_edges
|
| 29 |
+
"""
|
| 30 |
+
x_s, x_v = node_embeddings
|
| 31 |
+
e_s, e_v = edge_embeddings
|
| 32 |
+
batch_size, N = x_s.shape[0], x_s.shape[1]
|
| 33 |
+
node_embeddings = (torch.flatten(x_s, 0, 1), torch.flatten(x_v, 0, 1))
|
| 34 |
+
edge_embeddings = (torch.flatten(e_s, 0, 1), torch.flatten(e_v, 0, 1))
|
| 35 |
+
|
| 36 |
+
edge_mask = torch.any(edge_index != -1, dim=1)
|
| 37 |
+
# Re-number the nodes by adding batch_idx * N to each batch
|
| 38 |
+
edge_index = edge_index + (torch.arange(batch_size, device=edge_index.device) *
|
| 39 |
+
N).unsqueeze(-1).unsqueeze(-1)
|
| 40 |
+
edge_index = edge_index.permute(1, 0, 2).flatten(1, 2)
|
| 41 |
+
edge_mask = edge_mask.flatten()
|
| 42 |
+
edge_index = edge_index[:, edge_mask]
|
| 43 |
+
edge_embeddings = (
|
| 44 |
+
edge_embeddings[0][edge_mask, :],
|
| 45 |
+
edge_embeddings[1][edge_mask, :]
|
| 46 |
+
)
|
| 47 |
+
return node_embeddings, edge_embeddings, edge_index
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
def unflatten_graph(node_embeddings, batch_size):
|
| 51 |
+
"""
|
| 52 |
+
Unflattens node embeddings.
|
| 53 |
+
Args:
|
| 54 |
+
node_embeddings: node embeddings in tuple form (scalar, vector)
|
| 55 |
+
- scalar: shape batch total_nodes x node_embed_dim
|
| 56 |
+
- vector: shape batch total_nodes x node_embed_dim x 3
|
| 57 |
+
batch_size: int
|
| 58 |
+
Returns:
|
| 59 |
+
node_embeddings: node embeddings in tuple form (scalar, vector)
|
| 60 |
+
- scalar: shape batch size x nodes x node_embed_dim
|
| 61 |
+
- vector: shape batch size x nodes x node_embed_dim x 3
|
| 62 |
+
"""
|
| 63 |
+
x_s, x_v = node_embeddings
|
| 64 |
+
x_s = x_s.reshape(batch_size, -1, x_s.shape[1])
|
| 65 |
+
x_v = x_v.reshape(batch_size, -1, x_v.shape[1], x_v.shape[2])
|
| 66 |
+
return (x_s, x_v)
|
| 67 |
+
|
| 68 |
+
|
model/esm/inverse_folding/multichain_util.py
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
| 2 |
+
#
|
| 3 |
+
# This source code is licensed under the MIT license found in the
|
| 4 |
+
# LICENSE file in the root directory of this source tree.
|
| 5 |
+
|
| 6 |
+
import biotite.structure
|
| 7 |
+
import numpy as np
|
| 8 |
+
import torch
|
| 9 |
+
from typing import Sequence, Tuple, List
|
| 10 |
+
|
| 11 |
+
from model.esm.inverse_folding.util import (
|
| 12 |
+
load_structure,
|
| 13 |
+
extract_coords_from_structure,
|
| 14 |
+
load_coords,
|
| 15 |
+
get_sequence_loss,
|
| 16 |
+
get_encoder_output,
|
| 17 |
+
)
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def extract_coords_from_complex(structure: biotite.structure.AtomArray):
|
| 21 |
+
"""
|
| 22 |
+
Args:
|
| 23 |
+
structure: biotite AtomArray
|
| 24 |
+
Returns:
|
| 25 |
+
Tuple (coords_list, seq_list)
|
| 26 |
+
- coords: Dictionary mapping chain ids to L x 3 x 3 array for N, CA, C
|
| 27 |
+
coordinates representing the backbone of each chain
|
| 28 |
+
- seqs: Dictionary mapping chain ids to native sequences of each chain
|
| 29 |
+
"""
|
| 30 |
+
coords = {}
|
| 31 |
+
seqs = {}
|
| 32 |
+
all_chains = biotite.structure.get_chains(structure)
|
| 33 |
+
for chain_id in all_chains:
|
| 34 |
+
chain = structure[structure.chain_id == chain_id]
|
| 35 |
+
coords[chain_id], seqs[chain_id] = extract_coords_from_structure(chain)
|
| 36 |
+
return coords, seqs
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def load_complex_coords(fpath, chains):
|
| 40 |
+
"""
|
| 41 |
+
Args:
|
| 42 |
+
fpath: filepath to either pdb or cif file
|
| 43 |
+
chains: the chain ids (the order matters for autoregressive model)
|
| 44 |
+
Returns:
|
| 45 |
+
Tuple (coords_list, seq_list)
|
| 46 |
+
- coords: Dictionary mapping chain ids to L x 3 x 3 array for N, CA, C
|
| 47 |
+
coordinates representing the backbone of each chain
|
| 48 |
+
- seqs: Dictionary mapping chain ids to native sequences of each chain
|
| 49 |
+
"""
|
| 50 |
+
structure = load_structure(fpath, chains)
|
| 51 |
+
return extract_coords_from_complex(structure)
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
def _concatenate_coords(coords, target_chain_id, padding_length=10):
|
| 55 |
+
"""
|
| 56 |
+
Args:
|
| 57 |
+
coords: Dictionary mapping chain ids to L x 3 x 3 array for N, CA, C
|
| 58 |
+
coordinates representing the backbone of each chain
|
| 59 |
+
target_chain_id: The chain id to sample sequences for
|
| 60 |
+
padding_length: Length of padding between concatenated chains
|
| 61 |
+
Returns:
|
| 62 |
+
Tuple (coords, seq)
|
| 63 |
+
- coords is an L x 3 x 3 array for N, CA, C coordinates, a
|
| 64 |
+
concatenation of the chains with padding in between
|
| 65 |
+
- seq is the extracted sequence, with padding tokens inserted
|
| 66 |
+
between the concatenated chains
|
| 67 |
+
"""
|
| 68 |
+
pad_coords = np.full((padding_length, 3, 3), np.nan, dtype=np.float32)
|
| 69 |
+
# For best performance, put the target chain first in concatenation.
|
| 70 |
+
coords_list = [coords[target_chain_id]]
|
| 71 |
+
for chain_id in coords:
|
| 72 |
+
if chain_id == target_chain_id:
|
| 73 |
+
continue
|
| 74 |
+
coords_list.append(pad_coords)
|
| 75 |
+
coords_list.append(coords[chain_id])
|
| 76 |
+
coords_concatenated = np.concatenate(coords_list, axis=0)
|
| 77 |
+
return coords_concatenated
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
def sample_sequence_in_complex(model, coords, target_chain_id, temperature=1.,
|
| 81 |
+
padding_length=10):
|
| 82 |
+
"""
|
| 83 |
+
Samples sequence for one chain in a complex.
|
| 84 |
+
Args:
|
| 85 |
+
model: An instance of the GVPTransformer model
|
| 86 |
+
coords: Dictionary mapping chain ids to L x 3 x 3 array for N, CA, C
|
| 87 |
+
coordinates representing the backbone of each chain
|
| 88 |
+
target_chain_id: The chain id to sample sequences for
|
| 89 |
+
padding_length: padding length in between chains
|
| 90 |
+
Returns:
|
| 91 |
+
Sampled sequence for the target chain
|
| 92 |
+
"""
|
| 93 |
+
target_chain_len = coords[target_chain_id].shape[0]
|
| 94 |
+
all_coords = _concatenate_coords(coords, target_chain_id)
|
| 95 |
+
device = next(model.parameters()).device
|
| 96 |
+
|
| 97 |
+
# Supply padding tokens for other chains to avoid unused sampling for speed
|
| 98 |
+
padding_pattern = ['<pad>'] * all_coords.shape[0]
|
| 99 |
+
for i in range(target_chain_len):
|
| 100 |
+
padding_pattern[i] = '<mask>'
|
| 101 |
+
sampled = model.sample(all_coords, partial_seq=padding_pattern,
|
| 102 |
+
temperature=temperature, device=device)
|
| 103 |
+
sampled = sampled[:target_chain_len]
|
| 104 |
+
return sampled
|
| 105 |
+
|
| 106 |
+
|
| 107 |
+
def score_sequence_in_complex(model, alphabet, coords, target_chain_id,
|
| 108 |
+
target_seq, padding_length=10):
|
| 109 |
+
"""
|
| 110 |
+
Scores sequence for one chain in a complex.
|
| 111 |
+
Args:
|
| 112 |
+
model: An instance of the GVPTransformer model
|
| 113 |
+
alphabet: Alphabet for the model
|
| 114 |
+
coords: Dictionary mapping chain ids to L x 3 x 3 array for N, CA, C
|
| 115 |
+
coordinates representing the backbone of each chain
|
| 116 |
+
target_chain_id: The chain id to sample sequences for
|
| 117 |
+
target_seq: Target sequence for the target chain for scoring.
|
| 118 |
+
padding_length: padding length in between chains
|
| 119 |
+
Returns:
|
| 120 |
+
Tuple (ll_fullseq, ll_withcoord)
|
| 121 |
+
- ll_fullseq: Average log-likelihood over the full target chain
|
| 122 |
+
- ll_withcoord: Average log-likelihood in target chain excluding those
|
| 123 |
+
residues without coordinates
|
| 124 |
+
"""
|
| 125 |
+
all_coords = _concatenate_coords(coords, target_chain_id)
|
| 126 |
+
|
| 127 |
+
loss, target_padding_mask = get_sequence_loss(model, alphabet, all_coords,
|
| 128 |
+
target_seq)
|
| 129 |
+
ll_fullseq = -np.sum(loss * ~target_padding_mask) / np.sum(
|
| 130 |
+
~target_padding_mask)
|
| 131 |
+
|
| 132 |
+
# Also calculate average when excluding masked portions
|
| 133 |
+
coord_mask = np.all(np.isfinite(coords[target_chain_id]), axis=(-1, -2))
|
| 134 |
+
ll_withcoord = -np.sum(loss * coord_mask) / np.sum(coord_mask)
|
| 135 |
+
return ll_fullseq, ll_withcoord
|
| 136 |
+
|
| 137 |
+
|
| 138 |
+
def get_encoder_output_for_complex(model, alphabet, coords, target_chain_id):
|
| 139 |
+
"""
|
| 140 |
+
Args:
|
| 141 |
+
model: An instance of the GVPTransformer model
|
| 142 |
+
alphabet: Alphabet for the model
|
| 143 |
+
coords: Dictionary mapping chain ids to L x 3 x 3 array for N, CA, C
|
| 144 |
+
coordinates representing the backbone of each chain
|
| 145 |
+
target_chain_id: The chain id to sample sequences for
|
| 146 |
+
Returns:
|
| 147 |
+
Dictionary mapping chain id to encoder output for each chain
|
| 148 |
+
"""
|
| 149 |
+
all_coords = _concatenate_coords(coords, target_chain_id)
|
| 150 |
+
all_rep = get_encoder_output(model, alphabet, all_coords)
|
| 151 |
+
target_chain_len = coords[target_chain_id].shape[0]
|
| 152 |
+
return all_rep[:target_chain_len]
|
model/esm/inverse_folding/transformer_decoder.py
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
| 2 |
+
#
|
| 3 |
+
# Contents of this file were adapted from the open source fairseq repository.
|
| 4 |
+
#
|
| 5 |
+
# This source code is licensed under the MIT license found in the
|
| 6 |
+
# LICENSE file in the root directory of this source tree.
|
| 7 |
+
|
| 8 |
+
import math
|
| 9 |
+
from typing import Any, Dict, List, Optional
|
| 10 |
+
|
| 11 |
+
import torch
|
| 12 |
+
import torch.nn as nn
|
| 13 |
+
from torch import Tensor
|
| 14 |
+
|
| 15 |
+
from onescience.modules.esm import SinusoidalPositionalEmbedding
|
| 16 |
+
from .transformer_layer import TransformerDecoderLayer
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
def fill_with_neg_inf(t):
|
| 20 |
+
"""FP16-compatible function that fills a tensor with -inf."""
|
| 21 |
+
return t.float().fill_(float("-inf")).type_as(t)
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
class TransformerDecoder(nn.Module):
|
| 25 |
+
"""
|
| 26 |
+
Transformer decoder consisting of *args.decoder.layers* layers. Each layer
|
| 27 |
+
is a :class:`TransformerDecoderLayer`.
|
| 28 |
+
|
| 29 |
+
Args:
|
| 30 |
+
args (argparse.Namespace): parsed command-line arguments
|
| 31 |
+
dictionary (~fairseq.data.Dictionary): decoding dictionary
|
| 32 |
+
embed_tokens (torch.nn.Embedding): output embedding
|
| 33 |
+
no_encoder_attn (bool, optional): whether to attend to encoder outputs
|
| 34 |
+
(default: False).
|
| 35 |
+
"""
|
| 36 |
+
|
| 37 |
+
def __init__(
|
| 38 |
+
self,
|
| 39 |
+
args,
|
| 40 |
+
dictionary,
|
| 41 |
+
embed_tokens,
|
| 42 |
+
):
|
| 43 |
+
super().__init__()
|
| 44 |
+
self.args = args
|
| 45 |
+
self.dictionary = dictionary
|
| 46 |
+
self._future_mask = torch.empty(0)
|
| 47 |
+
|
| 48 |
+
self.dropout_module = nn.Dropout(args.dropout)
|
| 49 |
+
|
| 50 |
+
input_embed_dim = embed_tokens.embedding_dim
|
| 51 |
+
embed_dim = args.decoder_embed_dim
|
| 52 |
+
self.embed_dim = embed_dim
|
| 53 |
+
|
| 54 |
+
self.padding_idx = embed_tokens.padding_idx
|
| 55 |
+
|
| 56 |
+
self.embed_tokens = embed_tokens
|
| 57 |
+
self.embed_scale = math.sqrt(embed_dim)
|
| 58 |
+
|
| 59 |
+
self.project_in_dim = (
|
| 60 |
+
nn.Linear(input_embed_dim, embed_dim, bias=False)
|
| 61 |
+
if embed_dim != input_embed_dim
|
| 62 |
+
else None
|
| 63 |
+
)
|
| 64 |
+
self.embed_positions = SinusoidalPositionalEmbedding(
|
| 65 |
+
embed_dim,
|
| 66 |
+
self.padding_idx,
|
| 67 |
+
)
|
| 68 |
+
|
| 69 |
+
self.layers = nn.ModuleList([])
|
| 70 |
+
self.layers.extend(
|
| 71 |
+
[
|
| 72 |
+
self.build_decoder_layer(args)
|
| 73 |
+
for _ in range(args.decoder_layers)
|
| 74 |
+
]
|
| 75 |
+
)
|
| 76 |
+
self.num_layers = len(self.layers)
|
| 77 |
+
self.layer_norm = nn.LayerNorm(embed_dim)
|
| 78 |
+
|
| 79 |
+
self.build_output_projection(args, dictionary)
|
| 80 |
+
|
| 81 |
+
def build_output_projection(self, args, dictionary):
|
| 82 |
+
self.output_projection = nn.Linear(
|
| 83 |
+
args.decoder_embed_dim, len(dictionary), bias=False
|
| 84 |
+
)
|
| 85 |
+
nn.init.normal_(
|
| 86 |
+
self.output_projection.weight, mean=0, std=args.decoder_embed_dim ** -0.5
|
| 87 |
+
)
|
| 88 |
+
|
| 89 |
+
def build_decoder_layer(self, args):
|
| 90 |
+
return TransformerDecoderLayer(args)
|
| 91 |
+
|
| 92 |
+
def forward(
|
| 93 |
+
self,
|
| 94 |
+
prev_output_tokens,
|
| 95 |
+
encoder_out: Optional[Dict[str, List[Tensor]]] = None,
|
| 96 |
+
incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] = None,
|
| 97 |
+
features_only: bool = False,
|
| 98 |
+
return_all_hiddens: bool = False,
|
| 99 |
+
):
|
| 100 |
+
"""
|
| 101 |
+
Args:
|
| 102 |
+
prev_output_tokens (LongTensor): previous decoder outputs of shape
|
| 103 |
+
`(batch, tgt_len)`, for teacher forcing
|
| 104 |
+
encoder_out (optional): output from the encoder, used for
|
| 105 |
+
encoder-side attention, should be of size T x B x C
|
| 106 |
+
incremental_state (dict): dictionary used for storing state during
|
| 107 |
+
:ref:`Incremental decoding`
|
| 108 |
+
features_only (bool, optional): only return features without
|
| 109 |
+
applying output layer (default: False).
|
| 110 |
+
|
| 111 |
+
Returns:
|
| 112 |
+
tuple:
|
| 113 |
+
- the decoder's output of shape `(batch, tgt_len, vocab)`
|
| 114 |
+
- a dictionary with any model-specific outputs
|
| 115 |
+
"""
|
| 116 |
+
|
| 117 |
+
x, extra = self.extract_features(
|
| 118 |
+
prev_output_tokens,
|
| 119 |
+
encoder_out=encoder_out,
|
| 120 |
+
incremental_state=incremental_state,
|
| 121 |
+
)
|
| 122 |
+
|
| 123 |
+
if not features_only:
|
| 124 |
+
x = self.output_layer(x)
|
| 125 |
+
x = x.transpose(1, 2) # B x T x C -> B x C x T
|
| 126 |
+
return x, extra
|
| 127 |
+
|
| 128 |
+
def extract_features(
|
| 129 |
+
self,
|
| 130 |
+
prev_output_tokens,
|
| 131 |
+
encoder_out: Optional[Dict[str, List[Tensor]]],
|
| 132 |
+
incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] = None,
|
| 133 |
+
):
|
| 134 |
+
"""
|
| 135 |
+
Similar to *forward* but only return features.
|
| 136 |
+
|
| 137 |
+
Includes several features from "Jointly Learning to Align and
|
| 138 |
+
Translate with Transformer Models" (Garg et al., EMNLP 2019).
|
| 139 |
+
|
| 140 |
+
Returns:
|
| 141 |
+
tuple:
|
| 142 |
+
- the decoder's features of shape `(batch, tgt_len, embed_dim)`
|
| 143 |
+
- a dictionary with any model-specific outputs
|
| 144 |
+
"""
|
| 145 |
+
bs, slen = prev_output_tokens.size()
|
| 146 |
+
|
| 147 |
+
enc: Optional[Tensor] = None
|
| 148 |
+
padding_mask: Optional[Tensor] = None
|
| 149 |
+
if encoder_out is not None and len(encoder_out["encoder_out"]) > 0:
|
| 150 |
+
enc = encoder_out["encoder_out"][0]
|
| 151 |
+
assert (
|
| 152 |
+
enc.size()[1] == bs
|
| 153 |
+
), f"Expected enc.shape == (t, {bs}, c) got {enc.shape}"
|
| 154 |
+
if encoder_out is not None and len(encoder_out["encoder_padding_mask"]) > 0:
|
| 155 |
+
padding_mask = encoder_out["encoder_padding_mask"][0]
|
| 156 |
+
|
| 157 |
+
# embed positions
|
| 158 |
+
positions = self.embed_positions(
|
| 159 |
+
prev_output_tokens
|
| 160 |
+
)
|
| 161 |
+
|
| 162 |
+
if incremental_state is not None:
|
| 163 |
+
prev_output_tokens = prev_output_tokens[:, -1:]
|
| 164 |
+
positions = positions[:, -1:]
|
| 165 |
+
|
| 166 |
+
# embed tokens and positions
|
| 167 |
+
x = self.embed_scale * self.embed_tokens(prev_output_tokens)
|
| 168 |
+
|
| 169 |
+
if self.project_in_dim is not None:
|
| 170 |
+
x = self.project_in_dim(x)
|
| 171 |
+
|
| 172 |
+
x += positions
|
| 173 |
+
|
| 174 |
+
x = self.dropout_module(x)
|
| 175 |
+
|
| 176 |
+
# B x T x C -> T x B x C
|
| 177 |
+
x = x.transpose(0, 1)
|
| 178 |
+
|
| 179 |
+
self_attn_padding_mask: Optional[Tensor] = None
|
| 180 |
+
if prev_output_tokens.eq(self.padding_idx).any():
|
| 181 |
+
self_attn_padding_mask = prev_output_tokens.eq(self.padding_idx)
|
| 182 |
+
|
| 183 |
+
# decoder layers
|
| 184 |
+
attn: Optional[Tensor] = None
|
| 185 |
+
inner_states: List[Optional[Tensor]] = [x]
|
| 186 |
+
for idx, layer in enumerate(self.layers):
|
| 187 |
+
if incremental_state is None:
|
| 188 |
+
self_attn_mask = self.buffered_future_mask(x)
|
| 189 |
+
else:
|
| 190 |
+
self_attn_mask = None
|
| 191 |
+
|
| 192 |
+
x, layer_attn, _ = layer(
|
| 193 |
+
x,
|
| 194 |
+
enc,
|
| 195 |
+
padding_mask,
|
| 196 |
+
incremental_state,
|
| 197 |
+
self_attn_mask=self_attn_mask,
|
| 198 |
+
self_attn_padding_mask=self_attn_padding_mask,
|
| 199 |
+
need_attn=False,
|
| 200 |
+
need_head_weights=False,
|
| 201 |
+
)
|
| 202 |
+
inner_states.append(x)
|
| 203 |
+
|
| 204 |
+
if self.layer_norm is not None:
|
| 205 |
+
x = self.layer_norm(x)
|
| 206 |
+
|
| 207 |
+
# T x B x C -> B x C x T
|
| 208 |
+
x = x.transpose(0, 1)
|
| 209 |
+
|
| 210 |
+
return x, {"inner_states": inner_states}
|
| 211 |
+
|
| 212 |
+
def output_layer(self, features):
|
| 213 |
+
"""Project features to the vocabulary size."""
|
| 214 |
+
return self.output_projection(features)
|
| 215 |
+
|
| 216 |
+
def buffered_future_mask(self, tensor):
|
| 217 |
+
dim = tensor.size(0)
|
| 218 |
+
# self._future_mask.device != tensor.device is not working in TorchScript. This is a workaround.
|
| 219 |
+
if (
|
| 220 |
+
self._future_mask.size(0) == 0
|
| 221 |
+
or (not self._future_mask.device == tensor.device)
|
| 222 |
+
or self._future_mask.size(0) < dim
|
| 223 |
+
):
|
| 224 |
+
self._future_mask = torch.triu(
|
| 225 |
+
fill_with_neg_inf(torch.zeros([dim, dim])), 1
|
| 226 |
+
)
|
| 227 |
+
self._future_mask = self._future_mask.to(tensor)
|
| 228 |
+
return self._future_mask[:dim, :dim]
|
model/esm/inverse_folding/transformer_layer.py
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
| 2 |
+
#
|
| 3 |
+
# Contents of this file were adapted from the open source fairseq repository.
|
| 4 |
+
#
|
| 5 |
+
# This source code is licensed under the MIT license found in the
|
| 6 |
+
# LICENSE file in the root directory of this source tree.
|
| 7 |
+
|
| 8 |
+
from typing import Dict, List, Optional
|
| 9 |
+
|
| 10 |
+
import torch
|
| 11 |
+
import torch.nn as nn
|
| 12 |
+
import torch.nn.functional as F
|
| 13 |
+
from onescience.modules.attention import MultiheadAttention
|
| 14 |
+
from torch import Tensor
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
class TransformerEncoderLayer(nn.Module):
|
| 18 |
+
"""Encoder layer block.
|
| 19 |
+
`layernorm -> dropout -> add residual`
|
| 20 |
+
|
| 21 |
+
Args:
|
| 22 |
+
args (argparse.Namespace): parsed command-line arguments
|
| 23 |
+
"""
|
| 24 |
+
|
| 25 |
+
def __init__(self, args):
|
| 26 |
+
super().__init__()
|
| 27 |
+
self.args = args
|
| 28 |
+
self.embed_dim = args.encoder_embed_dim
|
| 29 |
+
self.self_attn = self.build_self_attention(self.embed_dim, args)
|
| 30 |
+
self.self_attn_layer_norm = torch.nn.LayerNorm(self.embed_dim)
|
| 31 |
+
self.dropout_module = nn.Dropout(args.dropout)
|
| 32 |
+
self.activation_fn = F.relu
|
| 33 |
+
self.fc1 = self.build_fc1(
|
| 34 |
+
self.embed_dim,
|
| 35 |
+
args.encoder_ffn_embed_dim,
|
| 36 |
+
)
|
| 37 |
+
self.fc2 = self.build_fc2(
|
| 38 |
+
args.encoder_ffn_embed_dim,
|
| 39 |
+
self.embed_dim,
|
| 40 |
+
)
|
| 41 |
+
|
| 42 |
+
self.final_layer_norm = nn.LayerNorm(self.embed_dim)
|
| 43 |
+
|
| 44 |
+
def build_fc1(self, input_dim, output_dim):
|
| 45 |
+
return nn.Linear(input_dim, output_dim)
|
| 46 |
+
|
| 47 |
+
def build_fc2(self, input_dim, output_dim):
|
| 48 |
+
return nn.Linear(input_dim, output_dim)
|
| 49 |
+
|
| 50 |
+
def build_self_attention(self, embed_dim, args):
|
| 51 |
+
return MultiheadAttention(
|
| 52 |
+
embed_dim,
|
| 53 |
+
args.encoder_attention_heads,
|
| 54 |
+
dropout=args.attention_dropout,
|
| 55 |
+
self_attention=True,
|
| 56 |
+
)
|
| 57 |
+
|
| 58 |
+
def residual_connection(self, x, residual):
|
| 59 |
+
return residual + x
|
| 60 |
+
|
| 61 |
+
def forward(
|
| 62 |
+
self,
|
| 63 |
+
x,
|
| 64 |
+
encoder_padding_mask: Optional[Tensor],
|
| 65 |
+
attn_mask: Optional[Tensor] = None,
|
| 66 |
+
):
|
| 67 |
+
"""
|
| 68 |
+
Args:
|
| 69 |
+
x (Tensor): input to the layer of shape `(seq_len, batch, embed_dim)`
|
| 70 |
+
encoder_padding_mask (ByteTensor): binary ByteTensor of shape
|
| 71 |
+
`(batch, seq_len)` where padding elements are indicated by ``1``.
|
| 72 |
+
attn_mask (ByteTensor): binary tensor of shape `(tgt_len, src_len)`,
|
| 73 |
+
where `tgt_len` is the length of output and `src_len` is the
|
| 74 |
+
length of input, though here both are equal to `seq_len`.
|
| 75 |
+
`attn_mask[tgt_i, src_j] = 1` means that when calculating the
|
| 76 |
+
embedding for `tgt_i`, we exclude (mask out) `src_j`. This is
|
| 77 |
+
useful for strided self-attention.
|
| 78 |
+
|
| 79 |
+
Returns:
|
| 80 |
+
encoded output of shape `(seq_len, batch, embed_dim)`
|
| 81 |
+
"""
|
| 82 |
+
# anything in original attn_mask = 1, becomes -1e8
|
| 83 |
+
# anything in original attn_mask = 0, becomes 0
|
| 84 |
+
# Note that we cannot use -inf here, because at some edge cases,
|
| 85 |
+
# the attention weight (before softmax) for some padded element in query
|
| 86 |
+
# will become -inf, which results in NaN in model parameters
|
| 87 |
+
if attn_mask is not None:
|
| 88 |
+
attn_mask = attn_mask.masked_fill(
|
| 89 |
+
attn_mask.to(torch.bool), -1e8 if x.dtype == torch.float32 else -1e4
|
| 90 |
+
)
|
| 91 |
+
|
| 92 |
+
residual = x
|
| 93 |
+
x = self.self_attn_layer_norm(x)
|
| 94 |
+
x, _ = self.self_attn(
|
| 95 |
+
query=x,
|
| 96 |
+
key=x,
|
| 97 |
+
value=x,
|
| 98 |
+
key_padding_mask=encoder_padding_mask,
|
| 99 |
+
need_weights=False,
|
| 100 |
+
attn_mask=attn_mask,
|
| 101 |
+
)
|
| 102 |
+
x = self.dropout_module(x)
|
| 103 |
+
x = self.residual_connection(x, residual)
|
| 104 |
+
|
| 105 |
+
residual = x
|
| 106 |
+
x = self.final_layer_norm(x)
|
| 107 |
+
x = self.activation_fn(self.fc1(x))
|
| 108 |
+
x = self.fc2(x)
|
| 109 |
+
x = self.dropout_module(x)
|
| 110 |
+
x = self.residual_connection(x, residual)
|
| 111 |
+
return x
|
| 112 |
+
|
| 113 |
+
|
| 114 |
+
class TransformerDecoderLayer(nn.Module):
|
| 115 |
+
"""Decoder layer block.
|
| 116 |
+
`layernorm -> dropout -> add residual`
|
| 117 |
+
|
| 118 |
+
Args:
|
| 119 |
+
args (argparse.Namespace): parsed command-line arguments
|
| 120 |
+
no_encoder_attn (bool, optional): whether to attend to encoder outputs
|
| 121 |
+
(default: False).
|
| 122 |
+
"""
|
| 123 |
+
|
| 124 |
+
def __init__(
|
| 125 |
+
self, args, no_encoder_attn=False, add_bias_kv=False, add_zero_attn=False
|
| 126 |
+
):
|
| 127 |
+
super().__init__()
|
| 128 |
+
self.embed_dim = args.decoder_embed_dim
|
| 129 |
+
self.dropout_module = nn.Dropout(args.dropout)
|
| 130 |
+
|
| 131 |
+
self.self_attn = self.build_self_attention(
|
| 132 |
+
self.embed_dim,
|
| 133 |
+
args,
|
| 134 |
+
add_bias_kv=add_bias_kv,
|
| 135 |
+
add_zero_attn=add_zero_attn,
|
| 136 |
+
)
|
| 137 |
+
self.nh = self.self_attn.num_heads
|
| 138 |
+
self.head_dim = self.self_attn.head_dim
|
| 139 |
+
|
| 140 |
+
self.activation_fn = F.relu
|
| 141 |
+
|
| 142 |
+
self.self_attn_layer_norm = nn.LayerNorm(self.embed_dim)
|
| 143 |
+
|
| 144 |
+
if no_encoder_attn:
|
| 145 |
+
self.encoder_attn = None
|
| 146 |
+
self.encoder_attn_layer_norm = None
|
| 147 |
+
else:
|
| 148 |
+
self.encoder_attn = self.build_encoder_attention(self.embed_dim, args)
|
| 149 |
+
self.encoder_attn_layer_norm = nn.LayerNorm(self.embed_dim)
|
| 150 |
+
|
| 151 |
+
self.ffn_layernorm = (
|
| 152 |
+
LayerNorm(args.decoder_ffn_embed_dim)
|
| 153 |
+
if getattr(args, "scale_fc", False)
|
| 154 |
+
else None
|
| 155 |
+
)
|
| 156 |
+
self.w_resid = (
|
| 157 |
+
nn.Parameter(
|
| 158 |
+
torch.ones(
|
| 159 |
+
self.embed_dim,
|
| 160 |
+
),
|
| 161 |
+
requires_grad=True,
|
| 162 |
+
)
|
| 163 |
+
if getattr(args, "scale_resids", False)
|
| 164 |
+
else None
|
| 165 |
+
)
|
| 166 |
+
|
| 167 |
+
self.fc1 = self.build_fc1(
|
| 168 |
+
self.embed_dim,
|
| 169 |
+
args.decoder_ffn_embed_dim,
|
| 170 |
+
)
|
| 171 |
+
self.fc2 = self.build_fc2(
|
| 172 |
+
args.decoder_ffn_embed_dim,
|
| 173 |
+
self.embed_dim,
|
| 174 |
+
)
|
| 175 |
+
|
| 176 |
+
self.final_layer_norm = nn.LayerNorm(self.embed_dim)
|
| 177 |
+
self.need_attn = True
|
| 178 |
+
|
| 179 |
+
def build_fc1(self, input_dim, output_dim):
|
| 180 |
+
return nn.Linear(input_dim, output_dim)
|
| 181 |
+
|
| 182 |
+
def build_fc2(self, input_dim, output_dim):
|
| 183 |
+
return nn.Linear(input_dim, output_dim)
|
| 184 |
+
|
| 185 |
+
def build_self_attention(
|
| 186 |
+
self, embed_dim, args, add_bias_kv=False, add_zero_attn=False
|
| 187 |
+
):
|
| 188 |
+
return MultiheadAttention(
|
| 189 |
+
embed_dim,
|
| 190 |
+
args.decoder_attention_heads,
|
| 191 |
+
dropout=args.attention_dropout,
|
| 192 |
+
add_bias_kv=add_bias_kv,
|
| 193 |
+
add_zero_attn=add_zero_attn,
|
| 194 |
+
self_attention=True,
|
| 195 |
+
)
|
| 196 |
+
|
| 197 |
+
def build_encoder_attention(self, embed_dim, args):
|
| 198 |
+
return MultiheadAttention(
|
| 199 |
+
embed_dim,
|
| 200 |
+
args.decoder_attention_heads,
|
| 201 |
+
kdim=args.encoder_embed_dim,
|
| 202 |
+
vdim=args.encoder_embed_dim,
|
| 203 |
+
dropout=args.attention_dropout,
|
| 204 |
+
encoder_decoder_attention=True,
|
| 205 |
+
)
|
| 206 |
+
|
| 207 |
+
def residual_connection(self, x, residual):
|
| 208 |
+
return residual + x
|
| 209 |
+
|
| 210 |
+
def forward(
|
| 211 |
+
self,
|
| 212 |
+
x,
|
| 213 |
+
encoder_out: Optional[torch.Tensor] = None,
|
| 214 |
+
encoder_padding_mask: Optional[torch.Tensor] = None,
|
| 215 |
+
incremental_state: Optional[Dict[str, Dict[str, Optional[Tensor]]]] = None,
|
| 216 |
+
prev_self_attn_state: Optional[List[torch.Tensor]] = None,
|
| 217 |
+
prev_attn_state: Optional[List[torch.Tensor]] = None,
|
| 218 |
+
self_attn_mask: Optional[torch.Tensor] = None,
|
| 219 |
+
self_attn_padding_mask: Optional[torch.Tensor] = None,
|
| 220 |
+
need_attn: bool = False,
|
| 221 |
+
need_head_weights: bool = False,
|
| 222 |
+
):
|
| 223 |
+
"""
|
| 224 |
+
Args:
|
| 225 |
+
x (Tensor): input to the layer of shape `(seq_len, batch, embed_dim)`
|
| 226 |
+
encoder_padding_mask (ByteTensor, optional): binary
|
| 227 |
+
ByteTensor of shape `(batch, src_len)` where padding
|
| 228 |
+
elements are indicated by ``1``.
|
| 229 |
+
need_attn (bool, optional): return attention weights
|
| 230 |
+
need_head_weights (bool, optional): return attention weights
|
| 231 |
+
for each head (default: return average over heads).
|
| 232 |
+
|
| 233 |
+
Returns:
|
| 234 |
+
encoded output of shape `(seq_len, batch, embed_dim)`
|
| 235 |
+
"""
|
| 236 |
+
if need_head_weights:
|
| 237 |
+
need_attn = True
|
| 238 |
+
|
| 239 |
+
residual = x
|
| 240 |
+
x = self.self_attn_layer_norm(x)
|
| 241 |
+
if prev_self_attn_state is not None:
|
| 242 |
+
prev_key, prev_value = prev_self_attn_state[:2]
|
| 243 |
+
saved_state: Dict[str, Optional[Tensor]] = {
|
| 244 |
+
"prev_key": prev_key,
|
| 245 |
+
"prev_value": prev_value,
|
| 246 |
+
}
|
| 247 |
+
if len(prev_self_attn_state) >= 3:
|
| 248 |
+
saved_state["prev_key_padding_mask"] = prev_self_attn_state[2]
|
| 249 |
+
assert incremental_state is not None
|
| 250 |
+
self.self_attn._set_input_buffer(incremental_state, saved_state)
|
| 251 |
+
_self_attn_input_buffer = self.self_attn._get_input_buffer(incremental_state)
|
| 252 |
+
y = x
|
| 253 |
+
|
| 254 |
+
x, attn = self.self_attn(
|
| 255 |
+
query=x,
|
| 256 |
+
key=y,
|
| 257 |
+
value=y,
|
| 258 |
+
key_padding_mask=self_attn_padding_mask,
|
| 259 |
+
incremental_state=incremental_state,
|
| 260 |
+
need_weights=False,
|
| 261 |
+
attn_mask=self_attn_mask,
|
| 262 |
+
)
|
| 263 |
+
x = self.dropout_module(x)
|
| 264 |
+
x = self.residual_connection(x, residual)
|
| 265 |
+
|
| 266 |
+
if self.encoder_attn is not None and encoder_out is not None:
|
| 267 |
+
residual = x
|
| 268 |
+
x = self.encoder_attn_layer_norm(x)
|
| 269 |
+
if prev_attn_state is not None:
|
| 270 |
+
prev_key, prev_value = prev_attn_state[:2]
|
| 271 |
+
saved_state: Dict[str, Optional[Tensor]] = {
|
| 272 |
+
"prev_key": prev_key,
|
| 273 |
+
"prev_value": prev_value,
|
| 274 |
+
}
|
| 275 |
+
if len(prev_attn_state) >= 3:
|
| 276 |
+
saved_state["prev_key_padding_mask"] = prev_attn_state[2]
|
| 277 |
+
assert incremental_state is not None
|
| 278 |
+
self.encoder_attn._set_input_buffer(incremental_state, saved_state)
|
| 279 |
+
|
| 280 |
+
x, attn = self.encoder_attn(
|
| 281 |
+
query=x,
|
| 282 |
+
key=encoder_out,
|
| 283 |
+
value=encoder_out,
|
| 284 |
+
key_padding_mask=encoder_padding_mask,
|
| 285 |
+
incremental_state=incremental_state,
|
| 286 |
+
static_kv=True,
|
| 287 |
+
need_weights=need_attn or (not self.training and self.need_attn),
|
| 288 |
+
need_head_weights=need_head_weights,
|
| 289 |
+
)
|
| 290 |
+
x = self.dropout_module(x)
|
| 291 |
+
x = self.residual_connection(x, residual)
|
| 292 |
+
|
| 293 |
+
residual = x
|
| 294 |
+
x = self.final_layer_norm(x)
|
| 295 |
+
|
| 296 |
+
x = self.activation_fn(self.fc1(x))
|
| 297 |
+
if self.ffn_layernorm is not None:
|
| 298 |
+
x = self.ffn_layernorm(x)
|
| 299 |
+
x = self.fc2(x)
|
| 300 |
+
x = self.dropout_module(x)
|
| 301 |
+
if self.w_resid is not None:
|
| 302 |
+
residual = torch.mul(self.w_resid, residual)
|
| 303 |
+
x = self.residual_connection(x, residual)
|
| 304 |
+
return x, attn, None
|
model/esm/inverse_folding/util.py
ADDED
|
@@ -0,0 +1,323 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
| 2 |
+
#
|
| 3 |
+
# This source code is licensed under the MIT license found in the
|
| 4 |
+
# LICENSE file in the root directory of this source tree.
|
| 5 |
+
|
| 6 |
+
import json
|
| 7 |
+
import math
|
| 8 |
+
|
| 9 |
+
import biotite.structure
|
| 10 |
+
from biotite.structure.io import pdbx, pdb
|
| 11 |
+
from biotite.structure.residues import get_residues
|
| 12 |
+
from biotite.structure import filter_backbone
|
| 13 |
+
from biotite.structure import get_chains
|
| 14 |
+
from biotite.sequence import ProteinSequence
|
| 15 |
+
import numpy as np
|
| 16 |
+
from scipy.spatial import transform
|
| 17 |
+
from scipy.stats import special_ortho_group
|
| 18 |
+
import torch
|
| 19 |
+
import torch.nn as nn
|
| 20 |
+
import torch.nn.functional as F
|
| 21 |
+
import torch.utils.data as data
|
| 22 |
+
from typing import Sequence, Tuple, List
|
| 23 |
+
|
| 24 |
+
from onescience.datapipes.esm import BatchConverter
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
def load_structure(fpath, chain=None):
|
| 28 |
+
"""
|
| 29 |
+
Args:
|
| 30 |
+
fpath: filepath to either pdb or cif file
|
| 31 |
+
chain: the chain id or list of chain ids to load
|
| 32 |
+
Returns:
|
| 33 |
+
biotite.structure.AtomArray
|
| 34 |
+
"""
|
| 35 |
+
if fpath.endswith('cif'):
|
| 36 |
+
with open(fpath) as fin:
|
| 37 |
+
pdbxf = pdbx.PDBxFile.read(fin)
|
| 38 |
+
structure = pdbx.get_structure(pdbxf, model=1)
|
| 39 |
+
elif fpath.endswith('pdb'):
|
| 40 |
+
with open(fpath) as fin:
|
| 41 |
+
pdbf = pdb.PDBFile.read(fin)
|
| 42 |
+
structure = pdb.get_structure(pdbf, model=1)
|
| 43 |
+
bbmask = filter_backbone(structure)
|
| 44 |
+
structure = structure[bbmask]
|
| 45 |
+
all_chains = get_chains(structure)
|
| 46 |
+
if len(all_chains) == 0:
|
| 47 |
+
raise ValueError('No chains found in the input file.')
|
| 48 |
+
if chain is None:
|
| 49 |
+
chain_ids = all_chains
|
| 50 |
+
elif isinstance(chain, list):
|
| 51 |
+
chain_ids = chain
|
| 52 |
+
else:
|
| 53 |
+
chain_ids = [chain]
|
| 54 |
+
for chain in chain_ids:
|
| 55 |
+
if chain not in all_chains:
|
| 56 |
+
raise ValueError(f'Chain {chain} not found in input file')
|
| 57 |
+
chain_filter = [a.chain_id in chain_ids for a in structure]
|
| 58 |
+
structure = structure[chain_filter]
|
| 59 |
+
return structure
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
def extract_coords_from_structure(structure: biotite.structure.AtomArray):
|
| 63 |
+
"""
|
| 64 |
+
Args:
|
| 65 |
+
structure: An instance of biotite AtomArray
|
| 66 |
+
Returns:
|
| 67 |
+
Tuple (coords, seq)
|
| 68 |
+
- coords is an L x 3 x 3 array for N, CA, C coordinates
|
| 69 |
+
- seq is the extracted sequence
|
| 70 |
+
"""
|
| 71 |
+
coords = get_atom_coords_residuewise(["N", "CA", "C"], structure)
|
| 72 |
+
residue_identities = get_residues(structure)[1]
|
| 73 |
+
seq = ''.join([ProteinSequence.convert_letter_3to1(r) for r in residue_identities])
|
| 74 |
+
return coords, seq
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
def load_coords(fpath, chain):
|
| 78 |
+
"""
|
| 79 |
+
Args:
|
| 80 |
+
fpath: filepath to either pdb or cif file
|
| 81 |
+
chain: the chain id
|
| 82 |
+
Returns:
|
| 83 |
+
Tuple (coords, seq)
|
| 84 |
+
- coords is an L x 3 x 3 array for N, CA, C coordinates
|
| 85 |
+
- seq is the extracted sequence
|
| 86 |
+
"""
|
| 87 |
+
structure = load_structure(fpath, chain)
|
| 88 |
+
return extract_coords_from_structure(structure)
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
def get_atom_coords_residuewise(atoms: List[str], struct: biotite.structure.AtomArray):
|
| 92 |
+
"""
|
| 93 |
+
Example for atoms argument: ["N", "CA", "C"]
|
| 94 |
+
"""
|
| 95 |
+
def filterfn(s, axis=None):
|
| 96 |
+
filters = np.stack([s.atom_name == name for name in atoms], axis=1)
|
| 97 |
+
sum = filters.sum(0)
|
| 98 |
+
if not np.all(sum <= np.ones(filters.shape[1])):
|
| 99 |
+
raise RuntimeError("structure has multiple atoms with same name")
|
| 100 |
+
index = filters.argmax(0)
|
| 101 |
+
coords = s[index].coord
|
| 102 |
+
coords[sum == 0] = float("nan")
|
| 103 |
+
return coords
|
| 104 |
+
|
| 105 |
+
return biotite.structure.apply_residue_wise(struct, struct, filterfn)
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
def get_sequence_loss(model, alphabet, coords, seq):
|
| 109 |
+
device = next(model.parameters()).device
|
| 110 |
+
batch_converter = CoordBatchConverter(alphabet)
|
| 111 |
+
batch = [(coords, None, seq)]
|
| 112 |
+
coords, confidence, strs, tokens, padding_mask = batch_converter(
|
| 113 |
+
batch, device=device)
|
| 114 |
+
|
| 115 |
+
prev_output_tokens = tokens[:, :-1].to(device)
|
| 116 |
+
target = tokens[:, 1:]
|
| 117 |
+
target_padding_mask = (target == alphabet.padding_idx)
|
| 118 |
+
logits, _ = model.forward(coords, padding_mask, confidence, prev_output_tokens)
|
| 119 |
+
loss = F.cross_entropy(logits, target, reduction='none')
|
| 120 |
+
loss = loss[0].cpu().detach().numpy()
|
| 121 |
+
target_padding_mask = target_padding_mask[0].cpu().numpy()
|
| 122 |
+
return loss, target_padding_mask
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
def score_sequence(model, alphabet, coords, seq):
|
| 126 |
+
loss, target_padding_mask = get_sequence_loss(model, alphabet, coords, seq)
|
| 127 |
+
ll_fullseq = -np.sum(loss * ~target_padding_mask) / np.sum(~target_padding_mask)
|
| 128 |
+
# Also calculate average when excluding masked portions
|
| 129 |
+
coord_mask = np.all(np.isfinite(coords), axis=(-1, -2))
|
| 130 |
+
ll_withcoord = -np.sum(loss * coord_mask) / np.sum(coord_mask)
|
| 131 |
+
return ll_fullseq, ll_withcoord
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
def get_encoder_output(model, alphabet, coords):
|
| 135 |
+
device = next(model.parameters()).device
|
| 136 |
+
batch_converter = CoordBatchConverter(alphabet)
|
| 137 |
+
batch = [(coords, None, None)]
|
| 138 |
+
coords, confidence, strs, tokens, padding_mask = batch_converter(
|
| 139 |
+
batch, device=device)
|
| 140 |
+
encoder_out = model.encoder.forward(coords, padding_mask, confidence,
|
| 141 |
+
return_all_hiddens=False)
|
| 142 |
+
# remove beginning and end (bos and eos tokens)
|
| 143 |
+
return encoder_out['encoder_out'][0][1:-1, 0]
|
| 144 |
+
|
| 145 |
+
|
| 146 |
+
def rotate(v, R):
|
| 147 |
+
"""
|
| 148 |
+
Rotates a vector by a rotation matrix.
|
| 149 |
+
|
| 150 |
+
Args:
|
| 151 |
+
v: 3D vector, tensor of shape (length x batch_size x channels x 3)
|
| 152 |
+
R: rotation matrix, tensor of shape (length x batch_size x 3 x 3)
|
| 153 |
+
|
| 154 |
+
Returns:
|
| 155 |
+
Rotated version of v by rotation matrix R.
|
| 156 |
+
"""
|
| 157 |
+
R = R.unsqueeze(-3)
|
| 158 |
+
v = v.unsqueeze(-1)
|
| 159 |
+
return torch.sum(v * R, dim=-2)
|
| 160 |
+
|
| 161 |
+
|
| 162 |
+
def get_rotation_frames(coords):
|
| 163 |
+
"""
|
| 164 |
+
Returns a local rotation frame defined by N, CA, C positions.
|
| 165 |
+
|
| 166 |
+
Args:
|
| 167 |
+
coords: coordinates, tensor of shape (batch_size x length x 3 x 3)
|
| 168 |
+
where the third dimension is in order of N, CA, C
|
| 169 |
+
|
| 170 |
+
Returns:
|
| 171 |
+
Local relative rotation frames in shape (batch_size x length x 3 x 3)
|
| 172 |
+
"""
|
| 173 |
+
v1 = coords[:, :, 2] - coords[:, :, 1]
|
| 174 |
+
v2 = coords[:, :, 0] - coords[:, :, 1]
|
| 175 |
+
e1 = normalize(v1, dim=-1)
|
| 176 |
+
u2 = v2 - e1 * torch.sum(e1 * v2, dim=-1, keepdim=True)
|
| 177 |
+
e2 = normalize(u2, dim=-1)
|
| 178 |
+
e3 = torch.cross(e1, e2, dim=-1)
|
| 179 |
+
R = torch.stack([e1, e2, e3], dim=-2)
|
| 180 |
+
return R
|
| 181 |
+
|
| 182 |
+
|
| 183 |
+
def nan_to_num(ts, val=0.0):
|
| 184 |
+
"""
|
| 185 |
+
Replaces nans in tensor with a fixed value.
|
| 186 |
+
"""
|
| 187 |
+
val = torch.tensor(val, dtype=ts.dtype, device=ts.device)
|
| 188 |
+
return torch.where(~torch.isfinite(ts), val, ts)
|
| 189 |
+
|
| 190 |
+
|
| 191 |
+
def rbf(values, v_min, v_max, n_bins=16):
|
| 192 |
+
"""
|
| 193 |
+
Returns RBF encodings in a new dimension at the end.
|
| 194 |
+
"""
|
| 195 |
+
rbf_centers = torch.linspace(v_min, v_max, n_bins, device=values.device)
|
| 196 |
+
rbf_centers = rbf_centers.view([1] * len(values.shape) + [-1])
|
| 197 |
+
rbf_std = (v_max - v_min) / n_bins
|
| 198 |
+
v_expand = torch.unsqueeze(values, -1)
|
| 199 |
+
z = (values.unsqueeze(-1) - rbf_centers) / rbf_std
|
| 200 |
+
return torch.exp(-z ** 2)
|
| 201 |
+
|
| 202 |
+
|
| 203 |
+
def norm(tensor, dim, eps=1e-8, keepdim=False):
|
| 204 |
+
"""
|
| 205 |
+
Returns L2 norm along a dimension.
|
| 206 |
+
"""
|
| 207 |
+
return torch.sqrt(
|
| 208 |
+
torch.sum(torch.square(tensor), dim=dim, keepdim=keepdim) + eps)
|
| 209 |
+
|
| 210 |
+
|
| 211 |
+
def normalize(tensor, dim=-1):
|
| 212 |
+
"""
|
| 213 |
+
Normalizes a tensor along a dimension after removing nans.
|
| 214 |
+
"""
|
| 215 |
+
return nan_to_num(
|
| 216 |
+
torch.div(tensor, norm(tensor, dim=dim, keepdim=True))
|
| 217 |
+
)
|
| 218 |
+
|
| 219 |
+
|
| 220 |
+
class CoordBatchConverter(BatchConverter):
|
| 221 |
+
def __call__(self, raw_batch: Sequence[Tuple[Sequence, str]], device=None):
|
| 222 |
+
"""
|
| 223 |
+
Args:
|
| 224 |
+
raw_batch: List of tuples (coords, confidence, seq)
|
| 225 |
+
In each tuple,
|
| 226 |
+
coords: list of floats, shape L x 3 x 3
|
| 227 |
+
confidence: list of floats, shape L; or scalar float; or None
|
| 228 |
+
seq: string of length L
|
| 229 |
+
Returns:
|
| 230 |
+
coords: Tensor of shape batch_size x L x 3 x 3
|
| 231 |
+
confidence: Tensor of shape batch_size x L
|
| 232 |
+
strs: list of strings
|
| 233 |
+
tokens: LongTensor of shape batch_size x L
|
| 234 |
+
padding_mask: ByteTensor of shape batch_size x L
|
| 235 |
+
"""
|
| 236 |
+
self.alphabet.cls_idx = self.alphabet.get_idx("<cath>")
|
| 237 |
+
batch = []
|
| 238 |
+
for coords, confidence, seq in raw_batch:
|
| 239 |
+
if confidence is None:
|
| 240 |
+
confidence = 1.
|
| 241 |
+
if isinstance(confidence, float) or isinstance(confidence, int):
|
| 242 |
+
confidence = [float(confidence)] * len(coords)
|
| 243 |
+
if seq is None:
|
| 244 |
+
seq = 'X' * len(coords)
|
| 245 |
+
batch.append(((coords, confidence), seq))
|
| 246 |
+
|
| 247 |
+
coords_and_confidence, strs, tokens = super().__call__(batch)
|
| 248 |
+
|
| 249 |
+
# pad beginning and end of each protein due to legacy reasons
|
| 250 |
+
coords = [
|
| 251 |
+
F.pad(torch.tensor(cd), (0, 0, 0, 0, 1, 1), value=np.inf)
|
| 252 |
+
for cd, _ in coords_and_confidence
|
| 253 |
+
]
|
| 254 |
+
confidence = [
|
| 255 |
+
F.pad(torch.tensor(cf), (1, 1), value=-1.)
|
| 256 |
+
for _, cf in coords_and_confidence
|
| 257 |
+
]
|
| 258 |
+
coords = self.collate_dense_tensors(coords, pad_v=np.nan)
|
| 259 |
+
confidence = self.collate_dense_tensors(confidence, pad_v=-1.)
|
| 260 |
+
if device is not None:
|
| 261 |
+
coords = coords.to(device)
|
| 262 |
+
confidence = confidence.to(device)
|
| 263 |
+
tokens = tokens.to(device)
|
| 264 |
+
padding_mask = torch.isnan(coords[:,:,0,0])
|
| 265 |
+
coord_mask = torch.isfinite(coords.sum(-2).sum(-1))
|
| 266 |
+
confidence = confidence * coord_mask + (-1.) * padding_mask
|
| 267 |
+
return coords, confidence, strs, tokens, padding_mask
|
| 268 |
+
|
| 269 |
+
def from_lists(self, coords_list, confidence_list=None, seq_list=None, device=None):
|
| 270 |
+
"""
|
| 271 |
+
Args:
|
| 272 |
+
coords_list: list of length batch_size, each item is a list of
|
| 273 |
+
floats in shape L x 3 x 3 to describe a backbone
|
| 274 |
+
confidence_list: one of
|
| 275 |
+
- None, default to highest confidence
|
| 276 |
+
- list of length batch_size, each item is a scalar
|
| 277 |
+
- list of length batch_size, each item is a list of floats of
|
| 278 |
+
length L to describe the confidence scores for the backbone
|
| 279 |
+
with values between 0. and 1.
|
| 280 |
+
seq_list: either None or a list of strings
|
| 281 |
+
Returns:
|
| 282 |
+
coords: Tensor of shape batch_size x L x 3 x 3
|
| 283 |
+
confidence: Tensor of shape batch_size x L
|
| 284 |
+
strs: list of strings
|
| 285 |
+
tokens: LongTensor of shape batch_size x L
|
| 286 |
+
padding_mask: ByteTensor of shape batch_size x L
|
| 287 |
+
"""
|
| 288 |
+
batch_size = len(coords_list)
|
| 289 |
+
if confidence_list is None:
|
| 290 |
+
confidence_list = [None] * batch_size
|
| 291 |
+
if seq_list is None:
|
| 292 |
+
seq_list = [None] * batch_size
|
| 293 |
+
raw_batch = zip(coords_list, confidence_list, seq_list)
|
| 294 |
+
return self.__call__(raw_batch, device)
|
| 295 |
+
|
| 296 |
+
@staticmethod
|
| 297 |
+
def collate_dense_tensors(samples, pad_v):
|
| 298 |
+
"""
|
| 299 |
+
Takes a list of tensors with the following dimensions:
|
| 300 |
+
[(d_11, ..., d_1K),
|
| 301 |
+
(d_21, ..., d_2K),
|
| 302 |
+
...,
|
| 303 |
+
(d_N1, ..., d_NK)]
|
| 304 |
+
and stack + pads them into a single tensor of:
|
| 305 |
+
(N, max_i=1,N { d_i1 }, ..., max_i=1,N {diK})
|
| 306 |
+
"""
|
| 307 |
+
if len(samples) == 0:
|
| 308 |
+
return torch.Tensor()
|
| 309 |
+
if len(set(x.dim() for x in samples)) != 1:
|
| 310 |
+
raise RuntimeError(
|
| 311 |
+
f"Samples has varying dimensions: {[x.dim() for x in samples]}"
|
| 312 |
+
)
|
| 313 |
+
(device,) = tuple(set(x.device for x in samples)) # assumes all on same device
|
| 314 |
+
max_shape = [max(lst) for lst in zip(*[x.shape for x in samples])]
|
| 315 |
+
result = torch.empty(
|
| 316 |
+
len(samples), *max_shape, dtype=samples[0].dtype, device=device
|
| 317 |
+
)
|
| 318 |
+
result.fill_(pad_v)
|
| 319 |
+
for i in range(len(samples)):
|
| 320 |
+
result_i = result[i]
|
| 321 |
+
t = samples[i]
|
| 322 |
+
result_i[tuple(slice(0, k) for k in t.shape)] = t
|
| 323 |
+
return result
|
model/esm/msa_transformer.py
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
| 2 |
+
#
|
| 3 |
+
# This source code is licensed under the MIT license found in the
|
| 4 |
+
# LICENSE file in the root directory of this source tree.
|
| 5 |
+
|
| 6 |
+
import torch
|
| 7 |
+
import torch.nn as nn
|
| 8 |
+
|
| 9 |
+
from onescience.modules.esm import (
|
| 10 |
+
AxialTransformerLayer,
|
| 11 |
+
LearnedPositionalEmbedding,
|
| 12 |
+
RobertaLMHead,
|
| 13 |
+
ESM1bLayerNorm,
|
| 14 |
+
ContactPredictionHead,
|
| 15 |
+
)
|
| 16 |
+
|
| 17 |
+
from onescience.modules.attention import RowSelfAttention, ColumnSelfAttention
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
class MSATransformer(nn.Module):
|
| 22 |
+
@classmethod
|
| 23 |
+
def add_args(cls, parser):
|
| 24 |
+
# fmt: off
|
| 25 |
+
parser.add_argument(
|
| 26 |
+
"--num_layers",
|
| 27 |
+
default=12,
|
| 28 |
+
type=int,
|
| 29 |
+
metavar="N",
|
| 30 |
+
help="number of layers"
|
| 31 |
+
)
|
| 32 |
+
parser.add_argument(
|
| 33 |
+
"--embed_dim",
|
| 34 |
+
default=768,
|
| 35 |
+
type=int,
|
| 36 |
+
metavar="N",
|
| 37 |
+
help="embedding dimension"
|
| 38 |
+
)
|
| 39 |
+
parser.add_argument(
|
| 40 |
+
"--logit_bias",
|
| 41 |
+
action="store_true",
|
| 42 |
+
help="whether to apply bias to logits"
|
| 43 |
+
)
|
| 44 |
+
parser.add_argument(
|
| 45 |
+
"--ffn_embed_dim",
|
| 46 |
+
default=3072,
|
| 47 |
+
type=int,
|
| 48 |
+
metavar="N",
|
| 49 |
+
help="embedding dimension for FFN",
|
| 50 |
+
)
|
| 51 |
+
parser.add_argument(
|
| 52 |
+
"--attention_heads",
|
| 53 |
+
default=12,
|
| 54 |
+
type=int,
|
| 55 |
+
metavar="N",
|
| 56 |
+
help="number of attention heads",
|
| 57 |
+
)
|
| 58 |
+
parser.add_argument(
|
| 59 |
+
"--dropout",
|
| 60 |
+
default=0.1,
|
| 61 |
+
type=float,
|
| 62 |
+
help="Dropout to apply."
|
| 63 |
+
)
|
| 64 |
+
parser.add_argument(
|
| 65 |
+
"--attention_dropout",
|
| 66 |
+
default=0.1,
|
| 67 |
+
type=float,
|
| 68 |
+
help="Dropout to apply."
|
| 69 |
+
)
|
| 70 |
+
parser.add_argument(
|
| 71 |
+
"--activation_dropout",
|
| 72 |
+
default=0.1,
|
| 73 |
+
type=float,
|
| 74 |
+
help="Dropout to apply."
|
| 75 |
+
)
|
| 76 |
+
parser.add_argument(
|
| 77 |
+
"--max_tokens_per_msa",
|
| 78 |
+
default=2 ** 14,
|
| 79 |
+
type=int,
|
| 80 |
+
help=(
|
| 81 |
+
"Used during inference to batch attention computations in a single "
|
| 82 |
+
"forward pass. This allows increased input sizes with less memory."
|
| 83 |
+
),
|
| 84 |
+
)
|
| 85 |
+
# fmt: on
|
| 86 |
+
|
| 87 |
+
def __init__(self, args, alphabet):
|
| 88 |
+
super().__init__()
|
| 89 |
+
self.args = args
|
| 90 |
+
self.alphabet_size = len(alphabet)
|
| 91 |
+
self.padding_idx = alphabet.padding_idx
|
| 92 |
+
self.mask_idx = alphabet.mask_idx
|
| 93 |
+
self.cls_idx = alphabet.cls_idx
|
| 94 |
+
self.eos_idx = alphabet.eos_idx
|
| 95 |
+
self.prepend_bos = alphabet.prepend_bos
|
| 96 |
+
self.append_eos = alphabet.append_eos
|
| 97 |
+
|
| 98 |
+
self.embed_tokens = nn.Embedding(
|
| 99 |
+
self.alphabet_size, self.args.embed_dim, padding_idx=self.padding_idx
|
| 100 |
+
)
|
| 101 |
+
|
| 102 |
+
if getattr(self.args, "embed_positions_msa", False):
|
| 103 |
+
emb_dim = getattr(self.args, "embed_positions_msa_dim", self.args.embed_dim)
|
| 104 |
+
self.msa_position_embedding = nn.Parameter(
|
| 105 |
+
0.01 * torch.randn(1, 1024, 1, emb_dim),
|
| 106 |
+
requires_grad=True,
|
| 107 |
+
)
|
| 108 |
+
else:
|
| 109 |
+
self.register_parameter("msa_position_embedding", None)
|
| 110 |
+
|
| 111 |
+
self.dropout_module = nn.Dropout(self.args.dropout)
|
| 112 |
+
self.layers = nn.ModuleList(
|
| 113 |
+
[
|
| 114 |
+
AxialTransformerLayer(
|
| 115 |
+
self.args.embed_dim,
|
| 116 |
+
self.args.ffn_embed_dim,
|
| 117 |
+
self.args.attention_heads,
|
| 118 |
+
self.args.dropout,
|
| 119 |
+
self.args.attention_dropout,
|
| 120 |
+
self.args.activation_dropout,
|
| 121 |
+
getattr(self.args, "max_tokens_per_msa", self.args.max_tokens),
|
| 122 |
+
)
|
| 123 |
+
for _ in range(self.args.layers)
|
| 124 |
+
]
|
| 125 |
+
)
|
| 126 |
+
|
| 127 |
+
self.contact_head = ContactPredictionHead(
|
| 128 |
+
self.args.layers * self.args.attention_heads,
|
| 129 |
+
self.prepend_bos,
|
| 130 |
+
self.append_eos,
|
| 131 |
+
eos_idx=self.eos_idx,
|
| 132 |
+
)
|
| 133 |
+
self.embed_positions = LearnedPositionalEmbedding(
|
| 134 |
+
self.args.max_positions,
|
| 135 |
+
self.args.embed_dim,
|
| 136 |
+
self.padding_idx,
|
| 137 |
+
)
|
| 138 |
+
self.emb_layer_norm_before = ESM1bLayerNorm(self.args.embed_dim)
|
| 139 |
+
self.emb_layer_norm_after = ESM1bLayerNorm(self.args.embed_dim)
|
| 140 |
+
self.lm_head = RobertaLMHead(
|
| 141 |
+
embed_dim=self.args.embed_dim,
|
| 142 |
+
output_dim=self.alphabet_size,
|
| 143 |
+
weight=self.embed_tokens.weight,
|
| 144 |
+
)
|
| 145 |
+
|
| 146 |
+
def forward(self, tokens, repr_layers=[], need_head_weights=False, return_contacts=False):
|
| 147 |
+
if return_contacts:
|
| 148 |
+
need_head_weights = True
|
| 149 |
+
|
| 150 |
+
assert tokens.ndim == 3
|
| 151 |
+
batch_size, num_alignments, seqlen = tokens.size()
|
| 152 |
+
padding_mask = tokens.eq(self.padding_idx) # B, R, C
|
| 153 |
+
if not padding_mask.any():
|
| 154 |
+
padding_mask = None
|
| 155 |
+
|
| 156 |
+
x = self.embed_tokens(tokens)
|
| 157 |
+
x += self.embed_positions(tokens.view(batch_size * num_alignments, seqlen)).view(x.size())
|
| 158 |
+
if self.msa_position_embedding is not None:
|
| 159 |
+
if x.size(1) > 1024:
|
| 160 |
+
raise RuntimeError(
|
| 161 |
+
"Using model with MSA position embedding trained on maximum MSA "
|
| 162 |
+
f"depth of 1024, but received {x.size(1)} alignments."
|
| 163 |
+
)
|
| 164 |
+
x += self.msa_position_embedding[:, :num_alignments]
|
| 165 |
+
|
| 166 |
+
x = self.emb_layer_norm_before(x)
|
| 167 |
+
|
| 168 |
+
x = self.dropout_module(x)
|
| 169 |
+
|
| 170 |
+
if padding_mask is not None:
|
| 171 |
+
x = x * (1 - padding_mask.unsqueeze(-1).type_as(x))
|
| 172 |
+
|
| 173 |
+
repr_layers = set(repr_layers)
|
| 174 |
+
hidden_representations = {}
|
| 175 |
+
if 0 in repr_layers:
|
| 176 |
+
hidden_representations[0] = x
|
| 177 |
+
|
| 178 |
+
if need_head_weights:
|
| 179 |
+
row_attn_weights = []
|
| 180 |
+
col_attn_weights = []
|
| 181 |
+
|
| 182 |
+
# B x R x C x D -> R x C x B x D
|
| 183 |
+
x = x.permute(1, 2, 0, 3)
|
| 184 |
+
|
| 185 |
+
for layer_idx, layer in enumerate(self.layers):
|
| 186 |
+
x = layer(
|
| 187 |
+
x,
|
| 188 |
+
self_attn_padding_mask=padding_mask,
|
| 189 |
+
need_head_weights=need_head_weights,
|
| 190 |
+
)
|
| 191 |
+
if need_head_weights:
|
| 192 |
+
x, col_attn, row_attn = x
|
| 193 |
+
# H x C x B x R x R -> B x H x C x R x R
|
| 194 |
+
col_attn_weights.append(col_attn.permute(2, 0, 1, 3, 4))
|
| 195 |
+
# H x B x C x C -> B x H x C x C
|
| 196 |
+
row_attn_weights.append(row_attn.permute(1, 0, 2, 3))
|
| 197 |
+
if (layer_idx + 1) in repr_layers:
|
| 198 |
+
hidden_representations[layer_idx + 1] = x.permute(2, 0, 1, 3)
|
| 199 |
+
|
| 200 |
+
x = self.emb_layer_norm_after(x)
|
| 201 |
+
x = x.permute(2, 0, 1, 3) # R x C x B x D -> B x R x C x D
|
| 202 |
+
|
| 203 |
+
# last hidden representation should have layer norm applied
|
| 204 |
+
if (layer_idx + 1) in repr_layers:
|
| 205 |
+
hidden_representations[layer_idx + 1] = x
|
| 206 |
+
x = self.lm_head(x)
|
| 207 |
+
|
| 208 |
+
result = {"logits": x, "representations": hidden_representations}
|
| 209 |
+
if need_head_weights:
|
| 210 |
+
# col_attentions: B x L x H x C x R x R
|
| 211 |
+
col_attentions = torch.stack(col_attn_weights, 1)
|
| 212 |
+
# row_attentions: B x L x H x C x C
|
| 213 |
+
row_attentions = torch.stack(row_attn_weights, 1)
|
| 214 |
+
result["col_attentions"] = col_attentions
|
| 215 |
+
result["row_attentions"] = row_attentions
|
| 216 |
+
if return_contacts:
|
| 217 |
+
contacts = self.contact_head(tokens, row_attentions)
|
| 218 |
+
result["contacts"] = contacts
|
| 219 |
+
|
| 220 |
+
return result
|
| 221 |
+
|
| 222 |
+
def predict_contacts(self, tokens):
|
| 223 |
+
return self(tokens, return_contacts=True)["contacts"]
|
| 224 |
+
|
| 225 |
+
@property
|
| 226 |
+
def num_layers(self):
|
| 227 |
+
return self.args.layers
|
| 228 |
+
|
| 229 |
+
def max_tokens_per_msa_(self, value: int) -> None:
|
| 230 |
+
"""The MSA Transformer automatically batches attention computations when
|
| 231 |
+
gradients are disabled to allow you to pass in larger MSAs at test time than
|
| 232 |
+
you can fit in GPU memory. By default this occurs when more than 2^14 tokens
|
| 233 |
+
are passed in the input MSA. You can set this value to infinity to disable
|
| 234 |
+
this behavior.
|
| 235 |
+
"""
|
| 236 |
+
for module in self.modules():
|
| 237 |
+
if isinstance(module, (RowSelfAttention, ColumnSelfAttention)):
|
| 238 |
+
module.max_tokens_per_msa = value
|
model/esm/pretrained.py
ADDED
|
@@ -0,0 +1,553 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
| 2 |
+
#
|
| 3 |
+
# This source code is licensed under the MIT license found in the
|
| 4 |
+
# LICENSE file in the root directory of this source tree.
|
| 5 |
+
|
| 6 |
+
import re
|
| 7 |
+
import urllib
|
| 8 |
+
import warnings
|
| 9 |
+
from argparse import Namespace
|
| 10 |
+
from pathlib import Path
|
| 11 |
+
|
| 12 |
+
import torch
|
| 13 |
+
|
| 14 |
+
import model.esm as esm
|
| 15 |
+
from onescience.datapipes.esm import Alphabet
|
| 16 |
+
from model.esm.esm2 import ESM2
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
def _has_regression_weights(model_name):
|
| 20 |
+
"""Return whether we expect / require regression weights;
|
| 21 |
+
Right now that is all models except ESM-1v, ESM-IF, and partially trained ESM2 models"""
|
| 22 |
+
return not ("esm1v" in model_name or "esm_if" in model_name or "270K" in model_name or "500K" in model_name)
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def load_model_and_alphabet(model_name):
|
| 26 |
+
if model_name.endswith(".pt"): # treat as filepath
|
| 27 |
+
return load_model_and_alphabet_local(model_name)
|
| 28 |
+
else:
|
| 29 |
+
return load_model_and_alphabet_hub(model_name)
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
def load_hub_workaround(url):
|
| 33 |
+
try:
|
| 34 |
+
data = torch.hub.load_state_dict_from_url(url, progress=False, map_location="cpu")
|
| 35 |
+
except RuntimeError:
|
| 36 |
+
# Pytorch version issue - see https://github.com/pytorch/pytorch/issues/43106
|
| 37 |
+
fn = Path(url).name
|
| 38 |
+
data = torch.load(
|
| 39 |
+
f"{torch.hub.get_dir()}/checkpoints/{fn}",
|
| 40 |
+
map_location="cpu",
|
| 41 |
+
)
|
| 42 |
+
except urllib.error.HTTPError as e:
|
| 43 |
+
raise Exception(f"Could not load {url}, check if you specified a correct model name?")
|
| 44 |
+
return data
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
def load_regression_hub(model_name):
|
| 48 |
+
url = f"https://dl.fbaipublicfiles.com/fair-esm/regression/{model_name}-contact-regression.pt"
|
| 49 |
+
regression_data = load_hub_workaround(url)
|
| 50 |
+
return regression_data
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
def _download_model_and_regression_data(model_name):
|
| 54 |
+
url = f"https://dl.fbaipublicfiles.com/fair-esm/models/{model_name}.pt"
|
| 55 |
+
model_data = load_hub_workaround(url)
|
| 56 |
+
if _has_regression_weights(model_name):
|
| 57 |
+
regression_data = load_regression_hub(model_name)
|
| 58 |
+
else:
|
| 59 |
+
regression_data = None
|
| 60 |
+
return model_data, regression_data
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
def load_model_and_alphabet_hub(model_name):
|
| 64 |
+
model_data, regression_data = _download_model_and_regression_data(model_name)
|
| 65 |
+
return load_model_and_alphabet_core(model_name, model_data, regression_data)
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
def load_model_and_alphabet_local(model_location):
|
| 69 |
+
"""Load from local path. The regression weights need to be co-located"""
|
| 70 |
+
model_location = Path(model_location)
|
| 71 |
+
model_data = torch.load(str(model_location), map_location="cpu")
|
| 72 |
+
model_name = model_location.stem
|
| 73 |
+
if _has_regression_weights(model_name):
|
| 74 |
+
regression_location = str(model_location.with_suffix("")) + "-contact-regression.pt"
|
| 75 |
+
regression_data = torch.load(regression_location, map_location="cpu")
|
| 76 |
+
else:
|
| 77 |
+
regression_data = None
|
| 78 |
+
return load_model_and_alphabet_core(model_name, model_data, regression_data)
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
def has_emb_layer_norm_before(model_state):
|
| 82 |
+
"""Determine whether layer norm needs to be applied before the encoder"""
|
| 83 |
+
return any(k.startswith("emb_layer_norm_before") for k, param in model_state.items())
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
def _load_model_and_alphabet_core_v1(model_data):
|
| 87 |
+
import model.esm as esm # since esm.inverse_folding is imported below, you actually have to re-import esm here
|
| 88 |
+
|
| 89 |
+
alphabet = esm.Alphabet.from_architecture(model_data["args"].arch)
|
| 90 |
+
|
| 91 |
+
if model_data["args"].arch == "roberta_large":
|
| 92 |
+
# upgrade state dict
|
| 93 |
+
pra = lambda s: "".join(s.split("encoder_")[1:] if "encoder" in s else s)
|
| 94 |
+
prs1 = lambda s: "".join(s.split("encoder.")[1:] if "encoder" in s else s)
|
| 95 |
+
prs2 = lambda s: "".join(
|
| 96 |
+
s.split("sentence_encoder.")[1:] if "sentence_encoder" in s else s
|
| 97 |
+
)
|
| 98 |
+
model_args = {pra(arg[0]): arg[1] for arg in vars(model_data["args"]).items()}
|
| 99 |
+
model_state = {prs1(prs2(arg[0])): arg[1] for arg in model_data["model"].items()}
|
| 100 |
+
model_state["embed_tokens.weight"][alphabet.mask_idx].zero_() # For token drop
|
| 101 |
+
model_args["emb_layer_norm_before"] = has_emb_layer_norm_before(model_state)
|
| 102 |
+
model_type = esm.ProteinBertModel
|
| 103 |
+
|
| 104 |
+
elif model_data["args"].arch == "protein_bert_base":
|
| 105 |
+
|
| 106 |
+
# upgrade state dict
|
| 107 |
+
pra = lambda s: "".join(s.split("decoder_")[1:] if "decoder" in s else s)
|
| 108 |
+
prs = lambda s: "".join(s.split("decoder.")[1:] if "decoder" in s else s)
|
| 109 |
+
model_args = {pra(arg[0]): arg[1] for arg in vars(model_data["args"]).items()}
|
| 110 |
+
model_state = {prs(arg[0]): arg[1] for arg in model_data["model"].items()}
|
| 111 |
+
model_type = esm.ProteinBertModel
|
| 112 |
+
elif model_data["args"].arch == "msa_transformer":
|
| 113 |
+
|
| 114 |
+
# upgrade state dict
|
| 115 |
+
pra = lambda s: "".join(s.split("encoder_")[1:] if "encoder" in s else s)
|
| 116 |
+
prs1 = lambda s: "".join(s.split("encoder.")[1:] if "encoder" in s else s)
|
| 117 |
+
prs2 = lambda s: "".join(
|
| 118 |
+
s.split("sentence_encoder.")[1:] if "sentence_encoder" in s else s
|
| 119 |
+
)
|
| 120 |
+
prs3 = lambda s: s.replace("row", "column") if "row" in s else s.replace("column", "row")
|
| 121 |
+
model_args = {pra(arg[0]): arg[1] for arg in vars(model_data["args"]).items()}
|
| 122 |
+
model_state = {prs1(prs2(prs3(arg[0]))): arg[1] for arg in model_data["model"].items()}
|
| 123 |
+
if model_args.get("embed_positions_msa", False):
|
| 124 |
+
emb_dim = model_state["msa_position_embedding"].size(-1)
|
| 125 |
+
model_args["embed_positions_msa_dim"] = emb_dim # initial release, bug: emb_dim==1
|
| 126 |
+
|
| 127 |
+
model_type = esm.MSATransformer
|
| 128 |
+
|
| 129 |
+
elif "invariant_gvp" in model_data["args"].arch:
|
| 130 |
+
import model.esm.inverse_folding
|
| 131 |
+
|
| 132 |
+
model_type = esm.inverse_folding.gvp_transformer.GVPTransformerModel
|
| 133 |
+
model_args = vars(model_data["args"]) # convert Namespace -> dict
|
| 134 |
+
|
| 135 |
+
def update_name(s):
|
| 136 |
+
# Map the module names in checkpoints trained with internal code to
|
| 137 |
+
# the updated module names in open source code
|
| 138 |
+
s = s.replace("W_v", "embed_graph.embed_node")
|
| 139 |
+
s = s.replace("W_e", "embed_graph.embed_edge")
|
| 140 |
+
s = s.replace("embed_scores.0", "embed_confidence")
|
| 141 |
+
s = s.replace("embed_score.", "embed_graph.embed_confidence.")
|
| 142 |
+
s = s.replace("seq_logits_projection.", "")
|
| 143 |
+
s = s.replace("embed_ingraham_features", "embed_dihedrals")
|
| 144 |
+
s = s.replace("embed_gvp_in_local_frame.0", "embed_gvp_output")
|
| 145 |
+
s = s.replace("embed_features_in_local_frame.0", "embed_gvp_input_features")
|
| 146 |
+
return s
|
| 147 |
+
|
| 148 |
+
model_state = {
|
| 149 |
+
update_name(sname): svalue
|
| 150 |
+
for sname, svalue in model_data["model"].items()
|
| 151 |
+
if "version" not in sname
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
else:
|
| 155 |
+
raise ValueError("Unknown architecture selected")
|
| 156 |
+
|
| 157 |
+
model = model_type(
|
| 158 |
+
Namespace(**model_args),
|
| 159 |
+
alphabet,
|
| 160 |
+
)
|
| 161 |
+
|
| 162 |
+
return model, alphabet, model_state
|
| 163 |
+
|
| 164 |
+
|
| 165 |
+
def _load_model_and_alphabet_core_v2(model_data):
|
| 166 |
+
def upgrade_state_dict(state_dict):
|
| 167 |
+
"""Removes prefixes 'model.encoder.sentence_encoder.' and 'model.encoder.'."""
|
| 168 |
+
prefixes = ["encoder.sentence_encoder.", "encoder."]
|
| 169 |
+
pattern = re.compile("^" + "|".join(prefixes))
|
| 170 |
+
state_dict = {pattern.sub("", name): param for name, param in state_dict.items()}
|
| 171 |
+
return state_dict
|
| 172 |
+
|
| 173 |
+
cfg = model_data["cfg"]["model"]
|
| 174 |
+
state_dict = model_data["model"]
|
| 175 |
+
state_dict = upgrade_state_dict(state_dict)
|
| 176 |
+
alphabet = Alphabet.from_architecture("ESM-1b")
|
| 177 |
+
model = ESM2(
|
| 178 |
+
num_layers=cfg.encoder_layers,
|
| 179 |
+
embed_dim=cfg.encoder_embed_dim,
|
| 180 |
+
attention_heads=cfg.encoder_attention_heads,
|
| 181 |
+
alphabet=alphabet,
|
| 182 |
+
token_dropout=cfg.token_dropout,
|
| 183 |
+
)
|
| 184 |
+
return model, alphabet, state_dict
|
| 185 |
+
|
| 186 |
+
|
| 187 |
+
def load_model_and_alphabet_core(model_name, model_data, regression_data=None):
|
| 188 |
+
if regression_data is not None:
|
| 189 |
+
model_data["model"].update(regression_data["model"])
|
| 190 |
+
|
| 191 |
+
if model_name.startswith("esm2"):
|
| 192 |
+
model, alphabet, model_state = _load_model_and_alphabet_core_v2(model_data)
|
| 193 |
+
else:
|
| 194 |
+
model, alphabet, model_state = _load_model_and_alphabet_core_v1(model_data)
|
| 195 |
+
|
| 196 |
+
expected_keys = set(model.state_dict().keys())
|
| 197 |
+
found_keys = set(model_state.keys())
|
| 198 |
+
|
| 199 |
+
if regression_data is None:
|
| 200 |
+
expected_missing = {"contact_head.regression.weight", "contact_head.regression.bias"}
|
| 201 |
+
error_msgs = []
|
| 202 |
+
missing = (expected_keys - found_keys) - expected_missing
|
| 203 |
+
if missing:
|
| 204 |
+
error_msgs.append(f"Missing key(s) in state_dict: {missing}.")
|
| 205 |
+
unexpected = found_keys - expected_keys
|
| 206 |
+
if unexpected:
|
| 207 |
+
error_msgs.append(f"Unexpected key(s) in state_dict: {unexpected}.")
|
| 208 |
+
|
| 209 |
+
if error_msgs:
|
| 210 |
+
raise RuntimeError(
|
| 211 |
+
"Error(s) in loading state_dict for {}:\n\t{}".format(
|
| 212 |
+
model.__class__.__name__, "\n\t".join(error_msgs)
|
| 213 |
+
)
|
| 214 |
+
)
|
| 215 |
+
if expected_missing - found_keys:
|
| 216 |
+
warnings.warn(
|
| 217 |
+
"Regression weights not found, predicting contacts will not produce correct results."
|
| 218 |
+
)
|
| 219 |
+
|
| 220 |
+
model.load_state_dict(model_state, strict=regression_data is not None)
|
| 221 |
+
|
| 222 |
+
return model, alphabet
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
def esm1_t34_670M_UR50S():
|
| 226 |
+
"""34 layer transformer model with 670M params, trained on Uniref50 Sparse.
|
| 227 |
+
|
| 228 |
+
Returns a tuple of (Model, Alphabet).
|
| 229 |
+
"""
|
| 230 |
+
return load_model_and_alphabet_hub("esm1_t34_670M_UR50S")
|
| 231 |
+
|
| 232 |
+
|
| 233 |
+
def esm1_t34_670M_UR50D():
|
| 234 |
+
"""34 layer transformer model with 670M params, trained on Uniref50 Dense.
|
| 235 |
+
|
| 236 |
+
Returns a tuple of (Model, Alphabet).
|
| 237 |
+
"""
|
| 238 |
+
return load_model_and_alphabet_hub("esm1_t34_670M_UR50D")
|
| 239 |
+
|
| 240 |
+
|
| 241 |
+
def esm1_t34_670M_UR100():
|
| 242 |
+
"""34 layer transformer model with 670M params, trained on Uniref100.
|
| 243 |
+
|
| 244 |
+
Returns a tuple of (Model, Alphabet).
|
| 245 |
+
"""
|
| 246 |
+
return load_model_and_alphabet_hub("esm1_t34_670M_UR100")
|
| 247 |
+
|
| 248 |
+
|
| 249 |
+
def esm1_t12_85M_UR50S():
|
| 250 |
+
"""12 layer transformer model with 85M params, trained on Uniref50 Sparse.
|
| 251 |
+
|
| 252 |
+
Returns a tuple of (Model, Alphabet).
|
| 253 |
+
"""
|
| 254 |
+
return load_model_and_alphabet_hub("esm1_t12_85M_UR50S")
|
| 255 |
+
|
| 256 |
+
|
| 257 |
+
def esm1_t6_43M_UR50S():
|
| 258 |
+
"""6 layer transformer model with 43M params, trained on Uniref50 Sparse.
|
| 259 |
+
|
| 260 |
+
Returns a tuple of (Model, Alphabet).
|
| 261 |
+
"""
|
| 262 |
+
return load_model_and_alphabet_hub("esm1_t6_43M_UR50S")
|
| 263 |
+
|
| 264 |
+
|
| 265 |
+
def esm1b_t33_650M_UR50S():
|
| 266 |
+
"""33 layer transformer model with 650M params, trained on Uniref50 Sparse.
|
| 267 |
+
This is our best performing model, which will be described in a future publication.
|
| 268 |
+
|
| 269 |
+
Returns a tuple of (Model, Alphabet).
|
| 270 |
+
"""
|
| 271 |
+
return load_model_and_alphabet_hub("esm1b_t33_650M_UR50S")
|
| 272 |
+
|
| 273 |
+
|
| 274 |
+
def esm_msa1_t12_100M_UR50S():
|
| 275 |
+
warnings.warn(
|
| 276 |
+
"This model had a minor bug in the positional embeddings, "
|
| 277 |
+
"please use ESM-MSA-1b: esm.pretrained.esm_msa1b_t12_100M_UR50S()",
|
| 278 |
+
)
|
| 279 |
+
return load_model_and_alphabet_hub("esm_msa1_t12_100M_UR50S")
|
| 280 |
+
|
| 281 |
+
|
| 282 |
+
def esm_msa1b_t12_100M_UR50S():
|
| 283 |
+
return load_model_and_alphabet_hub("esm_msa1b_t12_100M_UR50S")
|
| 284 |
+
|
| 285 |
+
|
| 286 |
+
def esm1v_t33_650M_UR90S():
|
| 287 |
+
"""33 layer transformer model with 650M params, trained on Uniref90.
|
| 288 |
+
This is model 1 of a 5 model ensemble.
|
| 289 |
+
|
| 290 |
+
Returns a tuple of (Model, Alphabet).
|
| 291 |
+
"""
|
| 292 |
+
return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_1")
|
| 293 |
+
|
| 294 |
+
|
| 295 |
+
def esm1v_t33_650M_UR90S_1():
|
| 296 |
+
"""33 layer transformer model with 650M params, trained on Uniref90.
|
| 297 |
+
This is model 1 of a 5 model ensemble.
|
| 298 |
+
|
| 299 |
+
Returns a tuple of (Model, Alphabet).
|
| 300 |
+
"""
|
| 301 |
+
return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_1")
|
| 302 |
+
|
| 303 |
+
|
| 304 |
+
def esm1v_t33_650M_UR90S_2():
|
| 305 |
+
"""33 layer transformer model with 650M params, trained on Uniref90.
|
| 306 |
+
This is model 2 of a 5 model ensemble.
|
| 307 |
+
|
| 308 |
+
Returns a tuple of (Model, Alphabet).
|
| 309 |
+
"""
|
| 310 |
+
return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_2")
|
| 311 |
+
|
| 312 |
+
|
| 313 |
+
def esm1v_t33_650M_UR90S_3():
|
| 314 |
+
"""33 layer transformer model with 650M params, trained on Uniref90.
|
| 315 |
+
This is model 3 of a 5 model ensemble.
|
| 316 |
+
|
| 317 |
+
Returns a tuple of (Model, Alphabet).
|
| 318 |
+
"""
|
| 319 |
+
return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_3")
|
| 320 |
+
|
| 321 |
+
|
| 322 |
+
def esm1v_t33_650M_UR90S_4():
|
| 323 |
+
"""33 layer transformer model with 650M params, trained on Uniref90.
|
| 324 |
+
This is model 4 of a 5 model ensemble.
|
| 325 |
+
|
| 326 |
+
Returns a tuple of (Model, Alphabet).
|
| 327 |
+
"""
|
| 328 |
+
return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_4")
|
| 329 |
+
|
| 330 |
+
|
| 331 |
+
def esm1v_t33_650M_UR90S_5():
|
| 332 |
+
"""33 layer transformer model with 650M params, trained on Uniref90.
|
| 333 |
+
This is model 5 of a 5 model ensemble.
|
| 334 |
+
|
| 335 |
+
Returns a tuple of (Model, Alphabet).
|
| 336 |
+
"""
|
| 337 |
+
return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_5")
|
| 338 |
+
|
| 339 |
+
|
| 340 |
+
def esm_if1_gvp4_t16_142M_UR50():
|
| 341 |
+
"""Inverse folding model with 142M params, with 4 GVP-GNN layers, 8
|
| 342 |
+
Transformer encoder layers, and 8 Transformer decoder layers, trained on
|
| 343 |
+
CATH structures and 12 million alphafold2 predicted structures from UniRef50
|
| 344 |
+
sequences.
|
| 345 |
+
|
| 346 |
+
Returns a tuple of (Model, Alphabet).
|
| 347 |
+
"""
|
| 348 |
+
return load_model_and_alphabet_hub("esm_if1_gvp4_t16_142M_UR50")
|
| 349 |
+
|
| 350 |
+
|
| 351 |
+
def esm2_t6_8M_UR50D():
|
| 352 |
+
"""6 layer ESM-2 model with 8M params, trained on UniRef50.
|
| 353 |
+
|
| 354 |
+
Returns a tuple of (Model, Alphabet).
|
| 355 |
+
"""
|
| 356 |
+
return load_model_and_alphabet_hub("esm2_t6_8M_UR50D")
|
| 357 |
+
|
| 358 |
+
|
| 359 |
+
def esm2_t12_35M_UR50D():
|
| 360 |
+
"""12 layer ESM-2 model with 35M params, trained on UniRef50.
|
| 361 |
+
|
| 362 |
+
Returns a tuple of (Model, Alphabet).
|
| 363 |
+
"""
|
| 364 |
+
return load_model_and_alphabet_hub("esm2_t12_35M_UR50D")
|
| 365 |
+
|
| 366 |
+
|
| 367 |
+
def esm2_t30_150M_UR50D():
|
| 368 |
+
"""30 layer ESM-2 model with 150M params, trained on UniRef50.
|
| 369 |
+
|
| 370 |
+
Returns a tuple of (Model, Alphabet).
|
| 371 |
+
"""
|
| 372 |
+
return load_model_and_alphabet_hub("esm2_t30_150M_UR50D")
|
| 373 |
+
|
| 374 |
+
|
| 375 |
+
def esm2_t33_650M_UR50D():
|
| 376 |
+
"""33 layer ESM-2 model with 650M params, trained on UniRef50.
|
| 377 |
+
|
| 378 |
+
Returns a tuple of (Model, Alphabet).
|
| 379 |
+
"""
|
| 380 |
+
return load_model_and_alphabet_hub("esm2_t33_650M_UR50D")
|
| 381 |
+
|
| 382 |
+
|
| 383 |
+
def esm2_t36_3B_UR50D():
|
| 384 |
+
"""36 layer ESM-2 model with 3B params, trained on UniRef50.
|
| 385 |
+
|
| 386 |
+
Returns a tuple of (Model, Alphabet).
|
| 387 |
+
"""
|
| 388 |
+
return load_model_and_alphabet_hub("esm2_t36_3B_UR50D")
|
| 389 |
+
|
| 390 |
+
|
| 391 |
+
def esm2_t48_15B_UR50D():
|
| 392 |
+
"""48 layer ESM-2 model with 15B params, trained on UniRef50.
|
| 393 |
+
If you have OOM while loading this model, please refer to README
|
| 394 |
+
on how to employ FSDP and ZeRO CPU offloading
|
| 395 |
+
|
| 396 |
+
Returns a tuple of (Model, Alphabet).
|
| 397 |
+
"""
|
| 398 |
+
return load_model_and_alphabet_hub("esm2_t48_15B_UR50D")
|
| 399 |
+
|
| 400 |
+
|
| 401 |
+
def esmfold_v0():
|
| 402 |
+
"""
|
| 403 |
+
ESMFold v0 model with 3B ESM-2, 48 folding blocks.
|
| 404 |
+
This version was used for the paper (Lin et al, 2022). It was trained
|
| 405 |
+
on all PDB chains until 2020-05, to ensure temporal holdout with CASP14
|
| 406 |
+
and the CAMEO validation and test set reported there.
|
| 407 |
+
"""
|
| 408 |
+
import model.esm.esmfold.v1.pretrained
|
| 409 |
+
return esm.esmfold.v1.pretrained.esmfold_v0()
|
| 410 |
+
|
| 411 |
+
|
| 412 |
+
def esmfold_v1():
|
| 413 |
+
"""
|
| 414 |
+
ESMFold v1 model using 3B ESM-2, 48 folding blocks.
|
| 415 |
+
ESMFold provides fast high accuracy atomic level structure prediction
|
| 416 |
+
directly from the individual sequence of a protein. ESMFold uses the ESM2
|
| 417 |
+
protein language model to extract meaningful representations from the
|
| 418 |
+
protein sequence.
|
| 419 |
+
"""
|
| 420 |
+
import model.esm.esmfold.v1.pretrained
|
| 421 |
+
return esm.esmfold.v1.pretrained.esmfold_v1()
|
| 422 |
+
|
| 423 |
+
def esmfold_structure_module_only_8M():
|
| 424 |
+
"""
|
| 425 |
+
ESMFold baseline model using 8M ESM-2, 0 folding blocks.
|
| 426 |
+
ESM-2 here is trained out to 500K updates.
|
| 427 |
+
This is a model designed to test the capabilities of the language model
|
| 428 |
+
when ablated for number of parameters in the language model.
|
| 429 |
+
See table S1 in (Lin et al, 2022).
|
| 430 |
+
"""
|
| 431 |
+
import model.esm.esmfold.v1.pretrained
|
| 432 |
+
return esm.esmfold.v1.pretrained.esmfold_structure_module_only_8M()
|
| 433 |
+
|
| 434 |
+
|
| 435 |
+
def esmfold_structure_module_only_8M_270K():
|
| 436 |
+
"""
|
| 437 |
+
ESMFold baseline model using 8M ESM-2, 0 folding blocks.
|
| 438 |
+
ESM-2 here is trained out to 270K updates.
|
| 439 |
+
This is a model designed to test the capabilities of the language model
|
| 440 |
+
when ablated for number of parameters in the language model.
|
| 441 |
+
See table S1 in (Lin et al, 2022).
|
| 442 |
+
"""
|
| 443 |
+
import model.esm.esmfold.v1.pretrained
|
| 444 |
+
return esm.esmfold.v1.pretrained.esmfold_structure_module_only_8M_270K()
|
| 445 |
+
|
| 446 |
+
|
| 447 |
+
def esmfold_structure_module_only_35M():
|
| 448 |
+
"""
|
| 449 |
+
ESMFold baseline model using 35M ESM-2, 0 folding blocks.
|
| 450 |
+
ESM-2 here is trained out to 500K updates.
|
| 451 |
+
This is a model designed to test the capabilities of the language model
|
| 452 |
+
when ablated for number of parameters in the language model.
|
| 453 |
+
See table S1 in (Lin et al, 2022).
|
| 454 |
+
"""
|
| 455 |
+
import model.esm.esmfold.v1.pretrained
|
| 456 |
+
return esm.esmfold.v1.pretrained.esmfold_structure_module_only_35M()
|
| 457 |
+
|
| 458 |
+
|
| 459 |
+
def esmfold_structure_module_only_35M_270K():
|
| 460 |
+
"""
|
| 461 |
+
ESMFold baseline model using 35M ESM-2, 0 folding blocks.
|
| 462 |
+
ESM-2 here is trained out to 270K updates.
|
| 463 |
+
This is a model designed to test the capabilities of the language model
|
| 464 |
+
when ablated for number of parameters in the language model.
|
| 465 |
+
See table S1 in (Lin et al, 2022).
|
| 466 |
+
"""
|
| 467 |
+
import model.esm.esmfold.v1.pretrained
|
| 468 |
+
return esm.esmfold.v1.pretrained.esmfold_structure_module_only_35M_270K()
|
| 469 |
+
|
| 470 |
+
|
| 471 |
+
def esmfold_structure_module_only_150M():
|
| 472 |
+
"""
|
| 473 |
+
ESMFold baseline model using 150M ESM-2, 0 folding blocks.
|
| 474 |
+
ESM-2 here is trained out to 500K updates.
|
| 475 |
+
This is a model designed to test the capabilities of the language model
|
| 476 |
+
when ablated for number of parameters in the language model.
|
| 477 |
+
See table S1 in (Lin et al, 2022).
|
| 478 |
+
"""
|
| 479 |
+
import model.esm.esmfold.v1.pretrained
|
| 480 |
+
return esm.esmfold.v1.pretrained.esmfold_structure_module_only_150M()
|
| 481 |
+
|
| 482 |
+
|
| 483 |
+
def esmfold_structure_module_only_150M_270K():
|
| 484 |
+
"""
|
| 485 |
+
ESMFold baseline model using 150M ESM-2, 0 folding blocks.
|
| 486 |
+
ESM-2 here is trained out to 270K updates.
|
| 487 |
+
This is a model designed to test the capabilities of the language model
|
| 488 |
+
when ablated for number of parameters in the language model.
|
| 489 |
+
See table S1 in (Lin et al, 2022).
|
| 490 |
+
"""
|
| 491 |
+
import model.esm.esmfold.v1.pretrained
|
| 492 |
+
return esm.esmfold.v1.pretrained.esmfold_structure_module_only_150M_270K()
|
| 493 |
+
|
| 494 |
+
|
| 495 |
+
def esmfold_structure_module_only_650M():
|
| 496 |
+
"""
|
| 497 |
+
ESMFold baseline model using 650M ESM-2, 0 folding blocks.
|
| 498 |
+
ESM-2 here is trained out to 500K updates.
|
| 499 |
+
This is a model designed to test the capabilities of the language model
|
| 500 |
+
when ablated for number of parameters in the language model.
|
| 501 |
+
See table S1 in (Lin et al, 2022).
|
| 502 |
+
"""
|
| 503 |
+
import model.esm.esmfold.v1.pretrained
|
| 504 |
+
return esm.esmfold.v1.pretrained.esmfold_structure_module_only_650M()
|
| 505 |
+
|
| 506 |
+
|
| 507 |
+
def esmfold_structure_module_only_650M_270K():
|
| 508 |
+
"""
|
| 509 |
+
ESMFold baseline model using 650M ESM-2, 0 folding blocks.
|
| 510 |
+
ESM-2 here is trained out to 270K updates.
|
| 511 |
+
This is a model designed to test the capabilities of the language model
|
| 512 |
+
when ablated for number of parameters in the language model.
|
| 513 |
+
See table S1 in (Lin et al, 2022).
|
| 514 |
+
"""
|
| 515 |
+
import model.esm.esmfold.v1.pretrained
|
| 516 |
+
return esm.esmfold.v1.pretrained.esmfold_structure_module_only_650M_270K()
|
| 517 |
+
|
| 518 |
+
|
| 519 |
+
def esmfold_structure_module_only_3B():
|
| 520 |
+
"""
|
| 521 |
+
ESMFold baseline model using 3B ESM-2, 0 folding blocks.
|
| 522 |
+
ESM-2 here is trained out to 500K updates.
|
| 523 |
+
This is a model designed to test the capabilities of the language model
|
| 524 |
+
when ablated for number of parameters in the language model.
|
| 525 |
+
See table S1 in (Lin et al, 2022).
|
| 526 |
+
"""
|
| 527 |
+
import model.esm.esmfold.v1.pretrained
|
| 528 |
+
return esm.esmfold.v1.pretrained.esmfold_structure_module_only_3B()
|
| 529 |
+
|
| 530 |
+
|
| 531 |
+
def esmfold_structure_module_only_3B_270K():
|
| 532 |
+
"""
|
| 533 |
+
ESMFold baseline model using 3B ESM-2, 0 folding blocks.
|
| 534 |
+
ESM-2 here is trained out to 270K updates.
|
| 535 |
+
This is a model designed to test the capabilities of the language model
|
| 536 |
+
when ablated for number of parameters in the language model.
|
| 537 |
+
See table S1 in (Lin et al, 2022).
|
| 538 |
+
"""
|
| 539 |
+
import model.esm.esmfold.v1.pretrained
|
| 540 |
+
return esm.esmfold.v1.pretrained.esmfold_structure_module_only_3B_270K()
|
| 541 |
+
|
| 542 |
+
|
| 543 |
+
def esmfold_structure_module_only_15B():
|
| 544 |
+
"""
|
| 545 |
+
ESMFold baseline model using 15B ESM-2, 0 folding blocks.
|
| 546 |
+
ESM-2 here is trained out to 270K updates.
|
| 547 |
+
The 15B parameter ESM-2 was not trained out to 500K updates
|
| 548 |
+
This is a model designed to test the capabilities of the language model
|
| 549 |
+
when ablated for number of parameters in the language model.
|
| 550 |
+
See table S1 in (Lin et al, 2022).
|
| 551 |
+
"""
|
| 552 |
+
import model.esm.esmfold.v1.pretrained
|
| 553 |
+
return esm.esmfold.v1.pretrained.esmfold_structure_module_only_15B()
|
model/esm/version.py
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
| 2 |
+
#
|
| 3 |
+
# This source code is licensed under the MIT license found in the
|
| 4 |
+
# LICENSE file in the root directory of this source tree.
|
| 5 |
+
|
| 6 |
+
version = "2.0.1"
|