Source code for nemo_rl.experience.metric_utils

# Copyright (c) 2026, NVIDIA CORPORATION.  All rights reserved.
#
# 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.

"""Shared aggregation helpers for rollout metrics."""

import math
import statistics
from collections.abc import Sequence


[docs] def is_histogram_metric(name: str) -> bool: """Return whether a metric key represents raw histogram observations.""" return name.startswith("histogram/") or name.endswith("/histogram")
[docs] def calculate_single_metric( values: Sequence[float | int], batch_size: int, key_name: str ) -> dict: """Compute summary statistics for a metric as slash-prefixed keys. Args: values: Per-sample metric values to aggregate. batch_size: Denominator for the mean (sum(values) / batch_size, not len(values)); stddev still uses len(values). key_name: Prefix for the returned metric keys (e.g. "total_reward"). Returns: Dict mapping "{key_name}/{stat}" to its value for stat in mean, max, min, median, stddev (nan for a single value), and histogram. Histogram values remain backend-agnostic raw observations until the logger serializes them. """ return { f"{key_name}/mean": sum(values) / batch_size, f"{key_name}/max": max(values), f"{key_name}/min": min(values), f"{key_name}/median": statistics.median(values), f"{key_name}/stddev": statistics.stdev(values) if len(values) > 1 else math.nan, f"{key_name}/histogram": list(values), }
[docs] def pct(values: Sequence[float | int], p: float) -> float: """Percentile helper for buffer starvation diagnostics.""" if not values: return 0.0 sorted_v = sorted(values) idx = min(int(len(sorted_v) * p / 100), len(sorted_v) - 1) return float(sorted_v[idx])