feat(eval): support Common Voice gender classification - #1329
Conversation
REQUEST_CHANGESIndependent review of exact head Findings
Verified Evidence
Independent Tests
GitHub Gate
The exact-head CI and thread gates are green, but they do not cover finding 1. Any fixing push makes the current check/evidence gate stale and requires fresh exact-head verification. |
|
Addressed both findings from #issuecomment-5370529429 on repaired head
The published branch and PR head both resolve exactly to |
APPROVEIndependent successor review of exact head FindingsNo actionable blocker remains. Prior blocker closure
Stacked delta and evidence
Independent gates
GitHub gate
This is the skill-level |
Summary
This dependent contribution refines the existing WinML CPU FP32 and FP16 recipes for
prithivMLmods/Common-Voice-Gender-Detection, a Wav2Vec2 audio classifier that emits female or male voice labels, withexport.compatibility.transformers_attention=eager. Effort L2 ships those recipe refinements plus a class-wide scalar-string label-mapping extension; Outcome L2 is complete, and the highest tested Goal is L3 PASS. The branch is stacked on Draft #1326 at exact head1bd919b583aa8ccd974e35fa6a1a132ac7e1c9f8; that PR owns the generic audio-classification evaluator and raw-streaming implementation included in this PR's diff againstmain.Model metadata
What the model does
This Wav2Vec2 sequence-classification checkpoint accepts 16 kHz speech waveforms and emits two logits interpreted as female or male voice labels (
verified). Evidence: pinned checkpointprithivMLmods/Common-Voice-Gender-Detection@ebbf41293c8dbea45c5bb0de6e3ef77bf89cc2ee, its audio-classification model card, and the pinnedWav2Vec2ForSequenceClassificationimplementation.Primary user stories
verifiedfrom the checkpoint model card andid2labelmetadata).Supported tasks
audio-classificationacross the checkpoint, Transformers, Optimum ONNX, and WinML surfaces (verifiedfrom the checkpoint pipeline tag,Wav2Vec2ForSequenceClassification, the Optimum Wav2Vec2 ONNX task registry, and WinML inspect/config behavior).Model architecture
mapped).Validation and support evidence
1. Baseline
The frozen baseline is
microsoft/winml-climain commit0876e5ae1c98a169a6137e092e0d7b30bf9cee33, WinML0.3.0. Recipe-free FP32 CPU build passed in 46.1 s, producing an approximately 360.9 MB model with 619/619 tagged ONNX nodes andinput_values float32[1,16000] -> logits float32[1,2]. CPU perf over three measured iterations was 59.565 ms mean, 57.39 ms p50, 16.79 samples/s, and +63.55 MB RSS total delta. Eval failed before dataset loading because current-main WinML did not registeraudio-classification. Generated config already selectedexport.compatibility.transformers_attention=eager. Optimum exposedaudio-classificationandfeature-extractionboth before and after WinML registration, so the probe verdict wasVENDOR-ONLYwith no WinML-added task.2. Goal
3. Outcome
The shipped tier is L2 and the highest Goal verdict is L3 PASS, with full technical coverage. Required tuples
CPUExecutionProvider/cpu/fp32andCPUExecutionProvider/cpu/fp16both passed; no tuples are deferred. The contribution refines the two existing CPU recipes withexport.compatibility.transformers_attention=eagerand adds a generic, schema-driven scalarValue('string')mapping path. The model branch deliberately depends on Draft #1326 at1bd919b583aa8ccd974e35fa6a1a132ac7e1c9f8; #1326 retains ownership of evaluator registration, the base audio-classification implementation, rawAudio(decode=False)plus SoundFile decoding, fixed-window aggregation, and existing ClassLabel/sequence behavior. This PR adds only exact scalar-string mapping validation/resolution, atomic selected-target prevalidation, its focused tests, schema help, and the two model-specific recipe refinements.Lane A knowledge was refined separately in gim-home/ModelKitArtifacts#254 at commit
5f1368f5ee3296aab5799f55c31acf152e4f9c07, with publishedwav2vec2.jsonSHA-2562f2a0f861df22a728aaf4cd6e02979c0756f0702d82720130567519ab469b031.No methodology friction observed.4. Per-EP/device/precision results and Functional smoke Eval
The evaluator-only repair from
e4d19ba1d4af532ba4cf0b047ff2fb395ac9d868to final candidate8010667eb20d0eb08e916157a6cc5080c91d385ddid not change build, export, model, recipe, perf, parity, or Analyze paths. L0-L2 and Analyze results below are reused from the exact parent only after all four ONNX payloads were rehashed unchanged; the zero-forward discriminator, evaluator compatibility, L3 functional smoke, commands partition, license, Ruff, and mypy are fresh on8010667eb20d0eb08e916157a6cc5080c91d385d.L2 parity passed against pinned PyTorch
Wav2Vec2ForSequenceClassification@ebbf41293c8dbea45c5bb0de6e3ef77bf89cc2eeusing deterministic float32 input[1,16000]. FP32 cosine was0.9999999999999206, max absolute error8.821487426757812e-06, mean absolute error8.225440979003906e-06, finite output, and matching argmax. FP16 cosine was0.9999999999953266, max absolute error0.0008280277252197266, mean absolute error0.0007888078689575195, finite output, and matching argmax.Functional smoke Eval: L3 PASS fresh on final candidate
8010667eb20d0eb08e916157a6cc5080c91d385d, FP32 CPU, usingAsmaaQ/gender_audio_1080@47f6563cf1b819cbf1cbc8569a8dfe8fc426bab3, configdefault, splittest, streaming, no shuffle. Exact mapping wasfemale -> 0,male -> 1, matching the checkpoint. Selection took the first eligible row for each exact mapped label in source order. Accounting was requested/selected/processed/rejected =2/2/2/0, with no rejection reasons; both classes were represented. The female row was mono 16 kHz PCM16, 55,872 frames (3.492 s), four 16,000-sample windows; the male row was mono 16 kHz PCM16, 81,216 frames (5.076 s), six windows. Fan-out caps were 2 rows, 2 classes, 10 total windows, 1 beam, and 0 other expansion. Accuracy was1.0; macro-F1 was1.0; represented classes were2/2and class coverage was1.0.This is bounded real-data end-to-end operability evidence only. Two rows are not representative accuracy and are not a benchmark-quality claim. Only FP32 CPU Eval was measured; no FP16 or other-EP accuracy is implied. The former blocker was rejection of scalar
datasets.Value('string')targets before inference; the new capability accepts them only through a complete, exact, explicit mapping to checkpoint class IDs and pre-resolves every target in the bounded selected subset before the first model forward.5. Delta
Existing recipes refined:
examples/recipes/prithivMLmods_Common-Voice-Gender-Detection/cpu/cpu/audio-classification_fp32_config.json:/export/compatibility/transformers_attentionchanged from absent toeager, matching the generated baseline value.examples/recipes/prithivMLmods_Common-Voice-Gender-Detection/cpu/cpu/audio-classification_fp16_config.json:/export/compatibility/transformers_attentionchanged from absent toeager, matching baseline;/quantremains the existing FP16 quantization object, while baseline has no/quant.Parsed FP32 recipe content equals the generated baseline exactly. Parsed FP16 content equals baseline after substituting only the existing FP16
/quantobject. Recipe-free Eval acceptance passed through the final built FP32 model.examples/recipes/README.mdremains untouched.Code delta relative to dependency #1326:
src/winml/modelkit/eval/audio_classification_evaluator.py:_validate_target_schema,_target_for_row,_validate_scalar_string_mapping, andcomputeadd exact scalar-string mapping support and materialize all selected targets before inference.src/winml/modelkit/utils/eval_utils.py:_AUDIO_CLASSIFICATION_SCHEMAdocuments explicitly mapped scalar strings.tests/unit/eval/test_audio_classification_evaluator.py: focused class-wide regressions cover the new and preserved paths, including a valid-then-unmapped selected set that must fail with zero model forwards.Bug fix explanation:
datasets.Value('string')targets, such asfemaleandmale, was rejected during target-schema validation before inference even when the caller supplied an explicit mapping. The initial fix still resolved targets inside the inference loop, so a later unmapped value could fail only after an earlier row had already run inference.ClassLabeland sequence-valued label forms but had no scalar-string validation/resolution branch. The initial scalar-string path then interleaved_target_for_row()andpredict_logits()per row instead of validating the complete bounded selection atomically._validate_target_schemarecognizes scalar string features only when_validate_scalar_string_mappingproves a non-empty, one-to-one, complete mapping to contiguous checkpoint IDs;_target_for_rowresolves each observed value by exact key lookup;computematerializes every selected target before the firstpredict_logits()call._AUDIO_CLASSIFICATION_SCHEMAexposes that contract.ClassLabel, sequenceClassLabel/string multi-label behavior, metrics, raw streamingdecode=False, SoundFile decoding, and fixed-window aggregation are preserved. Intentional change is limited to target validation order and explicitly mapped scalar strings. Missing, empty, non-integer, duplicate-destination, out-of-range, incomplete, and unmapped observed values fail closed before inference; audio decode, preprocessing, and runtime failures remain per-row rejections with existing accounting.8010667eb20d0eb08e916157a6cc5080c91d385d, the reviewer's valid-then-unknown discriminator passed withforward_count=0and no partial output (1 passed in 37.77 s), and the full evaluator file passed18tests in10.76 s. The commands partition passed3,648tests with9skipped and1warning; license, Ruff oversrc/ tests/, full-package mypy over439source files, editor diagnostics, andgit diff --checkpassed. The earlier parent-head models partition remains prior unaffected evidence rather than a fresh repaired-head claim.6. Analyze summary - component level and op level
Analyze completed as
ANALYZE-PARTIAL-SUCCESSwith exit code 1 because six targets have no populated static rules. Static rule classification is not accelerator runtime execution. These results are reused from exact parente4d19ba1d4af532ba4cf0b047ff2fb395ac9d868after the evaluator-only repair was classified and all four model payloads were rehashed unchanged.Component-level summary
The five shared gaps are the final feature-extractor Gelu, feature-projection output Reshape, first encoder-layer Gemm input Reshape, projector Gemm input Reshape, and projector output Reshape. They remain unattributed because adjacency alone is not accepted as semantic ownership evidence. FP16 additionally has input/output precision-adapter Casts. Every source component is mapped; resolving transition ownership would require exporter provenance or an instrumented unoptimized export with stable correspondence, and requires no product repair.
Op-level summary
Rule-less targets CUDA/GPU, MIGraphX/GPU, TensorRT/GPU, DML/GPU, CPU/CPU, and VitisAI/NPU have no populated classifications. These are rules-availability gaps, not runtime failures or measured support claims.
7. Reproduce commands
Prerequisites: Windows PowerShell, Git,
uv, internet access to the public Hugging Face checkpoint/dataset, and sufficient disk/RAM for approximately 361 MB FP32 and 180 MB FP16 external-weight payloads. The commands clone the exact dependent branch, verify its SHA and dependency ancestry, install the locked environment, acquire the public static-rule repository, and reproduce build, perf, Analyze, bounded Eval, and quality checks.The Eval command is a two-row functional smoke only, not representative accuracy. Analyze is static rule classification, not accelerator runtime evidence.
Dependency and provenance
1bd919b583aa8ccd974e35fa6a1a132ac7e1c9f8, owns the generic audio evaluator implementation described above. This dependent PR does not duplicate or rewrite that ownership.ssss141414/add-common-voice-gender-dependent, exact head8010667eb20d0eb08e916157a6cc5080c91d385d; the dependency head is its verified ancestor.5f1368f5ee3296aab5799f55c31acf152e4f9c07, published knowledge-file SHA-2562f2a0f861df22a728aaf4cd6e02979c0756f0702d82720130567519ab469b031.