
    2Vh@D                        d dl Z d dl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Zd dlmZ d dlmZ d dlmZ d dlmZ  G d de      Z ed       G d dee             Z ed       G d dee             Z ed       G d  d!ee             Zy# e$ r- dZ G d d      Z G d d      Z G d d      Z G d d      ZY w xY w)"    N)keras_export)clone_model)Model)_routing_enabled)_validate_data)type_of_target)TargetReshaper)_check_model)assert_sklearn_installed)BaseEstimator)ClassifierMixin)RegressorMixin)TransformerMixinc                       e Zd Zy)r   N__name__
__module____qualname__     R/home/dcms/DCMS/lib/python3.12/site-packages/keras/src/wrappers/sklearn_wrapper.pyr   r          r   r   c                       e Zd Zy)r   Nr   r   r   r   r   r      r   r   r   c                       e Zd Zy)r   Nr   r   r   r   r   r      r   r   r   c                       e Zd Zy)r   Nr   r   r   r   r   r   !   r   r   r   c                   r     e Zd ZdZ	 	 	 ddZd Z fdZd Zed        Z	d Z
d Zd	 Zd
 ZddZd Z xZS )SKLBaseaT  Base class for scikit-learn wrappers.

    Note that there are sources of randomness in model initialization and
    training. Refer to [Reproducibility in Keras Models](
    https://keras.io/examples/keras_recipes/reproducibility_recipes/) on how to
    control randomness.

    Args:
        model: `Model`.
            An instance of `Model`, or a callable returning such an object.
            Note that if input is a `Model`, it will be cloned using
            `keras.models.clone_model` before being fitted, unless
            `warm_start=True`.
            The `Model` instance needs to be passed as already compiled.
            If callable, it must accept at least `X` and `y` as keyword
            arguments. Other arguments must be accepted if passed as
            `model_kwargs` by the user.
        warm_start: bool, defaults to `False`.
            Whether to reuse the model weights from the previous fit. If `True`,
            the given model won't be cloned and the weights from the previous
            fit will be reused.
        model_kwargs: dict, defaults to `None`.
            Keyword arguments passed to `model`, if `model` is callable.
        fit_kwargs: dict, defaults to `None`.
            Keyword arguments passed to `model.fit`. These can also be passed
            directly to the `fit` method of the scikit-learn wrapper. The
            values passed directly to the `fit` method take precedence over
            these.

    Attributes:
        model_ : `Model`
            The fitted model.
        history_ : dict
            The history of the fit, returned by `model.fit`.
    c                 z    t        | j                  j                         || _        || _        || _        || _        y N)r   	__class__r   model
warm_startmodel_kwargs
fit_kwargs)selfr!   r"   r#   r$   s        r   __init__zSKLBase.__init__J   s3     	!!8!89
$($r   c                 
    ddiS )Nnon_deterministicTr   r%   s    r   
_more_tagszSKLBase._more_tagsW   s    #T**r   c                 2    t         |          }d|_        |S NT)super__sklearn_tags__r(   r%   tagsr    s     r   r.   zSKLBase.__sklearn_tags__Z   s    w')!%r   c                     t        | j                        r| j                  nt        j                  | j                        } t	        |       || j
                  | j                        S )zeReturn a deep copy of the model.

        This is used by the `sklearn.base.clone` function.
        )r!   r"   r#   )callabler!   copydeepcopytyper"   r#   )r%   r!   s     r   __sklearn_clone__zSKLBase.__sklearn_clone___   sR     #4::.DJJDMM$**4M 	 tDz**
 	
r   c                 <    t        | di       j                  dd      S )zThe current training epoch.history_epochr   )getattrgetr)   s    r   epoch_zSKLBase.epoch_m   s      tZ,00!<<r   c                 4   t               st        d      t        j                  j                  j                  | j                  j                        | _        |j                         D ],  \  }}| j                  j                  j                  ||       . | S )a  Set requested parameters by the fit method.

        Please see [scikit-learn's metadata routing](
        https://scikit-learn.org/stable/metadata_routing.html) for more
        details.


        Arguments:
            kwargs : dict
                Arguments should be of the form `param_name=alias`, and `alias`
                can be one of `{True, False, None, str}`.

        Returns:
            self
        zThis method is only available when metadata routing is enabled. You can enable it using sklearn.set_config(enable_metadata_routing=True).)owner)paramalias)r   RuntimeErrorsklearnutilsmetadata_routingMetadataRequestr    r   _metadata_requestitemsscoreadd_request)r%   kwargsr?   r@   s       r   set_fit_requestzSKLBase.set_fit_requestr   s       !D  ")!?!?!O!O..)) "P "
 #LLN 	OLE5""((4454N	Or   c                     t        | j                  t              rt        | j                        S | j                  xs i } | j                  d||d|S )N)Xyr   )
isinstancer!   r   r   r#   )r%   rM   rN   argss       r   
_get_modelzSKLBase._get_model   sJ    djj%(tzz**$$*D4::/Q/$//r   c                    t        | ||      \  }}| j                  |d      }| j                  ||      }t        |       | j                  xs i }|j                  |        |j                  ||fi || _        || _        | S )a%  Fit the model.

        Args:
            X: array-like, shape=(n_samples, n_features)
                The input samples.
            y: array-like, shape=(n_samples,) or (n_samples, n_outputs)
                The targets.
            **kwargs: keyword arguments passed to `model.fit`
        Treset)	r   _process_targetrQ   r
   r$   updatefitr8   model_)r%   rM   rN   rJ   r!   r$   s         r   rW   zSKLBase.fit   s     dAq)1  $ /1%U__*
&!!		!Q5*5r   c                     t         j                  j                  |        t        | |d      }| j                  j                  |      }| j                  |      S )zPredict using the model.FrS   )rB   basecheck_is_fittedr   rX   predict_reverse_process_target)r%   rM   
raw_outputs      r   r\   zSKLBase.predict   sG    $$T*4%0[[((+
++J77r   c                     t        |d       |rt               j                  |      | _        | j                  j	                  |      S )z-Regressors are NOOP here, classifiers do OHE.Traise_unknown)r   r	   rW   _target_encoder	transform)r%   rN   rT   s      r   rU   zSKLBase._process_target   s>     	q-#1#3#7#7#:D ##--a00r   c                 8    | j                   j                  |      S )z2Regressors are NOOP here, classifiers reverse OHE.)rb   inverse_transform)r%   rN   s     r   r]   zSKLBase._reverse_process_target   s    ##55a88r   )FNNF)r   r   r   __doc__r&   r*   r.   r6   propertyr<   rK   rQ   rW   r\   rU   r]   __classcell__r    s   @r   r   r   %   sZ    "N %+

 = =<0,819r   r   z keras.wrappers.SKLearnClassifierc                   0     e Zd ZdZddZd Z fdZ xZS )SKLearnClassifiera  scikit-learn compatible classifier wrapper for Keras models.

    Note that there are sources of randomness in model initialization and
    training. Refer to [Reproducibility in Keras Models](
    https://keras.io/examples/keras_recipes/reproducibility_recipes/) on how to
    control randomness.

    Args:
        model: `Model`.
            An instance of `Model`, or a callable returning such an object.
            Note that if input is a `Model`, it will be cloned using
            `keras.models.clone_model` before being fitted, unless
            `warm_start=True`.
            The `Model` instance needs to be passed as already compiled.
            If callable, it must accept at least `X` and `y` as keyword
            arguments. Other arguments must be accepted if passed as
            `model_kwargs` by the user.
        warm_start: bool, defaults to `False`.
            Whether to reuse the model weights from the previous fit. If `True`,
            the given model won't be cloned and the weights from the previous
            fit will be reused.
        model_kwargs: dict, defaults to `None`.
            Keyword arguments passed to `model`, if `model` is callable.
        fit_kwargs: dict, defaults to `None`.
            Keyword arguments passed to `model.fit`. These can also be passed
            directly to the `fit` method of the scikit-learn wrapper. The
            values passed directly to the `fit` method take precedence over
            these.

    Attributes:
        model_ : `Model`
            The fitted model.
        history_ : dict
            The history of the fit, returned by `model.fit`.
        classes_ : array-like, shape=(n_classes,)
            The classes labels.

    Example:
    Here we use a function which creates a basic MLP model dynamically
    choosing the input and output shapes. We will use this to create our
    scikit-learn model.

    ``` python
    from keras.src.layers import Dense, Input, Model

    def dynamic_model(X, y, loss, layers=[10]):
        # Creates a basic MLP model dynamically choosing the input and
        # output shapes.
        n_features_in = X.shape[1]
        inp = Input(shape=(n_features_in,))

        hidden = inp
        for layer_size in layers:
            hidden = Dense(layer_size, activation="relu")(hidden)

        n_outputs = y.shape[1] if len(y.shape) > 1 else 1
        out = [Dense(n_outputs, activation="softmax")(hidden)]
        model = Model(inp, out)
        model.compile(loss=loss, optimizer="rmsprop")

        return model
    ```

    You can then use this function to create a scikit-learn compatible model
    and fit it on some data.

    ``` python
    from sklearn.datasets import make_classification
    from keras.wrappers import SKLearnClassifier

    X, y = make_classification(n_samples=1000, n_features=10, n_classes=3)
    est = SKLearnClassifier(
        model=dynamic_model,
        model_kwargs={
            "loss": "categorical_crossentropy",
            "layers": [20, 20, 20],
        },
    )

    est.fit(X, y, epochs=5)
    ```
    c                    t        |d      }|dvrt        d|       |rt        j                  j	                  t               t        j                  j                  d            j                  |      | _	        t        j                  |      | _        t        | j                        dk(  rt        d      | j                  j                  |      S )	zClassifiers do OHE.Tr`   )binary
multiclasszDOnly binary and multiclass target types are supported. Target type: F)sparse_output   z6Classifier can't train when only one class is present.)r   
ValueErrorrB   pipelinemake_pipeliner	   preprocessingOneHotEncoderrW   rb   npuniqueclasses_lenrc   )r%   rN   rT   target_types       r   rU   z!SKLearnClassifier._process_target  s    $Qd;66!!,/  #*#3#3#A#A %%33%3H$ c!f   IIaLDM4==!Q& L  ##--a00r   c                 
    ddiS N
poor_scoreTr   r)   s    r   r*   zSKLearnClassifier._more_tags*      d##r   c                 F    t         |          }d|j                  _        |S r,   )r-   r.   classifier_tagsr~   r/   s     r   r.   z"SKLearnClassifier.__sklearn_tags__.  s#    w')*.'r   rf   )r   r   r   rg   rU   r*   r.   ri   rj   s   @r   rl   rl      s    Qf1($ r   rl   zkeras.wrappers.SKLearnRegressorc                   (     e Zd ZdZd Z fdZ xZS )SKLearnRegressora4  scikit-learn compatible regressor wrapper for Keras models.

    Note that there are sources of randomness in model initialization and
    training. Refer to [Reproducibility in Keras Models](
    https://keras.io/examples/keras_recipes/reproducibility_recipes/) on how to
    control randomness.

    Args:
        model: `Model`.
            An instance of `Model`, or a callable returning such an object.
            Note that if input is a `Model`, it will be cloned using
            `keras.models.clone_model` before being fitted, unless
            `warm_start=True`.
            The `Model` instance needs to be passed as already compiled.
            If callable, it must accept at least `X` and `y` as keyword
            arguments. Other arguments must be accepted if passed as
            `model_kwargs` by the user.
        warm_start: bool, defaults to `False`.
            Whether to reuse the model weights from the previous fit. If `True`,
            the given model won't be cloned and the weights from the previous
            fit will be reused.
        model_kwargs: dict, defaults to `None`.
            Keyword arguments passed to `model`, if `model` is callable.
        fit_kwargs: dict, defaults to `None`.
            Keyword arguments passed to `model.fit`. These can also be passed
            directly to the `fit` method of the scikit-learn wrapper. The
            values passed directly to the `fit` method take precedence over
            these.

    Attributes:
        model_ : `Model`
            The fitted model.

    Example:
    Here we use a function which creates a basic MLP model dynamically
    choosing the input and output shapes. We will use this to create our
    scikit-learn model.

    ``` python
    from keras.src.layers import Dense, Input, Model

    def dynamic_model(X, y, loss, layers=[10]):
        # Creates a basic MLP model dynamically choosing the input and
        # output shapes.
        n_features_in = X.shape[1]
        inp = Input(shape=(n_features_in,))

        hidden = inp
        for layer_size in layers:
            hidden = Dense(layer_size, activation="relu")(hidden)

        n_outputs = y.shape[1] if len(y.shape) > 1 else 1
        out = [Dense(n_outputs, activation="softmax")(hidden)]
        model = Model(inp, out)
        model.compile(loss=loss, optimizer="rmsprop")

        return model
    ```

    You can then use this function to create a scikit-learn compatible model
    and fit it on some data.

    ``` python
    from sklearn.datasets import make_regression
    from keras.wrappers import SKLearnRegressor

    X, y = make_regression(n_samples=1000, n_features=10)
    est = SKLearnRegressor(
        model=dynamic_model,
        model_kwargs={
            "loss": "mse",
            "layers": [20, 20, 20],
        },
    )

    est.fit(X, y, epochs=5)
    ```
    c                 
    ddiS r}   r   r)   s    r   r*   zSKLearnRegressor._more_tags  r   r   c                 F    t         |          }d|j                  _        |S r,   )r-   r.   regressor_tagsr~   r/   s     r   r.   z!SKLearnRegressor.__sklearn_tags__  s#    w'))-&r   )r   r   r   rg   r*   r.   ri   rj   s   @r   r   r   4  s    M^$ r   r   z!keras.wrappers.SKLearnTransformerc                   .     e Zd ZdZd Zd Z fdZ xZS )SKLearnTransformera
  scikit-learn compatible transformer wrapper for Keras models.

    Note that this is a scikit-learn compatible transformer, and not a
    transformer in the deep learning sense.

    Also note that there are sources of randomness in model initialization and
    training. Refer to [Reproducibility in Keras Models](
    https://keras.io/examples/keras_recipes/reproducibility_recipes/) on how to
    control randomness.

    Args:
        model: `Model`.
            An instance of `Model`, or a callable returning such an object.
            Note that if input is a `Model`, it will be cloned using
            `keras.models.clone_model` before being fitted, unless
            `warm_start=True`.
            The `Model` instance needs to be passed as already compiled.
            If callable, it must accept at least `X` and `y` as keyword
            arguments. Other arguments must be accepted if passed as
            `model_kwargs` by the user.
        warm_start: bool, defaults to `False`.
            Whether to reuse the model weights from the previous fit. If `True`,
            the given model won't be cloned and the weights from the previous
            fit will be reused.
        model_kwargs: dict, defaults to `None`.
            Keyword arguments passed to `model`, if `model` is callable.
        fit_kwargs: dict, defaults to `None`.
            Keyword arguments passed to `model.fit`. These can also be passed
            directly to the `fit` method of the scikit-learn wrapper. The
            values passed directly to the `fit` method take precedence over
            these.

    Attributes:
        model_ : `Model`
            The fitted model.
        history_ : dict
            The history of the fit, returned by `model.fit`.

    Example:
    A common use case for a scikit-learn transformer, is to have a step
    which gives you the embedding of your data. Here we assume
    `my_package.my_model` is a Keras model which takes the input and gives
    embeddings of the data, and `my_package.my_data` is your dataset loader.

    ``` python
    from my_package import my_model, my_data
    from keras.wrappers import SKLearnTransformer
    from sklearn.frozen import FrozenEstimator # requires scikit-learn>=1.6
    from sklearn.pipeline import make_pipeline
    from sklearn.ensemble import HistGradientBoostingClassifier

    X, y = my_data()

    trs = FrozenEstimator(SKLearnTransformer(model=my_model))
    pipe = make_pipeline(trs, HistGradientBoostingClassifier())
    pipe.fit(X, y)
    ```

    Note that in the above example, `FrozenEstimator` prevents any further
    training of the transformer step in the pipeline, which can be the case
    if you don't want to change the embedding model at hand.
    c                     t         j                  j                  |        t        | |d      }| j                  j                  |      S )a  Transform the data.

        Args:
            X: array-like, shape=(n_samples, n_features)
                The input samples.

        Returns:
            X_transformed: array-like, shape=(n_samples, n_features)
                The transformed data.
        FrS   )rB   rZ   r[   r   rX   r\   )r%   rM   s     r   rc   zSKLearnTransformer.transform  s9     	$$T*4%0{{""1%%r   c                 
    dg iS )Npreserves_dtyper   r)   s    r   r*   zSKLearnTransformer._more_tags  s     r
 	
r   c                 F    t         |          }g |j                  _        |S r   )r-   r.   transformer_tagsr   r/   s     r   r.   z#SKLearnTransformer.__sklearn_tags__  s#    w')02-r   )r   r   r   rg   rc   r*   r.   ri   rj   s   @r   r   r     s    =~&
 r   r   )r3   numpyrw   keras.src.api_exportr   keras.src.models.cloningr   keras.src.models.modelr   keras.src.wrappers.fixesr   r   r   keras.src.wrappers.utilsr	   r
   r   rB   sklearn.baser   r   r   r   ImportErrorr   rl   r   r   r   r   r   <module>r      s      - 0 ( 5 3 3 3 1 =*,+-"Y9m Y9x 01o o 2od /0W~w W 1Wt 12X)7 X 3Xw  G    s    B- -/CC