Skip to content

fix(knn): accept k=1 in KNNClassifier - #476

Merged
Mec-iS merged 2 commits into
smartcorelib:mainfrom
NotAFlightRisk:fix-knn-classifier-k1
Oct 5, 2026
Merged

Mec-iS merged 2 commits into
smartcorelib:mainfrom
NotAFlightRisk:fix-knn-classifier-k1

Conversation

@NotAFlightRisk

Copy link
Copy Markdown
Contributor

Checklist

  • My branch is up-to-date with main branch.
  • Everything works and tested on latest stable Rust.
  • Coverage and Linting have been applied (fmt and clippy)

Current behaviour

KNNClassifier::fit with with_k(1) comes back with k should be > 1, k=[1], so there's no way to get a 1-nearest-neighbour classifier, and a loop over k from 1 upwards falls over on the first one. KNNRegressor has taken k = 1 since 92dad01 relaxed its copy of the check, the classifier just never got the same change.

New expected behaviour

Same check as KNNRegressor, so k = 1 works and k = 0 is still an error. The new test fits with k = 1 and checks taht every training point gets its own label back.

It's two characters of fix really, the test is most of the diff.

Change logs

Changed

  • KNNClassifier accepts k = 1

@NotAFlightRisk
NotAFlightRisk requested a review from Mec-iS as a code owner October 4, 2026 23:21
@Mec-iS

Mec-iS commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the fix, @NotAFlightRisk. I reviewed the diff (1 file, +12/−2) against main.

Summary: The change is correct and minimal. parameters.k <= 1 becomes parameters.k < 1, and the error text becomes k should be > 0. This is the same guard KNNRegressor::fit already uses (k < 1, "k should be > 0"), so the two estimators are now consistent. The downstream search code accepts k = 1 too: LinearKNNSearch requires k >= 1 && k <= len(data), and CoverTree::find only rejects k == 0. I don't see a reason for the old <= 1 restriction.

Suggestions (non-blocking):

  1. Test the boundary. The new knn_fit_predict_k1 test covers k = 1, but nothing pins down k = 0 still failing. The description says "k = 0 is still an error", so a short test would guard that: assert!(KNNClassifier::fit(&x, &y, KNNClassifierParameters::default().with_k(0)).is_err());.
  2. Strengthen the k=1 test. Five points with labels [2,3,2,3,2] only check that each training point returns its own label. That is fine, but it would also be worth running it against the non-default algorithms (KNNAlgorithmName::CoverTree and LinearSearch), since the two backends handle k independently. A predict_proba check at k = 1 (one-hot rows) would also be cheap and cover the second public entry point.
  3. CHANGELOG. Other recent fixes (predict method on DecisionTreeRegressor panics when tree is not fit #469/Decision tree panic #470) have entries in CHANGELOG.md. The PR description has a "Change logs" section but the file isn't touched. Please add a Fixed line under Unreleased. Because the error message string changes (> 1 → > 0), a downstream user matching on it would be affected, so it's worth a mention, as was done for MultiClassSVC.
  4. Docs. Please check whether the KNNClassifierParameters::k doc comment or the module docs say "k > 1" anywhere, and update them if so.
  5. Nit. There is a typo in the PR description: "taht" → "that".

CI: lint, MSRV (1.85), the check_features jobs and i686-linux tests have passed. The remaining test jobs (linux, macOS, Windows, wasm) and coverage were still running when I looked. Please confirm they are green, in particular that no existing test asserted the old k <= 1 failure.

With the k = 0 test and the CHANGELOG entry added, this looks good to merge from my side. cc @Mec-iS

@Mec-iS

Mec-iS commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the fix!

@Mec-iS
Mec-iS merged commit 98dc28e into smartcorelib:main Oct 5, 2026
12 of 13 checks passed
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