Cuml: [BUG] 2+ cuML preprocessors for single variable in Pipeline

Created on 26 Oct 2020  路  4Comments  路  Source: rapidsai/cuml

Is your feature request related to a problem? Please describe.
I want to build Pipelines with two or more cuML preprocessors that could fit on a DataFrame with a single column. For example:

import cudf
from cuml.experimental.preprocessing import SimpleImputer, StandardScaler
from sklearn.pipeline import Pipeline

X = cudf.DataFrame({'a': [0, 1, 2, 3]})
num_transformer = Pipeline(steps=[("imputer", SimpleImputer(copy=False)),
                                  ("scaler", StandardScaler(copy=False))
                                 ])
num_transformer.fit_transform(X)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-13-33119d16166e> in <module>
      8                                   ("scaler", StandardScaler(copy=False))
      9                                  ])
---> 10 num_transformer.fit_transform(X)

/opt/conda/envs/rapids/lib/python3.7/site-packages/sklearn/pipeline.py in fit_transform(self, X, y, **fit_params)
    374             fit_params_last_step = fit_params_steps[self.steps[-1][0]]
    375             if hasattr(last_step, 'fit_transform'):
--> 376                 return last_step.fit_transform(Xt, y, **fit_params_last_step)
    377             else:
    378                 return last_step.fit(Xt, y,

/opt/conda/envs/rapids/lib/python3.7/site-packages/cuml/_thirdparty/sklearn/utils/skl_dependencies.py in fit_transform(self, X, y, **fit_params)
    365         if y is None:
    366             # fit method of arity 1 (unsupervised transformation)
--> 367             return self.fit(X, **fit_params).transform(X)
    368         else:
    369             # fit method of arity 2 (supervised transformation)

/opt/conda/envs/rapids/lib/python3.7/site-packages/cuml/_thirdparty/sklearn/preprocessing/_data.py in fit(self, X, y)
    632         # Reset internal state before fitting
    633         self._reset()
--> 634         return self.partial_fit(X, y)
    635 
    636     def partial_fit(self, X, y=None):

/opt/conda/envs/rapids/lib/python3.7/site-packages/cuml/_thirdparty/sklearn/preprocessing/_data.py in partial_fit(self, X, y)
    663         X = self._validate_data(X, accept_sparse=('csr', 'csc'),
    664                                 estimator=self, dtype=FLOAT_DTYPES,
--> 665                                 force_all_finite='allow-nan')
    666 
    667         # Even in the case of `with_mean=False`, we update the mean anyway

/opt/conda/envs/rapids/lib/python3.7/site-packages/cuml/_thirdparty/sklearn/utils/skl_dependencies.py in _validate_data(self, X, y, reset, validate_separately, **check_params)
    314                     f"requires y to be passed, but the target y is None."
    315                 )
--> 316             X = check_array(X, **check_params)
    317             out = X
    318         else:

/opt/conda/envs/rapids/lib/python3.7/site-packages/cuml/thirdparty_adapters/adapters.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, warn_on_dtype, estimator)
    242     if ensure_2d and hasshape:
    243         if len(array.shape) != 2:
--> 244             raise ValueError("Not 2D")
    245 
    246     if not allow_nd and hasshape:

ValueError: Not 2D

Describe the solution you'd like
I want to fit preprocessors sequentially in a Pipeline on a single variable similar to sklearn:

import pandas as pd
from sklearn.preprocessing import StandardScaler
from sklearn.impute import SimpleImputer
from sklearn.pipeline import Pipeline

X = pd.DataFrame({'a': [0, 1, 2, 3]})
num_transformer = Pipeline(steps=[("imputer", SimpleImputer(copy=False)),
                                  ("scaler", StandardScaler(copy=False))])
num_transformer.fit_transform(X)
---------------------------------------------------------------------------
array([[-1.34164079],
       [-0.4472136 ],
       [ 0.4472136 ],
       [ 1.34164079]])

Describe alternatives you've considered
Use preprocessors outside a Pipeline.

Additional context
I am using cuml version 0.16.0a+882.g5851f4140.
@tfeher here's a example with two numerical preprocessors in a Pipeline

Cython / Python bug

All 4 comments

Thanks very much for the report, @yasmina-altair! This is definitely a bug. I'm working on tracking down the exact point of failure, but it looks like we're naively converting single-series data frames to Series rather than keeping them as the correct input type. We'll get a fix in ASAP and I'll keep you up-to-date on progress in this thread.

Fix is now available in #3069. After it gets reviewed and merged, you should see the proper behavior in the 0.17 nightly build. @yasmina-altair, please don't hesitate to ping me if you need more info on how to install the nightly build once the fix is in.

thank you @wphicks, really appreciate it

@yasmina-altair The fix from #3069 just got merged. You should see this problem resolved in the next nightly build. If you run into any further issues, please do reach out.

Was this page helpful?
0 / 5 - 0 ratings