pyntbci.classifiers.UnsupervisedRCCA
- class pyntbci.classifiers.UnsupervisedRCCA(stimulus: NDArray, fs: int, event: str = 'duration', onset_event: bool = True, decoding_length: float = None, decoding_stride: float = None, encoding_length: float | list[float] = 0.3, encoding_stride: float | list[float] = None, latency: NDArray = None, tmin: float = 0, n_components: int = 1, gamma_x: float | list[float] | NDArray = None, gamma_m: float | list[float] | NDArray = None, alpha_x: float = None, alpha_m: float = None, cumulative: bool = True, confidence: bool = False, posthoc: bool = False, response_prior: NDArray = None, response_prior_gamma: float = 1.0)[source]
Unsupervised adaptive reconvolution CCA classifier for calibration-free c-VEP decoding [6].
Instead of a supervised calibration, each trial is decoded by fitting a separate rCCA per candidate stimulus (as a hypothesis) and selecting the stimulus whose model best fits the trial, i.e. yields the highest correlation between the spatially filtered EEG and the temporally filtered stimulus structure matrix. This is the instantaneous mode (cumulative=False), which treats every trial independently.
Three cumulative extensions build a model from previously decoded trials, using their predicted labels as pseudo-labels (there are no ground-truth labels in a calibration-free setting):
cumulative=True: every hypothesis is fit on all previously decoded trials (at their pseudo-labels) plus the current trial (hypothesized as each candidate). This is mathematically identical to refitting from scratch on the full history every trial, but is done efficiently by keeping a single running covariance of the pseudo-labeled history (see RunningCovariance in utilities) shared across all hypotheses, so each trial only adds its own (bounded) contribution rather than reprocessing the whole history. The first trial, with no history, reduces to the instantaneous mode.
confidence=True (implies cumulative): each trial is weighted by a confidence, so that high-confidence trials drive the model updates and low-confidence trials are suppressed. The confidence is the normalized correlation margin (rho_winner - rho_runner_up) / std(rho_except_winner), estimated from an instantaneous pass (as in [6]), and used as a per-trial weight in the running covariance.
posthoc=True (implies cumulative): after each trial, all previously decoded trials are re-decoded with the just-updated (presumably better) model and their pseudo-labels are corrected, which then affects subsequent updates. This is the only mode that must retain the past trials’ EEG (in X_hist_), since re-decoding needs the raw data; a changed label is applied to the running covariance as an exact remove-then-re-add, avoiding a full refit. The other modes keep no raw data (only the running covariance and the list of pseudo-labels).
These flags reproduce the four variants of [6]: instantaneous (all False), cumulative (cumulative), confidence-weighted cumulative (cumulative, confidence), and confidence-weighted cumulative with post hoc re-analysis (cumulative, confidence, posthoc).
Note, decoding is inherently online and stateful: predict() streams trials in their given (chronological) order, decoding each with the model learned from the ones before it, and the internal session persists across calls. Decoding trials one at a time therefore accumulates exactly as decoding them in one call does (as needed for real-time use where trials arrive one by one): [predict(X[[i]]) for i in range(n_trials)] gives the same result as predict(X). Because state persists, predict()/decision_function() are not pure functions; call fit() (or pass reset=True) to start a fresh session, e.g. before an independent replay. The single-trial partial_fit_predict() is the same online step exposed directly. The structure-matrix machinery of rCCA (event and encoding matrices, latency correction, optional spatio-spectral decoding matrix) is reused, and the core CCA is solved with the same _solve_cca as CCA in transformers. With short trials or a wide encoding matrix, the per-hypothesis covariances can be ill-conditioned; set gamma_x/gamma_m (or alpha_x/alpha_m) to regularize, as for supervised rCCA.
- Parameters:
stimulus (NDArray) – The stimulus used for stimulation of shape (n_classes, n_samples). Should be sampled at fs. One cycle (i.e., one stimulus-repetition) is sufficient.
fs (int) – The sampling frequency of the EEG data in Hz.
event (str (default: "duration")) – The event definition to map stimulus to events.
onset_event (bool (default: True)) – Whether to add an event for the onset of stimulation. Added as last event.
decoding_length (float (default: None)) – The length of the spectral filter for each data channel in seconds. If None, it is set to 1/fs, equivalent to 1 sample, such that no phase-shifting is performed and thus no (spatio-)spectral filter is learned.
decoding_stride (float (default: None)) – The stride of the spectral filter for each data channel in seconds. If None, it is set to 1/fs.
encoding_length (float | list[float] (default: 0.3)) – The length of the transient response(s) for each of the events in seconds.
encoding_stride (float | list[float] (default: None)) – The stride of the transient response(s) for each of the events in seconds. If None, it is set to 1/fs.
latency (NDArray (default: None)) – The raster latencies of each of the classes of shape (n_classes,) that the templates need to be corrected for.
tmin (float (default: 0)) – The start of stimulation in seconds. Can be used if there was a delay in the marker.
n_components (int (default: 1)) – The number of CCA components to use. Decoding and confidence use the first component only, matching [6].
gamma_x (float | list[float] | NDArray (default: None)) – Regularization on the covariance matrix for CCA along X (channels), see rCCA.
gamma_m (float | list[float] | NDArray (default: None)) – Regularization on the covariance matrix for CCA along M (samples), see rCCA.
alpha_x (float (default: None)) – Amount of variance to retain in computing the inverse of the covariance matrix of X. If None, all variance.
alpha_m (float (default: None)) – Amount of variance to retain in computing the inverse of the covariance matrix of M. If None, all variance.
cumulative (bool (default: True)) – Whether to learn cumulatively from previously decoded trials (using their pseudo-labels). If False, each trial is decoded instantaneously and independently.
confidence (bool (default: False)) – Whether to weight each trial by its confidence during cumulative updates. Implies cumulative.
posthoc (bool (default: False)) – Whether to re-decode and relabel all previous trials after each update. Implies cumulative, and retains the past trials’ EEG in X_hist_.
response_prior (NDArray (default: None)) – A prior on the expected transient response (e.g. a flash-VEP: a negative peak near 75 ms, a positive peak near 100 ms, and a negative peak near 125 ms), sampled at fs. Either one response of length n_event_samples (applied to every event) or the full concatenation of the per-event responses of length n_features (matching the temporal filter r_; see encoding_length). If given, the learned response is softly regularized toward it (see response_prior_gamma), which anchors the response’s absolute phase. This is what makes decoding work for circularly-shifted codes (e.g. shifted m-sequences): without it, an unconstrained response can circularly slide to make every candidate stimulus fit equally well (the more so the longer encoding_length), so the classes become indistinguishable. If None (default), no prior is used.
response_prior_gamma (float (default: 1.0)) – The strength of the soft regularization toward response_prior, ranging from 0 (ignore the prior, purely data-driven) upwards (larger pulls the response more strongly toward the prior; in the limit the response equals the prior). Only used if response_prior is not None.
- classes_
The class labels of shape (n_classes,).
- Type:
NDArray
- events_
The list of events used to map the stimulus to, as set by the internal rCCA.
- Type:
list
- labels_
The pseudo-labels (predicted labels) of the decoded trials, in order.
- Type:
list
- confidences_
The confidence of each decoded trial, in order.
- Type:
list
- w_
The spatial filter of the most recently winning model of shape (n_channels, n_components).
- Type:
NDArray
- r_
The temporal filter of the most recently winning model of shape (n_features, n_components).
- Type:
NDArray
- cov_
The running covariance of the pseudo-labeled history (only populated if cumulative).
- Type:
- X_hist_
The (decoded) EEG of the decoded trials, retained only if posthoc, for re-decoding.
- Type:
list
References
- decision_function(X: NDArray, reset: bool = False) NDArray[source]
Decode a sequence of trials online and return the per-trial per-class correlation scores.
Stateful and online, see predict() (of which this is the score-returning counterpart).
- Parameters:
X (NDArray) – The EEG data of shape (n_trials, n_channels, n_samples), in chronological order.
reset (bool (default: False)) – Whether to discard the current online session and start fresh before decoding X, see predict().
- Returns:
scores – The per-trial per-class correlation scores of shape (n_trials, n_classes).
- Return type:
NDArray
- fit(X: NDArray = None, y: NDArray = None) ClassifierMixin[source]
Set up the classifier (calibration-free: no training data or labels are used).
- Parameters:
X (NDArray (default: None)) – Not used, present for scikit-learn API consistency.
y (NDArray (default: None)) – Not used, present for scikit-learn API consistency.
- Returns:
self – Returns the instance itself.
- Return type:
ClassifierMixin
- partial_fit_predict(X: NDArray) tuple[int, float, NDArray][source]
Decode a single trial online, updating the model (if cumulative) with its pseudo-label.
- Parameters:
X (NDArray) – The EEG data of a single trial of shape (n_channels, n_samples) or (1, n_channels, n_samples).
- Returns:
label (int) – The predicted (pseudo-) label of the trial.
confidence (float) – The confidence of the prediction.
scores (NDArray) – The per-class correlation scores of shape (n_classes,).
- predict(X: NDArray, reset: bool = False) NDArray[source]
Decode a sequence of trials online, in the given (chronological) order.
Each trial is decoded with the model learned from all trials decoded so far, and then folds into that model (using its own prediction as a pseudo-label) if cumulative. This is a stateful, online operation: the internal session persists across calls, so decoding trials one at a time is equivalent to decoding them in a single call, i.e.
[predict(X[[i]]) for i in range(n_trials)]gives the same result aspredict(X), as needed for real-time use where trials arrive one by one. Because it persists state, predict() is not a pure function: call fit() (or pass reset=True) to start a fresh session, e.g. before an independent replay.- Parameters:
X (NDArray) – The EEG data of shape (n_trials, n_channels, n_samples), in chronological order.
reset (bool (default: False)) – Whether to discard the current online session and start fresh before decoding X. Use reset=True (or a fresh instance, or fit()) for a self-contained replay; leave False to continue an ongoing session.
- Returns:
y – The predicted labels of shape (n_trials,).
- Return type:
NDArray
- set_decision_function_request(*, reset: bool | None | str = '$UNCHANGED$') UnsupervisedRCCA
Configure whether metadata should be requested to be passed to the
decision_functionmethod.Note that this method is only relevant when this estimator is used as a sub-estimator within a meta-estimator and metadata routing is enabled with
enable_metadata_routing=True(seesklearn.set_config()). Please check the User Guide on how the routing mechanism works.The options for each parameter are:
True: metadata is requested, and passed todecision_functionif provided. The request is ignored if metadata is not provided.False: metadata is not requested and the meta-estimator will not pass it todecision_function.None: metadata is not requested, and the meta-estimator will raise an error if the user provides it.str: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (
sklearn.utils.metadata_routing.UNCHANGED) retains the existing request. This allows you to change the request for some parameters and not others.Added in version 1.3.
- Parameters:
reset (str, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED) – Metadata routing for
resetparameter indecision_function.- Returns:
self – The updated object.
- Return type:
object
- set_predict_request(*, reset: bool | None | str = '$UNCHANGED$') UnsupervisedRCCA
Configure whether metadata should be requested to be passed to the
predictmethod.Note that this method is only relevant when this estimator is used as a sub-estimator within a meta-estimator and metadata routing is enabled with
enable_metadata_routing=True(seesklearn.set_config()). Please check the User Guide on how the routing mechanism works.The options for each parameter are:
True: metadata is requested, and passed topredictif provided. The request is ignored if metadata is not provided.False: metadata is not requested and the meta-estimator will not pass it topredict.None: metadata is not requested, and the meta-estimator will raise an error if the user provides it.str: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (
sklearn.utils.metadata_routing.UNCHANGED) retains the existing request. This allows you to change the request for some parameters and not others.Added in version 1.3.
- Parameters:
reset (str, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED) – Metadata routing for
resetparameter inpredict.- Returns:
self – The updated object.
- Return type:
object
- set_score_request(*, sample_weight: bool | None | str = '$UNCHANGED$') UnsupervisedRCCA
Configure whether metadata should be requested to be passed to the
scoremethod.Note that this method is only relevant when this estimator is used as a sub-estimator within a meta-estimator and metadata routing is enabled with
enable_metadata_routing=True(seesklearn.set_config()). Please check the User Guide on how the routing mechanism works.The options for each parameter are:
True: metadata is requested, and passed toscoreif provided. The request is ignored if metadata is not provided.False: metadata is not requested and the meta-estimator will not pass it toscore.None: metadata is not requested, and the meta-estimator will raise an error if the user provides it.str: metadata should be passed to the meta-estimator with this given alias instead of the original name.
The default (
sklearn.utils.metadata_routing.UNCHANGED) retains the existing request. This allows you to change the request for some parameters and not others.Added in version 1.3.
- Parameters:
sample_weight (str, True, False, or None, default=sklearn.utils.metadata_routing.UNCHANGED) – Metadata routing for
sample_weightparameter inscore.- Returns:
self – The updated object.
- Return type:
object