CoolFace
Apppublic

Aluode/PerceptionLabPortable

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
_data.py3707 linesDownload Raw Back to preprocessing
1# Authors: The scikit-learn developers
2# SPDX-License-Identifier: BSD-3-Clause
3
4
5import warnings
6from numbers import Integral, Real
7
8import numpy as np
9from scipy import sparse, stats
10from scipy.special import boxcox, inv_boxcox
11
12from sklearn.utils import metadata_routing
13
14from ..base import (
15    BaseEstimator,
16    ClassNamePrefixFeaturesOutMixin,
17    OneToOneFeatureMixin,
18    TransformerMixin,
19    _fit_context,
20)
21from ..utils import _array_api, check_array, resample
22from ..utils._array_api import (
23    _find_matching_floating_dtype,
24    _modify_in_place_if_numpy,
25    device,
26    get_namespace,
27    get_namespace_and_device,
28)
29from ..utils._param_validation import Interval, Options, StrOptions, validate_params
30from ..utils.extmath import _incremental_mean_and_var, row_norms
31from ..utils.fixes import _yeojohnson_lambda
32from ..utils.sparsefuncs import (
33    incr_mean_variance_axis,
34    inplace_column_scale,
35    mean_variance_axis,
36    min_max_axis,
37)
38from ..utils.sparsefuncs_fast import (
39    inplace_csr_row_normalize_l1,
40    inplace_csr_row_normalize_l2,
41)
42from ..utils.validation import (
43    FLOAT_DTYPES,
44    _check_sample_weight,
45    check_is_fitted,
46    check_random_state,
47    validate_data,
48)
49from ._encoders import OneHotEncoder
50
51BOUNDS_THRESHOLD = 1e-7
52
53__all__ = [
54    "Binarizer",
55    "KernelCenterer",
56    "MaxAbsScaler",
57    "MinMaxScaler",
58    "Normalizer",
59    "OneHotEncoder",
60    "PowerTransformer",
61    "QuantileTransformer",
62    "RobustScaler",
63    "StandardScaler",
64    "add_dummy_feature",
65    "binarize",
66    "maxabs_scale",
67    "minmax_scale",
68    "normalize",
69    "power_transform",
70    "quantile_transform",
71    "robust_scale",
72    "scale",
73]
74
75
76def _is_constant_feature(var, mean, n_samples):
77    """Detect if a feature is indistinguishable from a constant feature.
78
79    The detection is based on its computed variance and on the theoretical
80    error bounds of the '2 pass algorithm' for variance computation.
81
82    See "Algorithms for computing the sample variance: analysis and
83    recommendations", by Chan, Golub, and LeVeque.
84    """
85    # In scikit-learn, variance is always computed using float64 accumulators.
86    eps = np.finfo(np.float64).eps
87
88    upper_bound = n_samples * eps * var + (n_samples * mean * eps) ** 2
89    return var <= upper_bound
90
91
92def _handle_zeros_in_scale(scale, copy=True, constant_mask=None):
93    """Set scales of near constant features to 1.
94
95    The goal is to avoid division by very small or zero values.
96
97    Near constant features are detected automatically by identifying
98    scales close to machine precision unless they are precomputed by
99    the caller and passed with the `constant_mask` kwarg.
100
101    Typically for standard scaling, the scales are the standard
102    deviation while near constant features are better detected on the
103    computed variances which are closer to machine precision by
104    construction.
105    """
106    # if we are fitting on 1D arrays, scale might be a scalar
107    if np.isscalar(scale):
108        if scale == 0.0:
109            scale = 1.0
110        return scale
111    # scale is an array
112    else:
113        xp, _ = get_namespace(scale)
114        if constant_mask is None:
115            # Detect near constant values to avoid dividing by a very small
116            # value that could lead to surprising results and numerical
117            # stability issues.
118            constant_mask = scale < 10 * xp.finfo(scale.dtype).eps
119
120        if copy:
121            # New array to avoid side-effects
122            scale = xp.asarray(scale, copy=True)
123        scale[constant_mask] = 1.0
124        return scale
125
126
127@validate_params(
128    {
129        "X": ["array-like", "sparse matrix"],
130        "axis": [Options(Integral, {0, 1})],
131        "with_mean": ["boolean"],
132        "with_std": ["boolean"],
133        "copy": ["boolean"],
134    },
135    prefer_skip_nested_validation=True,
136)
137def scale(X, *, axis=0, with_mean=True, with_std=True, copy=True):
138    """Standardize a dataset along any axis.
139
140    Center to the mean and component wise scale to unit variance.
141
142    Read more in the :ref:`User Guide <preprocessing_scaler>`.
143
144    Parameters
145    ----------
146    X : {array-like, sparse matrix} of shape (n_samples, n_features)
147        The data to center and scale.
148
149    axis : {0, 1}, default=0
150        Axis used to compute the means and standard deviations along. If 0,
151        independently standardize each feature, otherwise (if 1) standardize
152        each sample.
153
154    with_mean : bool, default=True
155        If True, center the data before scaling.
156
157    with_std : bool, default=True
158        If True, scale the data to unit variance (or equivalently,
159        unit standard deviation).
160
161    copy : bool, default=True
162        If False, try to avoid a copy and scale in place.
163        This is not guaranteed to always work in place; e.g. if the data is
164        a numpy array with an int dtype, a copy will be returned even with
165        copy=False.
166
167    Returns
168    -------
169    X_tr : {ndarray, sparse matrix} of shape (n_samples, n_features)
170        The transformed data.
171
172    See Also
173    --------
174    StandardScaler : Performs scaling to unit variance using the Transformer
175        API (e.g. as part of a preprocessing
176        :class:`~sklearn.pipeline.Pipeline`).
177
178    Notes
179    -----
180    This implementation will refuse to center scipy.sparse matrices
181    since it would make them non-sparse and would potentially crash the
182    program with memory exhaustion problems.
183
184    Instead the caller is expected to either set explicitly
185    `with_mean=False` (in that case, only variance scaling will be
186    performed on the features of the CSC matrix) or to call `X.toarray()`
187    if he/she expects the materialized dense array to fit in memory.
188
189    To avoid memory copy the caller should pass a CSC matrix.
190
191    NaNs are treated as missing values: disregarded to compute the statistics,
192    and maintained during the data transformation.
193
194    We use a biased estimator for the standard deviation, equivalent to
195    `numpy.std(x, ddof=0)`. Note that the choice of `ddof` is unlikely to
196    affect model performance.
197
198    For a comparison of the different scalers, transformers, and normalizers,
199    see: :ref:`sphx_glr_auto_examples_preprocessing_plot_all_scaling.py`.
200
201    .. warning:: Risk of data leak
202
203        Do not use :func:`~sklearn.preprocessing.scale` unless you know
204        what you are doing. A common mistake is to apply it to the entire data
205        *before* splitting into training and test sets. This will bias the
206        model evaluation because information would have leaked from the test
207        set to the training set.
208        In general, we recommend using
209        :class:`~sklearn.preprocessing.StandardScaler` within a
210        :ref:`Pipeline <pipeline>` in order to prevent most risks of data
211        leaking: `pipe = make_pipeline(StandardScaler(), LogisticRegression())`.
212
213    Examples
214    --------
215    >>> from sklearn.preprocessing import scale
216    >>> X = [[-2, 1, 2], [-1, 0, 1]]
217    >>> scale(X, axis=0)  # scaling each column independently
218    array([[-1.,  1.,  1.],
219           [ 1., -1., -1.]])
220    >>> scale(X, axis=1)  # scaling each row independently
221    array([[-1.37,  0.39,  0.98],
222           [-1.22,  0.     ,  1.22]])
223    """
224    X = check_array(
225        X,
226        accept_sparse="csc",
227        copy=copy,
228        ensure_2d=False,
229        estimator="the scale function",
230        dtype=FLOAT_DTYPES,
231        ensure_all_finite="allow-nan",
232    )
233    if sparse.issparse(X):
234        if with_mean:
235            raise ValueError(
236                "Cannot center sparse matrices: pass `with_mean=False` instead"
237                " See docstring for motivation and alternatives."
238            )
239        if axis != 0:
240            raise ValueError(
241                "Can only scale sparse matrix on axis=0,  got axis=%d" % axis
242            )
243        if with_std:
244            _, var = mean_variance_axis(X, axis=0)
245            var = _handle_zeros_in_scale(var, copy=False)
246            inplace_column_scale(X, 1 / np.sqrt(var))
247    else:
248        X = np.asarray(X)
249        if with_mean:
250            mean_ = np.nanmean(X, axis)
251        if with_std:
252            scale_ = np.nanstd(X, axis)
253        # Xr is a view on the original array that enables easy use of
254        # broadcasting on the axis in which we are interested in
255        Xr = np.rollaxis(X, axis)
256        if with_mean:
257            Xr -= mean_
258            mean_1 = np.nanmean(Xr, axis=0)
259            # Verify that mean_1 is 'close to zero'. If X contains very
260            # large values, mean_1 can also be very large, due to a lack of
261            # precision of mean_. In this case, a pre-scaling of the
262            # concerned feature is efficient, for instance by its mean or
263            # maximum.
264            if not np.allclose(mean_1, 0):
265                warnings.warn(
266                    "Numerical issues were encountered "
267                    "when centering the data "
268                    "and might not be solved. Dataset may "
269                    "contain too large values. You may need "
270                    "to prescale your features."
271                )
272                Xr -= mean_1
273        if with_std:
274            scale_ = _handle_zeros_in_scale(scale_, copy=False)
275            Xr /= scale_
276            if with_mean:
277                mean_2 = np.nanmean(Xr, axis=0)
278                # If mean_2 is not 'close to zero', it comes from the fact that
279                # scale_ is very small so that mean_2 = mean_1/scale_ > 0, even
280                # if mean_1 was close to zero. The problem is thus essentially
281                # due to the lack of precision of mean_. A solution is then to
282                # subtract the mean again:
283                if not np.allclose(mean_2, 0):
284                    warnings.warn(
285                        "Numerical issues were encountered "
286                        "when scaling the data "
287                        "and might not be solved. The standard "
288                        "deviation of the data is probably "
289                        "very close to 0. "
290                    )
291                    Xr -= mean_2
292    return X
293
294
295class MinMaxScaler(OneToOneFeatureMixin, TransformerMixin, BaseEstimator):
296    """Transform features by scaling each feature to a given range.
297
298    This estimator scales and translates each feature individually such
299    that it is in the given range on the training set, e.g. between
300    zero and one.
301
302    The transformation is given by::
303
304        X_std = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0))
305        X_scaled = X_std * (max - min) + min
306
307    where min, max = feature_range.
308
309    This transformation is often used as an alternative to zero mean,
310    unit variance scaling.
311
312    `MinMaxScaler` doesn't reduce the effect of outliers, but it linearly
313    scales them down into a fixed range, where the largest occurring data point
314    corresponds to the maximum value and the smallest one corresponds to the
315    minimum value. For an example visualization, refer to :ref:`Compare
316    MinMaxScaler with other scalers <plot_all_scaling_minmax_scaler_section>`.
317
318    Read more in the :ref:`User Guide <preprocessing_scaler>`.
319
320    Parameters
321    ----------
322    feature_range : tuple (min, max), default=(0, 1)
323        Desired range of transformed data.
324
325    copy : bool, default=True
326        Set to False to perform inplace row normalization and avoid a
327        copy (if the input is already a numpy array).
328
329    clip : bool, default=False
330        Set to True to clip transformed values of held-out data to
331        provided `feature range`.
332
333        .. versionadded:: 0.24
334
335    Attributes
336    ----------
337    min_ : ndarray of shape (n_features,)
338        Per feature adjustment for minimum. Equivalent to
339        ``min - X.min(axis=0) * self.scale_``
340
341    scale_ : ndarray of shape (n_features,)
342        Per feature relative scaling of the data. Equivalent to
343        ``(max - min) / (X.max(axis=0) - X.min(axis=0))``
344
345        .. versionadded:: 0.17
346           *scale_* attribute.
347
348    data_min_ : ndarray of shape (n_features,)
349        Per feature minimum seen in the data
350
351        .. versionadded:: 0.17
352           *data_min_*
353
354    data_max_ : ndarray of shape (n_features,)
355        Per feature maximum seen in the data
356
357        .. versionadded:: 0.17
358           *data_max_*
359
360    data_range_ : ndarray of shape (n_features,)
361        Per feature range ``(data_max_ - data_min_)`` seen in the data
362
363        .. versionadded:: 0.17
364           *data_range_*
365
366    n_features_in_ : int
367        Number of features seen during :term:`fit`.
368
369        .. versionadded:: 0.24
370
371    n_samples_seen_ : int
372        The number of samples processed by the estimator.
373        It will be reset on new calls to fit, but increments across
374        ``partial_fit`` calls.
375
376    feature_names_in_ : ndarray of shape (`n_features_in_`,)
377        Names of features seen during :term:`fit`. Defined only when `X`
378        has feature names that are all strings.
379
380        .. versionadded:: 1.0
381
382    See Also
383    --------
384    minmax_scale : Equivalent function without the estimator API.
385
386    Notes
387    -----
388    NaNs are treated as missing values: disregarded in fit, and maintained in
389    transform.
390
391    Examples
392    --------
393    >>> from sklearn.preprocessing import MinMaxScaler
394    >>> data = [[-1, 2], [-0.5, 6], [0, 10], [1, 18]]
395    >>> scaler = MinMaxScaler()
396    >>> print(scaler.fit(data))
397    MinMaxScaler()
398    >>> print(scaler.data_max_)
399    [ 1. 18.]
400    >>> print(scaler.transform(data))
401    [[0.   0.  ]
402     [0.25 0.25]
403     [0.5  0.5 ]
404     [1.   1.  ]]
405    >>> print(scaler.transform([[2, 2]]))
406    [[1.5 0. ]]
407    """
408
409    _parameter_constraints: dict = {
410        "feature_range": [tuple],
411        "copy": ["boolean"],
412        "clip": ["boolean"],
413    }
414
415    def __init__(self, feature_range=(0, 1), *, copy=True, clip=False):
416        self.feature_range = feature_range
417        self.copy = copy
418        self.clip = clip
419
420    def _reset(self):
421        """Reset internal data-dependent state of the scaler, if necessary.
422
423        __init__ parameters are not touched.
424        """
425        # Checking one attribute is enough, because they are all set together
426        # in partial_fit
427        if hasattr(self, "scale_"):
428            del self.scale_
429            del self.min_
430            del self.n_samples_seen_
431            del self.data_min_
432            del self.data_max_
433            del self.data_range_
434
435    def fit(self, X, y=None):
436        """Compute the minimum and maximum to be used for later scaling.
437
438        Parameters
439        ----------
440        X : array-like of shape (n_samples, n_features)
441            The data used to compute the per-feature minimum and maximum
442            used for later scaling along the features axis.
443
444        y : None
445            Ignored.
446
447        Returns
448        -------
449        self : object
450            Fitted scaler.
451        """
452        # Reset internal state before fitting
453        self._reset()
454        return self.partial_fit(X, y)
455
456    @_fit_context(prefer_skip_nested_validation=True)
457    def partial_fit(self, X, y=None):
458        """Online computation of min and max on X for later scaling.
459
460        All of X is processed as a single batch. This is intended for cases
461        when :meth:`fit` is not feasible due to very large number of
462        `n_samples` or because X is read from a continuous stream.
463
464        Parameters
465        ----------
466        X : array-like of shape (n_samples, n_features)
467            The data used to compute the mean and standard deviation
468            used for later scaling along the features axis.
469
470        y : None
471            Ignored.
472
473        Returns
474        -------
475        self : object
476            Fitted scaler.
477        """
478        feature_range = self.feature_range
479        if feature_range[0] >= feature_range[1]:
480            raise ValueError(
481                "Minimum of desired feature range must be smaller than maximum. Got %s."
482                % str(feature_range)
483            )
484
485        if sparse.issparse(X):
486            raise TypeError(
487                "MinMaxScaler does not support sparse input. "
488                "Consider using MaxAbsScaler instead."
489            )
490
491        xp, _ = get_namespace(X)
492
493        first_pass = not hasattr(self, "n_samples_seen_")
494        X = validate_data(
495            self,
496            X,
497            reset=first_pass,
498            dtype=_array_api.supported_float_dtypes(xp),
499            ensure_all_finite="allow-nan",
500        )
501
502        device_ = device(X)
503        feature_range = (
504            xp.asarray(feature_range[0], dtype=X.dtype, device=device_),
505            xp.asarray(feature_range[1], dtype=X.dtype, device=device_),
506        )
507
508        data_min = _array_api._nanmin(X, axis=0, xp=xp)
509        data_max = _array_api._nanmax(X, axis=0, xp=xp)
510
511        if first_pass:
512            self.n_samples_seen_ = X.shape[0]
513        else:
514            data_min = xp.minimum(self.data_min_, data_min)
515            data_max = xp.maximum(self.data_max_, data_max)
516            self.n_samples_seen_ += X.shape[0]
517
518        data_range = data_max - data_min
519        self.scale_ = (feature_range[1] - feature_range[0]) / _handle_zeros_in_scale(
520            data_range, copy=True
521        )
522        self.min_ = feature_range[0] - data_min * self.scale_
523        self.data_min_ = data_min
524        self.data_max_ = data_max
525        self.data_range_ = data_range
526        return self
527
528    def transform(self, X):
529        """Scale features of X according to feature_range.
530
531        Parameters
532        ----------
533        X : array-like of shape (n_samples, n_features)
534            Input data that will be transformed.
535
536        Returns
537        -------
538        Xt : ndarray of shape (n_samples, n_features)
539            Transformed data.
540        """
541        check_is_fitted(self)
542
543        xp, _ = get_namespace(X)
544
545        X = validate_data(
546            self,
547            X,
548            copy=self.copy,
549            dtype=_array_api.supported_float_dtypes(xp),
550            force_writeable=True,
551            ensure_all_finite="allow-nan",
552            reset=False,
553        )
554
555        X *= self.scale_
556        X += self.min_
557        if self.clip:
558            device_ = device(X)
559            X = _modify_in_place_if_numpy(
560                xp,
561                xp.clip,
562                X,
563                xp.asarray(self.feature_range[0], dtype=X.dtype, device=device_),
564                xp.asarray(self.feature_range[1], dtype=X.dtype, device=device_),
565                out=X,
566            )
567        return X
568
569    def inverse_transform(self, X):
570        """Undo the scaling of X according to feature_range.
571
572        Parameters
573        ----------
574        X : array-like of shape (n_samples, n_features)
575            Input data that will be transformed. It cannot be sparse.
576
577        Returns
578        -------
579        X_original : ndarray of shape (n_samples, n_features)
580            Transformed data.
581        """
582        check_is_fitted(self)
583
584        xp, _ = get_namespace(X)
585
586        X = check_array(
587            X,
588            copy=self.copy,
589            dtype=_array_api.supported_float_dtypes(xp),
590            force_writeable=True,
591            ensure_all_finite="allow-nan",
592        )
593
594        X -= self.min_
595        X /= self.scale_
596        return X
597
598    def __sklearn_tags__(self):
599        tags = super().__sklearn_tags__()
600        tags.input_tags.allow_nan = True
601        tags.array_api_support = True
602        return tags
603
604
605@validate_params(
606    {
607        "X": ["array-like"],
608        "axis": [Options(Integral, {0, 1})],
609    },
610    prefer_skip_nested_validation=False,
611)
612def minmax_scale(X, feature_range=(0, 1), *, axis=0, copy=True):
613    """Transform features by scaling each feature to a given range.
614
615    This estimator scales and translates each feature individually such
616    that it is in the given range on the training set, i.e. between
617    zero and one.
618
619    The transformation is given by (when ``axis=0``)::
620
621        X_std = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0))
622        X_scaled = X_std * (max - min) + min
623
624    where min, max = feature_range.
625
626    The transformation is calculated as (when ``axis=0``)::
627
628       X_scaled = scale * X + min - X.min(axis=0) * scale
629       where scale = (max - min) / (X.max(axis=0) - X.min(axis=0))
630
631    This transformation is often used as an alternative to zero mean,
632    unit variance scaling.
633
634    Read more in the :ref:`User Guide <preprocessing_scaler>`.
635
636    .. versionadded:: 0.17
637       *minmax_scale* function interface
638       to :class:`~sklearn.preprocessing.MinMaxScaler`.
639
640    Parameters
641    ----------
642    X : array-like of shape (n_samples, n_features)
643        The data.
644
645    feature_range : tuple (min, max), default=(0, 1)
646        Desired range of transformed data.
647
648    axis : {0, 1}, default=0
649        Axis used to scale along. If 0, independently scale each feature,
650        otherwise (if 1) scale each sample.
651
652    copy : bool, default=True
653        If False, try to avoid a copy and scale in place.
654        This is not guaranteed to always work in place; e.g. if the data is
655        a numpy array with an int dtype, a copy will be returned even with
656        copy=False.
657
658    Returns
659    -------
660    X_tr : ndarray of shape (n_samples, n_features)
661        The transformed data.
662
663    .. warning:: Risk of data leak
664
665        Do not use :func:`~sklearn.preprocessing.minmax_scale` unless you know
666        what you are doing. A common mistake is to apply it to the entire data
667        *before* splitting into training and test sets. This will bias the
668        model evaluation because information would have leaked from the test
669        set to the training set.
670        In general, we recommend using
671        :class:`~sklearn.preprocessing.MinMaxScaler` within a
672        :ref:`Pipeline <pipeline>` in order to prevent most risks of data
673        leaking: `pipe = make_pipeline(MinMaxScaler(), LogisticRegression())`.
674
675    See Also
676    --------
677    MinMaxScaler : Performs scaling to a given range using the Transformer
678        API (e.g. as part of a preprocessing
679        :class:`~sklearn.pipeline.Pipeline`).
680
681    Notes
682    -----
683    For a comparison of the different scalers, transformers, and normalizers,
684    see: :ref:`sphx_glr_auto_examples_preprocessing_plot_all_scaling.py`.
685
686    Examples
687    --------
688    >>> from sklearn.preprocessing import minmax_scale
689    >>> X = [[-2, 1, 2], [-1, 0, 1]]
690    >>> minmax_scale(X, axis=0)  # scale each column independently
691    array([[0., 1., 1.],
692           [1., 0., 0.]])
693    >>> minmax_scale(X, axis=1)  # scale each row independently
694    array([[0.  , 0.75, 1.  ],
695           [0.  , 0.5 , 1.  ]])
696    """
697    # Unlike the scaler object, this function allows 1d input.
698    # If copy is required, it will be done inside the scaler object.
699    X = check_array(
700        X,
701        copy=False,
702        ensure_2d=False,
703        dtype=FLOAT_DTYPES,
704        ensure_all_finite="allow-nan",
705    )
706    original_ndim = X.ndim
707
708    if original_ndim == 1:
709        X = X.reshape(X.shape[0], 1)
710
711    s = MinMaxScaler(feature_range=feature_range, copy=copy)
712    if axis == 0:
713        X = s.fit_transform(X)
714    else:
715        X = s.fit_transform(X.T).T
716
717    if original_ndim == 1:
718        X = X.ravel()
719
720    return X
721
722
723class StandardScaler(OneToOneFeatureMixin, TransformerMixin, BaseEstimator):
724    """Standardize features by removing the mean and scaling to unit variance.
725
726    The standard score of a sample `x` is calculated as:
727
728    .. code-block:: text
729
730        z = (x - u) / s
731
732    where `u` is the mean of the training samples or zero if `with_mean=False`,
733    and `s` is the standard deviation of the training samples or one if
734    `with_std=False`.
735
736    Centering and scaling happen independently on each feature by computing
737    the relevant statistics on the samples in the training set. Mean and
738    standard deviation are then stored to be used on later data using
739    :meth:`transform`.
740
741    Standardization of a dataset is a common requirement for many
742    machine learning estimators: they might behave badly if the
743    individual features do not more or less look like standard normally
744    distributed data (e.g. Gaussian with 0 mean and unit variance).
745
746    For instance many elements used in the objective function of
747    a learning algorithm (such as the RBF kernel of Support Vector
748    Machines or the L1 and L2 regularizers of linear models) assume that
749    all features are centered around 0 and have variance in the same
750    order. If a feature has a variance that is orders of magnitude larger
751    than others, it might dominate the objective function and make the
752    estimator unable to learn from other features correctly as expected.
753
754    `StandardScaler` is sensitive to outliers, and the features may scale
755    differently from each other in the presence of outliers. For an example
756    visualization, refer to :ref:`Compare StandardScaler with other scalers
757    <plot_all_scaling_standard_scaler_section>`.
758
759    This scaler can also be applied to sparse CSR or CSC matrices by passing
760    `with_mean=False` to avoid breaking the sparsity structure of the data.
761
762    Read more in the :ref:`User Guide <preprocessing_scaler>`.
763
764    Parameters
765    ----------
766    copy : bool, default=True
767        If False, try to avoid a copy and do inplace scaling instead.
768        This is not guaranteed to always work inplace; e.g. if the data is
769        not a NumPy array or scipy.sparse CSR matrix, a copy may still be
770        returned.
771
772    with_mean : bool, default=True
773        If True, center the data before scaling.
774        This does not work (and will raise an exception) when attempted on
775        sparse matrices, because centering them entails building a dense
776        matrix which in common use cases is likely to be too large to fit in
777        memory.
778
779    with_std : bool, default=True
780        If True, scale the data to unit variance (or equivalently,
781        unit standard deviation).
782
783    Attributes
784    ----------
785    scale_ : ndarray of shape (n_features,) or None
786        Per feature relative scaling of the data to achieve zero mean and unit
787        variance. Generally this is calculated using `np.sqrt(var_)`. If a
788        variance is zero, we can't achieve unit variance, and the data is left
789        as-is, giving a scaling factor of 1. `scale_` is equal to `None`
790        when `with_std=False`.
791
792        .. versionadded:: 0.17
793           *scale_*
794
795    mean_ : ndarray of shape (n_features,) or None
796        The mean value for each feature in the training set.
797        Equal to ``None`` when ``with_mean=False`` and ``with_std=False``.
798
799    var_ : ndarray of shape (n_features,) or None
800        The variance for each feature in the training set. Used to compute
801        `scale_`. Equal to ``None`` when ``with_mean=False`` and
802        ``with_std=False``.
803
804    n_features_in_ : int
805        Number of features seen during :term:`fit`.
806
807        .. versionadded:: 0.24
808
809    feature_names_in_ : ndarray of shape (`n_features_in_`,)
810        Names of features seen during :term:`fit`. Defined only when `X`
811        has feature names that are all strings.
812
813        .. versionadded:: 1.0
814
815    n_samples_seen_ : int or ndarray of shape (n_features,)
816        The number of samples processed by the estimator for each feature.
817        If there are no missing samples, the ``n_samples_seen`` will be an
818        integer, otherwise it will be an array of dtype int. If
819        `sample_weights` are used it will be a float (if no missing data)
820        or an array of dtype float that sums the weights seen so far.
821        Will be reset on new calls to fit, but increments across
822        ``partial_fit`` calls.
823
824    See Also
825    --------
826    scale : Equivalent function without the estimator API.
827
828    :class:`~sklearn.decomposition.PCA` : Further removes the linear
829        correlation across features with 'whiten=True'.
830
831    Notes
832    -----
833    NaNs are treated as missing values: disregarded in fit, and maintained in
834    transform.
835
836    We use a biased estimator for the standard deviation, equivalent to
837    `numpy.std(x, ddof=0)`. Note that the choice of `ddof` is unlikely to
838    affect model performance.
839
840    Examples
841    --------
842    >>> from sklearn.preprocessing import StandardScaler
843    >>> data = [[0, 0], [0, 0], [1, 1], [1, 1]]
844    >>> scaler = StandardScaler()
845    >>> print(scaler.fit(data))
846    StandardScaler()
847    >>> print(scaler.mean_)
848    [0.5 0.5]
849    >>> print(scaler.transform(data))
850    [[-1. -1.]
851     [-1. -1.]
852     [ 1.  1.]
853     [ 1.  1.]]
854    >>> print(scaler.transform([[2, 2]]))
855    [[3. 3.]]
856    """
857
858    _parameter_constraints: dict = {
859        "copy": ["boolean"],
860        "with_mean": ["boolean"],
861        "with_std": ["boolean"],
862    }
863
864    def __init__(self, *, copy=True, with_mean=True, with_std=True):
865        self.with_mean = with_mean
866        self.with_std = with_std
867        self.copy = copy
868
869    def _reset(self):
870        """Reset internal data-dependent state of the scaler, if necessary.
871
872        __init__ parameters are not touched.
873        """
874        # Checking one attribute is enough, because they are all set together
875        # in partial_fit
876        if hasattr(self, "scale_"):
877            del self.scale_
878            del self.n_samples_seen_
879            del self.mean_
880            del self.var_
881
882    def fit(self, X, y=None, sample_weight=None):
883        """Compute the mean and std to be used for later scaling.
884
885        Parameters
886        ----------
887        X : {array-like, sparse matrix} of shape (n_samples, n_features)
888            The data used to compute the mean and standard deviation
889            used for later scaling along the features axis.
890
891        y : None
892            Ignored.
893
894        sample_weight : array-like of shape (n_samples,), default=None
895            Individual weights for each sample.
896
897            .. versionadded:: 0.24
898               parameter *sample_weight* support to StandardScaler.
899
900        Returns
901        -------
902        self : object
903            Fitted scaler.
904        """
905        # Reset internal state before fitting
906        self._reset()
907        return self.partial_fit(X, y, sample_weight)
908
909    @_fit_context(prefer_skip_nested_validation=True)
910    def partial_fit(self, X, y=None, sample_weight=None):
911        """Online computation of mean and std on X for later scaling.
912
913        All of X is processed as a single batch. This is intended for cases
914        when :meth:`fit` is not feasible due to very large number of
915        `n_samples` or because X is read from a continuous stream.
916
917        The algorithm for incremental mean and std is given in Equation 1.5a,b
918        in Chan, Tony F., Gene H. Golub, and Randall J. LeVeque. "Algorithms
919        for computing the sample variance: Analysis and recommendations."
920        The American Statistician 37.3 (1983): 242-247:
921
922        Parameters
923        ----------
924        X : {array-like, sparse matrix} of shape (n_samples, n_features)
925            The data used to compute the mean and standard deviation
926            used for later scaling along the features axis.
927
928        y : None
929            Ignored.
930
931        sample_weight : array-like of shape (n_samples,), default=None
932            Individual weights for each sample.
933
934            .. versionadded:: 0.24
935               parameter *sample_weight* support to StandardScaler.
936
937        Returns
938        -------
939        self : object
940            Fitted scaler.
941        """
942        first_call = not hasattr(self, "n_samples_seen_")
943        X = validate_data(
944            self,
945            X,
946            accept_sparse=("csr", "csc"),
947            dtype=FLOAT_DTYPES,
948            ensure_all_finite="allow-nan",
949            reset=first_call,
950        )
951        n_features = X.shape[1]
952
953        if sample_weight is not None:
954            sample_weight = _check_sample_weight(sample_weight, X, dtype=X.dtype)
955
956        # Even in the case of `with_mean=False`, we update the mean anyway
957        # This is needed for the incremental computation of the var
958        # See incr_mean_variance_axis and _incremental_mean_variance_axis
959
960        # if n_samples_seen_ is an integer (i.e. no missing values), we need to
961        # transform it to a NumPy array of shape (n_features,) required by
962        # incr_mean_variance_axis and _incremental_variance_axis
963        dtype = np.int64 if sample_weight is None else X.dtype
964        if not hasattr(self, "n_samples_seen_"):
965            self.n_samples_seen_ = np.zeros(n_features, dtype=dtype)
966        elif np.size(self.n_samples_seen_) == 1:
967            self.n_samples_seen_ = np.repeat(self.n_samples_seen_, X.shape[1])
968            self.n_samples_seen_ = self.n_samples_seen_.astype(dtype, copy=False)
969
970        if sparse.issparse(X):
971            if self.with_mean:
972                raise ValueError(
973                    "Cannot center sparse matrices: pass `with_mean=False` "
974                    "instead. See docstring for motivation and alternatives."
975                )
976            sparse_constructor = (
977                sparse.csr_matrix if X.format == "csr" else sparse.csc_matrix
978            )
979
980            if self.with_std:
981                # First pass
982                if not hasattr(self, "scale_"):
983                    self.mean_, self.var_, self.n_samples_seen_ = mean_variance_axis(
984                        X, axis=0, weights=sample_weight, return_sum_weights=True
985                    )
986                # Next passes
987                else:
988                    (
989                        self.mean_,
990                        self.var_,
991                        self.n_samples_seen_,
992                    ) = incr_mean_variance_axis(
993                        X,
994                        axis=0,
995                        last_mean=self.mean_,
996                        last_var=self.var_,
997                        last_n=self.n_samples_seen_,
998                        weights=sample_weight,
999                    )
1000                # We force the mean and variance to float64 for large arrays
1001                # See https://github.com/scikit-learn/scikit-learn/pull/12338
1002                self.mean_ = self.mean_.astype(np.float64, copy=False)
1003                self.var_ = self.var_.astype(np.float64, copy=False)
1004            else:
1005                self.mean_ = None  # as with_mean must be False for sparse
1006                self.var_ = None
1007                weights = _check_sample_weight(sample_weight, X)
1008                sum_weights_nan = weights @ sparse_constructor(
1009                    (np.isnan(X.data), X.indices, X.indptr), shape=X.shape
1010                )
1011                self.n_samples_seen_ += (np.sum(weights) - sum_weights_nan).astype(
1012                    dtype
1013                )
1014        else:
1015            # First pass
1016            if not hasattr(self, "scale_"):
1017                self.mean_ = 0.0
1018                if self.with_std:
1019                    self.var_ = 0.0
1020                else:
1021                    self.var_ = None
1022
1023            if not self.with_mean and not self.with_std:
1024                self.mean_ = None
1025                self.var_ = None
1026                self.n_samples_seen_ += X.shape[0] - np.isnan(X).sum(axis=0)
1027
1028            else:
1029                self.mean_, self.var_, self.n_samples_seen_ = _incremental_mean_and_var(
1030                    X,
1031                    self.mean_,
1032                    self.var_,
1033                    self.n_samples_seen_,
1034                    sample_weight=sample_weight,
1035                )
1036
1037        # for backward-compatibility, reduce n_samples_seen_ to an integer
1038        # if the number of samples is the same for each feature (i.e. no
1039        # missing values)
1040        if np.ptp(self.n_samples_seen_) == 0:
1041            self.n_samples_seen_ = self.n_samples_seen_[0]
1042
1043        if self.with_std:
1044            # Extract the list of near constant features on the raw variances,
1045            # before taking the square root.
1046            constant_mask = _is_constant_feature(
1047                self.var_, self.mean_, self.n_samples_seen_
1048            )
1049            self.scale_ = _handle_zeros_in_scale(
1050                np.sqrt(self.var_), copy=False, constant_mask=constant_mask
1051            )
1052        else:
1053            self.scale_ = None
1054
1055        return self
1056
1057    def transform(self, X, copy=None):
1058        """Perform standardization by centering and scaling.
1059
1060        Parameters
1061        ----------
1062        X : {array-like, sparse matrix of shape (n_samples, n_features)
1063            The data used to scale along the features axis.
1064        copy : bool, default=None
1065            Copy the input X or not.
1066
1067        Returns
1068        -------
1069        X_tr : {ndarray, sparse matrix} of shape (n_samples, n_features)
1070            Transformed array.
1071        """
1072        check_is_fitted(self)
1073
1074        copy = copy if copy is not None else self.copy
1075        X = validate_data(
1076            self,
1077            X,
1078            reset=False,
1079            accept_sparse="csr",
1080            copy=copy,
1081            dtype=FLOAT_DTYPES,
1082            force_writeable=True,
1083            ensure_all_finite="allow-nan",
1084        )
1085
1086        if sparse.issparse(X):
1087            if self.with_mean:
1088                raise ValueError(
1089                    "Cannot center sparse matrices: pass `with_mean=False` "
1090                    "instead. See docstring for motivation and alternatives."
1091                )
1092            if self.scale_ is not None:
1093                inplace_column_scale(X, 1 / self.scale_)
1094        else:
1095            if self.with_mean:
1096                X -= self.mean_
1097            if self.with_std:
1098                X /= self.scale_
1099        return X
1100
1101    def inverse_transform(self, X, copy=None):
1102        """Scale back the data to the original representation.
1103
1104        Parameters
1105        ----------
1106        X : {array-like, sparse matrix} of shape (n_samples, n_features)
1107            The data used to scale along the features axis.
1108
1109        copy : bool, default=None
1110            Copy the input `X` or not.
1111
1112        Returns
1113        -------
1114        X_original : {ndarray, sparse matrix} of shape (n_samples, n_features)
1115            Transformed array.
1116        """
1117        check_is_fitted(self)
1118
1119        copy = copy if copy is not None else self.copy
1120        X = check_array(
1121            X,
1122            accept_sparse="csr",
1123            copy=copy,
1124            dtype=FLOAT_DTYPES,
1125            force_writeable=True,
1126            ensure_all_finite="allow-nan",
1127        )
1128
1129        if sparse.issparse(X):
1130            if self.with_mean:
1131                raise ValueError(
1132                    "Cannot uncenter sparse matrices: pass `with_mean=False` "
1133                    "instead See docstring for motivation and alternatives."
1134                )
1135            if self.scale_ is not None:
1136                inplace_column_scale(X, self.scale_)
1137        else:
1138            if self.with_std:
1139                X *= self.scale_
1140            if self.with_mean:
1141                X += self.mean_
1142        return X
1143
1144    def __sklearn_tags__(self):
1145        tags = super().__sklearn_tags__()
1146        tags.input_tags.allow_nan = True
1147        tags.input_tags.sparse = not self.with_mean
1148        tags.transformer_tags.preserves_dtype = ["float64", "float32"]
1149        return tags
1150
1151
1152class MaxAbsScaler(OneToOneFeatureMixin, TransformerMixin, BaseEstimator):
1153    """Scale each feature by its maximum absolute value.
1154
1155    This estimator scales and translates each feature individually such
1156    that the maximal absolute value of each feature in the
1157    training set will be 1.0. It does not shift/center the data, and
1158    thus does not destroy any sparsity.
1159
1160    This scaler can also be applied to sparse CSR or CSC matrices.
1161
1162    `MaxAbsScaler` doesn't reduce the effect of outliers; it only linearly
1163    scales them down. For an example visualization, refer to :ref:`Compare
1164    MaxAbsScaler with other scalers <plot_all_scaling_max_abs_scaler_section>`.
1165
1166    .. versionadded:: 0.17
1167
1168    Parameters
1169    ----------
1170    copy : bool, default=True
1171        Set to False to perform inplace scaling and avoid a copy (if the input
1172        is already a numpy array).
1173
1174    Attributes
1175    ----------
1176    scale_ : ndarray of shape (n_features,)
1177        Per feature relative scaling of the data.
1178
1179        .. versionadded:: 0.17
1180           *scale_* attribute.
1181
1182    max_abs_ : ndarray of shape (n_features,)
1183        Per feature maximum absolute value.
1184
1185    n_features_in_ : int
1186        Number of features seen during :term:`fit`.
1187
1188        .. versionadded:: 0.24
1189
1190    feature_names_in_ : ndarray of shape (`n_features_in_`,)
1191        Names of features seen during :term:`fit`. Defined only when `X`
1192        has feature names that are all strings.
1193
1194        .. versionadded:: 1.0
1195
1196    n_samples_seen_ : int
1197        The number of samples processed by the estimator. Will be reset on
1198        new calls to fit, but increments across ``partial_fit`` calls.
1199
1200    See Also

Showing the first 1,200 of 3707 lines. Download the file for the rest.