Example #1
0
def _roc_compute(
    preds: Tensor,
    target: Tensor,
    num_classes: int,
    pos_label: int,
    sample_weights: Optional[Sequence] = None,
) -> Union[Tuple[Tensor, Tensor, Tensor], Tuple[List[Tensor], List[Tensor],
                                                List[Tensor]]]:
    with torch.no_grad():
        if num_classes == 1 and preds.ndim == 1:  # binary
            fps, tps, thresholds = _binary_clf_curve(
                preds=preds,
                target=target,
                sample_weights=sample_weights,
                pos_label=pos_label)
            # Add an extra threshold position
            # to make sure that the curve starts at (0, 0)
            tps = torch.cat(
                [torch.zeros(1, dtype=tps.dtype, device=tps.device), tps])
            fps = torch.cat(
                [torch.zeros(1, dtype=fps.dtype, device=fps.device), fps])
            thresholds = torch.cat([thresholds[0][None] + 1, thresholds])

            if fps[-1] <= 0:
                raise ValueError(
                    "No negative samples in targets, false positive value should be meaningless"
                )
            fpr = fps / fps[-1]

            if tps[-1] <= 0:
                raise ValueError(
                    "No positive samples in targets, true positive value should be meaningless"
                )
            tpr = tps / tps[-1]

            return fpr, tpr, thresholds

        # Recursively call per class
        fpr, tpr, thresholds = [], [], []
        for c in range(num_classes):
            if preds.shape == target.shape:
                preds_c = preds[:, c]
                target_c = target[:, c]
                pos_label = 1
            else:
                preds_c = preds[:, c]
                target_c = target
                pos_label = c
            res = roc(
                preds=preds_c,
                target=target_c,
                num_classes=1,
                pos_label=pos_label,
                sample_weights=sample_weights,
            )
            fpr.append(res[0])
            tpr.append(res[1])
            thresholds.append(res[2])

        return fpr, tpr, thresholds
Example #2
0
def _roc_compute_single_class(
    preds: Tensor,
    target: Tensor,
    pos_label: int,
    sample_weights: Optional[Sequence] = None,
) -> Tuple[Tensor, Tensor, Tensor]:
    fps, tps, thresholds = _binary_clf_curve(preds=preds,
                                             target=target,
                                             sample_weights=sample_weights,
                                             pos_label=pos_label)
    # Add an extra threshold position to make sure that the curve starts at (0, 0)
    tps = torch.cat([torch.zeros(1, dtype=tps.dtype, device=tps.device), tps])
    fps = torch.cat([torch.zeros(1, dtype=fps.dtype, device=fps.device), fps])
    thresholds = torch.cat([thresholds[0][None] + 1, thresholds])

    if fps[-1] <= 0:
        raise ValueError(
            "No negative samples in targets, false positive value should be meaningless"
        )
    fpr = fps / fps[-1]

    if tps[-1] <= 0:
        raise ValueError(
            "No positive samples in targets, true positive value should be meaningless"
        )
    tpr = tps / tps[-1]

    return fpr, tpr, thresholds
Example #3
0
def _roc_compute_single_class(
    preds: Tensor,
    target: Tensor,
    pos_label: int,
    sample_weights: Optional[Sequence] = None,
) -> Tuple[Tensor, Tensor, Tensor]:
    """Computes Receiver Operating Characteristic for single class inputs. Returns tensor with false positive
    rates, tensor with true positive rates, tensor with thresholds used for computing false- and true postive
    rates.

    Args:
        preds: Predicted tensor
        target: Ground truth tensor
        pos_label: integer determining the positive class. Default is ``None``
            which for binary problem is translate to 1. For multiclass problems
            this argument should not be set as we iteratively change it in the
            range [0,num_classes-1]
        sample_weights: sample weights for each data point
    """

    fps, tps, thresholds = _binary_clf_curve(preds=preds,
                                             target=target,
                                             sample_weights=sample_weights,
                                             pos_label=pos_label)
    # Add an extra threshold position to make sure that the curve starts at (0, 0)
    tps = torch.cat([torch.zeros(1, dtype=tps.dtype, device=tps.device), tps])
    fps = torch.cat([torch.zeros(1, dtype=fps.dtype, device=fps.device), fps])
    thresholds = torch.cat([thresholds[0][None] + 1, thresholds])

    if fps[-1] <= 0:
        rank_zero_warn(
            "No negative samples in targets, false positive value should be meaningless."
            " Returning zero tensor in false positive score",
            UserWarning,
        )
        fpr = torch.zeros_like(thresholds)
    else:
        fpr = fps / fps[-1]

    if tps[-1] <= 0:
        rank_zero_warn(
            "No positive samples in targets, true positive value should be meaningless."
            " Returning zero tensor in true positive score",
            UserWarning,
        )
        tpr = torch.zeros_like(thresholds)
    else:
        tpr = tps / tps[-1]

    return fpr, tpr, thresholds
def test_binary_clf_curve(sample_weight, pos_label, exp_shape):
    # TODO: move back the pred and target to test func arguments
    #  if you fix the array inside the function, you'd also have fix the shape,
    #  because when the array changes, you also have to fix the shape
    seed_everything(0)
    pred = torch.randint(low=51, high=99, size=(100, ),
                         dtype=torch.float) / 100
    target = torch.tensor([0, 1] * 50, dtype=torch.int)
    if sample_weight is not None:
        sample_weight = torch.ones_like(pred) * sample_weight

    fps, tps, thresh = _binary_clf_curve(preds=pred,
                                         target=target,
                                         sample_weights=sample_weight,
                                         pos_label=pos_label)

    assert isinstance(tps, torch.Tensor)
    assert isinstance(fps, torch.Tensor)
    assert isinstance(thresh, torch.Tensor)
    assert tps.shape == (exp_shape, )
    assert fps.shape == (exp_shape, )
    assert thresh.shape == (exp_shape, )