Problems about ''SVD did not converge''

Hello everyone:

I am a beginner in EEG processing.I following the example CSPto write my own code,but I had some problems.
In tutorial of CSP, he doesn’t use ica.But someting wrong when I after ICA.
After ICA, I use the raw data to make epoch, in tutorial he dosen’t use baseline, But I let it use the default settings. Later I got the error
I try many times, and find
if ICA + mne.Epochs(baseline=None) = no error
if no ICA + mne.Epochs(baseline = (None,0) ) = no error
if ICA + mne.Epochs(baseline = (None,0)) = error ‘‘SVD did not converge’’
What’s wrong with my code, or is my thinking wrong?
Forgive me my English is too bad, I hope you can understand :slightly_frowning_face:

  • MNE version:1.0.3
  • operating system:Windows 10
  • dataset: BCI Competition datasets IV-2a
import mne
import numpy as np
import scipy.io as sio
import matplotlib.pyplot as plt
from mne.decoding import CSP
from sklearn.svm import SVC
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import cross_val_score, StratifiedKFold
from sklearn.metrics import  cohen_kappa_score

mne.set_log_level('warning')
sfreq = 250
tmin, tmax = -1., 4.
event_id = dict(left=1, right=2, foot=3, tougue=4)
eog = ['EOG-left', 'EOG-central', 'EOG-right']
input_fname = "D:\BCI Competition\week16\A01T.gdf"
raw = mne.io.read_raw_gdf(input_fname, eog=eog, preload=True)

old_chans_name = raw.info.get('ch_names')[:-3]
standard_chans_name = ['Fz', 'FC3', 'FC1', 'FCz', 'FC2', 
                       'FC4', 'C5', 'C3', 'C1', 'Cz', 
                       'C2', 'C4', 'C6', 'CP3', 'CP1',
                       'CPz', 'CP2', 'CP4', 'P1', 'Pz', 
                       'P2', 'POz']
rename_dict = {old_chans_name[i]:standard_chans_name[i] for i in range(len(old_chans_name))}
raw.rename_channels(rename_dict)
raw.set_montage('standard_1020')

raw.filter(7., 30., fir_design='firwin', skip_by_annotation='edge')

ica = mne.preprocessing.ICA(n_components=15, 
                            random_state=97)
ica.fit(raw)
# ica.plot_sources(raw)
# ica.plot_components(outlines = "skirt")
bad_idx, scores =ica.find_bads_eog(raw)
# print(bad_idx)
ica.exclude = bad_idx
# ica.plot_overlay(raw, picks='eeg')
raw_data = ica.apply(raw,exclude = ica.exclude)

mapping = {'769': 1, '770': 2, '771': 3, '772': 4}
events,_ = mne.events_from_annotations(raw_data, event_id=mapping)
picks = mne.pick_types(raw_data.info, eeg=True)
epochs = mne.Epochs(raw_data, 
                    events, 
                    event_id, 
                    tmin, tmax, 
                    proj=True, 
                    picks=picks, 
#                     baseline=None, 
                    preload=True
                   )
epochs_train = epochs.copy().crop(tmin=1, tmax=4)         
labels = epochs.events[:, -1]

scores = []
epochs_data = epochs.get_data()                                                        
epochs_data_train = epochs_train.get_data()                                            
kf = StratifiedKFold(n_splits=5, 
                     shuffle=True, 
                     random_state=10
                    )                                 
cv_split = kf.split(epochs_data_train,
                    labels)
svm = SVC()                                          
mms = MinMaxScaler()
csp = CSP(n_components=4,
          reg=None,
          log=False,
          norm_trace=False
         )
clf = Pipeline([('CSP', csp), ('MMS', mms), ('SVM', svm)])  
scores = cross_val_score(clf, 
                         epochs_data_train, 
                         labels, 
                         cv=kf, 
                         n_jobs=-1
                        ) 
print("Classification accuracy: {:.4f}".format(np.mean(scores)))                          
csp.fit_transform(epochs_data, labels)

csp.plot_patterns(epochs.info, 
                  ch_type='eeg', 
                  units='Patterns (AU)', 
                  size=1.5
                 )

ValueError                                Traceback (most recent call last)
Input In [13], in <cell line: 19>()
     13 csp = CSP(n_components=4,
     14           reg=None,
     15           log=False,
     16           norm_trace=False
     17          )
     18 clf = Pipeline([('CSP', csp), ('MMS', mms), ('SVM', svm)])  
---> 19 scores = cross_val_score(clf, 
     20                          epochs_data_train, 
     21                          labels, 
     22                          cv=kf, 
     23                          n_jobs=-1
     24                         ) 
     25 print("Classification accuracy: {:.4f}".format(np.mean(scores)))                          
     26 csp.fit_transform(epochs_data, labels)

File ~\.conda\envs\pytorch\lib\site-packages\sklearn\model_selection\_validation.py:515, in cross_val_score(estimator, X, y, groups, scoring, cv, n_jobs, verbose, fit_params, pre_dispatch, error_score)
    512 # To ensure multimetric format is not supported
    513 scorer = check_scoring(estimator, scoring=scoring)
--> 515 cv_results = cross_validate(
    516     estimator=estimator,
    517     X=X,
    518     y=y,
    519     groups=groups,
    520     scoring={"score": scorer},
    521     cv=cv,
    522     n_jobs=n_jobs,
    523     verbose=verbose,
    524     fit_params=fit_params,
    525     pre_dispatch=pre_dispatch,
    526     error_score=error_score,
    527 )
    528 return cv_results["test_score"]

File ~\.conda\envs\pytorch\lib\site-packages\sklearn\model_selection\_validation.py:285, in cross_validate(estimator, X, y, groups, scoring, cv, n_jobs, verbose, fit_params, pre_dispatch, return_train_score, return_estimator, error_score)
    265 parallel = Parallel(n_jobs=n_jobs, verbose=verbose, pre_dispatch=pre_dispatch)
    266 results = parallel(
    267     delayed(_fit_and_score)(
    268         clone(estimator),
   (...)
    282     for train, test in cv.split(X, y, groups)
    283 )
--> 285 _warn_or_raise_about_fit_failures(results, error_score)
    287 # For callabe scoring, the return type is only know after calling. If the
    288 # return type is a dictionary, the error scores can now be inserted with
    289 # the correct key.
    290 if callable(scoring):

File ~\.conda\envs\pytorch\lib\site-packages\sklearn\model_selection\_validation.py:367, in _warn_or_raise_about_fit_failures(results, error_score)
    360 if num_failed_fits == num_fits:
    361     all_fits_failed_message = (
    362         f"\nAll the {num_fits} fits failed.\n"
    363         "It is very likely that your model is misconfigured.\n"
    364         "You can try to debug the error by setting error_score='raise'.\n\n"
    365         f"Below are more details about the failures:\n{fit_errors_summary}"
    366     )
--> 367     raise ValueError(all_fits_failed_message)
    369 else:
    370     some_fits_failed_message = (
    371         f"\n{num_failed_fits} fits failed out of a total of {num_fits}.\n"
    372         "The score on these train-test partitions for these parameters"
   (...)
    376         f"Below are more details about the failures:\n{fit_errors_summary}"
    377     )

ValueError: 
All the 5 fits failed.
It is very likely that your model is misconfigured.
You can try to debug the error by setting error_score='raise'.

Below are more details about the failures:
--------------------------------------------------------------------------------
5 fits failed with the following error:
Traceback (most recent call last):
  File "C:\Users\Admin\.conda\envs\pytorch\lib\site-packages\sklearn\model_selection\_validation.py", line 686, in _fit_and_score
    estimator.fit(X_train, y_train, **fit_params)
  File "C:\Users\Admin\.conda\envs\pytorch\lib\site-packages\sklearn\pipeline.py", line 378, in fit
    Xt = self._fit(X, y, **fit_params_steps)
  File "C:\Users\Admin\.conda\envs\pytorch\lib\site-packages\sklearn\pipeline.py", line 336, in _fit
    X, fitted_transformer = fit_transform_one_cached(
  File "C:\Users\Admin\.conda\envs\pytorch\lib\site-packages\joblib\memory.py", line 349, in __call__
    return self.func(*args, **kwargs)
  File "C:\Users\Admin\.conda\envs\pytorch\lib\site-packages\sklearn\pipeline.py", line 870, in _fit_transform_one
    res = transformer.fit_transform(X, y, **fit_params)
  File "C:\Users\Admin\.conda\envs\pytorch\lib\site-packages\mne\decoding\csp.py", line 236, in fit_transform
    return super().fit_transform(X, y=y, **fit_params)
  File "C:\Users\Admin\.conda\envs\pytorch\lib\site-packages\mne\decoding\mixin.py", line 33, in fit_transform
    return self.fit(X, y, **fit_params).transform(X)
  File "C:\Users\Admin\.conda\envs\pytorch\lib\site-packages\mne\decoding\csp.py", line 184, in fit
    self.patterns_ = pinv(eigen_vectors)
  File "C:\Users\Admin\.conda\envs\pytorch\lib\site-packages\mne\fixes.py", line 1056, in pinv
    u, s, vh = np.linalg.svd(a, full_matrices=False)
  File "<__array_function__ internals>", line 180, in svd
  File "C:\Users\Admin\.conda\envs\pytorch\lib\site-packages\numpy\linalg\linalg.py", line 1648, in svd
    u, s, vh = gufunc(a, signature=signature, extobj=extobj)
  File "C:\Users\Admin\.conda\envs\pytorch\lib\site-packages\numpy\linalg\linalg.py", line 97, in _raise_linalgerror_svd_nonconvergence
    raise LinAlgError("SVD did not converge")
numpy.linalg.LinAlgError: SVD did not converge

Hello @Hongyuan and welcome to the forum!

I wonder if it may have something to do with the reduced rank of your data after rejecting ICA components. Could you try with

n_eeg_chans = len(
    raw
    .copy()
    .pick_types(eeg=True)
    .ch_names
)
rank = {
    'eeg': n_eeg_chans - len(ica.exclude)
}
csp = CSP(
    ...,
    rank=rank
)

Best wishes,
Richard

Thank you for your reply Richard!
I put them in there(right?)
but, it still dosen’t work. If I use baseline,the wrong codes are same as above.

scores = []
epochs_data = epochs.get_data()                                                        
epochs_data_train = epochs_train.get_data()                                            
kf = StratifiedKFold(n_splits=5, 
                     shuffle=True, 
                     random_state=10
                    )                                 
cv_split = kf.split(epochs_data_train,
                    labels)

n_eeg_chans = len(raw.copy().pick_types(eeg=True).ch_names)
rank = {'eeg': n_eeg_chans - len(ica.exclude)}

svm = SVC()                                          
mms = MinMaxScaler()
csp = CSP(n_components=4,
#           reg=None,
#           log=True,
#           norm_trace=False
          rank=rank
         )
clf = Pipeline([('CSP', csp), ('MMS', mms), ('SVM', svm)])  
scores = cross_val_score(clf, 
                         epochs_data_train, 
                         labels, 
                         cv=kf, 
                         n_jobs=-1
                        ) 
print("Classification accuracy: {:.4f}".format(np.mean(scores)))                          
csp.fit_transform(epochs_data, labels)

csp.plot_patterns(epochs.info, 
                  ch_type='eeg', 
                  units='Patterns (AU)', 
                  size=1.5
                 )