Пример #1
0
    def __call__(self,  # type: ignore
                 predictions: torch.LongTensor,
                 gold_targets: torch.LongTensor) -> None:
        """
        Update precision counts.

        Parameters
        ----------
        predictions : ``torch.LongTensor``, required
            Batched predicted tokens of shape `(batch_size, max_sequence_length)`.
        references : ``torch.LongTensor``, required
            Batched reference (gold) translations with shape `(batch_size, max_gold_sequence_length)`.

        Returns
        -------
        None
        """
        with torch.no_grad():
            predictions, gold_targets = predictions.detach(), gold_targets.detach()
            for ngram_size, _ in enumerate(self._ngram_weights, start=1):
                precision_matches, precision_totals = self._get_modified_precision_counts(
                        predictions, gold_targets, ngram_size)
                self._precision_matches[ngram_size] += precision_matches
                self._precision_totals[ngram_size] += precision_totals
            if not self._exclude_indices:
                self._prediction_lengths += predictions.size(0) * predictions.size(1)
                self._reference_lengths += gold_targets.size(0) * gold_targets.size(1)
            else:
                valid_predictions_mask = self._get_valid_tokens_mask(predictions)
                self._prediction_lengths += valid_predictions_mask.sum().item()
                valid_gold_targets_mask = self._get_valid_tokens_mask(gold_targets)
                self._reference_lengths += valid_gold_targets_mask.sum().item()
    def _get_mask_for_eval(self,
                           mask: torch.LongTensor,
                           pos_tags: torch.LongTensor) -> torch.LongTensor:
        """
        Dependency evaluation excludes words are punctuation.
        Here, we create a new mask to exclude word indices which
        have a "punctuation-like" part of speech tag.

        Parameters
        ----------
        mask : ``torch.LongTensor``, required.
            The original mask.
        pos_tags : ``torch.LongTensor``, required.
            The pos tags for the sequence.

        Returns
        -------
        A new mask, where any indices equal to labels
        we should be ignoring are masked.
        """
        new_mask = mask.detach()
        for label in self._pos_to_ignore:
            label_mask = pos_tags.eq(label).long()
            new_mask = new_mask * (1 - label_mask)
        return new_mask
Пример #3
0
    def _get_mask_for_eval(self,
                           mask: torch.LongTensor,
                           pos_tags: torch.LongTensor) -> torch.LongTensor:
        """
        Dependency evaluation excludes words are punctuation.
        Here, we create a new mask to exclude word indices which
        have a "punctuation-like" part of speech tag.

        Parameters
        ----------
        mask : ``torch.LongTensor``, required.
            The original mask.
        pos_tags : ``torch.LongTensor``, required.
            The pos tags for the sequence.

        Returns
        -------
        A new mask, where any indices equal to labels
        we should be ignoring are masked.
        """
        new_mask = mask.detach()
        for label in self._pos_to_ignore:
            label_mask = pos_tags.eq(label).long()
            new_mask = new_mask * (1 - label_mask)
        return new_mask
Пример #4
0
    def decode_answer(self, original_numbers: List[Union[int, float]],
                      number_indices: torch.LongTensor,
                      best_signs_for_numbers: torch.LongTensor,
                      **kwargs: Dict[str, Any]) -> Dict[str, Any]:
        sign_remap = {0: 0, 1: 1, 2: -1}
        original_numbers = self._special_numbers + original_numbers
        predicted_signs = [
            sign_remap[it]
            for it in best_signs_for_numbers.detach().cpu().numpy()
        ]
        result = sum([
            sign * number
            for sign, number in zip(predicted_signs, original_numbers)
        ])
        predicted_answer = str(round(result, self._arithmetic_round_ndigits))
        numbers = []
        for i, (value,
                sign) in enumerate(zip(original_numbers, predicted_signs)):
            numbers.append({
                'value': value,
                'sign': sign,
                'is_special': i < len(self._special_numbers)
            })
        if number_indices[-1][0] == -1:
            # There is a dummy 0 number at position -1 added in some cases; we are
            # removing that here.
            numbers.pop()

        answer_dict = {'value': predicted_answer, 'numbers': numbers}
        return answer_dict
    def decode_answer(self, best_count_number: torch.LongTensor,
                      **kwargs: Dict[str, Any]) -> Dict[str, Any]:
        predicted_count = best_count_number.detach().cpu().numpy().tolist()
        predicted_answer = str(predicted_count)

        answer_dict = {'value': predicted_answer, 'count': predicted_count}
        return answer_dict
Пример #6
0
 def _get_unknown_tag_mask(self, mask: torch.LongTensor,
                           head_tags: torch.LongTensor) -> torch.LongTensor:
     oov = self.vocab.get_token_index(DEFAULT_OOV_TOKEN, 'head_tags')
     new_mask = mask.detach()
     oov_mask = head_tags.eq(oov).long()
     new_mask = new_mask * (1 - oov_mask)
     return new_mask
Пример #7
0
    def __call__(self, prediction_labels: torch.Tensor,
                 gold_labels: torch.Tensor,
                 mask: torch.LongTensor) -> Dict[str, float]:
        """
        计算 metric.

        :param prediction_labels: 预测结果 shape: (B,), 这是模型解码成label的结果,注意是 label,不是 logits
        :param gold_labels: 实际结果 shape: (B,)
        :param mask: mask, shape: (B,)
        :return 每一个label的f1值。这包括 precision, recall, f1。具体结果类似:

        {"precision_[label]": [value],
         "recall_[label]" : [value],
         "f1-measure_[label]": [value],
         "precision-overall": [value],
         "recall-overall": [value],
         "f1-measure-overall": [value]}

         说明: "*-overall" 表示的是所有 命中 在初始化参数的 labels 的综合 metric 值。
         这是有必要的,作为一个综合的值作为统一衡量。
        """

        assert prediction_labels.dim() == 1, "predictions shape 是 (B,)"
        assert gold_labels.dim() == 1, "gold_labels shape 是 (B,)"

        if mask is not None:
            assert mask.dim() == 1, "mask shape 是 (B,)"

        # 转换到 cpu 进行计算
        prediction_labels, gold_labels = prediction_labels.detach().cpu(
        ), gold_labels.detach().cpu()

        if mask is not None:
            bool_mask = mask.detach().cpu().bool()

            prediction_labels = prediction_labels.masked_select(bool_mask)
            gold_labels = gold_labels.masked_select(bool_mask)

        # 当前 batch 下的 true_positives
        true_positives = defaultdict(int)
        false_positives = defaultdict(int)
        false_negatives = defaultdict(int)

        for label, label_index in zip(self._labels, self._label_indices):
            num_prediction = (prediction_labels == label_index).sum().item()
            num_golden = (gold_labels == label_index).sum().item()

            # 计算 true positives
            label_mask = (prediction_labels == label_index)
            label_predictions = prediction_labels.masked_select(label_mask)
            label_gold = gold_labels.masked_select(label_mask)

            true_positives[label] = (
                label_predictions == label_gold).sum().item()
            false_positives[label] = num_prediction - true_positives[label]
            false_negatives[label] = num_golden - true_positives[label]

        return self._metric(true_positives=true_positives,
                            false_positives=false_positives,
                            false_negatives=false_negatives)
    def __call__(self,
                 predictions: torch.LongTensor,
                 gold_labels: torch.LongTensor,
                 mask: torch.LongTensor = None):
        """
        Parameters
        ----------
        predictions : ``torch.Tensor``, required.
            A tensor of real-valued predictions of shape (batch_size, slate_length).
        gold_labels : ``torch.Tensor``, required.
            A tensor of real-valued labels of shape (batch_size, slate_length).
        """

        if mask is None:
            mask = torch.ones_like(gold_labels).bool()

        self._all_predictions.append(predictions.detach().cpu())
        self._all_gold_labels.append(gold_labels.detach().cpu())
        self._all_masks.append(mask.detach().cpu())
Пример #9
0
def _save_ply(
    f,
    verts: torch.Tensor,
    faces: torch.LongTensor,
    verts_normals: torch.Tensor,
    decimal_places: Optional[int] = None,
) -> None:
    """
    Internal implementation for saving 3D data to a .ply file.

    Args:
        f: File object to which the 3D data should be written.
        verts: FloatTensor of shape (V, 3) giving vertex coordinates.
        faces: LongTensor of shsape (F, 3) giving faces.
        verts_normals: FloatTensor of shape (V, 3) giving vertex normals.
        decimal_places: Number of decimal places for saving.
    """
    assert not len(verts) or (verts.dim() == 2 and verts.size(1) == 3)
    assert not len(faces) or (faces.dim() == 2 and faces.size(1) == 3)
    assert not len(verts_normals) or (
        verts_normals.dim() == 2 and verts_normals.size(1) == 3
    )

    print('ply\nformat ascii 1.0', file=f)
    print(f'element vertex {verts.shape[0]}', file=f)
    print('property float x', file=f)
    print('property float y', file=f)
    print('property float z', file=f)
    if verts_normals.numel() > 0:
        print('property float nx', file=f)
        print('property float ny', file=f)
        print('property float nz', file=f)
    print(f'element face {faces.shape[0]}', file=f)
    print('property list uchar int vertex_index', file=f)
    print('end_header', file=f)

    if not (len(verts) or len(faces)):
        warnings.warn("Empty 'verts' and 'faces' arguments provided")
        return

    if decimal_places is None:
        float_str = '%f'
    else:
        float_str = '%' + '.%df' % decimal_places

    vert_data = torch.cat((verts, verts_normals), dim=1)
    np.savetxt(f, vert_data.detach().numpy(), float_str)

    faces_array = faces.detach().numpy()

    if torch.any(faces >= verts.shape[0]) or torch.any(faces < 0):
        warnings.warn('Faces have invalid indices')

    if len(faces_array):
        np.savetxt(f, faces_array, '3 %d %d %d')
Пример #10
0
    def decode_label(self, model_outputs: MRCNerOutput,
                     label_indices: torch.LongTensor) -> List:
        """
        将 label indices 解码成 span list
        :param model_outputs: 模型输出
        :param label_indices: label indices
        :return: span list
        """

        mask = model_outputs.mask.detach().cpu()
        label_indices = label_indices.detach().cpu()
        return self._label_decoder(label_indices=label_indices, mask=mask)
Пример #11
0
 def next_inputs(self, time: int, outputs: torch.Tensor,
                 sample_ids: torch.LongTensor) -> NextInputTuple:
     del time, outputs  # unused by next_inputs_fn
     if self._use_finish:
         hard_ids = torch.argmax(sample_ids, dim=-1)
         finished = (hard_ids == self._end_token)
     else:
         finished = self._start_tokens.new_zeros(self._batch_size,
                                                 dtype=torch.uint8)
     if self._stop_gradient:
         sample_ids = sample_ids.detach()
     next_inputs = torch.matmul(sample_ids, self._embedding)
     return (finished, next_inputs)
    def decode_label(self, model_outputs: NerModelOutputs,
                     label_indices: torch.LongTensor) -> List:
        """
        将 label indices 解码成 span list
        :param model_outputs: 模型输出
        :param label_indices: label indices
        :return: span list
        """
        if self._label_decoder is None:
            self._label_decoder = SequenceLabelDecoder(
                label_vocabulary=self._label_vocabulary)

        mask = model_outputs.mask.detach().cpu()
        label_indices = label_indices.detach().cpu()
        return self._label_decoder(label_indices=label_indices, mask=mask)
    def _process_scores(
        self,
        keys: torch.LongTensor,
        scores: torch.FloatTensor,
        positive_mask: torch.FloatTensor,
        head_side: bool,
    ) -> None:
        # Transfer to cpu and convert to numpy
        scores = scores.detach().cpu().numpy()
        positive_mask = positive_mask.detach().cpu().numpy()
        keys = keys.detach().cpu().numpy()

        # Ensure that each key gets counted only once
        for i in range(keys.shape[0]):
            # include head_side flag into key to differentiate between (h, r) and (r, t)
            key = (head_side, ) + tuple(map(int, keys[i]))
            self.all_scores[key] = scores[i]
            self.all_positives[key] = positive_mask[i]
Пример #14
0
    def next_inputs(self, embedding_fn: EmbeddingFn,
                    time: int, outputs: torch.Tensor,
                    sample_ids: torch.LongTensor) -> NextInputTuple:
        del outputs  # unused by next_inputs_fn
        if self._use_finish:
            hard_ids = torch.argmax(sample_ids, dim=-1)
            finished = (hard_ids == self._end_token)
        else:
            finished = torch.zeros_like(self._start_tokens, dtype=torch.uint8)
        if self._stop_gradient:
            sample_ids = sample_ids.detach()

        indices = torch.arange(sample_ids.size(-1), device=sample_ids.device)
        times = torch.full_like(indices, time + 1)
        embeddings = embedding_fn(indices, times)

        next_inputs = torch.matmul(sample_ids, embeddings)
        return (finished, next_inputs)
    def forward(
            self,
            passage_attention: torch.Tensor,
            passage_lengths: List[int],
            count_answer: torch.LongTensor = None,
            metadata: List[Dict[str, Any]] = None) -> Dict[str, torch.Tensor]:
        device_id = allenutil.get_device_of(passage_attention)

        batch_size, max_passage_length = passage_attention.size()

        # Shape: (B, passage_length)
        passage_mask = (passage_attention >= 0).float()

        # List of (B, P) shaped tensors
        scaled_attentions = [
            passage_attention * sf for sf in self.scaling_vals
        ]
        # Shape: (B, passage_length, num_scaling_factors)
        scaled_passage_attentions = torch.stack(scaled_attentions, dim=2)

        # Shape (batch_size, 1)
        passage_len_bias = self.passagelength_to_bias(
            passage_mask.sum(1, keepdim=True))

        scaled_passage_attentions = scaled_passage_attentions * passage_mask.unsqueeze(
            2)

        # Shape: (B, passage_length, hidden_dim)
        count_hidden_repr = self.passage_attention_to_count(
            scaled_passage_attentions, passage_mask)

        # Shape: (B, passage_length, 1) -- score for each token
        passage_span_logits = self.passage_count_hidden2logits(
            count_hidden_repr)
        # Shape: (B, passage_length) -- sigmoid on token-score
        token_sigmoids = torch.sigmoid(passage_span_logits.squeeze(2))
        token_sigmoids = token_sigmoids * passage_mask

        # Shape: (B, 1) -- sum of sigmoids. This will act as the predicted mean
        # passage_count_mean = torch.sum(token_sigmoids, dim=1, keepdim=True) + passage_len_bias
        passage_count_mean = torch.sum(token_sigmoids, dim=1, keepdim=True)

        # Shape: (1, count_vals)
        self.countvals = allenutil.get_range_vector(
            10, device=device_id).unsqueeze(0).float()

        variance = 0.2

        # Shape: (batch_size, count_vals)
        l2_by_vsquared = torch.pow(self.countvals - passage_count_mean,
                                   2) / (2 * variance * variance)
        exp_val = torch.exp(-1 * l2_by_vsquared) + 1e-30
        # Shape: (batch_size, count_vals)
        count_distribution = exp_val / (torch.sum(exp_val, 1, keepdim=True))

        # Loss computation
        output_dict = {}
        loss = 0.0
        pred_count_idx = torch.argmax(count_distribution, 1)
        if count_answer is not None:
            # L2-loss
            passage_count_mean = passage_count_mean.squeeze(1)
            L2Loss = F.mse_loss(input=passage_count_mean,
                                target=count_answer.float())
            loss = L2Loss
            predictions = passage_count_mean.detach().cpu().numpy()
            predictions = np.round_(predictions)

            gold_count = count_answer.detach().cpu().numpy()
            correct_vec = (predictions == gold_count)
            correct_perc = sum(correct_vec) / batch_size
            # print(f"{correct_perc} {predictions} {gold_count}")
            self.count_acc(correct_perc)

            # loss = F.cross_entropy(input=count_distribution, target=count_answer)
            # List of predicted count idxs, Shape: (B,)
            # correct_vec = (pred_count_idx == count_answer).float()
            # correct_perc = torch.sum(correct_vec) / batch_size
            # self.count_acc(correct_perc.item())

        batch_loss = loss / batch_size
        output_dict["loss"] = batch_loss
        output_dict["passage_attention"] = passage_attention
        output_dict["passage_sigmoid"] = token_sigmoids
        output_dict["count_mean"] = passage_count_mean
        output_dict["count_distritbuion"] = count_distribution
        output_dict["count_answer"] = count_answer
        output_dict["pred_count"] = pred_count_idx

        return output_dict
Пример #16
0
def _save_ply(
    f,
    verts: torch.Tensor,
    faces: torch.LongTensor,
    verts_normals: torch.Tensor,
    ascii: bool,
    decimal_places: Optional[int] = None,
) -> None:
    """
    Internal implementation for saving 3D data to a .ply file.

    Args:
        f: File object to which the 3D data should be written.
        verts: FloatTensor of shape (V, 3) giving vertex coordinates.
        faces: LongTensor of shsape (F, 3) giving faces.
        verts_normals: FloatTensor of shape (V, 3) giving vertex normals.
        ascii: (bool) whether to use the ascii ply format.
        decimal_places: Number of decimal places for saving if ascii=True.
    """
    assert not len(verts) or (verts.dim() == 2 and verts.size(1) == 3)
    assert not len(faces) or (faces.dim() == 2 and faces.size(1) == 3)
    assert not len(verts_normals) or (verts_normals.dim() == 2
                                      and verts_normals.size(1) == 3)

    if ascii:
        f.write(b"ply\nformat ascii 1.0\n")
    elif sys.byteorder == "big":
        f.write(b"ply\nformat binary_big_endian 1.0\n")
    else:
        f.write(b"ply\nformat binary_little_endian 1.0\n")
    f.write(f"element vertex {verts.shape[0]}\n".encode("ascii"))
    f.write(b"property float x\n")
    f.write(b"property float y\n")
    f.write(b"property float z\n")
    if verts_normals.numel() > 0:
        f.write(b"property float nx\n")
        f.write(b"property float ny\n")
        f.write(b"property float nz\n")
    f.write(f"element face {faces.shape[0]}\n".encode("ascii"))
    f.write(b"property list uchar int vertex_index\n")
    f.write(b"end_header\n")

    if not (len(verts) or len(faces)):
        warnings.warn("Empty 'verts' and 'faces' arguments provided")
        return

    vert_data = torch.cat((verts, verts_normals), dim=1).detach().numpy()
    if ascii:
        if decimal_places is None:
            float_str = "%f"
        else:
            float_str = "%" + ".%df" % decimal_places
        np.savetxt(f, vert_data, float_str)
    else:
        assert vert_data.dtype == np.float32
        if isinstance(f, BytesIO):
            # tofile only works with real files, but is faster than this.
            f.write(vert_data.tobytes())
        else:
            vert_data.tofile(f)

    faces_array = faces.detach().numpy()

    _check_faces_indices(faces, max_index=verts.shape[0])

    if len(faces_array):
        if ascii:
            np.savetxt(f, faces_array, "3 %d %d %d")
        else:
            # rows are 13 bytes: a one-byte 3 followed by three four-byte face indices.
            faces_uints = np.full((len(faces_array), 13), 3, dtype=np.uint8)
            faces_uints[:, 1:] = faces_array.astype(np.uint32).view(np.uint8)
            if isinstance(f, BytesIO):
                f.write(faces_uints.tobytes())
            else:
                faces_uints.tofile(f)