Feature-RSA Advanced Workflows
Source:vignettes/Feature_RSA_Advanced_Workflows.Rmd
Feature_RSA_Advanced_Workflows.RmdOnce ordinary feature-RSA is working, the next problem is usually transfer. Sometimes you want to stay within one ROI and ask whether a feature space explains held-out data. Sometimes you want to move across cognitive states. Sometimes you want to ask whether geometry learned in one ROI appears in another.
Those are different estimands. This vignette is a short guide to choosing the right one and interpreting the result without mixing them together.
What is the shortest map of the workflow space?
advanced_summary <- build_advanced_summary()
knitr::kable(advanced_summary, digits = 3)| workflow | core_function | summary_value |
|---|---|---|
| within_roi | feature_rsa_model() | 0.036 |
| cross_state_da | feature_rsa_da_model() | 0.090 |
| cross_roi_generalization | feature_rsa_cross_connectivity() | 0.000 |
| offset_diagnostics | feature_rsa_cross_connectivity(adjust = ‘double_center’) | 0.162 |
The table gives you four practical signals:
- a within-ROI held-out geometry score
- the gain from adapting across states instead of using source rows alone
- the diagonal advantage in the ROI_i -> ROI_j matrix
- the spread of source and target offsets that can create stripe patterns
When is standard feature-RSA enough?
Stay with feature_rsa_model() when your question is
local to one ROI and one state. You fit the model in the usual way, hold
out data within that state, and read the ROI-wise geometry scores from
run_regional().
base_fit <- build_base_feature_rsa()
base_fit$result$performance_table[, c("roinum", "rdm_correlation")]
#> # A tibble: 4 × 2
#> roinum rdm_correlation
#> <int> <dbl>
#> 1 1 -0.00825
#> 2 2 0.0563
#> 3 3 0.00301
#> 4 4 0.0912This is the right default when you want to know whether a feature space explains one parcel on its own terms.
When do you need domain adaptation?
Switch to feature_rsa_da_model() when the feature space
is shared but the state changes. The canonical example is encoding to
recall: the rows still refer to the same latent content, but the source
and target mappings need not be identical.
da_perf <- build_small_da_example()
knitr::kable(da_perf, digits = 3)| model | target_rdm_correlation | target_r2_full |
|---|---|---|
| source_only | 0.857 | 0.566 |
| coupled_da | 0.948 | 0.835 |
The important comparison is not just target prediction in the
abstract. It is whether a model that can adapt on target-train rows
recovers more held-out target geometry than a source-only baseline. When
the target-side representation is itself estimated from target data, use
a fold-aware target_builder as shown in
vignette("Feature_RSA_Domain_Adaptation").
When do you want ROI_i -> ROI_j transfer?
Use feature_rsa_cross_connectivity() when you want a
full asymmetric ROI x ROI matrix. The rows are source ROIs, the columns
are target ROIs, and the off-diagonals tell you whether geometry learned
in one parcel matches held-out observed geometry in another.
| 1 | 2 | 3 | 4 |
|---|---|---|---|
| -0.01 | 0.06 | -0.01 | 0.13 |
| 0.01 | 0.06 | 0.03 | 0.03 |
| -0.03 | 0.09 | 0.00 | 0.07 |
| 0.01 | 0.03 | 0.00 | 0.09 |
This is the right analysis when ROI size differs and voxel-space weight transfer would be ill-posed, but you still want to ask whether representational geometry generalizes across parcels.
What do you do about source-dominant and target-dominant ROIs?
If the ROI x ROI matrix shows vertical or horizontal striping, some ROIs are globally easy targets or globally strong sources. That can be a real feature of the data, but it can also swamp the pair-specific structure you actually care about.
offset_table <- build_offset_example()
knitr::kable(offset_table, digits = 2)| roinum | source_offset | target_offset |
|---|---|---|
| 1 | 0.13 | 0.13 |
| 2 | 0.08 | 0.11 |
| 3 | 0.00 | 0.05 |
| 4 | -0.21 | -0.29 |
Use adjust = "double_center" when you want to remove
additive source and target main effects from the ROI x ROI matrix
itself. Use adjust = "residualize_mean" when you think the
stripes are driven by one dominant common geometry that should be
removed before the cross-correlation is computed.
Decision rules
- Use
feature_rsa_model()for one ROI, one state, held-out evaluation in the same domain. - Use
feature_rsa_da_model()when the feature space is shared across states and the target mapping may shift. - Use
feature_rsa_cross_connectivity()when you want ROI-to-ROI generalization at the level of predicted versus observed geometry. - Use
feature_rsa_connectivity()when you want a symmetric similarity matrix of predicted geometries themselves. - Use
adjust = "double_center"oradjust = "residualize_mean"only after you are clear about which nuisance pattern you are trying to remove.
Next steps
For the full cross-state workflow, including fold-aware target
rebuilding, see vignette("Feature_RSA_Domain_Adaptation").
For the full ROI-to-ROI workflow and stripe-mitigation examples, see
vignette("Feature_RSA_Connectivity").