NeuroTechX / NeuroTechX/moabb

ValueError: need at least one array to concatenate When using Shin2017A dataset

Open
#549 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

braindecode bug moabb
Dominant language
Python
Stars
1.1k
Forks
264
Avg merge
1d 13m
Merged PRs (30d)
23

Description

Expected Result

Using Shin2017A dataset to do a CrossSession LeftRightImagery classification.

Current Result

Shin2017A-CrossSession:   0%|          | 0/29 [01:04<?, ?it/s]
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[9], line 3
      1 pipes = {}
      2 pipes["EEGNetV4"] = make_pipeline(clf)
----> 3 results = evaluation.process(pipelines=pipes)
      4 print("============results===========")
      5 print(results)

File /opt/conda/lib/python3.10/site-packages/moabb/evaluations/base.py:188, in BaseEvaluation.process(self, pipelines, param_grid, postprocess_pipeline)
    179     # (we only keep the pipeline for the first frequency band, better ideas?)
    181     results = self.evaluate(
    182         dataset,
    183         pipelines,
   (...)
    186         postprocess_pipeline=postprocess_pipeline,
    187     )
--> 188     for res in results:
    189         self.push_result(res, pipelines, process_pipeline)
    191 return self.results.to_dataframe(
    192     pipelines=pipelines, process_pipeline=process_pipeline
    193 )

File /opt/conda/lib/python3.10/site-packages/moabb/evaluations/evaluations.py:548, in CrossSessionEvaluation.evaluate(self, dataset, pipelines, param_grid, process_pipeline, postprocess_pipeline)
    542         save_model_cv(
    543             model=cvclf,
    544             save_path=model_save_path,
    545             cv_index=str(cv_ind),
    546         )
    547 else:
--> 548     result = _fit_and_score(
    549         clone(grid_clf),
    550         X,
    551         y,
    552         scorer,
    553         train,
    554         test,
    555         verbose=False,
    556         parameters=None,
    557         fit_params=None,
    558         error_score=self.error_score,
    559         return_estimator=True,
    560     )
    561     score = result["test_scores"]
    562     model_list = result["estimator"]

File /opt/conda/lib/python3.10/site-packages/sklearn/model_selection/_validation.py:686, in _fit_and_score(estimator, X, y, scorer, train, test, verbose, parameters, fit_params, return_train_score, return_parameters, return_n_test_samples, return_times, return_estimator, split_progress, candidate_progress, error_score)
    684         estimator.fit(X_train, **fit_params)
    685     else:
--> 686         estimator.fit(X_train, y_train, **fit_params)
    688 except Exception:
    689     # Note fit time as time until error
    690     fit_time = time.time() - start_time

File /opt/conda/lib/python3.10/site-packages/sklearn/pipeline.py:405, in Pipeline.fit(self, X, y, **fit_params)
    403     if self._final_estimator != "passthrough":
    404         fit_params_last_step = fit_params_steps[self.steps[-1][0]]
--> 405         self._final_estimator.fit(Xt, y, **fit_params_last_step)
    407 return self

File /opt/conda/lib/python3.10/site-packages/braindecode/eegneuralnet.py:384, in _EEGNeuralNet.fit(self, X, y, **fit_params)
    382     self._set_signal_args(X, y, classes=None)
    383     self.signal_args_set_ = True
--> 384 return super().fit(X=X, y=y, **fit_params)

File /opt/conda/lib/python3.10/site-packages/skorch/classifier.py:165, in NeuralNetClassifier.fit(self, X, y, **fit_params)
    154 """See ``NeuralNet.fit``.
    155 
    156 In contrast to ``NeuralNet.fit``, ``y`` is non-optional to
   (...)
    160 
    161 """
    162 # pylint: disable=useless-super-delegation
    163 # this is actually a pylint bug:
    164 # [https://github.com/PyCQA/pylint/issues/1085](https://github.com/PyCQA/pylint/issues/1085%3C/span%3E)
--> 165 return super(NeuralNetClassifier, self).fit(X, y, **fit_params)

File /opt/conda/lib/python3.10/site-packages/skorch/net.py:1319, in NeuralNet.fit(self, X, y, **fit_params)
   1316 if not self.warm_start or not self.initialized_:
   1317     self.initialize()
-> 1319 self.partial_fit(X, y, **fit_params)
   1320 return self

File /opt/conda/lib/python3.10/site-packages/braindecode/eegneuralnet.py:334, in _EEGNeuralNet.partial_fit(self, X, y, classes, **fit_params)
    332     self._set_signal_args(X, y, classes)
    333     self.signal_args_set_ = True
--> 334 return super().partial_fit(X=X, y=y, classes=classes, **fit_params)

File /opt/conda/lib/python3.10/site-packages/skorch/net.py:1278, in NeuralNet.partial_fit(self, X, y, classes, **fit_params)
   1276 self.notify('on_train_begin', X=X, y=y)
   1277 try:
-> 1278     self.fit_loop(X, y, **fit_params)
   1279 except KeyboardInterrupt:
   1280     pass

File /opt/conda/lib/python3.10/site-packages/skorch/net.py:1196, in NeuralNet.fit_loop(self, X, y, epochs, **fit_params)
   1190     self.run_single_epoch(iterator_train, training=True, prefix="train",
   1191                           step_fn=self.train_step, **fit_params)
   1193     self.run_single_epoch(iterator_valid, training=False, prefix="valid",
   1194                           step_fn=self.validation_step, **fit_params)
-> 1196     self.notify("on_epoch_end", **on_epoch_kwargs)
   1197 return self

File /opt/conda/lib/python3.10/site-packages/skorch/net.py:386, in NeuralNet.notify(self, method_name, **cb_kwargs)
    384 getattr(self, method_name)(self, **cb_kwargs)
    385 for _, cb in self.callbacks_:
--> 386     getattr(cb, method_name)(self, **cb_kwargs)

File /opt/conda/lib/python3.10/site-packages/skorch/callbacks/scoring.py:489, in EpochScoring.on_epoch_end(self, net, dataset_train, dataset_valid, **kwargs)
    486     return
    488 with _cache_net_forward_iter(net, self.use_caching, y_pred) as cached_net:
--> 489     current_score = self._scoring(cached_net, X_test, y_test)
    491 self._record_score(net.history, current_score)

File /opt/conda/lib/python3.10/site-packages/skorch/callbacks/scoring.py:181, in ScoringBase._scoring(self, net, X_test, y_test)
    178 """Resolve scoring and apply it to data. Use cached prediction
    179 instead of running inference again, if available."""
    180 scorer = check_scoring(net, self.scoring_)
--> 181 return scorer(net, X_test, y_test)

File /opt/conda/lib/python3.10/site-packages/sklearn/metrics/_scorer.py:234, in _BaseScorer.__call__(self, estimator, X, y_true, sample_weight)
    211 def __call__(self, estimator, X, y_true, sample_weight=None):
    212     """Evaluate predicted target values for X relative to y_true.
    213 
    214     Parameters
   (...)
    232         Score function applied to prediction of estimator on X.
    233     """
--> 234     return self._score(
    235         partial(_cached_call, None),
    236         estimator,
    237         X,
    238         y_true,
    239         sample_weight=sample_weight,
    240     )

File /opt/conda/lib/python3.10/site-packages/sklearn/metrics/_scorer.py:276, in _PredictScorer._score(self, method_caller, estimator, X, y_true, sample_weight)
    248 def _score(self, method_caller, estimator, X, y_true, sample_weight=None):
    249     """Evaluate predicted target values for X relative to y_true.
    250 
    251     Parameters
   (...)
    273         Score function applied to prediction of estimator on X.
    274     """
--> 276     y_pred = method_caller(estimator, "predict", X)
    277     if sample_weight is not None:
    278         return self._sign * self._score_func(
    279             y_true, y_pred, sample_weight=sample_weight, **self._kwargs
    280         )

File /opt/conda/lib/python3.10/site-packages/sklearn/metrics/_scorer.py:73, in _cached_call(cache, estimator, method, *args, **kwargs)
     71 """Call estimator with method and args and kwargs."""
     72 if cache is None:
---> 73     return getattr(estimator, method)(*args, **kwargs)
     75 try:
     76     return cache[method]

File /opt/conda/lib/python3.10/site-packages/braindecode/classifier.py:198, in EEGClassifier.predict(self, X)
    174 def predict(self, X):
    175     """Return class labels for samples in X.
    176 
    177     Parameters
   (...)
    196 
    197     """
--> 198     return self.predict_proba(X).argmax(1)

File /opt/conda/lib/python3.10/site-packages/braindecode/classifier.py:130, in EEGClassifier.predict_proba(self, X)
     97 def predict_proba(self, X):
     98     """Return the output of the module's forward method as a numpy
     99     array. In case of cropped decoding returns averaged values for
    100     each trial.
   (...)
    128 
    129     """
--> 130     y_pred = super().predict_proba(X)
    131     # Normally, we have to average the predictions across crops/timesteps
    132     # to get one prediction per window/trial
    133     # Predictions may be already averaged in CroppedTrialEpochScoring (y_pred.shape==2).
    134     # However, when predictions are computed outside of CroppedTrialEpochScoring
    135     # we have to average predictions, hence the check if len(y_pred.shape) == 3
    136     if self.cropped and self.aggregate_predictions and len(
    137             y_pred.shape) == 3:

File /opt/conda/lib/python3.10/site-packages/skorch/classifier.py:200, in NeuralNetClassifier.predict_proba(self, X)
    168 """Where applicable, return probability estimates for
    169 samples.
    170 
   (...)
    196 
    197 """
    198 # Only the docstring changed from parent.
    199 # pylint: disable=useless-super-delegation
--> 200 return super().predict_proba(X)

File /opt/conda/lib/python3.10/site-packages/skorch/net.py:1599, in NeuralNet.predict_proba(self, X)
   1597     yp = nonlin(yp)
   1598     y_probas.append(to_numpy(yp))
-> 1599 y_proba = np.concatenate(y_probas, 0)
   1600 return y_proba

ValueError: need at least one array to concatenate

Environment

Moabb Version: 1.0.0
Braindecode: 0.8.1

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the Shin2017A CrossSession LeftRightImagery run, then trace CrossSessionEvaluation.evaluate in evaluations/evaluations.py through the scoring path shown in evaluations/base.py. Investigate why braindecode/skorch produces no arrays for np.concatenate during prediction. Done means the reported evaluation no longer raises this error and the behavior is covered by an appropriate regression test.

Written by the indexing model from the issue text.

Assessment

Tech stack
numpy, python, scikit-learn
Domain
machine-learning
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.