GLOBAL_SEQUENTIAL_NAME = list()
            X = self._backend.transform(X, **kwargs)
def check_kwargs(kwargs, forbidden):
def print_job(lc, start_message):
    def __init__(self, name=None, verbose=False, stack=None, **kwargs):
    def __iter__(self):
    def fit(self, X, y=None, **kwargs):
    def fit_transform(self, X, y=None, **kwargs):
    def predict(self, X, **kwargs):
    def transform(self, X, **kwargs):
    def _predict(self, X, job, **kwargs):
    def data(self):
    def __init__(
            self, shuffle=False, random_state=None, scorer=None, verbose=False,
            layers=None, array_check=None, model_selection=False, sample_size=20,
            **kwargs):
    def add(self, estimators, indexer, preprocessing=None, **kwargs):
    def replace(self, idx, estimators, indexer, preprocessing=None, **kwargs):
    def remove(self, idx):
    def fit(self, X, y=None, **kwargs):
    def transform(self, X, y=None, **kwargs):
    def fit_transform(self, X, y, **kwargs):
    def predict(self, X, **kwargs):
    def predict_proba(self, X, **kwargs):
    def _build_layer(self, estimators, indexer, preprocessing, **kwargs):
    def model_selection(self):
    def model_selection(self, model_selection):
    def data(self):
    def verbose(self):
    def verbose(self, value):
class Sequential(BaseStacker):
class BaseEnsemble(BaseEstimator): class OLS(BaseEstimator):

    """No frills vanilla OLS estimator implemented through the normal equation.

    MWE of a Scikit-learn estimator.

    OLS is a simple estimator designed to allow for total control over
    predictions in unit testing. It implements OLS through the Normal
    Equation, no learning takes place. The ``offset`` option allows
    the user to offset weights by a scalar value, if different instances
    should be differentiated in their predictions.

    Parameters
    ----------
    offset : float (default = 0)
        scalar value to add to the coefficient vector after fitting.

    Examples
    --------

    Asserting the OLS passes the Scikit-learn estimator test

    >>> from sklearn.utils.estimator_checks import check_estimator
    >>> from mlens.utils.dummy import OLS
    >>> check_estimator(OLS)

    OLS comparison with Scikit-learn's LinearRegression

    >>> from numpy.testing import assert_array_equal
    >>> from mlens.utils.dummy import OLS
    >>> from sklearn.linear_model import LinearRegression
    >>> from sklearn.datasets import load_boston
    >>> X, y = load_boston(True)
    >>>
    >>> lr = LinearRegression(False)
    >>> lr.fit(X, y)
    >>>
    >>> ols = OLS()
    >>> ols.fit(X, y)
    >>>
    >>> assert_array_equal(lr.coef_, ols.coef_)
    """

    def __init__(self, offset=0):
        self.offset = offset

    def fit(self, X, y):
        """Fit coefficient vector."""
        X, y = check_X_y(X, y, dtype='float64')
        y = np.asarray(y, dtype=X.dtype)

        O = np.linalg.lstsq(X, y, rcond=None)

        self.coef_ = O[0] + self.offset
        self.resid_ = O[1]

        return self

    def predict(self, X):
        """Predict with fitted weights."""
        if not hasattr(self, 'coef_'):
            raise NotFittedError("Estimator not fitted. Call 'fit' first.")

        X = check_array(X, accept_sparse=False)

        return np.dot(X, self.coef_.T) class LogisticRegression(OLS):

    """No frill Logistic Regressor w. one-vs-rest estimation of P(label).

    MWE of a Scikit-learn classifier.

    LogisticRegression is a simple classifier estimator designed for
    transparency in unit testing. It implements a Logistic
    Regression with one-vs-rest strategy of classification.

    The estimator is a wrapper around the :class:`OLS`. The OLS
    prediction is squashed using the Sigmoid function, and classification
    is done by picking the label with the highest probability.

    The ``offset`` option allows the user to offset weights in the OLS by a
    scalar value, if different instances should be differentiated in their
    predictions.

    Examples
    --------

    Asserting the LogisticRegression passes the Scikit-learn estimator test

    >>> from sklearn.utils.estimator_checks import check_estimator
    >>> from mlens.utils.dummy import LogisticRegression
    >>> check_estimator(LogisticRegression)

    Comparison with Scikit-learn's LogisticRegression

    >>> from mlens.utils.dummy import LogisticRegression as mlensL
    >>> from sklearn.linear_model import LogisticRegression as sklearnL
    >>> from sklearn.datasets import make_classification
    >>> X, y = make_classification()
    >>>
    >>> slr = sklearnL()
    >>> slr.fit(X, y)
    >>>
    >>> mlr = mlensL()
    >>> mlr.fit(X, y)
    >>>
    >>> (mlr.predict(X) == slr.predict(X)).sum() / y.shape
    array([ 0.98])
    """

    def fit(self, X, y):
        """Fit one model per label."""
        X, y = check_X_y(X, y, accept_sparse=False)

        self.labels_ = np.unique(y)

        models = []
        for label in self.labels_:
            labels = y == label
            models.append(OLS().fit(X, labels))

        self._models_ = models
        self.coef_ = np.vstack([l.coef_ for l in self._models_])

        return self

    def predict_proba(self, X):
        """Get probability predictions."""
        if not hasattr(self, '_models_'):
            raise NotFittedError("Estimator not fitted. Call 'fit' first.")

        X = check_array(X, accept_sparse=False)

        preds = []
        for m in self._models_:

            p = 1 / (1 + np.exp(- m.predict(X)))

            preds.append(p)

        return np.vstack(preds).T

    def predict(self, X):
        """Get label predictions."""
        if not hasattr(self, '_models_'):
            raise NotFittedError("Estimator not fitted. Call 'fit' first.")

        X = check_array(X, accept_sparse=False)

        preds = self.predict_proba(X)

        labels = np.zeros(X.shape[0])
        for i in range(X.shape[0]):
            labels[i] = self.labels_[preds[i].argmax()]

        return labels class Scale(BaseEstimator, TransformerMixin):

    """Removes the a learnt mean in a column-wise manner in an array.

    MWE of a Scikit-learn transformer, to be used for unit-tests of ensemble
    classes.

    Parameters
    ----------
    copy : bool (default = True)
        Whether to copy X before transforming.

    Examples
    --------
    Asserting :class:`Scale` passes the Scikit-learn estimator test

    >>> from sklearn.utils.estimator_checks import check_estimator
    >>> from mlens.utils.dummy import Scale
    >>> check_estimator(Scale)

    Scaling elements

    >>> from numpy import arange
    >>> from mlens.utils.dummy import Scale
    >>> X = arange(6).reshape(3, 2)
    >>> X[:, 1] *= 2
    >>> print('X:')
    >>> print('%r' % X)
    >>> print('Scaled:')
    >>> S = Scale().fit_transform(X)
    >>> print('%r' % S)
    X:
    array([[ 0,  2],
           [ 2,  6],
           [ 4, 10]])
    Scaled:
    array([[-2., -4.],
           [ 0.,  0.],
           [ 2.,  4.]])
    """

    def __init__(self, copy=True):
        self.copy = copy
        self.__is_fitted__ = False

    __init__.deprecated_original = __init__

    def fit(self, X, y=None):
        """Estimate mean.

        Parameters
        ----------
        X : array-like
            training data to fit transformer on.

        y : array-like or None
            pass through for pipeline.
        """
        X = check_array(X, accept_sparse=False)
        self.__is_fitted__ = True
        self.mean_ = X.mean(axis=0)
        return self

    def transform(self, X):
        """Transform array by adjusting all elements with scale.

        Parameters
        ----------
        X : ndarray
            matrix to transform.
        """
        if not self.__is_fitted__:
            raise NotFittedError("Estimator not fitted.")
        X = check_array(X, accept_sparse=False)
        Xt = X.copy() if self.copy else X
        return Xt - self.mean_ ESTIMATORS = {'sc': [('offs', OLS(offset=2)), ('null', OLS())],
              'no': [('offs', OLS(offset=2)), ('null', OLS())]} PREPROCESSING = {'no': [], 'sc': [('scale', Scale())]} ESTIMATORS_PROBA = {'sc': [('offs', LogisticRegression(offset=2)),
                           ('null', LogisticRegression())],
                    'no': [('offs', LogisticRegression(offset=2)),
                           ('null', LogisticRegression())]} ECM = [('ols-%i' % i, OLS(offset=i)) for i in range(4)] ECM_PROBA = [('lr-%i' % i, LogisticRegression(offset=i)) for i in range(4)] class InitMixin(object):

    """Mixin to make a mlens ensemble behave as Scikit-learn estimator.

    Scikit-learn expects an estimator to be fully initialized when
    instantiated, but an ML-Ensemble estimator requires layers to be
    initialized before calling ``fit`` or ``predict`` makes sense.

    ``InitMixin`` is intended to be used to create temporary test classes
    of proper mlens ensemble classes that are identical to the parent class
    except that ``__init__`` will also initialize one layer with one
    estimator, and if applicable one meta estimator.

    The layer estimator and the meta estimator are both the dummy
    ``AverageRegressor`` class to minimize complexity and avoids raising
    errors due to the estimators in the layers.

    To create a testing class, modify the ``__init__`` of the test class
    to call ``super().__init__`` as in the example below.

    Examples
    --------

    Assert the :class:`SuperLearner` passes the Scikit-learn estimator test

    >>> from sklearn.utils.estimator_checks import check_estimator
    >>> from mlens.ensemble import SuperLearner
    >>> from mlens.testing.dummy import InitMixin
    >>>
    >>> class TestSuperLearner(InitMixin, SuperLearner):
    ...
    ...     def __init__(self):
    ...         super(TestSuperLearner, self).__init__()
    >>>
    >>> check_estimator(TestSuperLearner)
    """

    @abstractmethod
    def __init__(self):

        # Instantiate class
        super(InitMixin, self).__init__()

        # The test is parallelized and Scikit-learn estimators default to
        # n_jobs = 1, so need to coerce ensembles to the same behavior
        self.n_jobs = 1

        # Build an ensemble consisting of two OLS estimators in the first
        # layer, and a single on top.
        getattr(self, 'add')([OLS(offset=1), OLS(offset=2)])
        getattr(self, 'add_meta')(OLS()) class Data(object):

    """Class for getting data."""

    def __init__(self, cls, proba, preprocessing, is_learner=False,
                 *args, **kwargs):
        self.lr = is_learner
        self.proba = proba
        self.preprocessing = preprocessing
        self.cls = cls
        self.indexer = INDEXERS[cls](*args, **kwargs)

    def get_data(self, shape, m):
        """Generate X and y data with X.
        Parameters
        ----------
        shape : tuple
            shape of data to be generated
        m : int
            length of step function for y
        Returns
        -------
        train : ndarray
            generated as a sequence of  reshaped to (LEN, WIDTH)
        labels : ndarray
            generated as a step-function with a step every ``m``. As such,
            each prediction fold during cross-validation have
            a unique level value.
        """
        s = shape[0]
        w = shape[1]

        train = np.array(range(int(s * w)), dtype='float').reshape((s, w))
        train += 1

        labels = np.zeros(train.shape[0])

        if not self.proba:
            increment = 10
            for i in range(0, s, m):
                labels[i:i + m] += increment

                increment += 10

        else:
            labels = np.arange(train.shape[0]) % 2

        return train, labels

    def ground_truth(self, X, y, subsets=1, feature_prop=None):
        """Set up an experiment ground truth.
        Returns
        -------
        F : ndarray
            Full prediction array (train errors)
        P : ndarray
            Folded prediction array (test errors)
        Raises
        ------
        AssertionError :
            Raises assertion error if any weight vectors overlap or any
            predictions (as measured by columns in F and P) are judged to be
            equal.
        """
        P, weights_p = self._full_ests(X, y, subsets)
        if feature_prop:
            P = np.hstack([X[:, :feature_prop], P])

        if self.indexer.__class__.__name__.lower() == 'fullindex':
            return (P, weights_p), (P, weights_p)

        F, weights_f = self._folded_ests(X, y, subsets)
        if feature_prop:
            r = X.shape[0] - F.shape[0]
            F = np.hstack([X[r:][:, :feature_prop], F])

        return (F, weights_f), (P, weights_p)

    def _set_up_est(self, y):
        """Get estimators, preprocessing, num_ests, predict attr to use."""
        attr = 'predict_proba' if self.proba else 'predict'
        labels = len(np.unique(y)) if self.proba else 1

        if self.preprocessing:
            if self.lr:
                est = OLS() if not self.proba else LogisticRegression()
                ests = {'sc': [('est', est)]}
                prep = {'sc': [('scale', Scale())]}
            else:
                ests = ESTIMATORS_PROBA if self.proba else ESTIMATORS
                prep = PREPROCESSING

            n_ests = 0
            for case in ests:
                for _ in ests[case]:
                    n_ests += 1

        else:
            if self.lr:
                est = OLS() if not self.proba else LogisticRegression()
                ests = {'no-case': [('ols', est)]}
            else:
                ests = {'no-case': ECM_PROBA if self.proba else ECM}
            prep = {'no-case': []}

            n_ests = len(ests['no-case'])

        self.classes_ = labels
        self.n_pred = n_ests
        if self.cls == 'subsemble':
            self.n_pred *= self.indexer.partitions

        return ests, prep, n_ests, attr, labels

    def _folded_ests(self, X, y, subsets=1):
        """Build ground truth for each fold."""
        ests, prep, n_ests, attr, labels = self._set_up_est(y)

        t = [t for _, t in self.indexer.generate(X, True)]
        t = np.unique(np.hstack(t))
        t.sort()

        weights = []
        F = np.zeros((len(t), n_ests * subsets * labels), dtype=np.float)

        col_id = {}
        col_ass = 0

        # Sort at every occasion
        vps = [(c, e[0])
               for c in prep.keys()
               for e in ests[c]]

        for meta_key in sorted(vps):
            key, est_name = meta_key
            est = dict(ests[key])[est_name]
            for i, (tri, tei) in enumerate(self.indexer.generate(X, True)):

                if subsets > 1:
                    i = i // self.indexer.folds
                else:
                    i = 0

                if '%s-%s-%s' % (i, key, est_name) not in col_id:
                    col_id['%s-%s-%s' % (i, key, est_name)] = col_ass
                    col_ass += labels

                xtrain = X[tri]
                xtest = X[tei]

                # Transform inputs
                for _, tr in prep[key]:
                    t = clone(tr)
                    xtrain = t.fit_transform(xtrain)
                    xtest = t.transform(xtest)

                # Fit estimator
                e = clone(est).fit(xtrain, y[tri])
                w = e.coef_
                weights.append(w)

                # Get out-of-sample predictions
                p = getattr(e, attr)(xtest)

                rebase = X.shape[0] - F.shape[0]
                fix = tei - rebase

                if labels == 1:
                    F[fix, col_id['%s-%s-%s' % (i, key, est_name)]] = p
                else:
                    c = col_id['%s-%s-%s' % (i, key, est_name)]
                    F[np.ix_(fix, np.arange(c, c + labels))] = p

        return F, weights

    def _full_ests(self, X, y, subsets=1):
        """Get ground truth for train and predict on full data."""
        ests, prep, n_ests, attr, labels = self._set_up_est(y)
        if subsets == 1:
            indexer = DummyPartition(np.arange(X.shape[0]))
        else:
            indexer = self.indexer
            indexer.fit(X)

        P = np.zeros((X.shape[0], n_ests * subsets * labels), dtype=np.float)

        weights = list()
        col_id = {}
        col_ass = 0

        vps = ['%s__%s' % (c, e[0])
               for c in prep.keys()
               for e in ests[c]]
        for meta_key in sorted(vps):
            key, est_name = meta_key.split('__')
            est = dict(ests[key])[est_name]
            for i, tri in enumerate(indexer.partition(as_array=True)):
                if '%s-%s-%s' % (i, key, est_name) not in col_id:
                    col_id['%s-%s-%s' % (i, key, est_name)] = col_ass
                    col_ass += labels

                # Transform input
                xtrain = X[tri]
                ytrain = y[tri]

                xtest = X

                for _, tr in prep[key]:
                    t = clone(tr)
                    xtrain = t.fit_transform(xtrain)
                    xtest = t.transform(xtest)

                # Fit est
                e = clone(est).fit(xtrain, ytrain)
                w = e.coef_
                weights.append(w.tolist())

                # Predict
                p = getattr(e, attr)(xtest)
                c = col_id['%s-%s-%s' % (i, key, est_name)]
                if labels == 1:
                    P[:, c] = p
                else:
                    P[:, c:c + labels] = p

        return P, weights class EstimatorContainer(object):

    """Class for generating architectures of various types."""

    def __init__(self):
        pass

    def get_learner(self, kls, proba, preprocessing, *args, **kwargs):
        """Generate learner and transformer

        Parameters
        ----------
        kls : str
            class type

        proba : bool
            whether to set ``proba`` to ``True``

        preprocessing : bool
            layer with preprocessing cases
        """
        indexer, kwargs = self.load_indexer(kls, args, kwargs)
        est = OLS() if not proba else LogisticRegression()

        if preprocessing:
            transformer = Transformer(
                estimator=Pipeline(Scale(), return_y=True),
                indexer=indexer, name='sc')
        else:
            transformer = None

        learner = Learner(estimator=est, indexer=indexer,
                          preprocess='sc' if transformer else None,
                          scorer=mae if not proba else None,
                          name=kls, proba=proba)

        return learner, transformer

    def get_layer(self, kls, proba, preprocessing, *args, **kwargs):
        """Generate a layer instance.

        Parameters
        ----------
        kls : str
            class type

        proba : bool
            whether to set ``proba`` to ``True``

        preprocessing : bool
            layer with preprocessing cases
        """
        indexer, kwargs = self.load_indexer(kls, args, kwargs)

        learner_kwargs = {'proba': kwargs.pop('proba', proba),
                          'scorer': kwargs.pop('scorer', None)}

        layer = Layer(name='layer', dtype=np.float64, **kwargs)

        if preprocessing:
            ests = ESTIMATORS_PROBA if proba else ESTIMATORS
            prep = PREPROCESSING
        else:
            ests = ECM_PROBA if proba else ECM
            prep = []

        group = make_group(indexer, ests, prep,
                           learner_kwargs=learner_kwargs, name='group')
        layer.push(group)
        return layer

    def get_layer_estimator(self, kls, proba, preprocessing, *args, **kwargs):
        """Generate a layer estimator instance.

        Parameters
        ----------
        kls : str
            class type

        proba : bool
            whether to set ``proba`` to ``True``

        preprocessing : bool
            layer with preprocessing cases
        """
        indexer, kwargs = self.load_indexer(kls, args, kwargs)

        learner_kwargs = {'proba': kwargs.pop('proba', proba),
                          'scorer': kwargs.pop('scorer', None)}

        if preprocessing:
            ests = ESTIMATORS_PROBA if proba else ESTIMATORS
            prep = PREPROCESSING
        else:
            ests = ECM_PROBA if proba else ECM
            prep = []

        group = make_group(indexer, ests, prep,
                           learner_kwargs=learner_kwargs)
        layer = LayerEnsemble([group], dtype=np.float64, **kwargs)
        return layer

    def get_sequential(self, kls, proba, preprocessing, *args, **kwargs):
        """Generate a layer container instance.

        Parameters
        ----------
        kls : str
            class type

        proba : bool
            whether to set ``proba`` to ``True``

        preprocessing : bool
            layer with preprocessing cases
        """
        lyr = self.get_layer(kls, proba, preprocessing, *args, **kwargs)
        lyr.name += '-1'
        seq = Sequential()
        return seq.push(lyr)

    @staticmethod
    def load_indexer(kls, args, kwargs):
        """Load indexer and return remaining kwargs"""
        indexer = INDEXERS[kls]
        idx_kwargs = dict()
        for var in indexer.__init__.__code__.co_varnames:
            if var in kwargs:
                idx_kwargs[var] = kwargs.pop(var)
        indexer = indexer(*args, **idx_kwargs)
        return indexer, kwargs def assert_correct_format(estimators, preprocessing):
    """Initial check to assert layer can be constructed."""
    if (preprocessing is None) or (not isinstance(preprocessing, dict)):
        if isinstance(estimators, dict):
            # Either no or uniform preprocessing, estimators should be list
            msg = ("Preprocessing is either 'None' or 'list': 'estimators' "
                   "must be of type 'list'. Got %s.")
            raise LayerSpecificationError(msg % type(estimators))
    else:
        # Check that both estimators and preprocessing are dicts
        if not isinstance(preprocessing, dict):
            msg = ("Unexpected format of 'preprocessing'. Needs to be "
                   " of type 'None' or 'list' or 'dict'. Got %s .")
            raise LayerSpecificationError(msg % type(preprocessing))

        if not isinstance(estimators, dict):
            msg = ("Unexpected format of 'estimators'. Needs to be "
                   "'dict' when preprocessing is 'dict'. Got %s.")
            raise LayerSpecificationError(msg % type(estimators))

        # Check that keys overlap
        prep_check = [key in preprocessing for key in estimators]
        est_check = [key in estimators for key in preprocessing]

        if not all(est_check):
            msg = ("Too few estimator cases to match preprocessing cases:\n"
                   "estimator cases:     %r\npreprocessing cases: %r")
            raise LayerSpecificationError(msg % (list(estimators),
                                                 list(preprocessing)))
        if not all(prep_check):
            msg = ("Too few preprocessing cases to match estimators cases:\n"
                   "preprocessing cases: %r\nestimator cases:     %r")
            raise LayerSpecificationError(msg % (list(preprocessing),
                                                 list(estimators))) def _assert_format(instances, namespace=None):
    """Assert that a generic instances object is correctly formatted."""
    if not namespace:
        namespace = list()

    if isinstance(instances, dict):
        # Need to check every instance list across preprocessing cases
        for instance_list in instances.values():
            if not _check_format(instance_list, namespace=namespace):
                return False
            namespace.extend(n for n, e in instance_list)
        return True

    # For list, check the given list
    return _check_format(instances, namespace=namespace) def _format_instances(instances, namespace=None):
    """Format a list of instances to a list of named estimator tuples."""
    nested = isinstance(instances, dict)
    if nested:
        # Need to flatten, but record hierarchy
        instances_dict = instances
        vacuous = list()
        case_map = dict()
        instances = list()
        for case, instance_list in sorted(instances_dict.items()):
            case = '-'.join(case.lower().split())

            if not instance_list:
                vacuous.append((case, instance_list))
                continue

            for val in instance_list:
                instances.append(val)
                if isinstance(val, (list, tuple, set)):
                    val = val[1]  # Grab estimator
                case_map[val] = case

    named_instances = list()
    for val in instances:
        # Check that the instance appears correctly specified
        if not isinstance(val, (list, tuple, set)):
            # val is the instance
            instance = val
        else:
            # val is a list-like object. Assume instance is the last entry
            instance = val[-1]

        # Check if it appears to be an estimator
        assert_valid_estimator(instance)

        try:
            # Format instance names

            # We keep the instance as a list to change possible duplicate names
            # exploiting that lists are mutable, before switching to tuple
            if instance is val:
                tup = [instance.__class__.__name__.lower(), instance]
            else:
                tup = ['-'.join(val[0].split()).lower(), val[-1]]

            named_instances.append(tup)

        except Exception as e:
            msg = ("Could not format instance %s. Check that passed instance "
                   "iterables follow correct syntax:\n"
                   "- if multiple preprocessing cases, pass a dictionary with "
                   "instance lists as values and case name as key.\n"
                   "- else, pass list of (named) instances.\n"
                   "See documentation for further information.\n"
                   "Error details: %r")
            raise LayerSpecificationError(msg % (instance, e))

    # Check and correct duplicate names
    names = [tup[0] for tup in named_instances]
    if namespace:
        names.extend(namespace)
    duplicates = Counter(names)
    duplicates = {key: val for key, val in duplicates.items() if val > 1}

    out = list()  # final named_instances list
    name_count = {key: 1 for key in duplicates}
    for name, instance in named_instances:
        if name in duplicates:
            current_name_count = name_count[name]  # fix before update
            name_count[name] += 1
            name += '-%d' % current_name_count  # rename
        out.append((name, instance))
    out = sorted(out)

    if nested:
        # Rebuild hierarchy
        nested_out = dict()
        for name, instance in out:
            case = case_map[instance]
            if case not in nested_out:
                nested_out[case] = list()
            nested_out[case].append((name, instance))

        for k, v in vacuous:
            nested_out[k] = v

        out = nested_out

    return out class NotFittedError(ValueError, AttributeError):

    """Error class for an ensemble or estimator that is not fitted yet

    Raised when some method has been called that expects the instance to be
    fitted.
    """ class BaseEstimator(object):
    """Base class for all estimators in scikit-learn
    Notes
    -----
    All estimators should specify all the parameters that can be set
    at the class level in their ``__init__`` as explicit keyword
    arguments (no ``*args`` or ``**kwargs``).
    """

    @classmethod
    def _get_param_names(cls):
        """Get parameter names for the estimator"""
        # fetch the constructor or the original constructor before
        # deprecation wrapping if any
        init = getattr(cls.__init__, 'deprecated_original', cls.__init__)
        if init is object.__init__:
            # No explicit constructor to introspect
            return []

        # introspect the constructor arguments to find the model parameters
        # to represent
        init_signature = signature(init)
        # Consider the constructor parameters excluding 'self'
        parameters = [p for p in init_signature.parameters.values()
                      if p.name != 'self' and p.kind != p.VAR_KEYWORD]
        for p in parameters:
            if p.kind == p.VAR_POSITIONAL:
                raise RuntimeError("scikit-learn estimators should always "
                                   "specify their parameters in the signature"
                                   " of their __init__ (no varargs)."
                                   " %s with constructor %s doesn't "
                                   " follow this convention."
                                   % (cls, init_signature))
        # Extract and sort argument names excluding 'self'
        return sorted([p.name for p in parameters])

    def get_params(self, deep=True):
        """Get parameters for this estimator.
        Parameters
        ----------
        deep : boolean, optional
            If True, will return the parameters for this estimator and
            contained subobjects that are estimators.
        Returns
        -------
        params : mapping of string to any
            Parameter names mapped to their values.
        """
        out = dict()
        for key in self._get_param_names():
            value = getattr(self, key, None)
            if deep and hasattr(value, 'get_params'):
                deep_items = value.get_params().items()
                out.update((key + '__' + k, val) for k, val in deep_items)
            out[key] = value
        return out

    def set_params(self, **params):
        """Set the parameters of this estimator.
        The method works on simple estimators as well as on nested objects
        (such as pipelines). The latter have parameters of the form
        ``<component>__<parameter>`` so that it's possible to update each
        component of a nested object.
        Returns
        -------
        self
        """
        if not params:
            # Simple optimization to gain speed (inspect is slow)
            return self
        valid_params = self.get_params(deep=True)

        nested_params = defaultdict(dict)  # grouped by prefix
        for key, value in params.items():
            key, delim, sub_key = key.partition('__')
            if key not in valid_params:
                raise ValueError('Invalid parameter %s for estimator %s. '
                                 'Check the list of available parameters '
                                 'with `estimator.get_params().keys()`.' %
                                 (key, self))

            if delim:
                nested_params[key][sub_key] = value
            else:
                setattr(self, key, value)
                valid_params[key] = value

        for key, sub_params in nested_params.items():
            valid_params[key].set_params(**sub_params)

        return self

    def __repr__(self):
        class_name = self.__class__.__name__
        return '%s(%s)' % (class_name, _pprint(self.get_params(deep=False),
                                               offset=len(class_name),),)

    def __getstate__(self):
        try:
            state = super(BaseEstimator, self).__getstate__()
        except AttributeError:
            state = self.__dict__.copy()

        if type(self).__module__.startswith('sklearn.'):
            return dict(state.items(), _sklearn_version=__version__)
        else:
            return state

    def __setstate__(self, state):
        if type(self).__module__.startswith('sklearn.'):
            pickle_version = state.pop("_sklearn_version", "pre-0.18")
            if pickle_version != __version__:
                warnings.warn(
                    "Trying to unpickle estimator {0} from version {1} when "
                    "using version {2}. This might lead to breaking code or "
                    "invalid results. Use at your own risk.".format(
                        self.__class__.__name__, pickle_version, __version__),
                    UserWarning)
        try:
            super(BaseEstimator, self).__setstate__(state)
        except AttributeError:
            self.__dict__.update(state)
import numpy as np
import os
    from contextlib import redirect_stdout
    from mlens.externals.fixes import redirect as redirect_stdout
from mlens.ensemble.base import Layer, Sequential
from mlens.utils.dummy import OLS, LogisticRegression, Scale
from mlens.testing.dummy import ESTIMATORS, PREPROCESSING, ESTIMATORS_PROBA, \
    ECM, ECM_PROBA, InitMixin
from mlens.testing.dummy import Data, EstimatorContainer
from mlens.utils import assert_correct_format
from mlens.utils.formatting import _assert_format, _format_instances
from mlens.utils.exceptions import NotFittedError
from mlens.externals.sklearn.base import BaseEstimator
    from sklearn.utils.estimator_checks import check_estimator
"""ML-ENSEMBLE

"""


try:
except ImportError:




try:
except:
    check_estimator = None


X = np.arange(24).reshape(12, 2)

# Regression
y = X[:, 0] * 3 - X[:, 1] * 0.5

# Classification
z = np.ones(12)
z[:3] = 1
z[3:8] = 2
z[8:12] = 3


if check_estimator is not None:

    class Ens(BaseEstimator):

        """Dummy ensemble class for testing InitMixin."""

        def __init__(self, layers=None):
            self.layers = layers
        __init__.deprecated_original = __init__

        def add(self, e):
            """Pass through."""
            return self

        def add_meta(self, e):
            """Add estimator."""
            self.layers = e
            return self

        def fit(self, X, y):
            """Call fit on estimator."""
            self.layers.fit(X, y)
            return self

        def predict(self, X):
            """Call predict on estimator."""
            return self.layers.predict(X)



    class TestMixin(InitMixin, Ens):