Source code for physicsnemo.metrics.general.mse

# SPDX-FileCopyrightText: Copyright (c) 2023 - 2026 NVIDIA CORPORATION & AFFILIATES.
# SPDX-FileCopyrightText: All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# TODO(Dallas) Introduce Ensemble RMSE and MSE routines.

from typing import Union

import torch

Tensor = torch.Tensor


[docs] def mse( pred: Tensor, target: Tensor, dim: int = None, weights: Tensor = None, eps: float = 1e-8, ) -> Union[Tensor, float]: """Calculates Mean Squared error between two tensors Parameters ---------- pred : Tensor Input prediction tensor target : Tensor Target tensor dim : int, optional Reduction dimension. When None the losses are averaged or summed over all observations, by default None weights : Tensor, optional Element weights broadcastable to ``pred`` (e.g. a 0/1 validity mask or per-point weights). When given, a *weighted* mean ``sum(weights * err) / sum(weights)`` is taken over ``dim`` instead of a plain mean. When None (default), the result is identical to a plain ``torch.mean``. eps : float, optional Floor applied to the summed weights to guard against an all-zero (fully masked) reduction. Only used when ``weights`` is given, by default 1e-8 Returns ------- Union[Tensor, float] Mean squared error value(s) Notes ----- With ``weights=None`` and ``dim=None`` this returns the same value as ``torch.nn.functional.mse_loss(pred, target)`` (i.e. ``reduction="mean"``). It differs from ``mse_loss`` in two ways: ``dim`` selects the specific axis/axes to reduce over (``mse_loss`` only reduces over all elements via ``reduction="mean"``/``"sum"``, or not at all), and ``weights`` turns the reduction into a *weighted* mean (subsuming a validity mask or per-element weighting), with ``eps`` guarding a fully-masked reduction. ``mse_loss`` has no weighting argument. """ squared_error = (pred - target) ** 2 if weights is None: return torch.mean(squared_error, dim=dim) w = torch.broadcast_to( weights.to(device=squared_error.device, dtype=squared_error.dtype), squared_error.shape, ) if dim is None: return (w * squared_error).sum() / w.sum().clamp_min(eps) return (w * squared_error).sum(dim=dim) / w.sum(dim=dim).clamp_min(eps)
[docs] def rmse( pred: Tensor, target: Tensor, dim: int = None, weights: Tensor = None, eps: float = 1e-8, ) -> Union[Tensor, float]: """Calculates Root mean Squared error between two tensors Parameters ---------- pred : Tensor Input prediction tensor target : Tensor Target tensor dim : int, optional Reduction dimension. When None the losses are averaged or summed over all observations, by default None weights : Tensor, optional Element weights broadcastable to ``pred``; see :func:`mse`. When None (default), the result is identical to the unweighted RMSE. eps : float, optional Floor applied to the summed weights; see :func:`mse`. Only used when ``weights`` is given, by default 1e-8 Returns ------- Union[Tensor, float] Root mean squared error value(s) """ return torch.sqrt(mse(pred, target, dim=dim, weights=weights, eps=eps))