ICA n_components & n_pca_components

  • MNE version: 1.5.1
  • operating system:macOS-14.0-arm64-i386-64bit

Hi everyone,

I am somehow confused about accounting for rank deficiency during ICA.

Before ICA, I re-referenced the data to the average and interpolated bad channels. I did not reset the bad channels after interpolation to be able to use the #interpolated to calculate the n_components to reduce the dimensionality (by 1 for average reference and 1 for each interpolated channel).

It is somehow unpractical to not reset bads after interpolation, is there any other method or way in which I can store the #interpolated within the data?

            # decide on component number for ICA
            good_channels = mne.pick_types(raw_ica_filtered.info, meg=False, eeg=True, exclude='bads')
            best_n_components = len(good_channels) - 1 # -1 for the acerage rereferencing beforehand
            print("Components after having accounted for rank deficiency: ", best_n_components)
            
            # now reset bads because they have been interpolated beforehand
            raw_ica_filtered.info["bads"] = []
            prep_data.info["bads"] = []
            print("Number of bad channels for raw_ica_filtered: ", raw_ica_filtered.info["bads"])
            print("Number of bad channels for prep_data: ", prep_data.info["bads"])
            
            # Set up and fit the ICA
            ica = ICA(
                n_components=best_n_components, # reduce the dim (by 1 for average reference and 1 for each interpolated channel) for optimal ICA performance
                max_iter="auto", 
                method="infomax", 
                random_state=97,
                fit_params=dict(extended=True)
                ) 
            ica.fit(raw_ica_filtered)
            ica

Then when applying the ICA, I used the same number of n for n_pca_components:

            ica.apply(prep_ica_data, exclude=exclude_index, n_pca_components=best_n_components) 

So my two questions are:

  1. Having followed these steps, have I effectively accounted for rank deficiency?
  2. Is there any other method or way in which I can store the #interpolated within the data?

Cheers,
Deniz

Hello, you can simply stick with the default values here – we automatically account for rank deficiency, which seems to work in almost all cases. So: don’t set n_components, don’t set n_pca_components, and you should be good in 99% of the cases.

After fitting, check ica.n_components_ (mind the trailing underscore) to find out how many components were kept.

Richard

Sounds great, thank you!

So MNE does keep track of the preprocessing steps applied earlier, am I understanding it right?

No, or let’s say only to some extent. But by default, in ICA we use SVD and disregard values not contributing to 99.999% (or maybe there are another few 9’s more, cannot check right now!) of the variance. There ought to be some explanation in the ICA API documentation actually! @larsoner would know the nitty-gritty details.

Best wishes,
Richard

1 Like