Skip to content

Commit 6febaa4

Browse files
RicardoSantos-99josevalim
authored andcommitted
Fix CategoricalNB predict's feature-count check and min_categories option
check_dim compared x's feature count against Nx.axis_size(model.feature_count, 1), but feature_count here is {num_features, num_classes, num_categories} (unlike the 2D {num_classes, num_features} in the other NaiveBayes modules this was copied from), so axis 1 is num_classes. Every predict/*_probability call rejected correctly-shaped input whenever num_features didn't happen to equal num_classes, and would silently accept wrongly-shaped input in the reverse case. Fixed to read axis 0. Separately, fit's min_categories option was dead: Keyword.pop removed :min_categories from opts and rebound it, so the very next read of opts[:min_categories] (used to size the feature_count/ feature_log_probability tensors) always saw nil and silently fell back to inferring the category count from the training data alone. Kept a flag captured before the pop and branched on it instead, matching sklearn.naive_bayes.CategoricalNB's min_categories semantics (a literal per-feature category count, not a max index) - verified shapes match sklearn exactly for both list and tensor min_categories inputs.
1 parent 4deb282 commit 6febaa4

1 file changed

Lines changed: 8 additions & 7 deletions

File tree

lib/scholar/naive_bayes/categorical.ex

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -272,10 +272,11 @@ defmodule Scholar.NaiveBayes.Categorical do
272272
end
273273

274274
num_categories =
275-
(opts[:min_categories] || x)
276-
|> Nx.reduce_max()
277-
|> Nx.add(1)
278-
|> Nx.to_number()
275+
if min_categories_flag do
276+
min_categories |> Nx.reduce_max() |> Nx.to_number() |> trunc()
277+
else
278+
x |> Nx.reduce_max() |> Nx.add(1) |> Nx.to_number() |> trunc()
279+
end
279280

280281
opts =
281282
opts ++
@@ -360,7 +361,7 @@ defmodule Scholar.NaiveBayes.Categorical do
360361
"""
361362

362363
defn predict(%__MODULE__{} = model, x, classes) do
363-
check_dim(x, Nx.axis_size(model.feature_count, 1))
364+
check_dim(x, Nx.axis_size(model.feature_count, 0))
364365

365366
if Nx.rank(classes) != 1 do
366367
raise ArgumentError,
@@ -401,7 +402,7 @@ defmodule Scholar.NaiveBayes.Categorical do
401402
"""
402403

403404
defn predict_log_probability(%__MODULE__{} = model, x) do
404-
check_dim(x, Nx.axis_size(model.feature_count, 1))
405+
check_dim(x, Nx.axis_size(model.feature_count, 0))
405406
jll = joint_log_likelihood(model, x)
406407

407408
log_proba_x =
@@ -453,7 +454,7 @@ defmodule Scholar.NaiveBayes.Categorical do
453454
"""
454455

455456
defn predict_joint_log_probability(%__MODULE__{} = model, x) do
456-
check_dim(x, Nx.axis_size(model.feature_count, 1))
457+
check_dim(x, Nx.axis_size(model.feature_count, 0))
457458
joint_log_likelihood(model, x)
458459
end
459460

0 commit comments

Comments
 (0)