Download scripts/dataset/saprot/saprot_regression_dataset.py from OneScience-Group/SaProt: direct link, hf CLI and curl.
- Browser
- Download file 3.08 kB
-
https://huggingface.co/OneScience-Group/SaProt/resolve/main/scripts/dataset/saprot/saprot_regression_dataset.py
- Command line
-
hf download hf://OneScience-Group/SaProt/scripts/dataset/saprot/saprot_regression_dataset.py
-
curl -L -o saprot_regression_dataset.py https://huggingface.co/OneScience-Group/SaProt/resolve/main/scripts/dataset/saprot/saprot_regression_dataset.py
3.08 kB
| import torch | |
| import json | |
| import random | |
| from ..data_interface import register_dataset | |
| from transformers import EsmTokenizer | |
| from ..lmdb_dataset import * | |
| from ..lmdb_dataset import * | |
| from scripts.utils.others import setup_seed | |
| class SaprotRegressionDataset(LMDBDataset): | |
| def __init__(self, | |
| tokenizer: str, | |
| max_length: int = 1024, | |
| min_clip: [float, float] = None, | |
| mix_max_norm: [float, float] = None, | |
| mask_struc_ratio: float = None, | |
| plddt_threshold: float = None, | |
| **kwargs): | |
| """ | |
| Args: | |
| tokenizer: ESM tokenizer | |
| max_length: Maximum length of the sequence | |
| min_clip: [given_value, clip_value] | |
| Set the fitness value to a fixed value if it is less than a given value | |
| mix_max_norm: [min_norm, max_norm] | |
| Normalize the fitness value to [0, 1] by min-max normalization | |
| mask_struc_ratio: Ratio of masked structure tokens, replace structure tokens with "#" | |
| plddt_threshold: If not None, mask structure tokens with pLDDT < threshold | |
| **kwargs: | |
| """ | |
| super().__init__(**kwargs) | |
| self.tokenizer = EsmTokenizer.from_pretrained(tokenizer) | |
| self.max_length = max_length | |
| self.min_clip = min_clip | |
| self.mix_max_norm = mix_max_norm | |
| self.mask_struc_ratio = mask_struc_ratio | |
| self.plddt_threshold = plddt_threshold | |
| def __getitem__(self, index): | |
| entry = json.loads(self._get(index)) | |
| seq = entry['seq'] | |
| # Mask structure tokens | |
| if self.mask_struc_ratio is not None: | |
| tokens = self.tokenizer.tokenize(seq) | |
| mask_candi = [i for i, t in enumerate(tokens) if t[-1] != "#"] | |
| # Randomly shuffle the mask candidates and set seed to ensure mask is consistent | |
| setup_seed(20000812) | |
| random.shuffle(mask_candi) | |
| # Mask first n structure tokens | |
| mask_num = int(len(mask_candi) * self.mask_struc_ratio) | |
| for i in range(mask_num): | |
| idx = mask_candi[i] | |
| tokens[idx] = tokens[idx][:-1] + "#" | |
| seq = "".join(tokens) | |
| # Mask structure tokens with pLDDT < threshold | |
| if self.plddt_threshold is not None: | |
| plddt = entry["plddt"] | |
| tokens = self.tokenizer.tokenize(seq) | |
| seq = "" | |
| for token, score in zip(tokens, plddt): | |
| if score < self.plddt_threshold: | |
| seq += token[:-1] + "#" | |
| else: | |
| seq += token | |
| tokens = self.tokenizer.tokenize(seq)[:self.max_length] | |
| seq = " ".join(tokens) | |
| if self.min_clip is not None: | |
| given_min, clip_value = self.min_clip | |
| if entry['fitness'] < given_min: | |
| entry['fitness'] = clip_value | |
| if self.mix_max_norm is not None: | |
| min_norm, max_norm = self.mix_max_norm | |
| entry['fitness'] = (entry['fitness'] - min_norm) / (max_norm - min_norm) | |
| label = entry['fitness'] | |
| return seq, label | |
| def __len__(self): | |
| return int(self._get("length")) | |
| def collate_fn(self, batch): | |
| seqs, labels = tuple(zip(*batch)) | |
| labels = torch.tensor(labels) | |
| labels = {"labels": labels} | |
| encoder_info = self.tokenizer.batch_encode_plus(seqs, return_tensors='pt', padding=True) | |
| inputs = {"inputs": encoder_info} | |
| return inputs, labels |