U
    ½mœdt\  ã                   @   s4  d Z ddlmZ ddlZddlmZ ddlmZ ddl	m
Z
mZ dd	lmZmZ dd
lmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlmZ ddlm Z  ddl!m"Z" ddl#m$Z$ dgZ%dd„ Z&dd„ Z'dd„ Z(dddd d!dd"d#œd$d„Z)dS )%zBPartial dependence plots for regression and classification models.é    )ÚIterableN)Úsparse)Ú
mquantilesé   )Ú_check_feature_namesÚ_get_feature_indexé   )Úis_classifierÚis_regressor)Ú	cartesian)Úcheck_array)Úcheck_matplotlib_support)Ú_safe_indexing)Ú_safe_assign)Ú_determine_key_type)Ú_get_column_indices)Úcheck_is_fitted)ÚBunch)ÚDecisionTreeRegressor)ÚRandomForestRegressor)ÚNotFittedError)ÚBaseGradientBoosting)ÚBaseHistGradientBoostingÚpartial_dependencec                 C   sB  t |tƒrt|ƒdkrtdƒ‚tdd„ |D ƒƒs8tdƒ‚|d |d krPtdƒ‚|dkr`td	ƒ‚g }t|ƒD ]È\}}zt t| |dd
�¡}W n4 t	k
rÀ } ztd|› d�ƒ|‚W 5 d}~X Y nX |sÔ|j
d |k rÚ|}	nPtt| |dd
�|dd�}
t |
d |
d ¡�rtdƒ‚tj|
d |
d |dd�}	| |	¡ qlt|ƒ|fS )a   Generate a grid of points based on the percentiles of X.

    The grid is a cartesian product between the columns of ``values``. The
    ith column of ``values`` consists in ``grid_resolution`` equally-spaced
    points between the percentiles of the jth column of X.

    If ``grid_resolution`` is bigger than the number of unique values in the
    j-th column of X or if the feature is a categorical feature (by inspecting
    `is_categorical`) , then those unique values will be used instead.

    Parameters
    ----------
    X : array-like of shape (n_samples, n_target_features)
        The data.

    percentiles : tuple of float
        The percentiles which are used to construct the extreme values of
        the grid. Must be in [0, 1].

    is_categorical : list of bool
        For each feature, tells whether it is categorical or not. If a feature
        is categorical, then the values used will be the unique ones
        (i.e. categories) instead of the percentiles.

    grid_resolution : int
        The number of equally spaced points to be placed on the grid for each
        feature.

    Returns
    -------
    grid : ndarray of shape (n_points, n_target_features)
        A value for each feature at each point in the grid. ``n_points`` is
        always ``<= grid_resolution ** X.shape[1]``.

    values : list of 1d ndarrays
        The values with which the grid has been created. The size of each
        array ``values[j]`` is either ``grid_resolution``, or the number of
        unique values in ``X[:, j]``, whichever is smaller.
    r   z/'percentiles' must be a sequence of 2 elements.c                 s   s&   | ]}d |  kodkn  V  qdS )r   r   N© )Ú.0Úxr   r   ú_/home/sam/Atlas/atlas_env/lib/python3.8/site-packages/sklearn/inspection/_partial_dependence.pyÚ	<genexpr>Q   s     z_grid_from_X.<locals>.<genexpr>z''percentiles' values must be in [0, 1].r   r   z9percentiles[0] must be strictly less than percentiles[1].z2'grid_resolution' must be strictly greater than 1.©ÚaxiszThe column #zØ contains mixed data types. Finding unique categories fail due to sorting. It usually means that the column contains `np.nan` values together with `str` categories. Such use case is not yet supported in scikit-learn.N)Zprobr    ztpercentiles are too close to each other, unable to build the grid. Please choose percentiles that are further apart.T)ÚnumZendpoint)Ú
isinstancer   ÚlenÚ
ValueErrorÚallÚ	enumerateÚnpÚuniquer   Ú	TypeErrorÚshaper   ZallcloseZlinspaceÚappendr   )ÚXÚpercentilesÚis_categoricalÚgrid_resolutionÚvaluesÚfeatureZis_catZuniquesÚexcr    Zemp_percentilesr   r   r   Ú_grid_from_X'   sJ    (
ÿû  ÿÿür3   c                 C   s&   |   ||¡}|jdkr"| dd¡}|S )Nr   éÿÿÿÿ)Z%_compute_partial_dependence_recursionÚndimÚreshape)ÚestÚgridÚfeaturesÚaveraged_predictionsr   r   r   Ú_partial_dependence_recursionƒ   s    
r;   c                 C   sä  g }g }t | ƒr| j}nnt| dd ƒ}t| dd ƒ}	|dkrB|p>|	}n|dkrN|n|	}|d kr†|dkrltdƒ‚n|dkr~tdƒ‚ntdƒ‚| ¡ }
|D ]‚}t|ƒD ]\}}t|
|| |d� qžz*||
ƒ}| |¡ | tj	|dd	�¡ W q’ t
k
�r } ztd
ƒ|‚W 5 d }~X Y q’X q’|jd }t |¡j}t | ƒ�rP|jdk�rP| |d¡}n.t| ƒ�r~|jd dk�r~|d }| |d¡}t |¡j}t | ƒ�r®|jdk�r®| dd¡}n.t| ƒ�rÜ|jd dk�rÜ|d }| dd¡}||fS )NÚpredict_probaÚdecision_functionÚautozCThe estimator has no predict_proba and no decision_function method.z*The estimator has no predict_proba method.z.The estimator has no decision_function method.)Zcolumn_indexerr   r   z0'estimator' parameter must be a fitted estimatorr   r4   r   )r
   ZpredictÚgetattrr$   Úcopyr&   r   r+   r'   Zmeanr   r*   ÚarrayÚTr5   r6   r	   )r7   r8   r9   r,   Úresponse_methodÚpredictionsr:   Zprediction_methodr<   r=   ZX_evalÚ
new_valuesÚiÚvariableÚpredÚeZ	n_samplesr   r   r   Ú_partial_dependence_brute�   sX    
ÿýÿ


rJ   r>   )gš™™™™™©?gffffffî?éd   Úaverage)Úcategorical_featuresÚfeature_namesrC   r-   r/   ÚmethodÚkindc                   s^  t | ƒ t| ƒs t| ƒs tdƒ‚t| ƒrBt| jd tjƒrBtdƒ‚t|dƒsdt	 
|¡sdt|dtd�}d}
||
kr†td |d	 |
¡¡ƒ‚t| ƒrž|d
kržtdƒ‚d}||krÀtd |d	 |¡¡ƒ‚|	dkrÜ|dkrØtdƒ‚d}|d
k�r t| tƒ�r| jdk�rd}nt| tttfƒ�rd}nd}|dk�r|t| ttttfƒ�sVd}td d	 |¡¡ƒ‚|d
k�rdd}|dk�r|td |¡ƒ‚t|dd�dk�rºt t |d¡¡�rºtd |jd d ¡ƒ‚tjt||ƒtjdd� ¡ }t|ˆƒ‰|jd }ˆ dk�rdgt|ƒ }nštjˆ dd�‰ ˆ jj dk�rXˆ j!|k�rDtd ˆ j!› d!|› d"�ƒ‚‡ fd#d$„|D ƒ}nFˆ jj d%k�rŒ‡fd&d$„ˆ D ƒ‰‡fd'd$„|D ƒ}ntd(ˆ j› d)�ƒ‚t"t#||dd*�|||ƒ\}}|dk�rüt$| ||||ƒ\}}|j%d+|jd fd,d$„ |D ƒžŽ }nt&| ||ƒ}|j%d2d-d$„ |D ƒžŽ }|	dk�r6t'||d.�S |	d/k�rLt'||d0�S t'|||d1�S dS )3aý  Partial dependence of ``features``.

    Partial dependence of a feature (or a set of features) corresponds to
    the average response of an estimator for each possible value of the
    feature.

    Read more in the :ref:`User Guide <partial_dependence>`.

    .. warning::

        For :class:`~sklearn.ensemble.GradientBoostingClassifier` and
        :class:`~sklearn.ensemble.GradientBoostingRegressor`, the
        `'recursion'` method (used by default) will not account for the `init`
        predictor of the boosting process. In practice, this will produce
        the same values as `'brute'` up to a constant offset in the target
        response, provided that `init` is a constant estimator (which is the
        default). However, if `init` is not a constant estimator, the
        partial dependence values are incorrect for `'recursion'` because the
        offset will be sample-dependent. It is preferable to use the `'brute'`
        method. Note that this only applies to
        :class:`~sklearn.ensemble.GradientBoostingClassifier` and
        :class:`~sklearn.ensemble.GradientBoostingRegressor`, not to
        :class:`~sklearn.ensemble.HistGradientBoostingClassifier` and
        :class:`~sklearn.ensemble.HistGradientBoostingRegressor`.

    Parameters
    ----------
    estimator : BaseEstimator
        A fitted estimator object implementing :term:`predict`,
        :term:`predict_proba`, or :term:`decision_function`.
        Multioutput-multiclass classifiers are not supported.

    X : {array-like or dataframe} of shape (n_samples, n_features)
        ``X`` is used to generate a grid of values for the target
        ``features`` (where the partial dependence will be evaluated), and
        also to generate values for the complement features when the
        `method` is 'brute'.

    features : array-like of {int, str}
        The feature (e.g. `[0]`) or pair of interacting features
        (e.g. `[(0, 1)]`) for which the partial dependency should be computed.

    categorical_features : array-like of shape (n_features,) or shape             (n_categorical_features,), dtype={bool, int, str}, default=None
        Indicates the categorical features.

        - `None`: no feature will be considered categorical;
        - boolean array-like: boolean mask of shape `(n_features,)`
            indicating which features are categorical. Thus, this array has
            the same shape has `X.shape[1]`;
        - integer or string array-like: integer indices or strings
            indicating categorical features.

        .. versionadded:: 1.2

    feature_names : array-like of shape (n_features,), dtype=str, default=None
        Name of each feature; `feature_names[i]` holds the name of the feature
        with index `i`.
        By default, the name of the feature corresponds to their numerical
        index for NumPy array and their column name for pandas dataframe.

        .. versionadded:: 1.2

    response_method : {'auto', 'predict_proba', 'decision_function'},             default='auto'
        Specifies whether to use :term:`predict_proba` or
        :term:`decision_function` as the target response. For regressors
        this parameter is ignored and the response is always the output of
        :term:`predict`. By default, :term:`predict_proba` is tried first
        and we revert to :term:`decision_function` if it doesn't exist. If
        ``method`` is 'recursion', the response is always the output of
        :term:`decision_function`.

    percentiles : tuple of float, default=(0.05, 0.95)
        The lower and upper percentile used to create the extreme values
        for the grid. Must be in [0, 1].

    grid_resolution : int, default=100
        The number of equally spaced points on the grid, for each target
        feature.

    method : {'auto', 'recursion', 'brute'}, default='auto'
        The method used to calculate the averaged predictions:

        - `'recursion'` is only supported for some tree-based estimators
          (namely
          :class:`~sklearn.ensemble.GradientBoostingClassifier`,
          :class:`~sklearn.ensemble.GradientBoostingRegressor`,
          :class:`~sklearn.ensemble.HistGradientBoostingClassifier`,
          :class:`~sklearn.ensemble.HistGradientBoostingRegressor`,
          :class:`~sklearn.tree.DecisionTreeRegressor`,
          :class:`~sklearn.ensemble.RandomForestRegressor`,
          ) when `kind='average'`.
          This is more efficient in terms of speed.
          With this method, the target response of a
          classifier is always the decision function, not the predicted
          probabilities. Since the `'recursion'` method implicitly computes
          the average of the Individual Conditional Expectation (ICE) by
          design, it is not compatible with ICE and thus `kind` must be
          `'average'`.

        - `'brute'` is supported for any estimator, but is more
          computationally intensive.

        - `'auto'`: the `'recursion'` is used for estimators that support it,
          and `'brute'` is used otherwise.

        Please see :ref:`this note <pdp_method_differences>` for
        differences between the `'brute'` and `'recursion'` method.

    kind : {'average', 'individual', 'both'}, default='average'
        Whether to return the partial dependence averaged across all the
        samples in the dataset or one value per sample or both.
        See Returns below.

        Note that the fast `method='recursion'` option is only available for
        `kind='average'`. Computing individual dependencies requires using the
        slower `method='brute'` option.

        .. versionadded:: 0.24

    Returns
    -------
    predictions : :class:`~sklearn.utils.Bunch`
        Dictionary-like object, with the following attributes.

        individual : ndarray of shape (n_outputs, n_instances,                 len(values[0]), len(values[1]), ...)
            The predictions for all the points in the grid for all
            samples in X. This is also known as Individual
            Conditional Expectation (ICE)

        average : ndarray of shape (n_outputs, len(values[0]),                 len(values[1]), ...)
            The predictions for all the points in the grid, averaged
            over all samples in X (or over the training data if
            ``method`` is 'recursion').
            Only available when ``kind='both'``.

        values : seq of 1d ndarrays
            The values with which the grid has been created. The generated
            grid is a cartesian product of the arrays in ``values``.
            ``len(values) == len(features)``. The size of each array
            ``values[j]`` is either ``grid_resolution``, or the number of
            unique values in ``X[:, j]``, whichever is smaller.

        ``n_outputs`` corresponds to the number of classes in a multi-class
        setting, or to the number of tasks for multi-output regression.
        For classical regression and binary classification ``n_outputs==1``.
        ``n_values_feature_j`` corresponds to the size ``values[j]``.

    See Also
    --------
    PartialDependenceDisplay.from_estimator : Plot Partial Dependence.
    PartialDependenceDisplay : Partial Dependence visualization.

    Examples
    --------
    >>> X = [[0, 0, 2], [1, 0, 0]]
    >>> y = [0, 1]
    >>> from sklearn.ensemble import GradientBoostingClassifier
    >>> gb = GradientBoostingClassifier(random_state=0).fit(X, y)
    >>> partial_dependence(gb, features=[0], X=X, percentiles=(0, 1),
    ...                    grid_resolution=2) # doctest: +SKIP
    (array([[-4.52...,  4.52...]]), [array([ 0.,  1.])])
    z5'estimator' must be a fitted regressor or classifier.r   z3Multiclass-multioutput estimators are not supportedZ	__array__z	allow-nan)Zforce_all_finiteÚdtype)r>   r<   r=   zEresponse_method {} is invalid. Accepted response_method names are {}.z, r>   zKThe response_method parameter is ignored for regressors and must be 'auto'.)ÚbruteÚ	recursionr>   z3method {} is invalid. Accepted method names are {}.rL   rS   zCThe 'recursion' method only applies when 'kind' is set to 'average'rR   N)ZGradientBoostingClassifierZGradientBoostingRegressorZHistGradientBoostingClassifierÚHistGradientBoostingRegressorrT   r   r   z[Only the following estimators support the 'recursion' method: {}. Try using method='brute'.r=   zUWith the 'recursion' method, the response_method must be 'decision_function'. Got {}.F)Zaccept_sliceÚintzall features must be in [0, {}]r   ÚC)rQ   Úorder)r@   ÚbzeWhen `categorical_features` is a boolean array-like, the array should be of shape (n_features,). Got z elements while `X` contains z
 features.c                    s   g | ]}ˆ | ‘qS r   r   ©r   Úidx)rM   r   r   Ú
<listcomp>  s     z&partial_dependence.<locals>.<listcomp>)rF   ÚOÚUc                    s   g | ]}t |ˆ d �‘qS )©rN   )r   )r   Úcatr^   r   r   r[   
  s   ÿc                    s   g | ]}|ˆ k‘qS r   r   rY   )Úcategorical_features_idxr   r   r[     s    zXExpected `categorical_features` to be an array-like of boolean, integer, or string. Got z	 instead.r   r4   c                 S   s   g | ]}|j d  ‘qS ©r   ©r*   ©r   Úvalr   r   r   r[   &  s     c                 S   s   g | ]}|j d  ‘qS ra   rb   rc   r   r   r   r[   0  s     )rL   r0   Ú
individual)re   r0   )rL   re   r0   )r4   )(r   r	   r
   r$   r"   Zclasses_r'   ZndarrayÚhasattrr   Úissparser   ÚobjectÚformatÚjoinr   Úinitr   r   r   r   ÚanyÚlessr*   Zasarrayr   Zint32Zravelr   r#   rA   rQ   rP   Úsizer3   r   rJ   r6   r;   r   )Z	estimatorr,   r9   rM   rN   rC   r-   r/   rO   rP   Zaccepted_responsesZaccepted_methodsZsupported_classes_recursionZfeatures_indicesZ
n_featuresr.   r8   r0   r:   rD   r   )rM   r`   rN   r   r   ã   s    4 ÿÿÿ ÿÿÿ
þ
üþ		þÿ

ÿÿ  ÿ



ÿ
þ
ÿÿü
    ÿ ÿÿ  ÿ ÿÿ

ý)*Ú__doc__Úcollections.abcr   Únumpyr'   Zscipyr   Zscipy.stats.mstatsr   Z	_pd_utilsr   r   Úbaser	   r
   Zutils.extmathr   Úutilsr   r   r   r   r   r   Zutils.validationr   r   Útreer   Zensembler   Ú
exceptionsr   Zensemble._gbr   Z2ensemble._hist_gradient_boosting.gradient_boostingr   Ú__all__r3   r;   rJ   r   r   r   r   r   Ú<module>   sB   ÿ\
[õ