def forward_on_instances( self, instances: List[Instance], cuda_device: int) -> List[Dict[str, numpy.ndarray]]: """ Takes a list of :class:`~allennlp.data.instance.Instance`s, 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 separate the batched output into a list of individual dicts per instance. Note that typically this will be faster on a GPU (and conditionally, on a CPU) than repeated calls to :func:`forward_on_instance`. """ dataset = Dataset(instances) dataset.index_instances(self.vocab) model_input = dataset.as_tensor_dict(cuda_device=cuda_device, for_training=False) outputs = self.decode(self(**model_input)) instance_separated_output: List[Dict[str, numpy.ndarray]] = [ {} for _ in dataset.instances ] for name, output in list(outputs.items()): if isinstance(output, torch.autograd.Variable): output = output.data.cpu().numpy() outputs[name] = output for instance_output, batch_element in zip( instance_separated_output, output): instance_output[name] = batch_element return instance_separated_output
def get_answer(): # Take user input and convert to Instance user_context = request.args.get("context", "", type=str) user_question = request.args.get("question", "", type=str) input_instance = squad_reader.text_to_instance( question_text=user_question, passage_text=user_context) # Make a dataset from the instance dataset = Dataset([input_instance]) dataset.index_instances(train_vocab) batch = dataset.as_tensor_dict(cuda_device=0 if cuda else -1, for_training=False) # Extract relevant data from batch. passage = batch["passage"]["tokens"] question = batch["question"]["tokens"] metadata = batch.get("metadata", {}) # Run data through model to get start and end logits. output_dict = model(passage, question) start_logits = output_dict["start_logits"] end_logits = output_dict["end_logits"] # Compute the best span best_span = get_best_span(start_logits, end_logits) # Get the string corresponding to the best span passage_str = metadata[0]['original_passage'] offsets = metadata[0]['token_offsets'] predicted_span = tuple(best_span[0].data.cpu().numpy()) start_offset = offsets[predicted_span[0]][0] end_offset = offsets[predicted_span[1]][1] best_span_string = passage_str[start_offset:end_offset] # Return the best string back to the GUI return jsonify(answer=best_span_string)
def _sentences_to_ids(self, sentences): indexer = ELMoTokenCharactersIndexer() # For each sentence, first create a TextField, then create an instance instances = [] for sentence in sentences: tokens = [Token(token) for token in sentence] field = TextField(tokens, {'character_ids': indexer}) instance = Instance({'elmo': field}) instances.append(instance) dataset = Dataset(instances) vocab = Vocabulary() dataset.index_instances(vocab) return dataset.as_tensor_dict()['elmo']['character_ids']
def ensure_batch_predictions_are_consistent(self): self.model.eval() single_predictions = [] for i, instance in enumerate(self.dataset.instances): dataset = Dataset([instance]) tensors = dataset.as_tensor_dict(dataset.get_padding_lengths(), for_training=False) result = self.model(**tensors) single_predictions.append(result) batch_tensors = self.dataset.as_tensor_dict( self.dataset.get_padding_lengths(), for_training=False) batch_predictions = self.model(**batch_tensors) for i, instance_predictions in enumerate(single_predictions): for key, single_predicted in instance_predictions.items(): tolerance = 1e-6 if key == 'loss': # Loss is particularly unstable; we'll just be satisfied if everything else is # close. continue single_predicted = single_predicted[0] batch_predicted = batch_predictions[key][i] if isinstance(single_predicted, torch.autograd.Variable): if single_predicted.size() != batch_predicted.size(): # This is probably a sequence model, and our output shape has some padded # elements in the batched case. Fixing this in general is complicated; # we'll just fix some easy cases that we actually have, for now. num_tokens = single_predicted.size(0) if batch_predicted.dim() == 1: batch_predicted = batch_predicted[:num_tokens] elif batch_predicted.dim() == 2: batch_predicted = batch_predicted[:num_tokens, :] else: raise NotImplementedError assert_allclose(single_predicted.data.numpy(), batch_predicted.data.numpy(), atol=tolerance, err_msg=key) else: assert single_predicted == batch_predicted, key