def predict_span(self, question: TextField, passage: TextField) -> Dict[str, Any]: """ Given a question and a passage, predicts the span in the passage that answers the question. Parameters ---------- question : ``TextField`` passage : ``TextField`` A ``TextField`` containing the tokens in the passage. Note that we typically add ``SquadReader.STOP_TOKEN`` as the final token in the passage, because we use exclusive span indices. Be sure you've added that to the passage you pass in here. Returns ------- A Dict containing: span_start_probs : numpy.ndarray span_end_probs : numpy.ndarray best_span : (int, int) """ instance = Instance({'question': question, 'passage': passage}) instance.index_fields(self.vocab) model_input = util.arrays_to_variables(instance.as_array_dict(), add_batch_dimension=True, for_training=False) output_dict = self.forward(**model_input) # Here we're just removing the batch dimension and converting things to numpy arrays / # tuples instead of pytorch variables. return { "span_start_probs": output_dict["span_start_probs"].data.squeeze(0).cpu().numpy(), "span_end_probs": output_dict["span_end_probs"].data.squeeze(0).cpu().numpy(), "best_span": tuple(output_dict["best_span"].data.squeeze(0).cpu().numpy()), }
def forward_on_instance(self, instance: Instance) -> Dict[str, numpy.ndarray]: """ Takes an :class:`~allennlp.data.instance.Instance`, which typically has raw text in it, converts that text into arrays using this model's :class:`Vocabulary`, passes those arrays through :func:`self.forward()` and :func:`self.decode()` (which by default does nothing) and returns the result. Before returning the result, we convert any ``torch.autograd.Variables`` or ``torch.Tensors`` into numpy arrays and remove the batch dimension. """ # Hack to see what cuda device the model is on, so we know where to put these inputs. For # complicated models, or machines with multiple GPUs, this will not work. I couldn't find # a way to actually query what device a tensor / parameter is on. cuda_device = 0 if next(self.parameters()).is_cuda else -1 instance.index_fields(self.vocab) model_input = arrays_to_variables(instance.as_array_dict(), add_batch_dimension=True, cuda_device=cuda_device, for_training=False) outputs = self.decode(self.forward(**model_input)) for name, output in list(outputs.items()): output = output[0] if isinstance(output, torch.autograd.Variable): output = output.data.cpu().numpy() outputs[name] = output return outputs
def predict_entailment(self, premise: TextField, hypothesis: TextField) -> Dict[str, torch.Tensor]: """ Given a premise and a hypothesis sentence, predict the entailment relationship between them. Parameters ---------- premise : ``TextField`` hypothesis : ``TextField`` Returns ------- A Dict containing: label_probs : torch.FloatTensor A tensor of shape ``(num_labels,)`` representing probabilities of the entailment label. """ instance = Instance({"premise": premise, "hypothesis": hypothesis}) instance.index_fields(self._vocab) model_input = arrays_to_variables(instance.as_array_dict(), add_batch_dimension=True, for_training=False) output_dict = self.forward(**model_input) # Remove batch dimension, as we only had one input. label_probs = output_dict["label_probs"].data.squeeze(0) return {'label_probs': label_probs.numpy()}
def forward_on_instance( self, instance: Instance, cuda_device: int, calculate_loss: bool = True) -> Dict[str, numpy.ndarray]: """ Takes an :class:`~allennlp.data.instance.Instance`, which typically has raw text in it, converts that text into arrays using this model's :class:`Vocabulary`, passes those arrays through :func:`self.forward()` and :func:`self.decode()` (which by default does nothing) and returns the result. Before returning the result, we convert any ``torch.autograd.Variables`` or ``torch.Tensors`` into numpy arrays and remove the batch dimension. """ instance.index_fields(self.vocab) model_input = arrays_to_variables(instance.as_array_dict(), add_batch_dimension=True, cuda_device=cuda_device, for_training=False) forward_tensors = self.forward(**model_input, calculate_loss=calculate_loss) outputs = self.decode(forward_tensors) for name, output in list(outputs.items()): output = output[0] if isinstance(output, torch.autograd.Variable): output = output.data.cpu().numpy() elif isinstance(output, torch.Tensor): output = output.cpu().numpy() outputs[name] = output return outputs
def predict_entailment(self, premise: TextField, hypothesis: TextField) -> Dict[str, torch.Tensor]: """ Given a premise and a hypothesis sentence, predict the entailment relationship between them. Note that in the paper, a null token was appended to each sentence, to allow for words to align to nothing in the other sentence. If you've trained your model with a null token, you probably want to include it here, too. Parameters ---------- premise : ``TextField`` hypothesis : ``TextField`` Returns ------- A Dict containing: label_probs : torch.FloatTensor A tensor of shape ``(num_labels,)`` representing probabilities of the entailment label. """ instance = Instance({"premise": premise, "hypothesis": hypothesis}) instance.index_fields(self.vocab) model_input = arrays_to_variables(instance.as_array_dict(), add_batch_dimension=True, for_training=False) output_dict = self.forward(**model_input) # Remove batch dimension, as we only had one input. label_probs = output_dict["label_probs"].data.squeeze(0) return {'label_probs': label_probs.numpy()}
def tag(self, text_field: TextField, verb_indicator: IndexField) -> Dict[str, Any]: """ Perform inference on a ``Instance`` consisting of a single ``TextField`` representing the sentence and an ``IndexField`` representing an optional index into the sentence denoting a verbal predicate. Returned sequence is the maximum likelihood tag sequence under the constraint that the sequence must be a valid BIO sequence. Parameters ---------- text_field : ``TextField``, required. A ``TextField`` containing the text to be tagged. verb_indicator: ``IndexField``, required. The index of the verb whose arguments we are labeling. Returns ------- A Dict containing: tags : List[str] A list the length of the text input, containing the predicted (argmax) tag from the model per token. class_probabilities : numpy.Array An array of shape (text_input_length, num_classes), where each row is a distribution over classes for a given token in the sentence. """ instance = Instance({ "tokens": text_field, "verb_indicator": verb_indicator }) instance.index_fields(self.vocab) model_input = arrays_to_variables(instance.as_array_dict(), add_batch_dimension=True, for_training=False) output_dict = self.forward(**model_input) # Remove batch dimension, as we only had one input. predictions = output_dict["class_probabilities"].data.squeeze(0) transition_matrix = self.get_viterbi_pairwise_potentials() max_likelihood_sequence, _ = viterbi_decode(predictions, transition_matrix) tags = [ self.vocab.get_token_from_index(x, namespace="tags") for x in max_likelihood_sequence ] return {"tags": tags, "class_probabilities": predictions.numpy()}
def tag(self, text_field: TextField) -> Dict[str, Any]: """ Perform inference on a TextField to produce predicted tags and class probabilities over the possible tags. Parameters ---------- text_field : ``TextField``, required. A ``TextField`` containing the text to be tagged. Returns ------- A Dict containing: tags : List[str] A list the length of the text input, containing the predicted (argmax) tag from the model per token. class_probabilities : numpy.Array An array of shape (text_input_length, num_classes), where each row is a distribution over classes for a given token in the sentence. """ instance = Instance({'tokens': text_field}) instance.index_fields(self.vocab) model_input = arrays_to_variables(instance.as_array_dict(), add_batch_dimension=True, for_training=False) output_dict = self.forward(**model_input) # Remove batch dimension, as we only had one input. predictions = output_dict["class_probabilities"].data.squeeze(0) _, argmax = predictions.max(-1) indices = argmax.numpy() tags = [ self.vocab.get_token_from_index(x, namespace="labels") for x in indices ] return {"tags": tags, "class_probabilities": predictions.numpy()}