Add files using upload-large-folder tool
Browse files- config/callbacks/default.yaml +5 -0
- config/callbacks/model_summary.yaml +5 -0
- config/data/apo.yaml +3 -0
- config/data/pdb_sp_afesm.yaml +66 -0
- config/data/pdb_sp_afesme.yaml +67 -0
- config/experiment/test.yaml +30 -0
- config/experiment/train.yaml +55 -0
- config/experiment/train_plddt.yaml +85 -0
- config/extras/default.yaml +5 -0
- config/model/architecture/default.yaml +101 -0
- config/model/architecture/foldingdit_1.6B.yaml +99 -0
- config/model/architecture/plddt_module.yaml +24 -0
- config/model/default.yaml +39 -0
- config/model/processor/default.yaml +2 -0
- config/model/processor/protein_processor.yaml +2 -0
- config/model/simplefold.yaml +39 -0
- config/trainer/fsdp.yaml +18 -0
- models/__pycache__/__init__.cpython-310.pyc +0 -0
- models/__pycache__/__init__.cpython-311.pyc +0 -0
- models/esm/__init__.py +13 -0
- models/esm/__pycache__/__init__.cpython-311.pyc +0 -0
- models/esm/__pycache__/esm2.cpython-310.pyc +0 -0
- models/esm/__pycache__/msa_transformer.cpython-310.pyc +0 -0
- models/esm/__pycache__/version.cpython-310.pyc +0 -0
- models/esm/__pycache__/version.cpython-311.pyc +0 -0
- models/esm/esm2.py +152 -0
- models/esm/esmfold/__init__.py +0 -0
- models/esm/esmfold/v1/esmfold.py +364 -0
- models/esm/msa_transformer.py +238 -0
- models/esm/pretrained.py +545 -0
- models/esm/version.py +6 -0
- models/simplefold/mlx/__pycache__/esm_network.cpython-310.pyc +0 -0
- models/simplefold/mlx/__pycache__/esm_rotary_embedding.cpython-310.pyc +0 -0
- models/simplefold/mlx/__pycache__/sampler.cpython-310.pyc +0 -0
- models/simplefold/torch/__pycache__/__init__.cpython-310.pyc +0 -0
- models/simplefold/torch/__pycache__/architecture.cpython-310.pyc +0 -0
- models/simplefold/torch/__pycache__/architecture.cpython-311.pyc +0 -0
- models/simplefold/torch/__pycache__/blocks.cpython-310.pyc +0 -0
- models/simplefold/torch/__pycache__/blocks.cpython-311.pyc +0 -0
- models/simplefold/torch/__pycache__/confidence_module.cpython-310.pyc +0 -0
- models/simplefold/torch/__pycache__/confidence_module.cpython-311.pyc +0 -0
- models/simplefold/torch/__pycache__/layers.cpython-310.pyc +0 -0
- models/simplefold/torch/__pycache__/layers.cpython-311.pyc +0 -0
- models/simplefold/torch/__pycache__/pos_embed.cpython-310.pyc +0 -0
- models/simplefold/torch/__pycache__/sampler.cpython-310.pyc +0 -0
- models/simplefold/torch/__pycache__/sampler.cpython-311.pyc +0 -0
- models/simplefold/torch/blocks.py +146 -0
- models/simplefold/torch/confidence_module.py +85 -0
- models/simplefold/torch/sampler.py +108 -0
- weight/ccd.pkl +3 -0
config/callbacks/default.yaml
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
defaults:
|
| 2 |
+
- model_checkpoint
|
| 3 |
+
- model_summary
|
| 4 |
+
- _self_
|
| 5 |
+
|
config/callbacks/model_summary.yaml
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# https://lightning.ai/docs/pytorch/stable/api/lightning.pytorch.callbacks.RichModelSummary.html
|
| 2 |
+
|
| 3 |
+
model_summary:
|
| 4 |
+
_target_: lightning.pytorch.callbacks.RichModelSummary
|
| 5 |
+
max_depth: -1 # the maximum depth of layer nesting that the summary will include
|
config/data/apo.yaml
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
_target_: onescience.datapipes.simplefold.test_datamodule.SimpleFoldInferenceDataModule
|
| 2 |
+
target_dir: data/apo/
|
| 3 |
+
num_workers: 1
|
config/data/pdb_sp_afesm.yaml
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
_target_: onescience.datapipes.simplefold.train_datamodule.SimpleFoldTrainingDataModule
|
| 2 |
+
|
| 3 |
+
datasets:
|
| 4 |
+
- _target_: onescience.datapipes.simplefold.train_datamodule.DatasetConfig
|
| 5 |
+
data_name: rcsb_protein
|
| 6 |
+
tokenized_dir: data/rcsb_protein_tokenized
|
| 7 |
+
target_dir: data/rcsb_processed_targets
|
| 8 |
+
manifest_path: data/rcsb_protein_tokenized/manifest.json
|
| 9 |
+
cropper:
|
| 10 |
+
_target_: onescience.datapipes.boltz_data_pipeline.crop.boltz.BoltzCropper
|
| 11 |
+
min_neighborhood: 0
|
| 12 |
+
max_neighborhood: 40
|
| 13 |
+
filters:
|
| 14 |
+
- _target_: onescience.datapipes.boltz_data_pipeline.filter.dynamic.resolution.ResolutionFilter
|
| 15 |
+
resolution: 5.0
|
| 16 |
+
- _target_: onescience.datapipes.boltz_data_pipeline.filter.dynamic.date.DateFilter
|
| 17 |
+
date: "2020-05-01"
|
| 18 |
+
ref: released
|
| 19 |
+
|
| 20 |
+
- _target_: onescience.datapipes.simplefold.train_datamodule.DatasetConfig
|
| 21 |
+
data_name: swissprot
|
| 22 |
+
tokenized_dir: data/swissprot_tokenized
|
| 23 |
+
target_dir: data/swissprot_pdb_v4_boltz
|
| 24 |
+
manifest_path: data/swissprot_tokenized/manifest.json
|
| 25 |
+
record_list: data/swissprot_filtered.txt
|
| 26 |
+
cropper:
|
| 27 |
+
_target_: onescience.datapipes.boltz_data_pipeline.crop.boltz.BoltzCropper
|
| 28 |
+
min_neighborhood: 0
|
| 29 |
+
max_neighborhood: 40
|
| 30 |
+
|
| 31 |
+
- _target_: onescience.datapipes.simplefold.train_datamodule.DatasetConfig
|
| 32 |
+
data_name: processed_afesm
|
| 33 |
+
tokenized_dir: data/processed_afesm
|
| 34 |
+
target_dir: data/processed_afesm
|
| 35 |
+
manifest_path: data/processed_afesm/manifest.json
|
| 36 |
+
cropper:
|
| 37 |
+
_target_: onescience.datapipes.boltz_data_pipeline.crop.boltz.BoltzCropper
|
| 38 |
+
min_neighborhood: 0
|
| 39 |
+
max_neighborhood: 40
|
| 40 |
+
|
| 41 |
+
filters:
|
| 42 |
+
- _target_: onescience.datapipes.boltz_data_pipeline.filter.dynamic.size.SizeFilter
|
| 43 |
+
min_chains: 1
|
| 44 |
+
max_chains: 300
|
| 45 |
+
|
| 46 |
+
tokenizer:
|
| 47 |
+
_target_: onescience.datapipes.boltz_data_pipeline.tokenize.boltz_protein.BoltzTokenizer
|
| 48 |
+
|
| 49 |
+
featurizer:
|
| 50 |
+
_target_: onescience.datapipes.boltz_data_pipeline.feature.featurizer.BoltzFeaturizer
|
| 51 |
+
|
| 52 |
+
symmetries: data/symmetry.pkl
|
| 53 |
+
max_tokens: 256
|
| 54 |
+
max_atoms: 2304
|
| 55 |
+
pad_to_max_tokens: False
|
| 56 |
+
pad_to_max_atoms: False
|
| 57 |
+
batch_size: 256
|
| 58 |
+
num_workers: 16
|
| 59 |
+
pin_memory: True
|
| 60 |
+
return_train_symmetries: False
|
| 61 |
+
min_dist: 2.0
|
| 62 |
+
max_dist: 22.0
|
| 63 |
+
num_bins: 64
|
| 64 |
+
atoms_per_window_queries: 32
|
| 65 |
+
rotation_augment_ref_pos: False
|
| 66 |
+
rotation_augment_coords: True
|
config/data/pdb_sp_afesme.yaml
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
_target_: onescience.datapipes.simplefold.train_datamodule.SimpleFoldTrainingDataModule
|
| 2 |
+
|
| 3 |
+
datasets:
|
| 4 |
+
- _target_: onescience.datapipes.simplefold.train_datamodule.DatasetConfig
|
| 5 |
+
data_name: rcsb_protein
|
| 6 |
+
tokenized_dir: data/rcsb_protein_tokenized
|
| 7 |
+
target_dir: data/rcsb_processed_targets
|
| 8 |
+
manifest_path: data/rcsb_protein_tokenized/manifest.json
|
| 9 |
+
cropper:
|
| 10 |
+
_target_: onescience.datapipes.boltz_data_pipeline.crop.boltz.BoltzCropper
|
| 11 |
+
min_neighborhood: 0
|
| 12 |
+
max_neighborhood: 40
|
| 13 |
+
filters:
|
| 14 |
+
- _target_: onescience.datapipes.boltz_data_pipeline.filter.dynamic.resolution.ResolutionFilter
|
| 15 |
+
resolution: 5.0
|
| 16 |
+
- _target_: onescience.datapipes.boltz_data_pipeline.filter.dynamic.date.DateFilter
|
| 17 |
+
date: "2020-05-01"
|
| 18 |
+
ref: released
|
| 19 |
+
|
| 20 |
+
- _target_: onescience.datapipes.simplefold.train_datamodule.DatasetConfig
|
| 21 |
+
data_name: swissprot
|
| 22 |
+
tokenized_dir: data/swissprot_tokenized
|
| 23 |
+
target_dir: data/swissprot_pdb_v4_boltz
|
| 24 |
+
manifest_path: data/swissprot_tokenized/manifest.json
|
| 25 |
+
record_list: data/swissprot_filtered.txt
|
| 26 |
+
cropper:
|
| 27 |
+
_target_: onescience.datapipes.boltz_data_pipeline.crop.boltz.BoltzCropper
|
| 28 |
+
min_neighborhood: 0
|
| 29 |
+
max_neighborhood: 40
|
| 30 |
+
|
| 31 |
+
- _target_: onescience.datapipes.simplefold.train_datamodule.DatasetConfig
|
| 32 |
+
data_name: processed_afesm_cluster
|
| 33 |
+
tokenized_dir: data/tokenized_afesm_cluster
|
| 34 |
+
target_dir: data/processed_afesm_cluster
|
| 35 |
+
manifest_path: data/processed_afesm_cluster/manifest.json
|
| 36 |
+
cluster: data/filtered_afesm_cluster.json
|
| 37 |
+
cropper:
|
| 38 |
+
_target_: onescience.datapipes.boltz_data_pipeline.crop.boltz.BoltzCropper
|
| 39 |
+
min_neighborhood: 0
|
| 40 |
+
max_neighborhood: 40
|
| 41 |
+
|
| 42 |
+
filters:
|
| 43 |
+
- _target_: onescience.datapipes.boltz_data_pipeline.filter.dynamic.size.SizeFilter
|
| 44 |
+
min_chains: 1
|
| 45 |
+
max_chains: 300
|
| 46 |
+
|
| 47 |
+
tokenizer:
|
| 48 |
+
_target_: onescience.datapipes.boltz_data_pipeline.tokenize.boltz_protein.BoltzTokenizer
|
| 49 |
+
|
| 50 |
+
featurizer:
|
| 51 |
+
_target_: onescience.datapipes.boltz_data_pipeline.feature.featurizer.BoltzFeaturizer
|
| 52 |
+
|
| 53 |
+
symmetries: data/symmetry.pkl
|
| 54 |
+
max_tokens: 256
|
| 55 |
+
max_atoms: 2304
|
| 56 |
+
pad_to_max_tokens: False
|
| 57 |
+
pad_to_max_atoms: False
|
| 58 |
+
batch_size: 256
|
| 59 |
+
num_workers: 16
|
| 60 |
+
pin_memory: True
|
| 61 |
+
return_train_symmetries: False
|
| 62 |
+
min_dist: 2.0
|
| 63 |
+
max_dist: 22.0
|
| 64 |
+
num_bins: 64
|
| 65 |
+
atoms_per_window_queries: 32
|
| 66 |
+
rotation_augment_ref_pos: False
|
| 67 |
+
rotation_augment_coords: True
|
config/experiment/test.yaml
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# @package _global_
|
| 2 |
+
defaults:
|
| 3 |
+
- override /data: cameo22
|
| 4 |
+
- override /model: simplefold
|
| 5 |
+
- override /model/architecture: foldingdit_100M
|
| 6 |
+
- override /model/sampler: euler_maruyama
|
| 7 |
+
- override /model/processor: protein_processor
|
| 8 |
+
- override /callbacks: default
|
| 9 |
+
- override /trainer: default
|
| 10 |
+
|
| 11 |
+
load_ckpt_path: artifacts/simplefold_100M.ckpt
|
| 12 |
+
seed: 12345
|
| 13 |
+
|
| 14 |
+
data:
|
| 15 |
+
num_repeats: 1
|
| 16 |
+
filters:
|
| 17 |
+
- _target_: onescience.datapipes.boltz_data_pipeline.filter.dynamic.max_residues.MaxResiduesFilter
|
| 18 |
+
min_residues: 1
|
| 19 |
+
max_residues: 1000 # filter out T1044 in CASP14
|
| 20 |
+
|
| 21 |
+
model:
|
| 22 |
+
sampler:
|
| 23 |
+
num_timesteps: 500
|
| 24 |
+
t_start: 1e-4
|
| 25 |
+
tau: 0.01
|
| 26 |
+
log_timesteps: True
|
| 27 |
+
w_cutoff: 0.99
|
| 28 |
+
|
| 29 |
+
processor:
|
| 30 |
+
inference_multiplicity: 1
|
config/experiment/train.yaml
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# @package _global_
|
| 2 |
+
|
| 3 |
+
# All parameters below will be merged with parameters from default configurations set above
|
| 4 |
+
# this allows you to overwrite only specified parameters
|
| 5 |
+
|
| 6 |
+
# Options for training:
|
| 7 |
+
# - /data: [pdb, pdb_sp, pdb_sp_afesm, pdb_sp_afesme]
|
| 8 |
+
# - /model/architecture:
|
| 9 |
+
# [foldingdit_100M, foldingdit_360M, foldingdit_700M,
|
| 10 |
+
# foldingdit_1.1B, foldingdit_1.6B, foldingdit_3B]
|
| 11 |
+
# - /trainer: [default, fsdp]
|
| 12 |
+
|
| 13 |
+
defaults:
|
| 14 |
+
- override /data: pdb
|
| 15 |
+
- override /model: simplefold
|
| 16 |
+
- override /model/architecture: foldingdit_100M
|
| 17 |
+
- override /model/sampler: euler_maruyama
|
| 18 |
+
- override /model/processor: protein_processor
|
| 19 |
+
- override /callbacks: default
|
| 20 |
+
- override /trainer: default
|
| 21 |
+
- override /logger: tensorboard
|
| 22 |
+
|
| 23 |
+
# load_ckpt_path: [PATH_TO_YOUR_CKPT] # uncomment to load a checkpoint
|
| 24 |
+
seed: 12345
|
| 25 |
+
|
| 26 |
+
trainer:
|
| 27 |
+
max_steps: 300000
|
| 28 |
+
val_check_interval: 10000 # this controls BOTH checkpoint steps and validation
|
| 29 |
+
accumulate_grad_batches: 1 # gradient accumulation
|
| 30 |
+
|
| 31 |
+
data:
|
| 32 |
+
batch_size: 1 # should be the same as the number of GPUs
|
| 33 |
+
num_workers: 16
|
| 34 |
+
|
| 35 |
+
model:
|
| 36 |
+
_target_: models.simplefold.simplefold.SimpleFold
|
| 37 |
+
ema_decay: 0.999
|
| 38 |
+
clip_grad_norm_val: 2.0
|
| 39 |
+
esm_model: "esm2_3B"
|
| 40 |
+
lddt_weight_schedule: False # set to True in finetuning phase
|
| 41 |
+
|
| 42 |
+
scheduler:
|
| 43 |
+
_target_: onescience.utils.simplefold.lr_scheduler.LinearWarmup
|
| 44 |
+
_partial_: true
|
| 45 |
+
min_lr: 1e-6
|
| 46 |
+
max_lr: ${model.optimizer.lr}
|
| 47 |
+
warmup_steps: 5000
|
| 48 |
+
|
| 49 |
+
architecture:
|
| 50 |
+
esm_model: ${model.esm_model}
|
| 51 |
+
|
| 52 |
+
processor:
|
| 53 |
+
scale: 16.0
|
| 54 |
+
ref_scale: 5.0
|
| 55 |
+
multiplicity: 16 # number of copies per GPU
|
config/experiment/train_plddt.yaml
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# @package _global_
|
| 2 |
+
|
| 3 |
+
# All parameters below will be merged with parameters from default configurations set above
|
| 4 |
+
# this allows you to overwrite only specified parameters
|
| 5 |
+
|
| 6 |
+
# Options for training:
|
| 7 |
+
# - /data: [pdb, pdb_sp, pdb_sp_afesm, pdb_sp_afesme]
|
| 8 |
+
# - /model/architecture:
|
| 9 |
+
# [foldingdit_100M, foldingdit_360M, foldingdit_700M,
|
| 10 |
+
# foldingdit_1.1B, foldingdit_1.6B, foldingdit_3B]
|
| 11 |
+
# - /trainer: [default, fsdp]
|
| 12 |
+
|
| 13 |
+
defaults:
|
| 14 |
+
- override /data: pdb
|
| 15 |
+
- override /model: simplefold
|
| 16 |
+
- override /model/architecture: foldingdit_100M
|
| 17 |
+
- override /model/sampler: euler_maruyama
|
| 18 |
+
- override /model/processor: protein_processor
|
| 19 |
+
- override /callbacks: default
|
| 20 |
+
- override /trainer: default
|
| 21 |
+
- override /logger: tensorboard
|
| 22 |
+
|
| 23 |
+
# load_ckpt_path: [PATH_TO_YOUR_CKPT] # uncomment to load a checkpoint
|
| 24 |
+
seed: 12345
|
| 25 |
+
|
| 26 |
+
trainer:
|
| 27 |
+
max_steps: 10000
|
| 28 |
+
val_check_interval: 1000 # this controls BOTH checkpoint steps and validation
|
| 29 |
+
accumulate_grad_batches: 1 # gradient accumulation
|
| 30 |
+
|
| 31 |
+
data:
|
| 32 |
+
batch_size: 8 # should be the same as the number of GPUs
|
| 33 |
+
num_workers: 16
|
| 34 |
+
|
| 35 |
+
model:
|
| 36 |
+
_target_: models.simplefold.simplefold.SimpleFold
|
| 37 |
+
ema_decay: 0.999
|
| 38 |
+
clip_grad_norm_val: 2.0
|
| 39 |
+
esm_model: "esm2_3B"
|
| 40 |
+
plddt_training: True
|
| 41 |
+
|
| 42 |
+
plddt_module:
|
| 43 |
+
_target_: models.simplefold.torch.confidence_module.ConfidenceModule
|
| 44 |
+
hidden_size: ${model.architecture.hidden_size}
|
| 45 |
+
num_plddt_bins: 50
|
| 46 |
+
transformer_blocks:
|
| 47 |
+
_target_: models.simplefold.torch.blocks.HomogenTrunk
|
| 48 |
+
depth: 4
|
| 49 |
+
block:
|
| 50 |
+
_target_: models.simplefold.torch.blocks.TransformerBlock
|
| 51 |
+
_partial_: true
|
| 52 |
+
hidden_size: ${model.architecture.hidden_size}
|
| 53 |
+
mlp_ratio: 4.0
|
| 54 |
+
use_swiglu: True # SwiGLU FFN
|
| 55 |
+
self_attention_layer:
|
| 56 |
+
_target_: models.simplefold.torch.layers.EfficientSelfAttentionLayer
|
| 57 |
+
_partial_: True
|
| 58 |
+
hidden_size: ${model.architecture.hidden_size}
|
| 59 |
+
num_heads: ${model.architecture.num_heads}
|
| 60 |
+
qk_norm: True
|
| 61 |
+
pos_embedder:
|
| 62 |
+
_target_: models.simplefold.torch.pos_embed.AxialRotaryPositionEncoding
|
| 63 |
+
in_dim: 4
|
| 64 |
+
embed_dim: ${model.architecture.hidden_size}
|
| 65 |
+
num_heads: ${model.architecture.num_heads}
|
| 66 |
+
base: 100.0
|
| 67 |
+
|
| 68 |
+
scheduler:
|
| 69 |
+
_target_: onescience.utils.simplefold.lr_scheduler.LinearWarmup
|
| 70 |
+
_partial_: true
|
| 71 |
+
min_lr: 1e-6
|
| 72 |
+
max_lr: ${model.optimizer.lr}
|
| 73 |
+
warmup_steps: 5000
|
| 74 |
+
|
| 75 |
+
architecture:
|
| 76 |
+
esm_model: ${model.esm_model}
|
| 77 |
+
|
| 78 |
+
sampler:
|
| 79 |
+
num_timesteps: 150
|
| 80 |
+
tau: 0.3
|
| 81 |
+
|
| 82 |
+
processor:
|
| 83 |
+
scale: 16.0
|
| 84 |
+
ref_scale: 5.0
|
| 85 |
+
multiplicity: 16 # number of copies per GPU
|
config/extras/default.yaml
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# disable python warnings if they annoy you
|
| 2 |
+
ignore_warnings: False
|
| 3 |
+
|
| 4 |
+
# pretty print config tree at the start of the run using Rich library
|
| 5 |
+
print_config: True
|
config/model/architecture/default.yaml
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
_target_: models.simplefold.torch.architecture.FoldingDiT
|
| 2 |
+
|
| 3 |
+
hidden_size: 768
|
| 4 |
+
num_heads: 12
|
| 5 |
+
atom_num_heads: 4
|
| 6 |
+
output_channels: 3
|
| 7 |
+
use_atom_mask: False
|
| 8 |
+
use_length_condition: True
|
| 9 |
+
esm_dropout_prob: 0.0
|
| 10 |
+
esm_model: esm2_3B
|
| 11 |
+
|
| 12 |
+
time_embedder:
|
| 13 |
+
_target_: models.simplefold.torch.layers.TimestepEmbedder
|
| 14 |
+
hidden_size: 768
|
| 15 |
+
|
| 16 |
+
aminoacid_pos_embedder:
|
| 17 |
+
_target_: models.simplefold.torch.pos_embed.AbsolutePositionEncoding
|
| 18 |
+
in_dim: 1
|
| 19 |
+
embed_dim: 768
|
| 20 |
+
include_input: True
|
| 21 |
+
|
| 22 |
+
pos_embedder:
|
| 23 |
+
_target_: models.simplefold.torch.pos_embed.FourierPositionEncoding
|
| 24 |
+
in_dim: 3
|
| 25 |
+
include_input: True
|
| 26 |
+
min_freq_log2: 0
|
| 27 |
+
max_freq_log2: 12
|
| 28 |
+
num_freqs: 128
|
| 29 |
+
log_sampling: True
|
| 30 |
+
|
| 31 |
+
trunk:
|
| 32 |
+
_target_: models.simplefold.torch.blocks.HomogenTrunk
|
| 33 |
+
depth: 8
|
| 34 |
+
block:
|
| 35 |
+
_target_: models.simplefold.torch.blocks.DiTBlock
|
| 36 |
+
_partial_: True
|
| 37 |
+
hidden_size: 768
|
| 38 |
+
mlp_ratio: 4.0
|
| 39 |
+
use_swiglu: True
|
| 40 |
+
self_attention_layer:
|
| 41 |
+
_target_: models.simplefold.torch.layers.EfficientSelfAttentionLayer
|
| 42 |
+
_partial_: True
|
| 43 |
+
hidden_size: 768
|
| 44 |
+
num_heads: 12
|
| 45 |
+
qk_norm: True
|
| 46 |
+
pos_embedder:
|
| 47 |
+
_target_: models.simplefold.torch.pos_embed.AxialRotaryPositionEncoding
|
| 48 |
+
in_dim: 4
|
| 49 |
+
embed_dim: 768
|
| 50 |
+
num_heads: 12
|
| 51 |
+
base: 100.0
|
| 52 |
+
|
| 53 |
+
atom_hidden_size_enc: 256
|
| 54 |
+
atom_n_queries_enc: 32
|
| 55 |
+
atom_n_keys_enc: 128
|
| 56 |
+
atom_encoder_transformer:
|
| 57 |
+
_target_: models.simplefold.torch.blocks.HomogenTrunk
|
| 58 |
+
depth: 1
|
| 59 |
+
block:
|
| 60 |
+
_target_: models.simplefold.torch.blocks.DiTBlock
|
| 61 |
+
_partial_: True
|
| 62 |
+
hidden_size: 256
|
| 63 |
+
mlp_ratio: 4.0
|
| 64 |
+
use_swiglu: True
|
| 65 |
+
self_attention_layer:
|
| 66 |
+
_target_: models.simplefold.torch.layers.EfficientSelfAttentionLayer
|
| 67 |
+
_partial_: True
|
| 68 |
+
hidden_size: 256
|
| 69 |
+
num_heads: 4
|
| 70 |
+
qk_norm: True
|
| 71 |
+
pos_embedder:
|
| 72 |
+
_target_: models.simplefold.torch.pos_embed.AxialRotaryPositionEncoding
|
| 73 |
+
in_dim: 4
|
| 74 |
+
embed_dim: 256
|
| 75 |
+
num_heads: 4
|
| 76 |
+
base: 100.0
|
| 77 |
+
|
| 78 |
+
atom_hidden_size_dec: 256
|
| 79 |
+
atom_n_queries_dec: 32
|
| 80 |
+
atom_n_keys_dec: 128
|
| 81 |
+
atom_decoder_transformer:
|
| 82 |
+
_target_: models.simplefold.torch.blocks.HomogenTrunk
|
| 83 |
+
depth: 1
|
| 84 |
+
block:
|
| 85 |
+
_target_: models.simplefold.torch.blocks.DiTBlock
|
| 86 |
+
_partial_: True
|
| 87 |
+
hidden_size: 256
|
| 88 |
+
mlp_ratio: 4.0
|
| 89 |
+
use_swiglu: True
|
| 90 |
+
self_attention_layer:
|
| 91 |
+
_target_: models.simplefold.torch.layers.EfficientSelfAttentionLayer
|
| 92 |
+
_partial_: True
|
| 93 |
+
hidden_size: 256
|
| 94 |
+
num_heads: 4
|
| 95 |
+
qk_norm: True
|
| 96 |
+
pos_embedder:
|
| 97 |
+
_target_: models.simplefold.torch.pos_embed.AxialRotaryPositionEncoding
|
| 98 |
+
in_dim: 4
|
| 99 |
+
embed_dim: 256
|
| 100 |
+
num_heads: 4
|
| 101 |
+
base: 100.0
|
config/model/architecture/foldingdit_1.6B.yaml
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
_target_: models.simplefold.torch.architecture.FoldingDiT
|
| 2 |
+
|
| 3 |
+
hidden_size: 1536
|
| 4 |
+
num_heads: 24
|
| 5 |
+
atom_num_heads: 8
|
| 6 |
+
output_channels: 3
|
| 7 |
+
use_atom_mask: False
|
| 8 |
+
use_length_condition: True
|
| 9 |
+
esm_dropout_prob: 0.0
|
| 10 |
+
esm_model: esm2_3B
|
| 11 |
+
|
| 12 |
+
time_embedder:
|
| 13 |
+
_target_: models.simplefold.torch.layers.TimestepEmbedder
|
| 14 |
+
hidden_size: 1536
|
| 15 |
+
aminoacid_pos_embedder:
|
| 16 |
+
_target_: models.simplefold.torch.pos_embed.AbsolutePositionEncoding
|
| 17 |
+
in_dim: 1
|
| 18 |
+
embed_dim: 1536
|
| 19 |
+
include_input: True
|
| 20 |
+
pos_embedder:
|
| 21 |
+
_target_: models.simplefold.torch.pos_embed.FourierPositionEncoding
|
| 22 |
+
in_dim: 3
|
| 23 |
+
include_input: True
|
| 24 |
+
min_freq_log2: 0
|
| 25 |
+
max_freq_log2: 12
|
| 26 |
+
num_freqs: 128
|
| 27 |
+
log_sampling: True
|
| 28 |
+
|
| 29 |
+
trunk:
|
| 30 |
+
_target_: models.simplefold.torch.blocks.HomogenTrunk
|
| 31 |
+
depth: 36
|
| 32 |
+
block:
|
| 33 |
+
_target_: models.simplefold.torch.blocks.DiTBlock
|
| 34 |
+
_partial_: True # because in the for loop we create a new module
|
| 35 |
+
hidden_size: 1536
|
| 36 |
+
mlp_ratio: 4.0
|
| 37 |
+
use_swiglu: True # SwiGLU FFN
|
| 38 |
+
self_attention_layer:
|
| 39 |
+
_target_: models.simplefold.torch.layers.EfficientSelfAttentionLayer
|
| 40 |
+
_partial_: True
|
| 41 |
+
hidden_size: 1536
|
| 42 |
+
num_heads: 24
|
| 43 |
+
qk_norm: True
|
| 44 |
+
pos_embedder:
|
| 45 |
+
_target_: models.simplefold.torch.pos_embed.AxialRotaryPositionEncoding
|
| 46 |
+
in_dim: 4
|
| 47 |
+
embed_dim: 1536
|
| 48 |
+
num_heads: 24
|
| 49 |
+
base: 100.0
|
| 50 |
+
|
| 51 |
+
atom_hidden_size_enc: 512
|
| 52 |
+
atom_n_queries_enc: 32
|
| 53 |
+
atom_n_keys_enc: 128
|
| 54 |
+
atom_encoder_transformer:
|
| 55 |
+
_target_: models.simplefold.torch.blocks.HomogenTrunk
|
| 56 |
+
depth: 3
|
| 57 |
+
block:
|
| 58 |
+
_target_: models.simplefold.torch.blocks.DiTBlock
|
| 59 |
+
_partial_: True # because in the for loop we create a new module
|
| 60 |
+
hidden_size: 512
|
| 61 |
+
mlp_ratio: 4.0
|
| 62 |
+
use_swiglu: True # SwiGLU FFN
|
| 63 |
+
self_attention_layer:
|
| 64 |
+
_target_: models.simplefold.torch.layers.EfficientSelfAttentionLayer
|
| 65 |
+
_partial_: True
|
| 66 |
+
hidden_size: 512
|
| 67 |
+
num_heads: 8
|
| 68 |
+
qk_norm: True
|
| 69 |
+
pos_embedder:
|
| 70 |
+
_target_: models.simplefold.torch.pos_embed.AxialRotaryPositionEncoding
|
| 71 |
+
in_dim: 4
|
| 72 |
+
embed_dim: 512
|
| 73 |
+
num_heads: 8
|
| 74 |
+
base: 100.0
|
| 75 |
+
|
| 76 |
+
atom_hidden_size_dec: 512
|
| 77 |
+
atom_n_queries_dec: 32
|
| 78 |
+
atom_n_keys_dec: 128
|
| 79 |
+
atom_decoder_transformer:
|
| 80 |
+
_target_: models.simplefold.torch.blocks.HomogenTrunk
|
| 81 |
+
depth: 3
|
| 82 |
+
block:
|
| 83 |
+
_target_: models.simplefold.torch.blocks.DiTBlock
|
| 84 |
+
_partial_: True # because in the for loop we create a new module
|
| 85 |
+
hidden_size: 512
|
| 86 |
+
mlp_ratio: 4.0
|
| 87 |
+
use_swiglu: True # SwiGLU FFN
|
| 88 |
+
self_attention_layer:
|
| 89 |
+
_target_: models.simplefold.torch.layers.EfficientSelfAttentionLayer
|
| 90 |
+
_partial_: True
|
| 91 |
+
hidden_size: 512
|
| 92 |
+
num_heads: 8
|
| 93 |
+
qk_norm: True
|
| 94 |
+
pos_embedder:
|
| 95 |
+
_target_: models.simplefold.torch.pos_embed.AxialRotaryPositionEncoding
|
| 96 |
+
in_dim: 4
|
| 97 |
+
embed_dim: 512
|
| 98 |
+
num_heads: 8
|
| 99 |
+
base: 100.0
|
config/model/architecture/plddt_module.yaml
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
_target_: models.simplefold.torch.confidence_module.ConfidenceModule
|
| 2 |
+
hidden_size: 1536
|
| 3 |
+
num_plddt_bins: 50
|
| 4 |
+
transformer_blocks:
|
| 5 |
+
_target_: models.simplefold.torch.blocks.HomogenTrunk
|
| 6 |
+
depth: 4
|
| 7 |
+
block:
|
| 8 |
+
_target_: models.simplefold.torch.blocks.TransformerBlock
|
| 9 |
+
_partial_: true
|
| 10 |
+
hidden_size: 1536
|
| 11 |
+
mlp_ratio: 4.0
|
| 12 |
+
use_swiglu: True # SwiGLU FFN
|
| 13 |
+
self_attention_layer:
|
| 14 |
+
_target_: models.simplefold.torch.layers.EfficientSelfAttentionLayer
|
| 15 |
+
_partial_: True
|
| 16 |
+
hidden_size: 1536
|
| 17 |
+
num_heads: 24
|
| 18 |
+
qk_norm: True
|
| 19 |
+
pos_embedder:
|
| 20 |
+
_target_: models.simplefold.torch.pos_embed.AxialRotaryPositionEncoding
|
| 21 |
+
in_dim: 4
|
| 22 |
+
embed_dim: 1536
|
| 23 |
+
num_heads: 24
|
| 24 |
+
base: 100.0
|
config/model/default.yaml
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
_target_: models.simplefold.simplefold.SimpleFold
|
| 2 |
+
ema_decay: 0.999
|
| 3 |
+
clip_grad_norm_val: 2.0
|
| 4 |
+
use_rigid_align: True
|
| 5 |
+
smooth_lddt_loss_weight: 1.0
|
| 6 |
+
lddt_cutoff: 15.0
|
| 7 |
+
esm_model: "esm2_3B"
|
| 8 |
+
lddt_weight_schedule: False
|
| 9 |
+
sample_dir: ${paths.sample_dir}
|
| 10 |
+
|
| 11 |
+
architecture:
|
| 12 |
+
esm_model: ${model.esm_model}
|
| 13 |
+
|
| 14 |
+
path:
|
| 15 |
+
_target_: models.simplefold.flow.LinearPath
|
| 16 |
+
|
| 17 |
+
loss:
|
| 18 |
+
_target_: torch.nn.MSELoss
|
| 19 |
+
reduction: 'none'
|
| 20 |
+
reduce: False
|
| 21 |
+
|
| 22 |
+
optimizer:
|
| 23 |
+
_target_: torch.optim.AdamW
|
| 24 |
+
_partial_: true
|
| 25 |
+
lr: 1e-4
|
| 26 |
+
weight_decay: 0.0
|
| 27 |
+
max_steps: ???
|
| 28 |
+
|
| 29 |
+
scheduler:
|
| 30 |
+
_target_: onescience.utils.simplefold.lr_scheduler.LinearWarmup
|
| 31 |
+
_partial_: true
|
| 32 |
+
min_lr: 1e-6
|
| 33 |
+
max_lr: ${model.optimizer.lr}
|
| 34 |
+
warmup_steps: 10
|
| 35 |
+
|
| 36 |
+
processor:
|
| 37 |
+
scale: 16.0
|
| 38 |
+
ref_scale: 5.0
|
| 39 |
+
multiplicity: 16
|
config/model/processor/default.yaml
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
_target_: onescience.datapipes.simplefold.processor.protein_processor.ProteinDataProcessor
|
| 2 |
+
_partial_: True
|
config/model/processor/protein_processor.yaml
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
_target_: onescience.datapipes.simplefold.processor.protein_processor.ProteinDataProcessor
|
| 2 |
+
_partial_: True
|
config/model/simplefold.yaml
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
_target_: models.simplefold.simplefold.SimpleFold
|
| 2 |
+
ema_decay: 0.999
|
| 3 |
+
clip_grad_norm_val: 2.0
|
| 4 |
+
use_rigid_align: True
|
| 5 |
+
smooth_lddt_loss_weight: 1.0
|
| 6 |
+
lddt_cutoff: 15.0
|
| 7 |
+
esm_model: "esm2_3B"
|
| 8 |
+
lddt_weight_schedule: False
|
| 9 |
+
sample_dir: ${paths.sample_dir}
|
| 10 |
+
|
| 11 |
+
architecture:
|
| 12 |
+
esm_model: ${model.esm_model}
|
| 13 |
+
|
| 14 |
+
path:
|
| 15 |
+
_target_: models.simplefold.flow.LinearPath
|
| 16 |
+
|
| 17 |
+
loss:
|
| 18 |
+
_target_: torch.nn.MSELoss
|
| 19 |
+
reduction: 'none'
|
| 20 |
+
reduce: False
|
| 21 |
+
|
| 22 |
+
optimizer:
|
| 23 |
+
_target_: torch.optim.AdamW
|
| 24 |
+
_partial_: true
|
| 25 |
+
lr: 1e-4
|
| 26 |
+
weight_decay: 0.0
|
| 27 |
+
max_steps: ???
|
| 28 |
+
|
| 29 |
+
scheduler:
|
| 30 |
+
_target_: onescience.utils.simplefold.lr_scheduler.LinearWarmup
|
| 31 |
+
_partial_: true
|
| 32 |
+
min_lr: 1e-6
|
| 33 |
+
max_lr: ${model.optimizer.lr}
|
| 34 |
+
warmup_steps: 10
|
| 35 |
+
|
| 36 |
+
processor:
|
| 37 |
+
scale: 16.0
|
| 38 |
+
ref_scale: 5.0
|
| 39 |
+
multiplicity: 16
|
config/trainer/fsdp.yaml
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
_target_: lightning.pytorch.trainer.Trainer
|
| 2 |
+
|
| 3 |
+
default_root_dir: ${paths.output_dir}
|
| 4 |
+
|
| 5 |
+
# set True to to ensure deterministic results
|
| 6 |
+
# makes training slower but gives more reproducibility than just setting seeds
|
| 7 |
+
deterministic: False
|
| 8 |
+
|
| 9 |
+
accelerator: gpu
|
| 10 |
+
devices: auto
|
| 11 |
+
num_nodes: 1
|
| 12 |
+
min_epochs: 1 # prevents early stopping
|
| 13 |
+
max_steps: 100000
|
| 14 |
+
precision: bf16-mixed
|
| 15 |
+
val_check_interval: 5000
|
| 16 |
+
check_val_every_n_epoch: null
|
| 17 |
+
num_sanity_val_steps: 0
|
| 18 |
+
limit_val_batches: 0.0
|
models/__pycache__/__init__.cpython-310.pyc
ADDED
|
Binary file (188 Bytes). View file
|
|
|
models/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (206 Bytes). View file
|
|
|
models/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
|
models/esm/__pycache__/__init__.cpython-311.pyc
ADDED
|
Binary file (679 Bytes). View file
|
|
|
models/esm/__pycache__/esm2.cpython-310.pyc
ADDED
|
Binary file (3.46 kB). View file
|
|
|
models/esm/__pycache__/msa_transformer.cpython-310.pyc
ADDED
|
Binary file (5.5 kB). View file
|
|
|
models/esm/__pycache__/version.cpython-310.pyc
ADDED
|
Binary file (139 Bytes). View file
|
|
|
models/esm/__pycache__/version.cpython-311.pyc
ADDED
|
Binary file (191 Bytes). View file
|
|
|
models/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"]
|
models/esm/esmfold/__init__.py
ADDED
|
File without changes
|
models/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 onescience.models.esm as esm
|
| 15 |
+
from onescience.models.esm import Alphabet
|
| 16 |
+
from onescience.models.esm.esmfold.v1.categorical_mixture import categorical_lddt
|
| 17 |
+
from onescience.models.esm.esmfold.v1.misc import (
|
| 18 |
+
batch_encode_sequences,
|
| 19 |
+
collate_dense_tensors,
|
| 20 |
+
output_to_pdb,
|
| 21 |
+
)
|
| 22 |
+
from onescience.models.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 |
+
modules.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
|
models/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
|
models/esm/pretrained.py
ADDED
|
@@ -0,0 +1,545 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 onescience.models.esm as esm
|
| 15 |
+
from onescience.datapipes.esm import Alphabet
|
| 16 |
+
from models.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 |
+
raise FileNotFoundError(
|
| 34 |
+
"Remote ESM download is disabled in the packaged SimpleFold runtime. "
|
| 35 |
+
"Use load_model_and_alphabet_local() with a file under weight/esm_models."
|
| 36 |
+
)
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def load_regression_hub(model_name):
|
| 40 |
+
raise FileNotFoundError(
|
| 41 |
+
f"Remote ESM regression download is disabled: {model_name}. "
|
| 42 |
+
"Place the contact-regression file under weight/esm_models."
|
| 43 |
+
)
|
| 44 |
+
|
| 45 |
+
|
| 46 |
+
def _download_model_and_regression_data(model_name):
|
| 47 |
+
raise FileNotFoundError(
|
| 48 |
+
f"Remote ESM download is disabled: {model_name}. "
|
| 49 |
+
"Place the required ESM files under weight/esm_models."
|
| 50 |
+
)
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
def load_model_and_alphabet_hub(model_name):
|
| 54 |
+
raise FileNotFoundError(
|
| 55 |
+
f"Remote ESM download is disabled in the packaged SimpleFold runtime: {model_name}. "
|
| 56 |
+
"Place the required ESM .pt file and contact-regression file under weight/esm_models."
|
| 57 |
+
)
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
def load_model_and_alphabet_local(model_location):
|
| 61 |
+
"""Load from local path. The regression weights need to be co-located"""
|
| 62 |
+
model_location = Path(model_location)
|
| 63 |
+
model_data = torch.load(str(model_location), map_location="cpu")
|
| 64 |
+
model_name = model_location.stem
|
| 65 |
+
if _has_regression_weights(model_name):
|
| 66 |
+
regression_location = str(model_location.with_suffix("")) + "-contact-regression.pt"
|
| 67 |
+
regression_data = torch.load(regression_location, map_location="cpu")
|
| 68 |
+
else:
|
| 69 |
+
regression_data = None
|
| 70 |
+
return load_model_and_alphabet_core(model_name, model_data, regression_data)
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
def has_emb_layer_norm_before(model_state):
|
| 74 |
+
"""Determine whether layer norm needs to be applied before the encoder"""
|
| 75 |
+
return any(k.startswith("emb_layer_norm_before") for k, param in model_state.items())
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
def _load_model_and_alphabet_core_v1(model_data):
|
| 79 |
+
import models.esm as esm # since esm.inverse_folding is imported below, you actually have to re-import esm here
|
| 80 |
+
|
| 81 |
+
alphabet = esm.Alphabet.from_architecture(model_data["args"].arch)
|
| 82 |
+
|
| 83 |
+
if model_data["args"].arch == "roberta_large":
|
| 84 |
+
# upgrade state dict
|
| 85 |
+
pra = lambda s: "".join(s.split("encoder_")[1:] if "encoder" in s else s)
|
| 86 |
+
prs1 = lambda s: "".join(s.split("encoder.")[1:] if "encoder" in s else s)
|
| 87 |
+
prs2 = lambda s: "".join(
|
| 88 |
+
s.split("sentence_encoder.")[1:] if "sentence_encoder" in s else s
|
| 89 |
+
)
|
| 90 |
+
model_args = {pra(arg[0]): arg[1] for arg in vars(model_data["args"]).items()}
|
| 91 |
+
model_state = {prs1(prs2(arg[0])): arg[1] for arg in model_data["model"].items()}
|
| 92 |
+
model_state["embed_tokens.weight"][alphabet.mask_idx].zero_() # For token drop
|
| 93 |
+
model_args["emb_layer_norm_before"] = has_emb_layer_norm_before(model_state)
|
| 94 |
+
model_type = esm.ProteinBertModel
|
| 95 |
+
|
| 96 |
+
elif model_data["args"].arch == "protein_bert_base":
|
| 97 |
+
|
| 98 |
+
# upgrade state dict
|
| 99 |
+
pra = lambda s: "".join(s.split("decoder_")[1:] if "decoder" in s else s)
|
| 100 |
+
prs = lambda s: "".join(s.split("decoder.")[1:] if "decoder" in s else s)
|
| 101 |
+
model_args = {pra(arg[0]): arg[1] for arg in vars(model_data["args"]).items()}
|
| 102 |
+
model_state = {prs(arg[0]): arg[1] for arg in model_data["model"].items()}
|
| 103 |
+
model_type = esm.ProteinBertModel
|
| 104 |
+
elif model_data["args"].arch == "msa_transformer":
|
| 105 |
+
|
| 106 |
+
# upgrade state dict
|
| 107 |
+
pra = lambda s: "".join(s.split("encoder_")[1:] if "encoder" in s else s)
|
| 108 |
+
prs1 = lambda s: "".join(s.split("encoder.")[1:] if "encoder" in s else s)
|
| 109 |
+
prs2 = lambda s: "".join(
|
| 110 |
+
s.split("sentence_encoder.")[1:] if "sentence_encoder" in s else s
|
| 111 |
+
)
|
| 112 |
+
prs3 = lambda s: s.replace("row", "column") if "row" in s else s.replace("column", "row")
|
| 113 |
+
model_args = {pra(arg[0]): arg[1] for arg in vars(model_data["args"]).items()}
|
| 114 |
+
model_state = {prs1(prs2(prs3(arg[0]))): arg[1] for arg in model_data["model"].items()}
|
| 115 |
+
if model_args.get("embed_positions_msa", False):
|
| 116 |
+
emb_dim = model_state["msa_position_embedding"].size(-1)
|
| 117 |
+
model_args["embed_positions_msa_dim"] = emb_dim # initial release, bug: emb_dim==1
|
| 118 |
+
|
| 119 |
+
model_type = esm.MSATransformer
|
| 120 |
+
|
| 121 |
+
elif "invariant_gvp" in model_data["args"].arch:
|
| 122 |
+
import models.esm.inverse_folding
|
| 123 |
+
|
| 124 |
+
model_type = esm.inverse_folding.gvp_transformer.GVPTransformerModel
|
| 125 |
+
model_args = vars(model_data["args"]) # convert Namespace -> dict
|
| 126 |
+
|
| 127 |
+
def update_name(s):
|
| 128 |
+
# Map the module names in checkpoints trained with internal code to
|
| 129 |
+
# the updated module names in open source code
|
| 130 |
+
s = s.replace("W_v", "embed_graph.embed_node")
|
| 131 |
+
s = s.replace("W_e", "embed_graph.embed_edge")
|
| 132 |
+
s = s.replace("embed_scores.0", "embed_confidence")
|
| 133 |
+
s = s.replace("embed_score.", "embed_graph.embed_confidence.")
|
| 134 |
+
s = s.replace("seq_logits_projection.", "")
|
| 135 |
+
s = s.replace("embed_ingraham_features", "embed_dihedrals")
|
| 136 |
+
s = s.replace("embed_gvp_in_local_frame.0", "embed_gvp_output")
|
| 137 |
+
s = s.replace("embed_features_in_local_frame.0", "embed_gvp_input_features")
|
| 138 |
+
return s
|
| 139 |
+
|
| 140 |
+
model_state = {
|
| 141 |
+
update_name(sname): svalue
|
| 142 |
+
for sname, svalue in model_data["model"].items()
|
| 143 |
+
if "version" not in sname
|
| 144 |
+
}
|
| 145 |
+
|
| 146 |
+
else:
|
| 147 |
+
raise ValueError("Unknown architecture selected")
|
| 148 |
+
|
| 149 |
+
model = model_type(
|
| 150 |
+
Namespace(**model_args),
|
| 151 |
+
alphabet,
|
| 152 |
+
)
|
| 153 |
+
|
| 154 |
+
return model, alphabet, model_state
|
| 155 |
+
|
| 156 |
+
|
| 157 |
+
def _load_model_and_alphabet_core_v2(model_data):
|
| 158 |
+
def upgrade_state_dict(state_dict):
|
| 159 |
+
"""Removes prefixes 'model.encoder.sentence_encoder.' and 'model.encoder.'."""
|
| 160 |
+
prefixes = ["encoder.sentence_encoder.", "encoder."]
|
| 161 |
+
pattern = re.compile("^" + "|".join(prefixes))
|
| 162 |
+
state_dict = {pattern.sub("", name): param for name, param in state_dict.items()}
|
| 163 |
+
return state_dict
|
| 164 |
+
|
| 165 |
+
cfg = model_data["cfg"]["model"]
|
| 166 |
+
state_dict = model_data["model"]
|
| 167 |
+
state_dict = upgrade_state_dict(state_dict)
|
| 168 |
+
alphabet = Alphabet.from_architecture("ESM-1b")
|
| 169 |
+
model = ESM2(
|
| 170 |
+
num_layers=cfg.encoder_layers,
|
| 171 |
+
embed_dim=cfg.encoder_embed_dim,
|
| 172 |
+
attention_heads=cfg.encoder_attention_heads,
|
| 173 |
+
alphabet=alphabet,
|
| 174 |
+
token_dropout=cfg.token_dropout,
|
| 175 |
+
)
|
| 176 |
+
return model, alphabet, state_dict
|
| 177 |
+
|
| 178 |
+
|
| 179 |
+
def load_model_and_alphabet_core(model_name, model_data, regression_data=None):
|
| 180 |
+
if regression_data is not None:
|
| 181 |
+
model_data["model"].update(regression_data["model"])
|
| 182 |
+
|
| 183 |
+
if model_name.startswith("esm2"):
|
| 184 |
+
model, alphabet, model_state = _load_model_and_alphabet_core_v2(model_data)
|
| 185 |
+
else:
|
| 186 |
+
model, alphabet, model_state = _load_model_and_alphabet_core_v1(model_data)
|
| 187 |
+
|
| 188 |
+
expected_keys = set(model.state_dict().keys())
|
| 189 |
+
found_keys = set(model_state.keys())
|
| 190 |
+
|
| 191 |
+
if regression_data is None:
|
| 192 |
+
expected_missing = {"contact_head.regression.weight", "contact_head.regression.bias"}
|
| 193 |
+
error_msgs = []
|
| 194 |
+
missing = (expected_keys - found_keys) - expected_missing
|
| 195 |
+
if missing:
|
| 196 |
+
error_msgs.append(f"Missing key(s) in state_dict: {missing}.")
|
| 197 |
+
unexpected = found_keys - expected_keys
|
| 198 |
+
if unexpected:
|
| 199 |
+
error_msgs.append(f"Unexpected key(s) in state_dict: {unexpected}.")
|
| 200 |
+
|
| 201 |
+
if error_msgs:
|
| 202 |
+
raise RuntimeError(
|
| 203 |
+
"Error(s) in loading state_dict for {}:\n\t{}".format(
|
| 204 |
+
model.__class__.__name__, "\n\t".join(error_msgs)
|
| 205 |
+
)
|
| 206 |
+
)
|
| 207 |
+
if expected_missing - found_keys:
|
| 208 |
+
warnings.warn(
|
| 209 |
+
"Regression weights not found, predicting contacts will not produce correct results."
|
| 210 |
+
)
|
| 211 |
+
|
| 212 |
+
model.load_state_dict(model_state, strict=regression_data is not None)
|
| 213 |
+
|
| 214 |
+
return model, alphabet
|
| 215 |
+
|
| 216 |
+
|
| 217 |
+
def esm1_t34_670M_UR50S():
|
| 218 |
+
"""34 layer transformer model with 670M params, trained on Uniref50 Sparse.
|
| 219 |
+
|
| 220 |
+
Returns a tuple of (Model, Alphabet).
|
| 221 |
+
"""
|
| 222 |
+
return load_model_and_alphabet_hub("esm1_t34_670M_UR50S")
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
def esm1_t34_670M_UR50D():
|
| 226 |
+
"""34 layer transformer model with 670M params, trained on Uniref50 Dense.
|
| 227 |
+
|
| 228 |
+
Returns a tuple of (Model, Alphabet).
|
| 229 |
+
"""
|
| 230 |
+
return load_model_and_alphabet_hub("esm1_t34_670M_UR50D")
|
| 231 |
+
|
| 232 |
+
|
| 233 |
+
def esm1_t34_670M_UR100():
|
| 234 |
+
"""34 layer transformer model with 670M params, trained on Uniref100.
|
| 235 |
+
|
| 236 |
+
Returns a tuple of (Model, Alphabet).
|
| 237 |
+
"""
|
| 238 |
+
return load_model_and_alphabet_hub("esm1_t34_670M_UR100")
|
| 239 |
+
|
| 240 |
+
|
| 241 |
+
def esm1_t12_85M_UR50S():
|
| 242 |
+
"""12 layer transformer model with 85M params, trained on Uniref50 Sparse.
|
| 243 |
+
|
| 244 |
+
Returns a tuple of (Model, Alphabet).
|
| 245 |
+
"""
|
| 246 |
+
return load_model_and_alphabet_hub("esm1_t12_85M_UR50S")
|
| 247 |
+
|
| 248 |
+
|
| 249 |
+
def esm1_t6_43M_UR50S():
|
| 250 |
+
"""6 layer transformer model with 43M params, trained on Uniref50 Sparse.
|
| 251 |
+
|
| 252 |
+
Returns a tuple of (Model, Alphabet).
|
| 253 |
+
"""
|
| 254 |
+
return load_model_and_alphabet_hub("esm1_t6_43M_UR50S")
|
| 255 |
+
|
| 256 |
+
|
| 257 |
+
def esm1b_t33_650M_UR50S():
|
| 258 |
+
"""33 layer transformer model with 650M params, trained on Uniref50 Sparse.
|
| 259 |
+
This is our best performing model, which will be described in a future publication.
|
| 260 |
+
|
| 261 |
+
Returns a tuple of (Model, Alphabet).
|
| 262 |
+
"""
|
| 263 |
+
return load_model_and_alphabet_hub("esm1b_t33_650M_UR50S")
|
| 264 |
+
|
| 265 |
+
|
| 266 |
+
def esm_msa1_t12_100M_UR50S():
|
| 267 |
+
warnings.warn(
|
| 268 |
+
"This model had a minor bug in the positional embeddings, "
|
| 269 |
+
"please use ESM-MSA-1b: esm.pretrained.esm_msa1b_t12_100M_UR50S()",
|
| 270 |
+
)
|
| 271 |
+
return load_model_and_alphabet_hub("esm_msa1_t12_100M_UR50S")
|
| 272 |
+
|
| 273 |
+
|
| 274 |
+
def esm_msa1b_t12_100M_UR50S():
|
| 275 |
+
return load_model_and_alphabet_hub("esm_msa1b_t12_100M_UR50S")
|
| 276 |
+
|
| 277 |
+
|
| 278 |
+
def esm1v_t33_650M_UR90S():
|
| 279 |
+
"""33 layer transformer model with 650M params, trained on Uniref90.
|
| 280 |
+
This is model 1 of a 5 model ensemble.
|
| 281 |
+
|
| 282 |
+
Returns a tuple of (Model, Alphabet).
|
| 283 |
+
"""
|
| 284 |
+
return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_1")
|
| 285 |
+
|
| 286 |
+
|
| 287 |
+
def esm1v_t33_650M_UR90S_1():
|
| 288 |
+
"""33 layer transformer model with 650M params, trained on Uniref90.
|
| 289 |
+
This is model 1 of a 5 model ensemble.
|
| 290 |
+
|
| 291 |
+
Returns a tuple of (Model, Alphabet).
|
| 292 |
+
"""
|
| 293 |
+
return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_1")
|
| 294 |
+
|
| 295 |
+
|
| 296 |
+
def esm1v_t33_650M_UR90S_2():
|
| 297 |
+
"""33 layer transformer model with 650M params, trained on Uniref90.
|
| 298 |
+
This is model 2 of a 5 model ensemble.
|
| 299 |
+
|
| 300 |
+
Returns a tuple of (Model, Alphabet).
|
| 301 |
+
"""
|
| 302 |
+
return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_2")
|
| 303 |
+
|
| 304 |
+
|
| 305 |
+
def esm1v_t33_650M_UR90S_3():
|
| 306 |
+
"""33 layer transformer model with 650M params, trained on Uniref90.
|
| 307 |
+
This is model 3 of a 5 model ensemble.
|
| 308 |
+
|
| 309 |
+
Returns a tuple of (Model, Alphabet).
|
| 310 |
+
"""
|
| 311 |
+
return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_3")
|
| 312 |
+
|
| 313 |
+
|
| 314 |
+
def esm1v_t33_650M_UR90S_4():
|
| 315 |
+
"""33 layer transformer model with 650M params, trained on Uniref90.
|
| 316 |
+
This is model 4 of a 5 model ensemble.
|
| 317 |
+
|
| 318 |
+
Returns a tuple of (Model, Alphabet).
|
| 319 |
+
"""
|
| 320 |
+
return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_4")
|
| 321 |
+
|
| 322 |
+
|
| 323 |
+
def esm1v_t33_650M_UR90S_5():
|
| 324 |
+
"""33 layer transformer model with 650M params, trained on Uniref90.
|
| 325 |
+
This is model 5 of a 5 model ensemble.
|
| 326 |
+
|
| 327 |
+
Returns a tuple of (Model, Alphabet).
|
| 328 |
+
"""
|
| 329 |
+
return load_model_and_alphabet_hub("esm1v_t33_650M_UR90S_5")
|
| 330 |
+
|
| 331 |
+
|
| 332 |
+
def esm_if1_gvp4_t16_142M_UR50():
|
| 333 |
+
"""Inverse folding model with 142M params, with 4 GVP-GNN layers, 8
|
| 334 |
+
Transformer encoder layers, and 8 Transformer decoder layers, trained on
|
| 335 |
+
CATH structures and 12 million alphafold2 predicted structures from UniRef50
|
| 336 |
+
sequences.
|
| 337 |
+
|
| 338 |
+
Returns a tuple of (Model, Alphabet).
|
| 339 |
+
"""
|
| 340 |
+
return load_model_and_alphabet_hub("esm_if1_gvp4_t16_142M_UR50")
|
| 341 |
+
|
| 342 |
+
|
| 343 |
+
def esm2_t6_8M_UR50D():
|
| 344 |
+
"""6 layer ESM-2 model with 8M params, trained on UniRef50.
|
| 345 |
+
|
| 346 |
+
Returns a tuple of (Model, Alphabet).
|
| 347 |
+
"""
|
| 348 |
+
return load_model_and_alphabet_hub("esm2_t6_8M_UR50D")
|
| 349 |
+
|
| 350 |
+
|
| 351 |
+
def esm2_t12_35M_UR50D():
|
| 352 |
+
"""12 layer ESM-2 model with 35M params, trained on UniRef50.
|
| 353 |
+
|
| 354 |
+
Returns a tuple of (Model, Alphabet).
|
| 355 |
+
"""
|
| 356 |
+
return load_model_and_alphabet_hub("esm2_t12_35M_UR50D")
|
| 357 |
+
|
| 358 |
+
|
| 359 |
+
def esm2_t30_150M_UR50D():
|
| 360 |
+
"""30 layer ESM-2 model with 150M params, trained on UniRef50.
|
| 361 |
+
|
| 362 |
+
Returns a tuple of (Model, Alphabet).
|
| 363 |
+
"""
|
| 364 |
+
return load_model_and_alphabet_hub("esm2_t30_150M_UR50D")
|
| 365 |
+
|
| 366 |
+
|
| 367 |
+
def esm2_t33_650M_UR50D():
|
| 368 |
+
"""33 layer ESM-2 model with 650M params, trained on UniRef50.
|
| 369 |
+
|
| 370 |
+
Returns a tuple of (Model, Alphabet).
|
| 371 |
+
"""
|
| 372 |
+
return load_model_and_alphabet_hub("esm2_t33_650M_UR50D")
|
| 373 |
+
|
| 374 |
+
|
| 375 |
+
def esm2_t36_3B_UR50D():
|
| 376 |
+
"""36 layer ESM-2 model with 3B params, trained on UniRef50.
|
| 377 |
+
|
| 378 |
+
Returns a tuple of (Model, Alphabet).
|
| 379 |
+
"""
|
| 380 |
+
return load_model_and_alphabet_hub("esm2_t36_3B_UR50D")
|
| 381 |
+
|
| 382 |
+
|
| 383 |
+
def esm2_t48_15B_UR50D():
|
| 384 |
+
"""48 layer ESM-2 model with 15B params, trained on UniRef50.
|
| 385 |
+
If you have OOM while loading this model, please refer to README
|
| 386 |
+
on how to employ FSDP and ZeRO CPU offloading
|
| 387 |
+
|
| 388 |
+
Returns a tuple of (Model, Alphabet).
|
| 389 |
+
"""
|
| 390 |
+
return load_model_and_alphabet_hub("esm2_t48_15B_UR50D")
|
| 391 |
+
|
| 392 |
+
|
| 393 |
+
def esmfold_v0():
|
| 394 |
+
"""
|
| 395 |
+
ESMFold v0 model with 3B ESM-2, 48 folding blocks.
|
| 396 |
+
This version was used for the paper (Lin et al, 2022). It was trained
|
| 397 |
+
on all PDB chains until 2020-05, to ensure temporal holdout with CASP14
|
| 398 |
+
and the CAMEO validation and test set reported there.
|
| 399 |
+
"""
|
| 400 |
+
import models.esm.esmfold.v1.pretrained
|
| 401 |
+
return esm.esmfold.v1.pretrained.esmfold_v0()
|
| 402 |
+
|
| 403 |
+
|
| 404 |
+
def esmfold_v1():
|
| 405 |
+
"""
|
| 406 |
+
ESMFold v1 model using 3B ESM-2, 48 folding blocks.
|
| 407 |
+
ESMFold provides fast high accuracy atomic level structure prediction
|
| 408 |
+
directly from the individual sequence of a protein. ESMFold uses the ESM2
|
| 409 |
+
protein language model to extract meaningful representations from the
|
| 410 |
+
protein sequence.
|
| 411 |
+
"""
|
| 412 |
+
import models.esm.esmfold.v1.pretrained
|
| 413 |
+
return esm.esmfold.v1.pretrained.esmfold_v1()
|
| 414 |
+
|
| 415 |
+
def esmfold_structure_module_only_8M():
|
| 416 |
+
"""
|
| 417 |
+
ESMFold baseline model using 8M ESM-2, 0 folding blocks.
|
| 418 |
+
ESM-2 here is trained out to 500K updates.
|
| 419 |
+
This is a model designed to test the capabilities of the language model
|
| 420 |
+
when ablated for number of parameters in the language model.
|
| 421 |
+
See table S1 in (Lin et al, 2022).
|
| 422 |
+
"""
|
| 423 |
+
import models.esm.esmfold.v1.pretrained
|
| 424 |
+
return esm.esmfold.v1.pretrained.esmfold_structure_module_only_8M()
|
| 425 |
+
|
| 426 |
+
|
| 427 |
+
def esmfold_structure_module_only_8M_270K():
|
| 428 |
+
"""
|
| 429 |
+
ESMFold baseline model using 8M ESM-2, 0 folding blocks.
|
| 430 |
+
ESM-2 here is trained out to 270K updates.
|
| 431 |
+
This is a model designed to test the capabilities of the language model
|
| 432 |
+
when ablated for number of parameters in the language model.
|
| 433 |
+
See table S1 in (Lin et al, 2022).
|
| 434 |
+
"""
|
| 435 |
+
import models.esm.esmfold.v1.pretrained
|
| 436 |
+
return esm.esmfold.v1.pretrained.esmfold_structure_module_only_8M_270K()
|
| 437 |
+
|
| 438 |
+
|
| 439 |
+
def esmfold_structure_module_only_35M():
|
| 440 |
+
"""
|
| 441 |
+
ESMFold baseline model using 35M ESM-2, 0 folding blocks.
|
| 442 |
+
ESM-2 here is trained out to 500K updates.
|
| 443 |
+
This is a model designed to test the capabilities of the language model
|
| 444 |
+
when ablated for number of parameters in the language model.
|
| 445 |
+
See table S1 in (Lin et al, 2022).
|
| 446 |
+
"""
|
| 447 |
+
import models.esm.esmfold.v1.pretrained
|
| 448 |
+
return esm.esmfold.v1.pretrained.esmfold_structure_module_only_35M()
|
| 449 |
+
|
| 450 |
+
|
| 451 |
+
def esmfold_structure_module_only_35M_270K():
|
| 452 |
+
"""
|
| 453 |
+
ESMFold baseline model using 35M ESM-2, 0 folding blocks.
|
| 454 |
+
ESM-2 here is trained out to 270K updates.
|
| 455 |
+
This is a model designed to test the capabilities of the language model
|
| 456 |
+
when ablated for number of parameters in the language model.
|
| 457 |
+
See table S1 in (Lin et al, 2022).
|
| 458 |
+
"""
|
| 459 |
+
import models.esm.esmfold.v1.pretrained
|
| 460 |
+
return esm.esmfold.v1.pretrained.esmfold_structure_module_only_35M_270K()
|
| 461 |
+
|
| 462 |
+
|
| 463 |
+
def esmfold_structure_module_only_150M():
|
| 464 |
+
"""
|
| 465 |
+
ESMFold baseline model using 150M ESM-2, 0 folding blocks.
|
| 466 |
+
ESM-2 here is trained out to 500K updates.
|
| 467 |
+
This is a model designed to test the capabilities of the language model
|
| 468 |
+
when ablated for number of parameters in the language model.
|
| 469 |
+
See table S1 in (Lin et al, 2022).
|
| 470 |
+
"""
|
| 471 |
+
import models.esm.esmfold.v1.pretrained
|
| 472 |
+
return esm.esmfold.v1.pretrained.esmfold_structure_module_only_150M()
|
| 473 |
+
|
| 474 |
+
|
| 475 |
+
def esmfold_structure_module_only_150M_270K():
|
| 476 |
+
"""
|
| 477 |
+
ESMFold baseline model using 150M ESM-2, 0 folding blocks.
|
| 478 |
+
ESM-2 here is trained out to 270K updates.
|
| 479 |
+
This is a model designed to test the capabilities of the language model
|
| 480 |
+
when ablated for number of parameters in the language model.
|
| 481 |
+
See table S1 in (Lin et al, 2022).
|
| 482 |
+
"""
|
| 483 |
+
import models.esm.esmfold.v1.pretrained
|
| 484 |
+
return esm.esmfold.v1.pretrained.esmfold_structure_module_only_150M_270K()
|
| 485 |
+
|
| 486 |
+
|
| 487 |
+
def esmfold_structure_module_only_650M():
|
| 488 |
+
"""
|
| 489 |
+
ESMFold baseline model using 650M ESM-2, 0 folding blocks.
|
| 490 |
+
ESM-2 here is trained out to 500K updates.
|
| 491 |
+
This is a model designed to test the capabilities of the language model
|
| 492 |
+
when ablated for number of parameters in the language model.
|
| 493 |
+
See table S1 in (Lin et al, 2022).
|
| 494 |
+
"""
|
| 495 |
+
import models.esm.esmfold.v1.pretrained
|
| 496 |
+
return esm.esmfold.v1.pretrained.esmfold_structure_module_only_650M()
|
| 497 |
+
|
| 498 |
+
|
| 499 |
+
def esmfold_structure_module_only_650M_270K():
|
| 500 |
+
"""
|
| 501 |
+
ESMFold baseline model using 650M ESM-2, 0 folding blocks.
|
| 502 |
+
ESM-2 here is trained out to 270K updates.
|
| 503 |
+
This is a model designed to test the capabilities of the language model
|
| 504 |
+
when ablated for number of parameters in the language model.
|
| 505 |
+
See table S1 in (Lin et al, 2022).
|
| 506 |
+
"""
|
| 507 |
+
import models.esm.esmfold.v1.pretrained
|
| 508 |
+
return esm.esmfold.v1.pretrained.esmfold_structure_module_only_650M_270K()
|
| 509 |
+
|
| 510 |
+
|
| 511 |
+
def esmfold_structure_module_only_3B():
|
| 512 |
+
"""
|
| 513 |
+
ESMFold baseline model using 3B ESM-2, 0 folding blocks.
|
| 514 |
+
ESM-2 here is trained out to 500K updates.
|
| 515 |
+
This is a model designed to test the capabilities of the language model
|
| 516 |
+
when ablated for number of parameters in the language model.
|
| 517 |
+
See table S1 in (Lin et al, 2022).
|
| 518 |
+
"""
|
| 519 |
+
import models.esm.esmfold.v1.pretrained
|
| 520 |
+
return esm.esmfold.v1.pretrained.esmfold_structure_module_only_3B()
|
| 521 |
+
|
| 522 |
+
|
| 523 |
+
def esmfold_structure_module_only_3B_270K():
|
| 524 |
+
"""
|
| 525 |
+
ESMFold baseline model using 3B ESM-2, 0 folding blocks.
|
| 526 |
+
ESM-2 here is trained out to 270K updates.
|
| 527 |
+
This is a model designed to test the capabilities of the language model
|
| 528 |
+
when ablated for number of parameters in the language model.
|
| 529 |
+
See table S1 in (Lin et al, 2022).
|
| 530 |
+
"""
|
| 531 |
+
import models.esm.esmfold.v1.pretrained
|
| 532 |
+
return esm.esmfold.v1.pretrained.esmfold_structure_module_only_3B_270K()
|
| 533 |
+
|
| 534 |
+
|
| 535 |
+
def esmfold_structure_module_only_15B():
|
| 536 |
+
"""
|
| 537 |
+
ESMFold baseline model using 15B ESM-2, 0 folding blocks.
|
| 538 |
+
ESM-2 here is trained out to 270K updates.
|
| 539 |
+
The 15B parameter ESM-2 was not trained out to 500K updates
|
| 540 |
+
This is a model designed to test the capabilities of the language model
|
| 541 |
+
when ablated for number of parameters in the language model.
|
| 542 |
+
See table S1 in (Lin et al, 2022).
|
| 543 |
+
"""
|
| 544 |
+
import models.esm.esmfold.v1.pretrained
|
| 545 |
+
return esm.esmfold.v1.pretrained.esmfold_structure_module_only_15B()
|
models/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"
|
models/simplefold/mlx/__pycache__/esm_network.cpython-310.pyc
ADDED
|
Binary file (3.68 kB). View file
|
|
|
models/simplefold/mlx/__pycache__/esm_rotary_embedding.cpython-310.pyc
ADDED
|
Binary file (2.61 kB). View file
|
|
|
models/simplefold/mlx/__pycache__/sampler.cpython-310.pyc
ADDED
|
Binary file (2.61 kB). View file
|
|
|
models/simplefold/torch/__pycache__/__init__.cpython-310.pyc
ADDED
|
Binary file (171 Bytes). View file
|
|
|
models/simplefold/torch/__pycache__/architecture.cpython-310.pyc
ADDED
|
Binary file (6.23 kB). View file
|
|
|
models/simplefold/torch/__pycache__/architecture.cpython-311.pyc
ADDED
|
Binary file (12.9 kB). View file
|
|
|
models/simplefold/torch/__pycache__/blocks.cpython-310.pyc
ADDED
|
Binary file (3.99 kB). View file
|
|
|
models/simplefold/torch/__pycache__/blocks.cpython-311.pyc
ADDED
|
Binary file (8.74 kB). View file
|
|
|
models/simplefold/torch/__pycache__/confidence_module.cpython-310.pyc
ADDED
|
Binary file (1.9 kB). View file
|
|
|
models/simplefold/torch/__pycache__/confidence_module.cpython-311.pyc
ADDED
|
Binary file (3.5 kB). View file
|
|
|
models/simplefold/torch/__pycache__/layers.cpython-310.pyc
ADDED
|
Binary file (9.92 kB). View file
|
|
|
models/simplefold/torch/__pycache__/layers.cpython-311.pyc
ADDED
|
Binary file (19.1 kB). View file
|
|
|
models/simplefold/torch/__pycache__/pos_embed.cpython-310.pyc
ADDED
|
Binary file (5.23 kB). View file
|
|
|
models/simplefold/torch/__pycache__/sampler.cpython-310.pyc
ADDED
|
Binary file (2.39 kB). View file
|
|
|
models/simplefold/torch/__pycache__/sampler.cpython-311.pyc
ADDED
|
Binary file (4.09 kB). View file
|
|
|
models/simplefold/torch/blocks.py
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# For licensing see accompanying LICENSE file.
|
| 3 |
+
# Copyright (c) 2025 Apple Inc. Licensed under MIT License.
|
| 4 |
+
#
|
| 5 |
+
|
| 6 |
+
import torch
|
| 7 |
+
from torch import nn
|
| 8 |
+
from .layers import modulate, SwiGLUFeedForward
|
| 9 |
+
|
| 10 |
+
try:
|
| 11 |
+
from timm.models.vision_transformer import Mlp
|
| 12 |
+
except ModuleNotFoundError:
|
| 13 |
+
class Mlp(nn.Module):
|
| 14 |
+
def __init__(self, in_features, hidden_features=None, out_features=None, act_layer=nn.GELU, drop=0):
|
| 15 |
+
super().__init__()
|
| 16 |
+
out_features = out_features or in_features
|
| 17 |
+
hidden_features = hidden_features or in_features
|
| 18 |
+
self.fc1 = nn.Linear(in_features, hidden_features)
|
| 19 |
+
self.act = act_layer()
|
| 20 |
+
self.drop1 = nn.Dropout(drop)
|
| 21 |
+
self.fc2 = nn.Linear(hidden_features, out_features)
|
| 22 |
+
self.drop2 = nn.Dropout(drop)
|
| 23 |
+
|
| 24 |
+
def forward(self, x):
|
| 25 |
+
x = self.fc1(x)
|
| 26 |
+
x = self.act(x)
|
| 27 |
+
x = self.drop1(x)
|
| 28 |
+
x = self.fc2(x)
|
| 29 |
+
x = self.drop2(x)
|
| 30 |
+
return x
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
class DiTBlock(nn.Module):
|
| 34 |
+
"""
|
| 35 |
+
A DiT block with adaptive layer norm zero (adaLN-Zero) conditioning.
|
| 36 |
+
"""
|
| 37 |
+
|
| 38 |
+
def __init__(
|
| 39 |
+
self,
|
| 40 |
+
self_attention_layer,
|
| 41 |
+
hidden_size,
|
| 42 |
+
mlp_ratio=4.0,
|
| 43 |
+
use_swiglu=True,
|
| 44 |
+
):
|
| 45 |
+
super().__init__()
|
| 46 |
+
self.norm1 = nn.LayerNorm(hidden_size, elementwise_affine=False, eps=1e-6)
|
| 47 |
+
self.attn = self_attention_layer()
|
| 48 |
+
self.norm2 = nn.LayerNorm(hidden_size, elementwise_affine=False, eps=1e-6)
|
| 49 |
+
mlp_hidden_dim = int(hidden_size * mlp_ratio)
|
| 50 |
+
if use_swiglu:
|
| 51 |
+
self.mlp = SwiGLUFeedForward(hidden_size, mlp_hidden_dim)
|
| 52 |
+
else:
|
| 53 |
+
approx_gelu = lambda: nn.GELU(approximate="tanh")
|
| 54 |
+
self.mlp = Mlp(
|
| 55 |
+
in_features=hidden_size,
|
| 56 |
+
hidden_features=mlp_hidden_dim,
|
| 57 |
+
act_layer=approx_gelu,
|
| 58 |
+
drop=0,
|
| 59 |
+
)
|
| 60 |
+
self.adaLN_modulation = nn.Sequential(
|
| 61 |
+
nn.SiLU(), nn.Linear(hidden_size, 6 * hidden_size, bias=True)
|
| 62 |
+
)
|
| 63 |
+
self.initialize_weights()
|
| 64 |
+
|
| 65 |
+
def initialize_weights(self):
|
| 66 |
+
# Initialize transformer layers:
|
| 67 |
+
def _basic_init(module):
|
| 68 |
+
if isinstance(module, nn.Linear):
|
| 69 |
+
torch.nn.init.xavier_uniform_(module.weight)
|
| 70 |
+
if module.bias is not None:
|
| 71 |
+
nn.init.constant_(module.bias, 0)
|
| 72 |
+
|
| 73 |
+
self.apply(_basic_init)
|
| 74 |
+
|
| 75 |
+
# Zero-out adaLN modulation layers in DiT encoder blocks:
|
| 76 |
+
nn.init.constant_(self.adaLN_modulation[-1].weight, 0)
|
| 77 |
+
nn.init.constant_(self.adaLN_modulation[-1].bias, 0)
|
| 78 |
+
|
| 79 |
+
def forward(
|
| 80 |
+
self,
|
| 81 |
+
latents,
|
| 82 |
+
c,
|
| 83 |
+
**kwargs,
|
| 84 |
+
):
|
| 85 |
+
shift_msa, scale_msa, gate_msa, shift_mlp, scale_mlp, gate_mlp = (
|
| 86 |
+
self.adaLN_modulation(c).chunk(6, dim=1)
|
| 87 |
+
)
|
| 88 |
+
_latents = self.attn(
|
| 89 |
+
modulate(self.norm1(latents), shift_msa, scale_msa), **kwargs
|
| 90 |
+
)
|
| 91 |
+
latents = latents + gate_msa.unsqueeze(1) * _latents
|
| 92 |
+
latents = latents + gate_mlp.unsqueeze(1) * self.mlp(
|
| 93 |
+
modulate(self.norm2(latents), shift_mlp, scale_mlp)
|
| 94 |
+
)
|
| 95 |
+
return latents
|
| 96 |
+
|
| 97 |
+
|
| 98 |
+
class TransformerBlock(nn.Module):
|
| 99 |
+
"""
|
| 100 |
+
A DiT block with adaptive layer norm zero (adaLN-Zero) conditioning.
|
| 101 |
+
"""
|
| 102 |
+
|
| 103 |
+
def __init__(
|
| 104 |
+
self,
|
| 105 |
+
self_attention_layer,
|
| 106 |
+
hidden_size,
|
| 107 |
+
mlp_ratio=4.0,
|
| 108 |
+
use_swiglu=False,
|
| 109 |
+
):
|
| 110 |
+
super().__init__()
|
| 111 |
+
self.norm1 = nn.LayerNorm(hidden_size, elementwise_affine=False, eps=1e-6)
|
| 112 |
+
self.attn = self_attention_layer()
|
| 113 |
+
self.norm2 = nn.LayerNorm(hidden_size, elementwise_affine=False, eps=1e-6)
|
| 114 |
+
mlp_hidden_dim = int(hidden_size * mlp_ratio)
|
| 115 |
+
approx_gelu = lambda: nn.GELU(approximate="tanh")
|
| 116 |
+
if use_swiglu:
|
| 117 |
+
self.mlp = SwiGLUFeedForward(hidden_size, mlp_hidden_dim)
|
| 118 |
+
else:
|
| 119 |
+
self.mlp = Mlp(
|
| 120 |
+
in_features=hidden_size,
|
| 121 |
+
hidden_features=mlp_hidden_dim,
|
| 122 |
+
act_layer=approx_gelu,
|
| 123 |
+
drop=0,
|
| 124 |
+
)
|
| 125 |
+
|
| 126 |
+
def forward(
|
| 127 |
+
self,
|
| 128 |
+
latents,
|
| 129 |
+
**kwargs,
|
| 130 |
+
):
|
| 131 |
+
_latents = self.attn(self.norm1(latents), **kwargs)
|
| 132 |
+
latents = latents + _latents
|
| 133 |
+
latents = latents + self.mlp(self.norm2(latents))
|
| 134 |
+
return latents
|
| 135 |
+
|
| 136 |
+
|
| 137 |
+
class HomogenTrunk(nn.Module):
|
| 138 |
+
def __init__(self, block, depth):
|
| 139 |
+
super().__init__()
|
| 140 |
+
self.blocks = nn.ModuleList([block() for _ in range(depth)])
|
| 141 |
+
|
| 142 |
+
def forward(self, latents, c, **kwargs):
|
| 143 |
+
for i, block in enumerate(self.blocks):
|
| 144 |
+
kwargs["layer_idx"] = i
|
| 145 |
+
latents = block(latents=latents, c=c, **kwargs)
|
| 146 |
+
return latents
|
models/simplefold/torch/confidence_module.py
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# For licensing see accompanying LICENSE file.
|
| 3 |
+
# Copyright (c) 2025 Apple Inc. Licensed under MIT License.
|
| 4 |
+
#
|
| 5 |
+
|
| 6 |
+
import torch
|
| 7 |
+
from torch import nn
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
def compute_aggregated_metric(logits, end=1.0):
|
| 11 |
+
"""Compute the metric from the logits.
|
| 12 |
+
|
| 13 |
+
Parameters
|
| 14 |
+
----------
|
| 15 |
+
logits : torch.Tensor
|
| 16 |
+
The logits of the metric
|
| 17 |
+
end : float
|
| 18 |
+
Max value of the metric, by default 1.0
|
| 19 |
+
|
| 20 |
+
Returns
|
| 21 |
+
-------
|
| 22 |
+
Tensor
|
| 23 |
+
The metric value
|
| 24 |
+
|
| 25 |
+
"""
|
| 26 |
+
num_bins = logits.shape[-1]
|
| 27 |
+
bin_width = end / num_bins
|
| 28 |
+
bounds = torch.arange(
|
| 29 |
+
start=0.5 * bin_width, end=end, step=bin_width, device=logits.device
|
| 30 |
+
)
|
| 31 |
+
probs = nn.functional.softmax(logits, dim=-1)
|
| 32 |
+
plddt = torch.sum(
|
| 33 |
+
probs * bounds.view(*((1,) * len(probs.shape[:-1])), *bounds.shape),
|
| 34 |
+
dim=-1,
|
| 35 |
+
)
|
| 36 |
+
return plddt
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
class ConfidenceModule(nn.Module):
|
| 40 |
+
def __init__(
|
| 41 |
+
self,
|
| 42 |
+
hidden_size,
|
| 43 |
+
transformer_blocks,
|
| 44 |
+
num_plddt_bins=50,
|
| 45 |
+
):
|
| 46 |
+
super().__init__()
|
| 47 |
+
self.transformer_blocks = transformer_blocks
|
| 48 |
+
self.to_plddt_logits = nn.Sequential(
|
| 49 |
+
nn.Linear(hidden_size, hidden_size),
|
| 50 |
+
nn.LayerNorm(hidden_size),
|
| 51 |
+
nn.SiLU(),
|
| 52 |
+
nn.Linear(hidden_size, num_plddt_bins),
|
| 53 |
+
)
|
| 54 |
+
|
| 55 |
+
def forward(
|
| 56 |
+
self,
|
| 57 |
+
latent,
|
| 58 |
+
feats,
|
| 59 |
+
):
|
| 60 |
+
token_pe_pos = torch.cat(
|
| 61 |
+
[
|
| 62 |
+
feats["residue_index"].unsqueeze(-1).float(), # (B, M, 1)
|
| 63 |
+
feats["entity_id"].unsqueeze(-1).float(), # (B, M, 1)
|
| 64 |
+
feats["asym_id"].unsqueeze(-1).float(), # (B, M, 1)
|
| 65 |
+
feats["sym_id"].unsqueeze(-1).float(), # (B, M, 1)
|
| 66 |
+
],
|
| 67 |
+
dim=-1,
|
| 68 |
+
)
|
| 69 |
+
|
| 70 |
+
latent = self.transformer_blocks(
|
| 71 |
+
latents=latent,
|
| 72 |
+
c=None,
|
| 73 |
+
pos=token_pe_pos,
|
| 74 |
+
)
|
| 75 |
+
|
| 76 |
+
# Compute the pLDDT
|
| 77 |
+
plddt_logits = self.to_plddt_logits(latent)
|
| 78 |
+
|
| 79 |
+
# Compute the aggregated pLDDT
|
| 80 |
+
plddt = compute_aggregated_metric(plddt_logits)
|
| 81 |
+
|
| 82 |
+
return dict(
|
| 83 |
+
plddt=plddt,
|
| 84 |
+
plddt_logits=plddt_logits,
|
| 85 |
+
)
|
models/simplefold/torch/sampler.py
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#
|
| 2 |
+
# For licensing see accompanying LICENSE file.
|
| 3 |
+
# Copyright (c) 2025 Apple Inc. Licensed under MIT License.
|
| 4 |
+
#
|
| 5 |
+
|
| 6 |
+
import torch
|
| 7 |
+
from tqdm import tqdm
|
| 8 |
+
from einops import repeat
|
| 9 |
+
from onescience.utils.simplefold.boltz_utils import center_random_augmentation
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
class EMSampler():
|
| 13 |
+
"""
|
| 14 |
+
A Euler-Maruyama solver for SDEs.
|
| 15 |
+
"""
|
| 16 |
+
def __init__(
|
| 17 |
+
self,
|
| 18 |
+
num_timesteps=500,
|
| 19 |
+
t_start=1e-4,
|
| 20 |
+
tau=0.3,
|
| 21 |
+
log_timesteps=False,
|
| 22 |
+
w_cutoff=0.99,
|
| 23 |
+
):
|
| 24 |
+
self.num_timesteps = num_timesteps
|
| 25 |
+
self.log_timesteps = log_timesteps
|
| 26 |
+
self.t_start = t_start
|
| 27 |
+
self.tau = tau
|
| 28 |
+
self.w_cutoff = w_cutoff
|
| 29 |
+
|
| 30 |
+
if self.log_timesteps:
|
| 31 |
+
t = 1.0 - torch.logspace(-2, 0, self.num_timesteps + 1).flip(0)
|
| 32 |
+
t = t - torch.min(t)
|
| 33 |
+
t = t / torch.max(t)
|
| 34 |
+
self.steps = t.clamp(min=self.t_start, max=1.0)
|
| 35 |
+
else:
|
| 36 |
+
self.steps = torch.linspace(
|
| 37 |
+
self.t_start, 1.0, steps=self.num_timesteps + 1
|
| 38 |
+
)
|
| 39 |
+
|
| 40 |
+
def diffusion_coefficient(self, t, eps=0.01):
|
| 41 |
+
# determine diffusion coefficient
|
| 42 |
+
w = (1.0 - t) / (t + eps)
|
| 43 |
+
if t >= self.w_cutoff:
|
| 44 |
+
w = 0.0
|
| 45 |
+
return w
|
| 46 |
+
|
| 47 |
+
@torch.no_grad()
|
| 48 |
+
def euler_maruyama_step(
|
| 49 |
+
self,
|
| 50 |
+
model_fn,
|
| 51 |
+
flow,
|
| 52 |
+
y,
|
| 53 |
+
t,
|
| 54 |
+
t_next,
|
| 55 |
+
batch,
|
| 56 |
+
):
|
| 57 |
+
dt = t_next - t
|
| 58 |
+
eps = torch.randn_like(y).to(y)
|
| 59 |
+
|
| 60 |
+
y = center_random_augmentation(
|
| 61 |
+
y,
|
| 62 |
+
batch["atom_pad_mask"],
|
| 63 |
+
augmentation=False,
|
| 64 |
+
centering=True,
|
| 65 |
+
)
|
| 66 |
+
|
| 67 |
+
batched_t = repeat(t, " -> b", b=y.shape[0])
|
| 68 |
+
velocity = model_fn(
|
| 69 |
+
noised_pos=y,
|
| 70 |
+
t=batched_t,
|
| 71 |
+
feats=batch,
|
| 72 |
+
)['predict_velocity']
|
| 73 |
+
score = flow.compute_score_from_velocity(velocity, y, t)
|
| 74 |
+
|
| 75 |
+
diff_coeff = self.diffusion_coefficient(t)
|
| 76 |
+
drift = velocity + diff_coeff * score
|
| 77 |
+
mean_y = y + drift * dt
|
| 78 |
+
y_sample = mean_y + torch.sqrt(2.0 * dt * diff_coeff * self.tau) * eps
|
| 79 |
+
|
| 80 |
+
return y_sample
|
| 81 |
+
|
| 82 |
+
@torch.no_grad()
|
| 83 |
+
def sample(self, model_fn, flow, noise, batch):
|
| 84 |
+
sampling_timesteps = self.num_timesteps
|
| 85 |
+
steps = self.steps.to(noise.device)
|
| 86 |
+
y_sampled = noise
|
| 87 |
+
feats = batch
|
| 88 |
+
|
| 89 |
+
for i in tqdm(
|
| 90 |
+
range(sampling_timesteps),
|
| 91 |
+
desc="Sampling",
|
| 92 |
+
total=sampling_timesteps,
|
| 93 |
+
):
|
| 94 |
+
t = steps[i]
|
| 95 |
+
t_next = steps[i + 1]
|
| 96 |
+
|
| 97 |
+
y_sampled = self.euler_maruyama_step(
|
| 98 |
+
model_fn,
|
| 99 |
+
flow,
|
| 100 |
+
y_sampled,
|
| 101 |
+
t,
|
| 102 |
+
t_next,
|
| 103 |
+
feats,
|
| 104 |
+
)
|
| 105 |
+
|
| 106 |
+
return {
|
| 107 |
+
"denoised_coords": y_sampled
|
| 108 |
+
}
|
weight/ccd.pkl
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:2d3b2f03a3c5665944adba51e33263511e51b21c9cd05d902f9c4b7c1e58d2f4
|
| 3 |
+
size 345859128
|