scikit-learn / scikit-learn/scikit-learn
`OneVsOneClassifier` does not accept custom input types
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 67.3k
- Forks
- 27.4k
- Avg merge
- 1d 15h
- Merged PRs (30d)
- 58
Description
Describe the bug
Due to the additional validation in #6626, OneVsOneClassifier cannot be used with custom types that work like arrays but cannot be converted to arrays. In my case I am the maintainer of scikit-fda, a functional data library that attempts to be compatible with scikit-learn. The metaestimators OneVsRestClassifier and OneVsOneClassifier should be trivially compatible with our data. Currently OneVsRestClassifier works fine, while OneVsOneClassifier doesn't.
I think that scikit-learn has sometimes very aggressive validation that makes it difficult to extend it for custom objects, as in this case.
Steps/Code to Reproduce
I have no example using only scikit-learn, as you need custom types and classifiers / transformers to trigger it
The following code is adapted from https://fda.readthedocs.io/en/latest/auto_tutorial/plot_skfda_sklearn.html#multiclass-and-multioutput-classification-utilities
Note that the code works if you replace OneVsOneClassifier with OneVsRestClassifier, as the later does not have that aggressive validation.
import skfda
import skfda.preprocessing.dim_reduction.variable_selection as vs
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.pipeline import Pipeline
from sklearn.multiclass import OneVsOneClassifier
X, y = skfda.datasets.fetch_phoneme(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)
pipeline = Pipeline([
("dim_reduction", vs.RKHSVariableSelection(n_features_to_select=3)),
("classifier", SVC()),
])
multiclass = OneVsOneClassifier(pipeline)
multiclass.fit(X_train, y_train)
multiclass.score(X_test, y_test)
Expected Results
The result of the classification.
Actual Results
TypeError Traceback (most recent call last)
TypeError: float() argument must be a string or a number, not 'FDataGrid'
The above exception was the direct cause of the following exception:
ValueError Traceback (most recent call last)
<ipython-input-2-66e12b97fe3e> in <module>
17 multiclass = OneVsOneClassifier(pipeline)
18
---> 19 multiclass.fit(X_train, y_train)
20 multiclass.score(X_test, y_test)
~/Programas/Utilidades/Lenguajes/miniconda3/envs/fda38/lib/python3.8/site-packages/sklearn/multiclass.py in fit(self, X, y)
726 """
727 # We need to validate the data because we do a safe_indexing later.
--> 728 X, y = self._validate_data(
729 X, y, accept_sparse=["csr", "csc"], force_all_finite=False
730 )
~/Programas/Utilidades/Lenguajes/miniconda3/envs/fda38/lib/python3.8/site-packages/sklearn/base.py in _validate_data(self, X, y, reset, validate_separately, **check_params)
579 y = check_array(y, **check_y_params)
580 else:
--> 581 X, y = check_X_y(X, y, **check_params)
582 out = X, y
583
~/Programas/Utilidades/Lenguajes/miniconda3/envs/fda38/lib/python3.8/site-packages/sklearn/utils/validation.py in check_X_y(X, y, accept_sparse, accept_large_sparse, dtype, order, copy, force_all_finite, ensure_2d, allow_nd, multi_output, ensure_min_samples, ensure_min_features, y_numeric, estimator)
962 raise ValueError("y cannot be None")
963
--> 964 X = check_array(
965 X,
966 accept_sparse=accept_sparse,
~/Programas/Utilidades/Lenguajes/miniconda3/envs/fda38/lib/python3.8/site-packages/sklearn/utils/validation.py in check_array(array, accept_sparse, accept_large_sparse, dtype, order, copy, force_all_finite, ensure_2d, allow_nd, ensure_min_samples, ensure_min_features, estimator)
744 array = array.astype(dtype, casting="unsafe", copy=False)
745 else:
--> 746 array = np.asarray(array, order=order, dtype=dtype)
747 except ComplexWarning as complex_warning:
748 raise ValueError(
ValueError: setting an array element with a sequence.
Versions
System:
python: 3.8.0 | packaged by conda-forge | (default, Nov 22 2019, 19:11:38) [GCC 7.3.0]
executable: /home/carlos/Programas/Utilidades/Lenguajes/miniconda3/envs/fda38/bin/python3.8
machine: Linux-5.4.0-92-generic-x86_64-with-glibc2.10
Python dependencies:
pip: 21.3.1
setuptools: 60.5.0
sklearn: 1.0.2
numpy: 1.22.0
scipy: 1.7.3
Cython: 0.29.26
pandas: 1.4.0
matplotlib: 3.5.1
joblib: 1.1.0
threadpoolctl: 3.0.0
Built with OpenMP: True
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the supplied scikit-fda example and read sklearn/multiclass.py around OneVsOneClassifier.fit and its _validate_data call. Compare its handling with OneVsRestClassifier, then verify that the same FDataGrid pipeline can fit and score with OneVsOneClassifier without the reported conversion error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- numpy, python
- Domain
- machine-learning
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100