Skip to contents

Overview

Naive cross-decoding classifies test-domain patterns by correlating them with training-domain prototypes (class-mean patterns) — no domain adaptation, no learned transformation. It is the natural baseline for any cross-domain analysis: if it works, your representations generalise across contexts without correction.

Algorithm:

  1. Compute a prototype (mean pattern) for each category in the training domain.
  2. Correlate every test pattern with each prototype.
  3. Assign the category whose prototype has the highest correlation.

Correlations are passed through softmax to produce pseudo-probabilities.

Quick example

set.seed(42)
data_info <- gen_sample_dataset(
  D = c(10, 10, 10), nobs = 80, nlevels = 4,
  blocks = 4, external_test = TRUE
)

# Three ROIs
roi_mask <- NeuroVol(
  sample(1:3, length(data_info$dataset$mask), replace = TRUE),
  space(data_info$dataset$mask)
)

model <- naive_xdec_model(
  dataset = data_info$dataset,
  design  = data_info$design,
  return_predictions = TRUE
)

print(model)
#> Naive Cross-Decoding Model
#>   link_by:             (class labels) 
#>   training levels:     a, b, c, d 
#>   n_train:             80 
#>   n_test:              80 
#>   return_predictions:  TRUE
results <- run_regional(model, roi_mask)
results$performance_table
#> # A tibble: 3 × 3
#>   roinum Accuracy     AUC
#>    <int>    <dbl>   <dbl>
#> 1      1    0.2   -0.0292
#> 2      2    0.238 -0.0562
#> 3      3    0.212  0.0558
chance <- 1 / nlevels(data_info$design$y_test)
cat(sprintf("Chance level: %.0f%%\n", chance * 100))
#> Chance level: 25%

With random data, accuracy hovers around chance. With real fMRI data, above-chance accuracy indicates that category representations transfer across domains.

By default (link_by = NULL), prototypes are keyed by class label: all training trials for category A are averaged into one prototype, and each test trial is classified against these category prototypes.

When the same individual items appear in both domains (e.g., the same images during perception and recall), you can form item-level prototypes instead:

model <- naive_xdec_model(
  dataset = dataset,
  design  = design,
  link_by = "item_id"
)

This creates one prototype per item rather than per category, giving finer-grained matching when item identity is meaningful.

Searchlight analysis

Naive cross-decoding plugs directly into run_searchlight():

model <- naive_xdec_model(dataset = dataset, design = design)
sl_results <- run_searchlight(model, radius = 3)

The resulting accuracy map shows where category structure transfers across domains, voxel by voxel.

Troubleshooting

“requires external test set” — Naive cross-decoding needs separate train and test data. Provide external_test = TRUE in gen_sample_dataset(), or construct your mvpa_dataset() with both train_data and test_data.

All predictions are the same class — Prototypes may be too similar. Check inter-prototype correlations; if all are above ~0.9, the training domain does not carry enough discriminative information for the method to work.

Chance-level performance everywhere — This is the expected outcome when there is a large systematic domain shift. Consider domain-adaptive models such as remap_rrr_model() (see vignette("REMAP_RRR")).

Next steps