Variance of ICA Components

Hello!

I am running ICA in order to process EEG data, and I would like to know the variance for each component that is removed. I can access this information if I create an HTML report, but is there a way to export this information to a dataframe or table?

Here is some necessary information:

  • MNE version: 1.0.3
  • operating system: Windows 11

Thank you for your help!

Hi, please take a look at the following example, which should answer your question.

# %%
import mne

sample_dir = mne.datasets.sample.data_path()
sample_fname = sample_dir / 'MEG' / 'sample' / 'sample_audvis_raw.fif'

raw = (
    mne.io.read_raw_fif(sample_fname)
    .crop(tmax=60)
    .pick_types(eeg=True)
    .load_data()
)

# %% Fit ICA
ica = mne.preprocessing.ICA(n_components=15, method='picard')
ica.fit(raw)

# %% Retrieve explained variance
# unitize variances explained by PCA components, so the values sum to 1
pca_explained_variances = ica.pca_explained_variance_ / ica.pca_explained_variance_.sum()

# Now extract the variances for those components that were used to perform ICA
ica_explained_variances = pca_explained_variances[:ica.n_components_]

for idx, var in enumerate(ica_explained_variances):
    print(
        f'Explained variance for ICA component {idx}: '
        f'{round(100 * var, 1)}%'
    )
Explained variance for ICA component 0: 66.9%
Explained variance for ICA component 1: 11.3%
Explained variance for ICA component 2: 3.4%
Explained variance for ICA component 3: 2.4%
Explained variance for ICA component 4: 1.9%
Explained variance for ICA component 5: 1.6%
Explained variance for ICA component 6: 1.3%
Explained variance for ICA component 7: 1.1%
Explained variance for ICA component 8: 1.0%
Explained variance for ICA component 9: 0.8%
Explained variance for ICA component 10: 0.7%
Explained variance for ICA component 11: 0.6%
Explained variance for ICA component 12: 0.6%
Explained variance for ICA component 13: 0.6%
Explained variance for ICA component 14: 0.5%

Best wishes,
Richard

3 Likes

(Note, there was a bug in my above code related to unitizing the variances. I have now fixed this, and also updated the produced output.)

1 Like

This is very helpful. Thank you, Richard!

@lmctx13

@agramfort just pointed out on GitHub that this approach is actually mathematically incorrect. We’re working on something that will make it easy for users to directly retrieve the explained variance from the ICA object after fitting. I’ll let you know when it’s ready (end of this week). If you’re curious, you can track our progress here:

Best wishes,
Richard

1 Like

That sounds great, and I will check it out. Thank you so much!

Hi @richard,

Thanks for that function! I would have a question regarding the interpretation of those values. As is mentioned in the documentation, because ica components are not orthogonal, negative explained variances are possible. Based, on the formula how the variance is computed:

that would occur when the variance of the data after removal of the components has more variance than the original data (so mean_var_diff > mean_var_orig). Intuitively this sounds, as if it wouldn’t be a good idea to remove those components then (if they increase the variance).
Do you happen to have more insights under which circumstances these negative variances can occur, what that means and what to do about it?

Thanks,
Eduard

Hello, it’s actually quite possible that the removal of one specific component increases variance of the reconstructed data. The algorithm implemented here is the one used by EEGLAB; I suggest you read up on it here:

Search that page for “pvaf”, which is the metric we’re calculating.

Best wishes,
Richarfd

Thanks! Yeah, I read that, unfortunately, they don’t give much info on the how’s and why’s of this phenomenon/algorithm. But, I guess if it’s rather normal, there is no reason to worry.

Thanks,
Eduard

You could maybe ask on the EEGLAB mailing list :thinking:

1 Like