ML Foundations

Choose no winner for an all-NaN candidate row

Detect missing score rows before applying NumPy nanargmax, and keep a validity mask separate from the returned indices.

Evidence and testing

Review record: Tensor Almanac automated evidence gate (no independent human review). Example versions, recorded outputs and limitations appear below.

An all-missing row has no candidate index

A row of candidate scores can contain ordinary negative numbers alongside missing values. NumPy nanargmax ignores NaNs, but raises ValueError for an all-NaN slice. A single missing row can therefore stop a reduction over a whole matrix. NumPy also warns that results cannot be trusted for slices containing only NaNs and negative infinity. [1]

Decide what absence means before choosing a fallback. Returning zero for a missing row would point to the first candidate, even though no score supports that selection. Returning minus one without a separate validity mask is also dangerous: Python and NumPy use negative indices to address from the end.

References: [1]

Reduce only rows that contain an observation

Run python examples/numpy_all_nan_candidates.py. The helper accepts a two-dimensional matrix, rejects infinite scores, and computes a boolean valid-row mask with isnan followed by all across each row. It applies nanargmax only to valid rows and initializes missing positions to minus one. The return value includes both the indices and the validity mask. [1] [2]

The three fixed rows include negative scores, an all-NaN row and a row with one missing score. Their output indices are 2, minus one and 0; the corresponding mask is true, false and true. The example uses the mask before indexing, so the missing-row sentinel is never interpreted as a candidate. The chosen scores are minus two and minus three.

The separate direct reduction demonstrates the actual ValueError. The example also rejects an infinity fixture instead of relying on nanargmax behavior for infinity. Its input contract is deliberately narrower than NumPy's general API.

Executed with Python 3.12.14 and NumPy 2.3.5; exact stdout and code checksum are saved in private evidence.

"""Select a finite maximum per row, keeping absence separate from indices."""
import numpy as np


def choose(rows):
    x = np.asarray(rows, dtype=float)
    if x.ndim != 2 or x.shape[1] == 0:
        raise ValueError('expected a 2-D array with at least one candidate per row')
    if np.isinf(x).any():
        raise ValueError('infinite scores are outside this example contract')
    valid = ~np.isnan(x).all(axis=1)
    indices = np.full(x.shape[0], -1, dtype=int)
    if valid.any():
        indices[valid] = np.nanargmax(x[valid], axis=1)
    return indices, valid


def main():
    scores = np.array([[np.nan, -4, -2], [np.nan, np.nan, np.nan], [-3, np.nan, -8]])
    indices, valid = choose(scores)
    assert indices.tolist() == [2, -1, 0]
    assert valid.tolist() == [True, False, True]
    chosen = scores[np.flatnonzero(valid), indices[valid]]
    assert chosen.tolist() == [-2.0, -3.0]
    try:
        np.nanargmax(scores, axis=1)
    except ValueError:
        print('whole reduction: ValueError')
    else:
        raise AssertionError('expected all-NaN error')
    try:
        choose([[np.nan, -np.inf]])
    except ValueError:
        print('infinite scores: rejected')
    else:
        raise AssertionError('expected infinity guard')
    print('indices:', indices.tolist())
    print('valid rows:', valid.tolist())
    print('chosen finite scores:', chosen.tolist())


if __name__ == '__main__':
    main()

Recorded output

whole reduction: ValueError
infinite scores: rejected
indices: [2, -1, 0]
valid rows: [True, False, True]
chosen finite scores: [-2.0, -3.0]

References: [1], [2]

Keep the validity decision with the result

Carry the mask into the next stage and decide explicitly whether to skip, log or separately handle missing rows. Do not use the sentinel to index the original array. The helper chooses one maximum per row; it does not define a special policy for tied scores, missing model outputs, streaming data or infinite values.

This is a small invented fixture, not a performance benchmark or evidence about the prevalence of missing values in a real system. For production, choose a missing-data policy appropriate to the application and test it with representative inputs.

References: [1], [2]

Sources

  1. NumPy nanargmax and all-NaN slices
  2. NumPy isnan element-wise missing-value detection