Download model/saprot/saprot_regression_model.py from OneScience-Group/SaProt: direct link, hf CLI and curl.
- Browser
- Download file 3.58 kB
-
https://huggingface.co/OneScience-Group/SaProt/resolve/main/model/saprot/saprot_regression_model.py
- Command line
-
hf download hf://OneScience-Group/SaProt/model/saprot/saprot_regression_model.py
-
curl -L -o saprot_regression_model.py https://huggingface.co/OneScience-Group/SaProt/resolve/main/model/saprot/saprot_regression_model.py
3.58 kB
| import torch.distributed as dist | |
| import torchmetrics | |
| import torch | |
| from ..model_interface import register_model | |
| from .base import SaprotBaseModel | |
| class SaprotRegressionModel(SaprotBaseModel): | |
| def __init__(self, test_result_path: str = None, **kwargs): | |
| """ | |
| Args: | |
| test_result_path: path to save test result | |
| **kwargs: other arguments for SaprotBaseModel | |
| """ | |
| self.test_result_path = test_result_path | |
| super().__init__(task="regression", **kwargs) | |
| def initialize_metrics(self, stage): | |
| return {f"{stage}_loss": torchmetrics.MeanSquaredError(), | |
| f"{stage}_spearman": torchmetrics.SpearmanCorrCoef(), | |
| f"{stage}_R2": torchmetrics.R2Score(), | |
| f"{stage}_pearson": torchmetrics.PearsonCorrCoef()} | |
| def forward(self, inputs, structure_info=None): | |
| if structure_info: | |
| # To be implemented | |
| raise NotImplementedError | |
| # If backbone is frozen, the embedding will be the average of all residues | |
| if self.freeze_backbone: | |
| repr = torch.stack(self.get_hidden_states(inputs, reduction="mean")) | |
| x = self.model.classifier.dropout(repr) | |
| x = self.model.classifier.dense(x) | |
| x = torch.tanh(x) | |
| x = self.model.classifier.dropout(x) | |
| logits = self.model.classifier.out_proj(x).squeeze(dim=-1) | |
| else: | |
| logits = self.model(**inputs).logits.squeeze(dim=-1) | |
| return logits | |
| def loss_func(self, stage, outputs, labels): | |
| fitness = labels['labels'].to(outputs) | |
| loss = torch.nn.functional.mse_loss(outputs, fitness) | |
| # Update metrics | |
| for metric in self.metrics[stage].values(): | |
| # Training is on half precision, but metrics expect float to compute correctly. | |
| metric.update(outputs.detach().float(), fitness.float()) | |
| if stage == "train": | |
| # Skip calculating metrics if the batch size is 1 | |
| if fitness.shape[0] > 1: | |
| log_dict = self.get_log_dict("train") | |
| self.log_info(log_dict) | |
| # Reset train metrics | |
| self.reset_metrics("train") | |
| return loss | |
| def test_epoch_end(self, outputs): | |
| if self.test_result_path is not None: | |
| from torchmetrics.utilities.distributed import gather_all_tensors | |
| preds = self.test_spearman.preds | |
| preds[-1] = preds[-1].unsqueeze(dim=0) if preds[-1].shape == () else preds[-1] | |
| preds = torch.cat(gather_all_tensors(torch.cat(preds, dim=0))) | |
| targets = self.test_spearman.target | |
| targets[-1] = targets[-1].unsqueeze(dim=0) if targets[-1].shape == () else targets[-1] | |
| targets = torch.cat(gather_all_tensors(torch.cat(targets, dim=0))) | |
| if dist.get_rank() == 0: | |
| with open(self.test_result_path, 'w') as w: | |
| w.write("pred\ttarget\n") | |
| for pred, target in zip(preds, targets): | |
| w.write(f"{pred.item()}\t{target.item()}\n") | |
| log_dict = self.get_log_dict("test") | |
| print(log_dict) | |
| self.log_info(log_dict) | |
| self.reset_metrics("test") | |
| def validation_epoch_end(self, outputs): | |
| log_dict = self.get_log_dict("valid") | |
| self.log_info(log_dict) | |
| self.reset_metrics("valid") | |
| self.check_save_condition(log_dict["valid_loss"], mode="min") | |