aeon-toolkit / aeon

A toolkit for machine learning from time series
https://aeon-toolkit.org/
BSD 3-Clause "New" or "Revised" License
882 stars 93 forks source link

[BUG] MultiRocket does not accept singular series in `transform` #1713

Open MatthewMiddlehurst opened 1 week ago

MatthewMiddlehurst commented 1 week ago

Describe the bug

From #1696

The MultiRocket transform does not accept collections of size 1 when transforming. Discovered through the Arsenal classifier.

We should add to the general testing a line to predict cases like this. Should be relatively easy and cheap.

Steps/Code to reproduce the bug

from aeon.classification.convolution_based import Arsenal
import numpy as np

X = np.random.random((10, 20))
y = np.array([0, 1, 2, 3, 3, 1, 0, 0, 2, 1])
afc = Arsenal(rocket_transform='multirocket')
afc.fit(X, y)
X2 = np.random.random((1, 20))
afc.predict(X2)

Expected results

transformer transforms the single case without exception

Actual results

Traceback (most recent call last):
  File "D:\CMP_Machine_Learning\Repositories\aeon\local_code\local_code.py", line 9, in <module>
    afc.predict(X2)
  File "D:\CMP_Machine_Learning\Repositories\aeon\aeon\classification\base.py", line 175, in predict
    return self._predict(X)
  File "D:\CMP_Machine_Learning\Repositories\aeon\aeon\classification\convolution_based\_arsenal.py", line 195, in _predict
    for prob in self._predict_proba(X)
  File "D:\CMP_Machine_Learning\Repositories\aeon\aeon\classification\convolution_based\_arsenal.py", line 212, in _predict_proba
    y_probas = Parallel(n_jobs=self._n_jobs, prefer="threads")(
  File "D:\CMP_Machine_Learning\Repositories\aeon\.venv\lib\site-packages\joblib\parallel.py", line 1863, in __call__
    return output if self.return_generator else list(output)
  File "D:\CMP_Machine_Learning\Repositories\aeon\.venv\lib\site-packages\joblib\parallel.py", line 1792, in _get_sequential_output
    res = func(*args, **kwargs)
  File "D:\CMP_Machine_Learning\Repositories\aeon\aeon\classification\convolution_based\_arsenal.py", line 381, in _predict_proba_for_estimator
    preds = classifier.predict(X)
  File "D:\CMP_Machine_Learning\Repositories\aeon\.venv\lib\site-packages\sklearn\pipeline.py", line 602, in predict
    Xt = transform.transform(Xt)
  File "D:\CMP_Machine_Learning\Repositories\aeon\aeon\transformations\collection\base.py", line 126, in transform
    Xt = self._transform(X=X_inner, y=y_inner)
  File "D:\CMP_Machine_Learning\Repositories\aeon\aeon\transformations\collection\convolution_based\_multirocket.py", line 159, in _transform
    X = _transform(
  File "D:\CMP_Machine_Learning\Repositories\aeon\.venv\lib\site-packages\numba\core\dispatcher.py", line 703, in _explain_matching_error
    raise TypeError(msg)
TypeError: No matching definition for argument type(s) array(float32, 1d, C), array(float32, 1d, C), Tuple(array(int32, 1d, C), array(int32, 1d, C), array(float32, 1d, C)), Tuple(array(int32, 1d, C), array(int32, 1d, C), array(float32, 1d, C)), int64

Versions

N/A

TonyBagnall commented 1 week ago

note that multirocketmultivariate is fine. Inappropriate squeezing I guess. I can fix in #1711, I'll add a test for all base collection transformers

from aeon.transformations.collection.convolution_based import MultiRocket, MultiRocketMultivariate
import numpy as np
)

X = np.random.random((40,1,20))
mr = MultiRocketMultivariate()
mr.fit(X)
print("Finished fit for multirocket multivariate")
X2 = np.random.random((1,20))
Xt = mr.transform(X2)
print(Xt)
mr = MultiRocket()
mr.fit(X)
print("Finished fit for multirocket")
X2 = np.random.random((1,20))
Xt = mr.transform(X2)
print(Xt)