SaProt / model /saprot /saprot_annotation_model.py
anzhi2710gmailcom's picture
Upload folder using huggingface_hub
3b99abb verified
Raw
History Blame Contribute Delete
3.41 kB
import torchmetrics
import torch
from torch.nn.functional import binary_cross_entropy_with_logits
from scripts.utils.metrics import count_f1_max
from ..model_interface import register_model
from .base import SaprotBaseModel
@register_model
class SaprotAnnotationModel(SaprotBaseModel):
def __init__(self, anno_type: str, **kwargs):
"""
Args:
anno_type: one of EC, GO, GO_MF, GO_CC
**kwargs: other parameters for SaprotBaseModel
"""
label2num = {"EC": 585, "GO_BP": 1943, "GO_MF": 489, "GO_CC": 320}
self.num_labels = label2num[anno_type]
super().__init__(task="classification", **kwargs)
def initialize_metrics(self, stage):
return {f"{stage}_aupr": torchmetrics.AveragePrecision(pos_label=1, average='micro')}
def forward(self, inputs, coords=None):
if coords is not None:
inputs = self.add_bias_feature(inputs, coords)
# 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)
else:
logits = self.model(**inputs).logits
return logits
def loss_func(self, stage, logits, labels):
label = labels['labels'].to(logits)
# add weight to balance positive and negative samples
# num_pos = label.sum()
# pos_weight = (label.numel() - num_pos) / num_pos
loss = binary_cross_entropy_with_logits(logits, label.float())
aupr = getattr(self, f"{stage}_aupr")(logits.sigmoid().detach(), label)
if stage == "train":
log_dict = {"train_loss": loss,
# "train_aupr": aupr
}
self.log_info(log_dict)
self.reset_metrics("train")
return loss
def test_epoch_end(self, outputs):
preds = self.all_gather(torch.cat(self.test_aupr.preds, dim=-1)).view(-1, self.num_labels)
target = self.all_gather(torch.cat(self.test_aupr.target, dim=-1)).long().view(-1, self.num_labels)
fmax = count_f1_max(preds, target)
log_dict = {"test_f1_max": fmax,
"test_loss": torch.cat(self.all_gather(outputs), dim=-1).mean(),
# "test_aupr": self.test_aupr.compute()
}
self.log_info(log_dict)
print(log_dict)
self.reset_metrics("test")
def validation_epoch_end(self, outputs):
aupr = self.valid_aupr.compute()
preds = self.all_gather(torch.cat(self.valid_aupr.preds, dim=-1)).view(-1, self.num_labels)
target = self.all_gather(torch.cat(self.valid_aupr.target, dim=-1)).long().view(-1, self.num_labels)
f1_max = count_f1_max(preds, target)
log_dict = {"valid_f1_max": f1_max,
"valid_loss": torch.cat(self.all_gather(outputs), dim=-1).mean(),
# "valid_aupr": aupr
}
self.log_info(log_dict)
self.reset_metrics("valid")
self.check_save_condition(log_dict["valid_f1_max"], mode="max")