Skip to content

[Lane 2 · kotlin-core] Precision metric #1227

Closed

Description

@michalharakal

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

Lane: 2 · Kotlin core
Skill needed: Kotlin. Read Accuracy.kt and ConfusionMatrixAccumulator first — this task is mostly wiring.
Size: s (~2–3 h)
Blocked by: #1226 (accumulator + Averaging)

What to do

  1. Add public class Precision(averaging: Averaging = Averaging.MACRO, dim: Int = -1, threshold: Float? = null) : Metric
    in skainet-lang/skainet-lang-core/src/commonMain/kotlin/sk/ainet/lang/nn/metrics/Precision.kt:
    • override val name = "precision";
    • update(...) delegates to a private ConfusionMatrixAccumulator(dim, threshold);
    • compute() = reduce(acc.counts(), averaging) { tp, fp, fn -> if (tp + fp == 0L) 0.0 else tp.toDouble() / (tp + fp) };
    • reset() delegates.
      Mirror Accuracy.kt's KDoc style (what the metric means, the dim / threshold semantics, what averaging does).
  2. Add factory functions at the bottom of the file mirroring accuracy() / binaryAccuracy():
    public fun precision(averaging: Averaging = Averaging.MACRO, dim: Int = -1): Metric and
    public fun binaryPrecision(threshold: Float = 0.5f): Metric.
  3. Tests in skainet-backends/skainet-backend-cpu/src/commonTest/kotlin/sk/ainet/exec/metrics/PrecisionTest.kt,
    copying AccuracyTest.kt's tensor helpers. Cover, with hand-computed expected values
    (see the parent issue and [Lane 1 · numerics] Precision/Recall/F1 — averaging-mode and zero-division conventions #1224 for the reference fixture pred [2,0,1,2], target [2,1,1,0]):
    • macro multi-class with Int32 index targets → 0.5;
    • micro multi-class → 0.5 (and assert it equals Accuracy on the same batch);
    • the same batch with soft (FP32 one-hot) targets gives the same result;
    • binary with threshold, 2-class logits;
    • accumulation across two update() calls equals one call on the concatenated batch;
    • zero-division: a class with TP+FP+FN = 0 contributes 0.0 (per [Lane 1 · numerics] Precision/Recall/F1 — averaging-mode and zero-division conventions #1224), and
      compute() on a fresh metric returns 0.0.
  4. ./gradlew :skainet-lang:skainet-lang-core:apiDump and
    ./gradlew :skainet-backends:skainet-backend-cpu:jvmTest --tests "sk.ainet.exec.metrics.*".

Acceptance

Notes

Precision answers "of what I predicted positive, how much was right". The twin task #1228 (Recall) is the same shape with tp / (tp + fn) — if you take both, fine, but they are filed separately so two people can each ship one.

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 29, 2026

    @EdinEd
    Contributor

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

  3. michalharakal commented on Oct 29, 2026

    @michalharakal
    ContributorAuthor

    Cool, thanks. Go for it.

  4. added a commit that references this issue on Oct 30, 2026
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 assumedsize: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