def __init__( self, data_range: Optional[float] = None, base: float = 10.0, reduction: Literal["elementwise_mean", "sum", "none", None] = "elementwise_mean", dim: Optional[Union[int, Tuple[int, ...]]] = None, compute_on_step: Optional[bool] = None, **kwargs: Dict[str, Any], ) -> None: super().__init__(compute_on_step=compute_on_step, **kwargs) if dim is None and reduction != "elementwise_mean": rank_zero_warn( f"The `reduction={reduction}` will not have any effect when `dim` is None." ) if dim is None: self.add_state("sum_squared_error", default=tensor(0.0), dist_reduce_fx="sum") self.add_state("total", default=tensor(0), dist_reduce_fx="sum") else: self.add_state("sum_squared_error", default=[]) self.add_state("total", default=[]) if data_range is None: if dim is not None: # Maybe we could use `torch.amax(target, dim=dim) - torch.amin(target, dim=dim)` in PyTorch 1.7 to # calculate `data_range` in the future. raise ValueError( "The `data_range` must be given when `dim` is not None.") self.data_range = None self.add_state("min_target", default=tensor(0.0), dist_reduce_fx=torch.min) self.add_state("max_target", default=tensor(0.0), dist_reduce_fx=torch.max) else: self.add_state("data_range", default=tensor(float(data_range)), dist_reduce_fx="mean") self.base = base self.reduction = reduction self.dim = tuple(dim) if isinstance(dim, Sequence) else dim
def __init__( self, num_classes: Optional[int] = None, pos_label: Optional[int] = None, average: Optional[str] = 'macro', max_fpr: Optional[float] = None, compute_on_step: bool = True, dist_sync_on_step: bool = False, process_group: Optional[Any] = None, dist_sync_fn: Callable = None, ): super().__init__( compute_on_step=compute_on_step, dist_sync_on_step=dist_sync_on_step, process_group=process_group, dist_sync_fn=dist_sync_fn, ) self.num_classes = num_classes self.pos_label = pos_label self.average = average self.max_fpr = max_fpr allowed_average = (None, 'macro', 'weighted', 'micro') if self.average not in allowed_average: raise ValueError( f'Argument `average` expected to be one of the following: {allowed_average} but got {average}' ) if self.max_fpr is not None: if not isinstance(max_fpr, float) or not 0 < max_fpr <= 1: raise ValueError( f"`max_fpr` should be a float in range (0, 1], got: {max_fpr}" ) if _TORCH_LOWER_1_6: raise RuntimeError( '`max_fpr` argument requires `torch.bucketize` which is not available below PyTorch version 1.6' ) self.mode = None self.add_state("preds", default=[], dist_reduce_fx=None) self.add_state("target", default=[], dist_reduce_fx=None) rank_zero_warn( 'Metric `AUROC` will save all targets and predictions in buffer.' ' For large datasets this may lead to large memory footprint.')
def __init__( self, ratio: Union[int, float] = 4, reduction: Literal["elementwise_mean", "sum", "none", None] = "elementwise_mean", **kwargs: Any, ) -> None: super().__init__(**kwargs) rank_zero_warn( "Metric `UniversalImageQualityIndex` will save all targets and" " predictions in buffer. For large datasets this may lead" " to large memory footprint.") self.add_state("preds", default=[], dist_reduce_fx="cat") self.add_state("target", default=[], dist_reduce_fx="cat") self.ratio = ratio self.reduction = reduction
def __init__( self, reorder: bool = False, compute_on_step: Optional[bool] = None, **kwargs: Dict[str, Any], ) -> None: super().__init__(compute_on_step=compute_on_step, **kwargs) self.reorder = reorder self.add_state("x", default=[], dist_reduce_fx="cat") self.add_state("y", default=[], dist_reduce_fx="cat") rank_zero_warn( "Metric `AUC` will save all targets and predictions in buffer." " For large datasets this may lead to large memory footprint." )
def _precision_recall_curve_update( preds: Tensor, target: Tensor, num_classes: Optional[int] = None, pos_label: Optional[int] = None, ) -> Tuple[Tensor, Tensor, int, Optional[int]]: if len(preds.shape) == len(target.shape): if pos_label is None: rank_zero_warn('`pos_label` automatically set 1.') pos_label = 1 if num_classes is not None and num_classes != 1: # multilabel problem if num_classes != preds.shape[1]: raise ValueError( f'Argument `num_classes` was set to {num_classes} in' f' metric `precision_recall_curve` but detected {preds.shape[1]}' ' number of classes from predictions' ) preds = preds.transpose(0, 1).reshape(num_classes, -1).transpose(0, 1) target = target.transpose(0, 1).reshape(num_classes, -1).transpose(0, 1) else: # binary problem preds = preds.flatten() target = target.flatten() num_classes = 1 # multi class problem elif len(preds.shape) == len(target.shape) + 1: if pos_label is not None: rank_zero_warn( 'Argument `pos_label` should be `None` when running' f' multiclass precision recall curve. Got {pos_label}' ) if num_classes != preds.shape[1]: raise ValueError( f'Argument `num_classes` was set to {num_classes} in' f' metric `precision_recall_curve` but detected {preds.shape[1]}' ' number of classes from predictions' ) preds = preds.transpose(0, 1).reshape(num_classes, -1).transpose(0, 1) target = target.flatten() else: raise ValueError("preds and target must have same number of dimensions, or one additional dimension for preds") return preds, target, num_classes, pos_label
def _squad_update( preds: Dict[str, str], target: List[Dict[str, List[Dict[str, List[Dict[str, Any]]]]]], ) -> Tuple[Tensor, Tensor, Tensor]: """Compute F1 Score and Exact Match for a collection of predictions and references. Args: preds: A dictionary mapping an `id` to the predicted `answer`. target: A list of dictionary mapping `paragraphs` to list of dictionary mapping `qas` to a list of dictionary containing `id` and list of all possible `answers`. Return: Tuple containing F1 score, Exact match score and total number of examples. Example: >>> from torchmetrics.functional.text.squad import _squad_update >>> preds = [{"prediction_text": "1976", "id": "56e10a3be3433e1400422b22"}] >>> target = [{"answers": {"answer_start": [97], "text": ["1976"]}, "id": "56e10a3be3433e1400422b22"}] >>> preds_dict = {pred["id"]: pred["prediction_text"] for pred in preds} >>> targets_dict = [ ... dict(paragraphs=[dict(qas=[dict(answers=[ ... {"text": txt} for txt in tgt["answers"]["text"]], id=tgt["id"]) for tgt in target ... ])]) ... ] >>> _squad_update(preds_dict, targets_dict) (tensor(1.), tensor(1.), tensor(1)) """ f1 = tensor(0.0) exact_match = tensor(0.0) total = tensor(0) for article in target: for paragraph in article["paragraphs"]: for qa in paragraph["qas"]: total += 1 if qa["id"] not in preds: rank_zero_warn(f"Unanswered question {qa['id']} will receive score 0.") continue ground_truths = list(map(lambda x: x["text"], qa["answers"])) # type: ignore pred = preds[qa["id"]] # type: ignore exact_match += _metric_max_over_ground_truths(_compute_exact_match_score, pred, ground_truths) f1 += _metric_max_over_ground_truths(_compute_f1_score, pred, ground_truths) return f1, exact_match, total
def wrapped_func(*args, **kwargs): if not self._update_called: rank_zero_warn( f"The ``compute`` method of metric {self.__class__.__name__}" " was called before the ``update`` method which may lead to errors," " as metric states have not yet been updated.", UserWarning ) # return cached value if self._computed is not None: return self._computed with self.sync_context( dist_sync_fn=self.dist_sync_fn, should_sync=self._to_sync, restore_cache=self._restore_cache ): self._computed = compute(*args, **kwargs) return self._computed
def _confusion_matrix_compute(confmat: torch.Tensor, normalize: Optional[str] = None) -> torch.Tensor: allowed_normalize = ('true', 'pred', 'all', 'none', None) assert normalize in allowed_normalize, \ f"Argument average needs to one of the following: {allowed_normalize}" confmat = confmat.float() if normalize is not None and normalize != 'none': if normalize == 'true': cm = confmat / confmat.sum(axis=1, keepdim=True) elif normalize == 'pred': cm = confmat / confmat.sum(axis=0, keepdim=True) elif normalize == 'all': cm = confmat / confmat.sum() nan_elements = cm[torch.isnan(cm)].nelement() if nan_elements != 0: cm[torch.isnan(cm)] = 0 rank_zero_warn(f'{nan_elements} nan values found in confusion matrix have been replaced with zeros.') return cm return confmat
def __init__( self, num_classes: Optional[int] = None, pos_label: Optional[int] = None, compute_on_step: Optional[bool] = None, **kwargs: Dict[str, Any], ) -> None: super().__init__(compute_on_step=compute_on_step, **kwargs) self.num_classes = num_classes self.pos_label = pos_label self.add_state("preds", default=[], dist_reduce_fx=None) self.add_state("target", default=[], dist_reduce_fx=None) rank_zero_warn( "Metric `ROC` will save all targets and predictions in buffer." " For large datasets this may lead to large memory footprint.")
def __init__( self, compute_on_step: bool = True, dist_sync_on_step: bool = False, process_group: Optional[Any] = None, ): super().__init__( compute_on_step=compute_on_step, dist_sync_on_step=dist_sync_on_step, process_group=process_group, ) rank_zero_warn( 'Metric `PearsonCorrcoef` will save all targets and predictions in buffer.' ' For large datasets this may lead to large memory footprint.') self.add_state("preds", default=[], dist_reduce_fx="cat") self.add_state("target", default=[], dist_reduce_fx="cat")
def __init__( self, kernel_size: Sequence[int] = (11, 11), sigma: Sequence[float] = (1.5, 1.5), reduction: Literal["elementwise_mean", "sum", "none", None] = "elementwise_mean", data_range: Optional[float] = None, k1: float = 0.01, k2: float = 0.03, betas: Tuple[float, ...] = (0.0448, 0.2856, 0.3001, 0.2363, 0.1333), normalize: Literal["relu", "simple", None] = None, compute_on_step: Optional[bool] = None, **kwargs: Dict[str, Any], ) -> None: super().__init__(compute_on_step=compute_on_step, **kwargs) rank_zero_warn( "Metric `MS_SSIM` will save all targets and" " predictions in buffer. For large datasets this may lead" " to large memory footprint." ) self.add_state("preds", default=[], dist_reduce_fx="cat") self.add_state("target", default=[], dist_reduce_fx="cat") all_kernel_ints = all(isinstance(ks, int) for ks in kernel_size) if not isinstance(kernel_size, Sequence) or len(kernel_size) != 2 or not all_kernel_ints: raise ValueError( "Argument `kernel_size` expected to be an sequence of size 2 where each element is an int" f" but got {kernel_size}" ) self.kernel_size = kernel_size self.sigma = sigma self.data_range = data_range self.k1 = k1 self.k2 = k2 self.reduction = reduction if not isinstance(betas, tuple): raise ValueError("Argument `betas` is expected to be of a type tuple.") if isinstance(betas, tuple) and not all(isinstance(beta, float) for beta in betas): raise ValueError("Argument `betas` is expected to be a tuple of floats.") self.betas = betas if normalize and normalize not in ("relu", "simple"): raise ValueError("Argument `normalize` to be expected either `None` or one of 'relu' or 'simple'") self.normalize = normalize
def _r2score_compute( sum_squared_error: Tensor, sum_error: Tensor, residual: Tensor, total: Tensor, adjusted: int = 0, multioutput: str = "uniform_average", ) -> Tensor: mean_error = sum_error / total diff = sum_squared_error - sum_error * mean_error raw_scores = 1 - (residual / diff) if multioutput == "raw_values": r2score = raw_scores elif multioutput == "uniform_average": r2score = torch.mean(raw_scores) elif multioutput == "variance_weighted": diff_sum = torch.sum(diff) r2score = torch.sum(diff / diff_sum * raw_scores) else: raise ValueError( 'Argument `multioutput` must be either `raw_values`,' f' `uniform_average` or `variance_weighted`. Received {multioutput}.' ) if adjusted < 0 or not isinstance(adjusted, int): raise ValueError('`adjusted` parameter should be an integer larger or' ' equal to 0.') if adjusted != 0: if adjusted > total - 1: rank_zero_warn( "More independent regressions than data points in" " adjusted r2 score. Falls back to standard r2 score.", UserWarning) elif adjusted == total - 1: rank_zero_warn( "Division by zero in adjusted r2 score. Falls back to" " standard r2 score.", UserWarning) else: r2score = 1 - (1 - r2score) * (total - 1) / (total - adjusted - 1) return r2score
def __init__( self, feature: Union[str, int, torch.nn.Module] = 'logits_unbiased', splits: int = 10, compute_on_step: bool = False, dist_sync_on_step: bool = False, process_group: Optional[Any] = None, dist_sync_fn: Callable[[Tensor], List[Tensor]] = None) -> None: super().__init__( compute_on_step=compute_on_step, dist_sync_on_step=dist_sync_on_step, process_group=process_group, dist_sync_fn=dist_sync_fn, ) rank_zero_warn( 'Metric `IS` will save all extracted features in buffer.' ' For large datasets this may lead to large memory footprint.', UserWarning) if isinstance(feature, (str, int)): if not _TORCH_FIDELITY_AVAILABLE: raise ValueError( 'IS metric requires that Torch-fidelity is installed.' 'Either install as `pip install torchmetrics[image]`' ' or `pip install torch-fidelity`') valid_int_input = ('logits_unbiased', 64, 192, 768, 2048) if feature not in valid_int_input: raise ValueError( f'Integer input to argument `feature` must be one of {valid_int_input},' f' but got {feature}.') self.inception = NoTrainInceptionV3(name='inception-v3-compat', features_list=[str(feature)]) elif isinstance(feature, torch.nn.Module): self.inception = feature else: raise TypeError('Got unknown input to argument `feature`') self.splits = splits self.add_state("features", [], dist_reduce_fx=None)
def wrapped_func(*args: Any, **kwargs: Any) -> Any: if not self._update_called: rank_zero_warn( f"The ``compute`` method of metric {self.__class__.__name__}" " was called before the ``update`` method which may lead to errors," " as metric states have not yet been updated.", UserWarning) # return cached value if self._computed is not None: return self._computed # compute relies on the sync context manager to gather the states across processes and apply reduction # if synchronization happened, the current rank accumulated states will be restored to keep # accumulation going if ``should_unsync=True``, with self.sync_context(dist_sync_fn=self.dist_sync_fn, should_sync=self._to_sync, should_unsync=self._should_unsync): self._computed = compute(*args, **kwargs) return self._computed
def __init__( self, data_range: Optional[float] = None, base: float = 10.0, reduction: str = 'elementwise_mean', dim: Optional[Union[int, Tuple[int, ...]]] = None, compute_on_step: bool = True, dist_sync_on_step: bool = False, process_group: Optional[Any] = None, ): super().__init__( compute_on_step=compute_on_step, dist_sync_on_step=dist_sync_on_step, process_group=process_group, ) if dim is None and reduction != 'elementwise_mean': rank_zero_warn(f'The `reduction={reduction}` will not have any effect when `dim` is None.') if dim is None: self.add_state("sum_squared_error", default=tensor(0.0), dist_reduce_fx="sum") self.add_state("total", default=tensor(0), dist_reduce_fx="sum") else: self.add_state("sum_squared_error", default=[]) self.add_state("total", default=[]) if data_range is None: if dim is not None: # Maybe we could use `torch.amax(target, dim=dim) - torch.amin(target, dim=dim)` in PyTorch 1.7 to # calculate `data_range` in the future. raise ValueError("The `data_range` must be given when `dim` is not None.") self.data_range = None self.add_state("min_target", default=tensor(0.0), dist_reduce_fx=torch.min) self.add_state("max_target", default=tensor(0.0), dist_reduce_fx=torch.max) else: self.register_buffer("data_range", tensor(float(data_range))) self.base = base self.reduction = reduction self.dim = tuple(dim) if isinstance(dim, Sequence) else dim
def __init__( self, num_classes: Optional[int] = None, pos_label: Optional[int] = None, average: Optional[str] = "macro", max_fpr: Optional[float] = None, compute_on_step: Optional[bool] = None, **kwargs: Dict[str, Any], ) -> None: super().__init__(compute_on_step=compute_on_step, **kwargs) self.num_classes = num_classes self.pos_label = pos_label self.average = average self.max_fpr = max_fpr allowed_average = (None, "macro", "weighted", "micro") if self.average not in allowed_average: raise ValueError( f"Argument `average` expected to be one of the following: {allowed_average} but got {average}" ) if self.max_fpr is not None: if not isinstance(max_fpr, float) or not 0 < max_fpr <= 1: raise ValueError( f"`max_fpr` should be a float in range (0, 1], got: {max_fpr}" ) if _TORCH_LOWER_1_6: raise RuntimeError( "`max_fpr` argument requires `torch.bucketize` which is not available below PyTorch version 1.6" ) self.mode: DataType = None # type: ignore self.add_state("preds", default=[], dist_reduce_fx="cat") self.add_state("target", default=[], dist_reduce_fx="cat") rank_zero_warn( "Metric `AUROC` will save all targets and predictions in buffer." " For large datasets this may lead to large memory footprint.")
def __init__( self, feature: Union[int, torch.nn.Module] = 2048, reset_real_features: bool = True, compute_on_step: Optional[bool] = None, **kwargs: Dict[str, Any], ) -> None: super().__init__(compute_on_step=compute_on_step, **kwargs) rank_zero_warn( "Metric `FrechetInceptionDistance` will save all extracted features in buffer." " For large datasets this may lead to large memory footprint.", UserWarning, ) if isinstance(feature, int): if not _TORCH_FIDELITY_AVAILABLE: raise ModuleNotFoundError( "FrechetInceptionDistance metric requires that `Torch-fidelity` is installed." " Either install as `pip install torchmetrics[image]` or `pip install torch-fidelity`." ) valid_int_input = [64, 192, 768, 2048] if feature not in valid_int_input: raise ValueError( f"Integer input to argument `feature` must be one of {valid_int_input}, but got {feature}." ) self.inception = NoTrainInceptionV3(name="inception-v3-compat", features_list=[str(feature)]) elif isinstance(feature, torch.nn.Module): self.inception = feature else: raise TypeError("Got unknown input to argument `feature`") if not isinstance(reset_real_features, bool): raise ValueError("Argument `reset_real_features` expected to be a bool") self.reset_real_features = reset_real_features self.add_state("real_features", [], dist_reduce_fx=None) self.add_state("fake_features", [], dist_reduce_fx=None)
def __init__( self, kernel_size: Sequence[int] = (11, 11), sigma: Sequence[float] = (1.5, 1.5), reduction: Literal["elementwise_mean", "sum", "none", None] = "elementwise_mean", data_range: Optional[float] = None, compute_on_step: Optional[bool] = None, **kwargs: Dict[str, Any], ) -> None: super().__init__(compute_on_step=compute_on_step, **kwargs) rank_zero_warn( "Metric `UniversalImageQualityIndex` will save all targets and" " predictions in buffer. For large datasets this may lead" " to large memory footprint." ) self.add_state("preds", default=[], dist_reduce_fx="cat") self.add_state("target", default=[], dist_reduce_fx="cat") self.kernel_size = kernel_size self.sigma = sigma self.data_range = data_range self.reduction = reduction
def wrapped_func(*args, **kwargs): if not self._update_called: rank_zero_warn( f"The ``compute`` method of metric {self.__class__.__name__}" " was called before the ``update`` method which may lead to errors," " as metric states have not yet been updated.", UserWarning) # return cached value if self._computed is not None: return self._computed dist_sync_fn = self.dist_sync_fn if dist_sync_fn is None and torch.distributed.is_available( ) and torch.distributed.is_initialized(): # User provided a bool, so we assume DDP if available dist_sync_fn = gather_all_tensors synced = False cache = [] if self._to_sync and dist_sync_fn is not None: # cache prior to syncing cache = { attr: getattr(self, attr) for attr in self._defaults.keys() } # sync self._sync_dist(dist_sync_fn) synced = True self._computed = compute(*args, **kwargs) if synced: # if we synced, restore to cache so that we can continue to accumulate un-synced state for attr, val in cache.items(): setattr(self, attr, val) return self._computed
def __init__( self, num_classes: int, threshold: float = 0.5, average: str = "micro", multilabel: bool = False, compute_on_step: bool = True, dist_sync_on_step: bool = False, process_group: Optional[Any] = None, ): if multilabel is not False: rank_zero_warn(f'The `multilabel={multilabel}` parameter is unused and will not have any effect.') super().__init__( num_classes=num_classes, beta=1.0, threshold=threshold, average=average, multilabel=multilabel, compute_on_step=compute_on_step, dist_sync_on_step=dist_sync_on_step, process_group=process_group, )
def _reflection_pad_3d(inputs: Tensor, pad_h: int, pad_w: int, pad_d: int) -> Tensor: """Reflective padding of 3d input. Args: inputs: tensor to pad, should be a 3D tensor of shape ``[N, C, H, W, D]`` pad_w: amount of padding in the height dimension pad_h: amount of padding in the width dimension pad_d: amount of padding in the depth dimension Returns: padded input tensor """ if _TORCH_GREATER_EQUAL_1_10: inputs = F.pad(inputs, (pad_h, pad_h, pad_w, pad_w, pad_d, pad_d), mode="reflect") else: rank_zero_warn( "An older version of pyTorch is used. For optimal speed, please upgrade to at least pyTorch 1.10." ) for dim, pad in enumerate([pad_h, pad_w, pad_d]): inputs = _single_dimension_pad(inputs, dim + 2, pad) return inputs
def __init__(self, p: int = 1, reduction: Literal["elementwise_mean", "sum", "none"] = "elementwise_mean", **kwargs: Any) -> None: super().__init__(**kwargs) rank_zero_warn( "Metric `SpectralDistortionIndex` will save all targets and" " predictions in buffer. For large datasets this may lead" " to large memory footprint.") if not isinstance(p, int) or p <= 0: raise ValueError( f"Expected `p` to be a positive integer. Got p: {p}.") self.p = p ALLOWED_REDUCTION = ("elementwise_mean", "sum", "none") if reduction not in ALLOWED_REDUCTION: raise ValueError( f"Expected argument `reduction` be one of {ALLOWED_REDUCTION} but got {reduction}" ) self.reduction = reduction self.add_state("preds", default=[], dist_reduce_fx="cat") self.add_state("target", default=[], dist_reduce_fx="cat")
def __init__( self, reorder: bool = False, compute_on_step: bool = True, dist_sync_on_step: bool = False, process_group: Optional[Any] = None, dist_sync_fn: Callable = None, ) -> None: super().__init__( compute_on_step=compute_on_step, dist_sync_on_step=dist_sync_on_step, process_group=process_group, dist_sync_fn=dist_sync_fn, ) self.reorder = reorder self.add_state("x", default=[], dist_reduce_fx="cat") self.add_state("y", default=[], dist_reduce_fx="cat") rank_zero_warn( 'Metric `AUC` will save all targets and predictions in buffer.' ' For large datasets this may lead to large memory footprint.')
def __init__( self, num_classes: Optional[int] = None, pos_label: Optional[int] = None, compute_on_step: bool = True, dist_sync_on_step: bool = False, process_group: Optional[Any] = None, ): super().__init__( compute_on_step=compute_on_step, dist_sync_on_step=dist_sync_on_step, process_group=process_group, ) self.num_classes = num_classes self.pos_label = pos_label self.add_state("preds", default=[], dist_reduce_fx=None) self.add_state("target", default=[], dist_reduce_fx=None) rank_zero_warn( 'Metric `PrecisionRecallCurve` will save all targets and predictions in buffer.' ' For large datasets this may lead to large memory footprint.')
def _confusion_matrix_compute(confmat: Tensor, normalize: Optional[str] = None) -> Tensor: allowed_normalize = ('true', 'pred', 'all', 'none', None) if normalize not in allowed_normalize: raise ValueError( f"Argument average needs to one of the following: {allowed_normalize}" ) if normalize is not None and normalize != 'none': confmat = confmat.float( ) if not confmat.is_floating_point() else confmat if normalize == 'true': confmat = confmat / confmat.sum(axis=1, keepdim=True) elif normalize == 'pred': confmat = confmat / confmat.sum(axis=0, keepdim=True) elif normalize == 'all': confmat = confmat / confmat.sum() nan_elements = confmat[torch.isnan(confmat)].nelement() if nan_elements != 0: confmat[torch.isnan(confmat)] = 0 rank_zero_warn( f'{nan_elements} nan values found in confusion matrix have been replaced with zeros.' ) return confmat
def __init__( self, num_classes: Optional[int] = None, pos_label: Optional[int] = None, average: Optional[str] = "macro", compute_on_step: Optional[bool] = None, **kwargs: Dict[str, Any], ) -> None: super().__init__(compute_on_step=compute_on_step, **kwargs) self.num_classes = num_classes self.pos_label = pos_label allowed_average = ("micro", "macro", "weighted", None) if average not in allowed_average: raise ValueError(f"Expected argument `average` to be one of {allowed_average}" f" but got {average}") self.average = average self.add_state("preds", default=[], dist_reduce_fx="cat") self.add_state("target", default=[], dist_reduce_fx="cat") rank_zero_warn( "Metric `AveragePrecision` will save all targets and predictions in buffer." " For large datasets this may lead to large memory footprint." )
def __init__( self, feature: Union[str, int, torch.nn.Module] = "logits_unbiased", splits: int = 10, compute_on_step: Optional[bool] = None, **kwargs: Dict[str, Any], ) -> None: super().__init__(compute_on_step=compute_on_step, **kwargs) rank_zero_warn( "Metric `InceptionScore` will save all extracted features in buffer." " For large datasets this may lead to large memory footprint.", UserWarning, ) if isinstance(feature, (str, int)): if not _TORCH_FIDELITY_AVAILABLE: raise ModuleNotFoundError( "InceptionScore metric requires that `Torch-fidelity` is installed." " Either install as `pip install torchmetrics[image]` or `pip install torch-fidelity`." ) valid_int_input = ("logits_unbiased", 64, 192, 768, 2048) if feature not in valid_int_input: raise ValueError( f"Integer input to argument `feature` must be one of {valid_int_input}," f" but got {feature}.") self.inception = NoTrainInceptionV3(name="inception-v3-compat", features_list=[str(feature)]) elif isinstance(feature, torch.nn.Module): self.inception = feature else: raise TypeError("Got unknown input to argument `feature`") self.splits = splits self.add_state("features", [], dist_reduce_fx=None)
def __init__( self, feature: Union[str, int, torch.nn.Module] = 2048, subsets: int = 100, subset_size: int = 1000, degree: int = 3, gamma: Optional[float] = None, # type: ignore coef: float = 1.0, reset_real_features: bool = True, compute_on_step: Optional[bool] = None, **kwargs: Dict[str, Any], ) -> None: super().__init__(compute_on_step=compute_on_step, **kwargs) rank_zero_warn( "Metric `Kernel Inception Distance` will save all extracted features in buffer." " For large datasets this may lead to large memory footprint.", UserWarning, ) if isinstance(feature, (str, int)): if not _TORCH_FIDELITY_AVAILABLE: raise ModuleNotFoundError( "Kernel Inception Distance metric requires that `Torch-fidelity` is installed." " Either install as `pip install torchmetrics[image]` or `pip install torch-fidelity`." ) valid_int_input = ("logits_unbiased", 64, 192, 768, 2048) if feature not in valid_int_input: raise ValueError( f"Integer input to argument `feature` must be one of {valid_int_input}," f" but got {feature}." ) self.inception: Module = NoTrainInceptionV3(name="inception-v3-compat", features_list=[str(feature)]) elif isinstance(feature, Module): self.inception = feature else: raise TypeError("Got unknown input to argument `feature`") if not (isinstance(subsets, int) and subsets > 0): raise ValueError("Argument `subsets` expected to be integer larger than 0") self.subsets = subsets if not (isinstance(subset_size, int) and subset_size > 0): raise ValueError("Argument `subset_size` expected to be integer larger than 0") self.subset_size = subset_size if not (isinstance(degree, int) and degree > 0): raise ValueError("Argument `degree` expected to be integer larger than 0") self.degree = degree if gamma is not None and not (isinstance(gamma, float) and gamma > 0): raise ValueError("Argument `gamma` expected to be `None` or float larger than 0") self.gamma = gamma if not (isinstance(coef, float) and coef > 0): raise ValueError("Argument `coef` expected to be float larger than 0") self.coef = coef if not isinstance(reset_real_features, bool): raise ValueError("Arugment `reset_real_features` expected to be a bool") self.reset_real_features = reset_real_features # states for extracted features self.add_state("real_features", [], dist_reduce_fx=None) self.add_state("fake_features", [], dist_reduce_fx=None)
def peak_signal_noise_ratio( preds: Tensor, target: Tensor, data_range: Optional[float] = None, base: float = 10.0, reduction: Literal["elementwise_mean", "sum", "none", None] = "elementwise_mean", dim: Optional[Union[int, Tuple[int, ...]]] = None, ) -> Tensor: """Computes the peak signal-to-noise ratio. Args: preds: estimated signal target: groun truth signal data_range: the range of the data. If None, it is determined from the data (max - min). ``data_range`` must be given when ``dim`` is not None. base: a base of a logarithm to use reduction: a method to reduce metric score over labels. - ``'elementwise_mean'``: takes the mean (default) - ``'sum'``: takes the sum - ``'none'`` or None``: no reduction will be applied dim: Dimensions to reduce PSNR scores over provided as either an integer or a list of integers. Default is None meaning scores will be reduced across all dimensions. Return: Tensor with PSNR score Raises: ValueError: If ``dim`` is not ``None`` and ``data_range`` is not provided. Example: >>> from torchmetrics.functional import peak_signal_noise_ratio >>> pred = torch.tensor([[0.0, 1.0], [2.0, 3.0]]) >>> target = torch.tensor([[3.0, 2.0], [1.0, 0.0]]) >>> peak_signal_noise_ratio(pred, target) tensor(2.5527) .. note:: Half precision is only support on GPU for this metric """ if dim is None and reduction != "elementwise_mean": rank_zero_warn( f"The `reduction={reduction}` will not have any effect when `dim` is None." ) if data_range is None: if dim is not None: # Maybe we could use `torch.amax(target, dim=dim) - torch.amin(target, dim=dim)` in PyTorch 1.7 to calculate # `data_range` in the future. raise ValueError( "The `data_range` must be given when `dim` is not None.") data_range = target.max() - target.min() else: data_range = tensor(float(data_range)) sum_squared_error, n_obs = _psnr_update(preds, target, dim=dim) return _psnr_compute(sum_squared_error, n_obs, data_range, base=base, reduction=reduction)
def _confusion_matrix_compute(confmat: Tensor, normalize: Optional[str] = None) -> Tensor: """Computes confusion matrix based on the normalization mode. Args: confmat: Confusion matrix without normalization normalize: Normalization mode for confusion matrix. Choose from - ``None`` or ``'none'``: no normalization (default) - ``'true'``: normalization over the targets (most commonly used) - ``'pred'``: normalization over the predictions - ``'all'``: normalization over the whole matrix Example: >>> # binary case >>> target = torch.tensor([1, 1, 0, 0]) >>> preds = torch.tensor([0, 1, 0, 0]) >>> confmat = _confusion_matrix_update(preds, target, num_classes=2) >>> _confusion_matrix_compute(confmat) tensor([[2, 0], [1, 1]]) >>> # multiclass case >>> target = torch.tensor([2, 1, 0, 0]) >>> preds = torch.tensor([2, 1, 0, 1]) >>> confmat = _confusion_matrix_update(preds, target, num_classes=3) >>> _confusion_matrix_compute(confmat) tensor([[1, 1, 0], [0, 1, 0], [0, 0, 1]]) >>> # multilabel case >>> target = torch.tensor([[0, 1, 0], [1, 0, 1]]) >>> preds = torch.tensor([[0, 0, 1], [1, 0, 1]]) >>> confmat = _confusion_matrix_update(preds, target, num_classes=3, multilabel=True) >>> _confusion_matrix_compute(confmat) tensor([[[1, 0], [0, 1]], [[1, 0], [1, 0]], [[0, 1], [0, 1]]]) """ allowed_normalize = ("true", "pred", "all", "none", None) if normalize not in allowed_normalize: raise ValueError( f"Argument average needs to one of the following: {allowed_normalize}" ) if normalize is not None and normalize != "none": confmat = confmat.float( ) if not confmat.is_floating_point() else confmat if normalize == "true": confmat = confmat / confmat.sum(axis=1, keepdim=True) elif normalize == "pred": confmat = confmat / confmat.sum(axis=0, keepdim=True) elif normalize == "all": confmat = confmat / confmat.sum() nan_elements = confmat[torch.isnan(confmat)].nelement() if nan_elements != 0: confmat[torch.isnan(confmat)] = 0 rank_zero_warn( f"{nan_elements} nan values found in confusion matrix have been replaced with zeros." ) return confmat