Skip to content

Fix confusion_matrix raising on tensor sample weights - #365

Merged
josevalim merged 1 commit into
elixir-nx:mainfrom
RicardoSantos-99:fix-confusion-matrix-tensor-weights
Aug 28, 2026
Merged

Fix confusion_matrix raising on tensor sample weights#365
josevalim merged 1 commit into
elixir-nx:mainfrom
RicardoSantos-99:fix-confusion-matrix-tensor-weights

Conversation

@RicardoSantos-99

Copy link
Copy Markdown
Contributor

Scholar.Metrics.Classification.confusion_matrix/3 takes :sample_weights as a list but raises on a tensor:

y_true = Nx.tensor([0, 0, 1, 1], type: :u32)
y_pred = Nx.tensor([0, 1, 1, 1], type: :u32)

Classification.confusion_matrix(y_true, y_pred, num_classes: 2, sample_weights: [1, 2, 1, 1])
#Nx.Tensor<
  s64[2][2]
  [
    [1, 2],
    [0, 2]
  ]
>

Classification.confusion_matrix(y_true, y_pred, num_classes: 2, sample_weights: Nx.tensor([1, 2, 1, 1]))
** (ArgumentError) invalid numerical type: nil (see Nx.Type docs for all supported types)

A scalar weight tensor fails the same way. Both shapes are accepted input: Scholar.Options.weights validates rank 0 and rank 1 tensors, and validate_weights/3 lists [{}, {num_samples}] among the shapes it handles. So the option accepts shapes the implementation then rejects, and the error names none of it.

Shared.validate_weights/3 reads :type from its opts, which is optional. The nil and list branches work without it, since Nx.tensor(weights, type: nil) infers the type. The tensor branch calls Nx.as_type(weights, nil), which raises. Of the ten call sites, confusion_matrix is the only one that passes no type, so it is the only one that reaches this.

The fix converts only when a type is given, which leaves the tensor branch behaving like the list branch: the weights keep their own type.

Fixing it at the call site instead, passing to_float_type(y_true) like the other callers do, also works but changes what the function returns. An unnormalized count matrix built from integer weights would come back as floats.

Two tests cover it: tensor weights matching the same weights as a list, and a scalar weight applying to every sample.

validate_weights reads :type from opts, which is optional. The nil and
list branches work without it, but the tensor branch calls Nx.as_type
with a nil type, which raises. confusion_matrix is the only caller that
passes no type, so it is the only one that hits this.

Convert only when a type is given, so the tensor branch behaves like
the list branch instead.
@josevalim
josevalim merged commit 5328494 into elixir-nx:main Aug 28, 2026
2 checks passed
@josevalim

Copy link
Copy Markdown
Contributor

💚 💙 💜 💛 ❤️

@RicardoSantos-99
RicardoSantos-99 deleted the fix-confusion-matrix-tensor-weights branch August 28, 2026 12:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants