Spaces:
Sleeping
Sleeping
| """Protein target encoder combining ESM-2 with residue descriptors. | |
| It accepts frozen ESM-2 embeddings, four physicochemical descriptors, and an | |
| optional categorical label channel. The browser demo supplies the ``NONE`` | |
| label for arbitrary user inputs; that channel is not Pfam/InterPro annotation | |
| or evidence of protein function. | |
| """ | |
| import torch | |
| import torch.nn as nn | |
| class TargetEncoder(nn.Module): | |
| """ | |
| Protein residue-level encoder. | |
| Input: | |
| - ESM-2 embeddings: (B, L, 1280) — pretrained, frozen | |
| - Physicochemical features: (B, L, 4) — amino acid properties | |
| - Domain labels: (B, L) — functional domain type indices | |
| Output: | |
| - Residue representations: (B, L, projection_dim) | |
| The optional label embedding is a model input channel. In the browser demo | |
| it is the shared ``NONE`` label and is not a domain, binding-site, or | |
| functional assignment. | |
| """ | |
| def __init__(self, | |
| esm2_dim: int = 1280, | |
| projection_dim: int = 256, | |
| physchem_dim: int = 4, | |
| domain_embed_dim: int = 32, | |
| num_domain_types: int = 50, | |
| use_domain_features: bool = True, | |
| dropout: float = 0.1): | |
| super().__init__() | |
| self.use_domain = use_domain_features | |
| self.projection_dim = projection_dim | |
| # total input dimension | |
| input_dim = esm2_dim + physchem_dim | |
| if use_domain_features: | |
| input_dim += domain_embed_dim | |
| self.domain_embedding = nn.Embedding( | |
| num_domain_types + 1, # +1 for padding | |
| domain_embed_dim, | |
| padding_idx=num_domain_types, | |
| ) | |
| # projection: compress concatenated features to target dim | |
| self.projection = nn.Sequential( | |
| nn.Linear(input_dim, projection_dim * 2), | |
| nn.LayerNorm(projection_dim * 2), | |
| nn.GELU(), | |
| nn.Dropout(dropout), | |
| nn.Linear(projection_dim * 2, projection_dim), | |
| nn.LayerNorm(projection_dim), | |
| ) | |
| def forward(self, | |
| esm2_embedding: torch.Tensor, | |
| physicochemical: torch.Tensor, | |
| domain_labels: torch.Tensor = None, | |
| protein_mask: torch.Tensor = None) -> torch.Tensor: | |
| """ | |
| Args: | |
| esm2_embedding: (B, L, 1280) pretrained embeddings | |
| physicochemical: (B, L, 4) amino acid properties | |
| domain_labels: (B, L) LongTensor of domain type indices | |
| protein_mask: (B, L) boolean mask (True = valid residue) | |
| Returns: | |
| residue_repr: (B, L, projection_dim) residue representations | |
| """ | |
| parts = [esm2_embedding, physicochemical] | |
| if self.use_domain and domain_labels is not None: | |
| domain_emb = self.domain_embedding(domain_labels) | |
| parts.append(domain_emb) | |
| # concatenate all feature sources | |
| combined = torch.cat(parts, dim=-1) | |
| # project | |
| residue_repr = self.projection(combined) | |
| # zero out padded positions | |
| if protein_mask is not None: | |
| residue_repr = residue_repr * protein_mask.unsqueeze(-1).float() | |
| return residue_repr | |