(
self, hidden_states, start_positions=None, end_positions=None, cls_index=None, is_impossible=None, p_mask=None,
)
| 1000 | self.answer_class = PoolerAnswerClass(config) |
| 1001 | |
| 1002 | def forward( |
| 1003 | self, hidden_states, start_positions=None, end_positions=None, cls_index=None, is_impossible=None, p_mask=None, |
| 1004 | ): |
| 1005 | outputs = () |
| 1006 | |
| 1007 | start_logits = self.start_logits(hidden_states, p_mask=p_mask) |
| 1008 | |
| 1009 | if start_positions is not None and end_positions is not None: |
| 1010 | # If we are on multi-GPU, let's remove the dimension added by batch splitting |
| 1011 | for x in (start_positions, end_positions, cls_index, is_impossible): |
| 1012 | if x is not None and x.dim() > 1: |
| 1013 | x.squeeze_(-1) |
| 1014 | |
| 1015 | # during training, compute the end logits based on the ground truth of the start position |
| 1016 | end_logits = self.end_logits(hidden_states, start_positions=start_positions, p_mask=p_mask) |
| 1017 | |
| 1018 | loss_fct = CrossEntropyLoss() |
| 1019 | start_loss = loss_fct(start_logits, start_positions) |
| 1020 | end_loss = loss_fct(end_logits, end_positions) |
| 1021 | total_loss = (start_loss + end_loss) / 2 |
| 1022 | |
| 1023 | if cls_index is not None and is_impossible is not None: |
| 1024 | # Predict answerability from the representation of CLS and START |
| 1025 | cls_logits = self.answer_class(hidden_states, start_positions=start_positions, cls_index=cls_index) |
| 1026 | loss_fct_cls = nn.BCEWithLogitsLoss() |
| 1027 | cls_loss = loss_fct_cls(cls_logits, is_impossible) |
| 1028 | |
| 1029 | # note(zhiliny): by default multiply the loss by 0.5 so that the scale is comparable to start_loss and end_loss |
| 1030 | total_loss += cls_loss * 0.5 |
| 1031 | |
| 1032 | outputs = (total_loss,) + outputs |
| 1033 | |
| 1034 | else: |
| 1035 | # during inference, compute the end logits based on beam search |
| 1036 | bsz, slen, hsz = hidden_states.size() |
| 1037 | start_log_probs = F.softmax(start_logits, dim=-1) # shape (bsz, slen) |
| 1038 | |
| 1039 | start_top_log_probs, start_top_index = torch.topk( |
| 1040 | start_log_probs, self.start_n_top, dim=-1 |
| 1041 | ) # shape (bsz, start_n_top) |
| 1042 | start_top_index_exp = start_top_index.unsqueeze(-1).expand(-1, -1, hsz) # shape (bsz, start_n_top, hsz) |
| 1043 | start_states = torch.gather(hidden_states, -2, start_top_index_exp) # shape (bsz, start_n_top, hsz) |
| 1044 | start_states = start_states.unsqueeze(1).expand(-1, slen, -1, -1) # shape (bsz, slen, start_n_top, hsz) |
| 1045 | |
| 1046 | hidden_states_expanded = hidden_states.unsqueeze(2).expand_as( |
| 1047 | start_states |
| 1048 | ) # shape (bsz, slen, start_n_top, hsz) |
| 1049 | p_mask = p_mask.unsqueeze(-1) if p_mask is not None else None |
| 1050 | end_logits = self.end_logits(hidden_states_expanded, start_states=start_states, p_mask=p_mask) |
| 1051 | end_log_probs = F.softmax(end_logits, dim=1) # shape (bsz, slen, start_n_top) |
| 1052 | |
| 1053 | end_top_log_probs, end_top_index = torch.topk( |
| 1054 | end_log_probs, self.end_n_top, dim=1 |
| 1055 | ) # shape (bsz, end_n_top, start_n_top) |
| 1056 | end_top_log_probs = end_top_log_probs.view(-1, self.start_n_top * self.end_n_top) |
| 1057 | end_top_index = end_top_index.view(-1, self.start_n_top * self.end_n_top) |
| 1058 | |
| 1059 | start_states = torch.einsum("blh,bl->bh", hidden_states, start_log_probs) |
nothing calls this directly
no outgoing calls
no test coverage detected