← All notes

A CWT node encoder, and what node_only actually tests

A new, opt-in encoder module was added on top of the existing coherence-graph model: a small convolutional network that learns a per-channel embedding directly from each channel's own time-frequency wavelet representation, independent of any cross-channel coherence. The natural question it raises — does this add anything the coherence features don't already provide, or could it stand in for the STFT-CNN baseline's own per-channel view — got a direct test this session, and the answer for the "stand in" framing turned out to be no.

What it is, and what it isn't

Each channel's wavelet coefficients get pooled down in time, run through a couple of small convolutions, then globally pooled to a single 8-number summary per channel. Those per-channel summaries feed into the same message-passing head the coherence-based model already uses. An ablation mode strips out the coherence features entirely, leaving only these per-channel summaries — the hope going in was that this would approximate what the project's STFT-CNN baseline sees: a per-channel time-frequency view with no explicit cross-channel structure.

That comparison doesn't actually hold up on inspection. The baseline's own convolution mixes all electrodes together directly on local time-frequency patches, over roughly 114 frequency bins, and its classifier reads a full spectrogram-like representation the whole way through. This new encoder looks at each channel completely alone, over only 8 frequency bins, and collapses everything down to 8 numbers per channel before any classification happens — and those 8 numbers still get routed through the coherence model's own edge-pair readout, which was built to summarize coherence vectors, not to classify from per-channel embeddings directly. It's a real ablation of the coherence-based model with its coherence stripped out, not a good-faith stand-in for the baseline architecture.

The direct test: does coherence-free ranking work at all?

Trained and evaluated on one real fold with coherence features removed entirely (only the per-channel encoder feeding the existing edge-pair head), against the same fold's numbers from the working coherence-only model and from the project's STFT-CNN baseline:

APROChit (raw→smoothed)
coherence-free encoder only0.032~0.50miss → miss
coherence-only model0.108–0.1410.83–0.88hit (mixed after smoothing)
STFT-CNN baseline0.1470.887hit → hit

Chance-level average precision on this fold's class balance is about 0.04. The coherence-free encoder landed right at chance; both the existing coherence-only model and the baseline clearly rank this fold well above it. Training loss on the coherence-free run stayed flat around chance for every epoch before early stopping ended it — not a crash or a broken gradient (verified the encoder's gradients do flow, and confirmed via direct log output that it really was running), just a signal that never learned to rank anything on this data in the time it was given.

Why adding it to the working model probably won't help either

The natural next question — if it doesn't work alone, does concatenating it onto the coherence model's existing, working edge features help or hurt? — wasn't run at real scale this session, but the reasoning against it is fairly direct. The coherence-based edge features already rank this data well and converge quickly; the new encoder is a randomly-initialized network that would need substantially more training to learn anything useful, so by the time the coherence side has a good checkpoint, the encoder side is still close to its starting point. And structurally, the model's readout was built around coherence-pair vectors, which isn't obviously the right place to route useful per-channel information even if the encoder had learned something. The most likely outcome of adding it to the working model is a small, hard-to-attribute change in either direction from the extra parameters and different initialization, not a meaningful capability gain.

Open items

The combined coherence-plus-encoder model hasn't actually been run at real scale to confirm the reasoning above, though it's treated as low priority given the direct evidence that the encoder alone doesn't rank this data. A genuinely fair "does raw per-channel time-frequency information add anything" test would need a baseline-style architecture — a shared convolution mixing channels directly, classifying from something spectrogram-like, no graph — rather than routing through the coherence model's edge-pair head; that was discussed and explicitly deferred, not built. And the channel-subset selector used elsewhere in the project doesn't shrink the channel count here either way — this encoder always runs on the full 23 channels regardless of that setting, only affecting how many coherence pairs get computed on top of it.