Skip to content

[Lane 2 · kotlin-core] Precision/Recall/F1 — extract Accuracy's class-matching helpers into a shared internal file #1225

Closed

Description

@michalharakal

Sub-issue of #1222 (Precision, Recall and F1Score metrics).

Lane: 2 · Kotlin core (preparatory refactor)
Skill needed: Kotlin. No tensor-internals knowledge needed — everything you move already exists and already has tests.
Size: s (~2–3 h)
Blocked by: nothing. Unblocks #1226.

What to do

Accuracy.kt (skainet-lang/skainet-lang-core/src/commonMain/kotlin/sk/ainet/lang/nn/metrics/Accuracy.kt)
carries, as private members, all the class-matching machinery the three new metrics also
need: argmax, argmaxTarget, insertClassIndex, validateIndexTargetShapes,
validatePredictions, normalizeDim, iterateOverSamples, plus the "hard Int32 targets
vs. soft FP32/FP16 targets" dispatch and the binary-threshold branch in
computeWithIndexTargets / computeWithSoftTargets. Copying that three more times is the
duplication git blame will ask about in six months.

  1. Create ClassificationSupport.kt in the same package. Move the helpers there as
    internal top-level functions (or one internal object ClassificationSupport). Keep
    names and signatures; keep error messages, but make the "Accuracy …" prefixes
    metric-agnostic (pass the metric name in, or drop it).
  2. Add one internal entry point that does the per-sample walk once for both target
    kinds and hands (predictedClass, targetClass) pairs to a callback, e.g.
    internal inline fun forEachPrediction(predictions, targets, dim, threshold, action: (predicted: Int, target: Int) -> Unit).
    Accuracy.update becomes a ~5-line call to it that counts matches. This is what
    ConfusionMatrixAccumulator ([Lane 2 · kotlin-core] Precision/Recall/F1 — Averaging enum + internal ConfusionMatrixAccumulator #1226) will call too.
  3. Accuracy's public surface must not change: same constructor, same accuracy() /
    binaryAccuracy() factories, same behaviour. Run
    ./gradlew :skainet-lang:skainet-lang-core:apiCheck — the API dump must be unchanged
    (everything you add is internal).
  4. Run the existing tests unchanged:
    ./gradlew :skainet-backends:skainet-backend-cpu:jvmTest --tests "sk.ainet.exec.metrics.*".

Acceptance

  • Accuracy.kt contains no argmax / index-walking code of its own
  • apiCheck passes with no dump change
  • AccuracyTest passes unmodified
  • PR title refactor(metrics): extract classification helpers from Accuracy (#1222)

Notes

Pure refactor — no new behaviour, so no new tests needed beyond the existing ones passing.
If you find Accuracy has a latent bug while you're in there (for example the
threshold branch reads logit index 1 when classCount == 2 but index 0 when
classCount == 1 — check that this is intended), don't fix it here; open a separate
bug and link it on the parent.

Activity

  1. added
    good first issueGood for newcomers; no prior SKaiNET codebase knowledge assumed
    trainingTraining pipeline, optimizers, loss
    sub-issueSub-issue of a tracking issue
    codingImplementation task (DARC: C)
    skill:kotlin-coreKotlin implementation in commonMain
    on Aug 31, 2026
  2. EdinEd commented on Oct 20, 2026

    @EdinEd
    Contributor

    Hi @michalharakal , I would like to take on this issue.

  3. michalharakal commented on Oct 20, 2026

    @michalharakal
    ContributorAuthor

    Hi @EdinEd , I've assigned this issue to you. Feel free to start working on it. Thanks for contributing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

codingImplementation task (DARC: C)good first issueGood for newcomers; no prior SKaiNET codebase knowledge assumedrefactorsize:sA few hoursskill:kotlin-coreKotlin implementation in commonMainsub-issueSub-issue of a tracking issuetrainingTraining pipeline, optimizers, loss

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions