Skip to content

Multi-class merging with arbitrary class axis placement (resolves #20) - #30

Open
the-lay wants to merge 1 commit into
modernizefrom
multiclass-merger
Open

Multi-class merging with arbitrary class axis placement (resolves #20)#30
the-lay wants to merge 1 commit into
modernizefrom
multiclass-merger

Conversation

@the-lay

@the-lay the-lay commented Aug 2, 2026

Copy link
Copy Markdown
Owner

What & why

Rebuilds the 2022 multiclass Merger prototype (PR #21, unmergeable since the src-layout move) on the current codebase. Resolves #20 — the only externally-reported feature gap, open since 2022: model outputs like (256, 256, 6) for input tiles (256, 256, 4) were rejected by Merger.add because the class axis could only be prepended.

Stacked on #29 (revival baseline) — merge that first; GitHub will retarget this PR automatically.

API (deliberately smaller than the #21 prototype)

  • Merger(logits=N, logits_dim=d) — place the class axis at any position of the added tiles and merged output; negative indexing allowed. Default logits_dim=0 reproduces the previous prepend-only behavior exactly (verified by an equivalence test and the untouched pre-existing suite).
  • Merger(ignore_channels=True) — expect tiles without the Tiler's channel dimension, for models that consume all channels and emit class logits (the [IDEA] Figuring out how to use this library with TensorFlow multi-class and binary classification #20 scenario) or a single map. Requires channel_dimension on the Tiler.
  • merge(argmax=True) — argmaxes the logits axis wherever it lives.

Differences from the #21 sketch, for the record: logits keeps its name and validation (no logits_n rename), argmax stays a bool — #21's argmax: Optional[int] would have silently treated argmax=True as axis 1 — and no buffer renames (weights_sum/data_visits/save_visits untouched), so nothing breaks for existing users.

Implementation notes

  • Weights and visits buffers deliberately have no class axis (the window weight is identical for every class); broadcasting happens once at normalization via np.expand_dims.
  • With ignore_channels, the applied window drops the channel axis (which is always boxcar-weighted) and tile bboxes come from get_tile_bbox(..., with_channel_dim=False).
  • README gains a multi-class segmentation example.

Verification

🤖 Generated with Claude Code

https://claude.ai/code/session_01PvVX1JaNVaXJ2PJEu4KJzE

Resolves #20, supersedes #21.

- Merger(logits=N, logits_dim=d) places the class axis at any position
  of the added tiles and the merged output (negative indexing allowed);
  the default logits_dim=0 reproduces the previous prepend-only behavior
  exactly
- Merger(ignore_channels=True) makes Merger expect tiles without the
  Tiler's channel dimension, for models that consume all channels and
  emit per-class or single-map predictions
- merge(argmax=True) argmaxes the logits axis wherever it is
- weights/visits buffers stay class-axis-free (same weight per class),
  with broadcasting handled at normalization time

Compared to the 2022 prototype in #21, the public surface is smaller:
the logits parameter keeps its name and semantics, argmax stays a bool
(an int argmax would silently treat True as axis 1), and buffer names
are unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PvVX1JaNVaXJ2PJEu4KJzE
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.

1 participant