| 9 | |
| 10 | @R.register("tasks.ResidueTypePrediction") |
| 11 | class ResidueTypePrediction(tasks.AttributeMasking, core.Configurable): |
| 12 | |
| 13 | def __init__(self, model, mask_rate=0.15, dropout=0.5, graph_construction_model=None, plddt_threshold=None): |
| 14 | super(ResidueTypePrediction, self).__init__(model, mask_rate=mask_rate, num_mlp_layer=1, graph_construction_model=graph_construction_model) |
| 15 | if hasattr(self.model, "node_output_dim"): |
| 16 | model_output_dim = self.model.node_output_dim |
| 17 | else: |
| 18 | model_output_dim = self.model.output_dim |
| 19 | num_label = 20 |
| 20 | self.dropout = nn.Dropout(dropout) |
| 21 | self.linear = nn.Linear(model_output_dim, num_label) |
| 22 | self.plddt_threshold = plddt_threshold |
| 23 | |
| 24 | def preprocess(self, train_set, valid_set, test_set): |
| 25 | return |
| 26 | |
| 27 | def predict_and_target(self, batch, all_loss=None, metric=None): |
| 28 | graph = batch["graph"] |
| 29 | if self.graph_construction_model: |
| 30 | graph = self.graph_construction_model.apply_node_layer(graph) |
| 31 | |
| 32 | # Random select residues to be masked |
| 33 | num_nodes = graph.num_residues |
| 34 | num_cum_nodes = num_nodes.cumsum(0) |
| 35 | num_samples = (num_nodes * self.mask_rate).long().clamp(1) |
| 36 | num_sample = num_samples.sum() |
| 37 | sample2graph = torch.repeat_interleave(num_samples) |
| 38 | node_index = (torch.rand(num_sample, device=self.device) * num_nodes[sample2graph]).long() |
| 39 | node_index = node_index + (num_cum_nodes - num_nodes)[sample2graph] |
| 40 | node_index = node_index.clamp(max=num_cum_nodes[-1]-1) |
| 41 | |
| 42 | target = graph.residue_type[node_index] |
| 43 | mask_id = self.model.sequence_model.alphabet.get_idx("<mask>") |
| 44 | with graph.residue(): |
| 45 | graph.residue_feature[node_index] = 0 |
| 46 | graph.residue_type[node_index] = mask_id |
| 47 | |
| 48 | # 80% mask, 10% replace, 10% unchange |
| 49 | replace_prob = torch.rand_like(target.float()) |
| 50 | replace_mask = replace_prob < 0.1 |
| 51 | mutant_residue_type = torch.randint_like(replace_mask.long(), 20) |
| 52 | with graph.residue(): |
| 53 | graph.residue_feature[node_index[replace_mask], mutant_residue_type[replace_mask]] = 1 |
| 54 | graph.residue_type[node_index[replace_mask]] = mutant_residue_type[replace_mask] |
| 55 | unchanged_mask = (replace_prob < 0.2) & (replace_prob >= 0.1) |
| 56 | with graph.residue(): |
| 57 | graph.residue_feature[node_index[unchanged_mask], target[unchanged_mask]] = 1 |
| 58 | graph.residue_type[node_index[unchanged_mask]] = target[unchanged_mask] |
| 59 | |
| 60 | if self.graph_construction_model: |
| 61 | graph = self.graph_construction_model.apply_edge_layer(graph) |
| 62 | input = graph.residue_feature.float() |
| 63 | |
| 64 | if isinstance(self.model.structure_model, gvp.SurfGVP): |
| 65 | output = self.model(graph, input, batch["surf_graph"], all_loss, metric) |
| 66 | else: |
| 67 | output = self.model(graph, input, all_loss, metric) |
| 68 | node_feature = output["node_feature"][node_index] |
nothing calls this directly
no outgoing calls
no test coverage detected