a
    Sic,                     @   s   d Z ddlZddlm  mZ ddlmZ ddl	m
Z
 ddl	mZ ddlmZ ddgZed	G d
d de
jZdd Zdd ZdS )zGKeras layers that implement explicit (approximate) kernel feature maps.    N)initializers)
base_layer)
input_spec)keras_exportgaussian	laplacianz/keras.layers.experimental.RandomFourierFeaturesc                       sJ   e Zd ZdZd fdd	Z fddZd	d
 Zdd Z fddZ  Z	S )RandomFourierFeaturesa7  Layer that projects its inputs into a random feature space.

    This layer implements a mapping from input space to a space with
    `output_dim` dimensions, which approximates shift-invariant kernels. A
    kernel function `K(x, y)` is shift-invariant if `K(x, y) == k(x - y)` for
    some function `k`.  Many popular Radial Basis Functions (RBF), including
    Gaussian and Laplacian kernels, are shift-invariant.

    The implementation of this layer is based on the following paper:
    ["Random Features for Large-Scale Kernel Machines"](
      https://people.eecs.berkeley.edu/~brecht/papers/07.rah.rec.nips.pdf)
    by Ali Rahimi and Ben Recht.

    The distribution from which the parameters of the random features map
    (layer) are sampled determines which shift-invariant kernel the layer
    approximates (see paper for more details). You can use the distribution of
    your choice. The layer supports out-of-the-box approximations of the
    following two RBF kernels:

    - Gaussian: `K(x, y) == exp(- square(x - y) / (2 * square(scale)))`
    - Laplacian: `K(x, y) = exp(-abs(x - y) / scale))`

    **Note:** Unlike what is described in the paper and unlike what is used in
    the Scikit-Learn implementation, the output of this layer does not apply
    the `sqrt(2 / D)` normalization factor.

    **Usage:** Typically, this layer is used to "kernelize" linear models by
    applying a non-linear transformation (this layer) to the input features and
    then training a linear model on top of the transformed features. Depending
    on the loss function of the linear model, the composition of this layer and
    the linear model results to models that are equivalent (up to approximation)
    to kernel SVMs (for hinge loss), kernel logistic regression (for logistic
    loss), kernel linear regression (for squared loss), etc.

    Examples:

    A kernel multinomial logistic regression model with Gaussian kernel for
    MNIST:

    ```python
    model = keras.Sequential([
      keras.Input(shape=(784,)),
      RandomFourierFeatures(
          output_dim=4096,
          scale=10.,
          kernel_initializer='gaussian'),
      layers.Dense(units=10, activation='softmax'),
    ])
    model.compile(
        optimizer='adam',
        loss='categorical_crossentropy',
        metrics=['categorical_accuracy']
    )
    ```

    A quasi-SVM classifier for MNIST:

    ```python
    model = keras.Sequential([
      keras.Input(shape=(784,)),
      RandomFourierFeatures(
          output_dim=4096,
          scale=10.,
          kernel_initializer='gaussian'),
      layers.Dense(units=10),
    ])
    model.compile(
        optimizer='adam',
        loss='hinge',
        metrics=['categorical_accuracy']
    )
    ```

    To use another kernel, just replace the layer creation line with:

    ```python
    random_features_layer = RandomFourierFeatures(
        output_dim=500,
        kernel_initializer=<my_initializer>,
        scale=...,
        ...)
    ```

    Args:
      output_dim: Positive integer, the dimension of the layer's output, i.e.,
        the number of random features used to approximate the kernel.
      kernel_initializer: Determines the distribution of the parameters of the
        random features map (and therefore the kernel approximated by the
        layer).  It can be either a string identifier or a Keras `Initializer`
        instance.  Currently only 'gaussian' and 'laplacian' are supported
        string identifiers (case insensitive). Note that the kernel matrix is
        not trainable.
      scale: For Gaussian and Laplacian kernels, this corresponds to a scaling
        factor of the corresponding kernel approximated by the layer (see
        concrete definitions above). When provided, it should be a positive
        float. If None, a default value is used: if the kernel initializer is
        set to "gaussian", `scale` defaults to `sqrt(input_dim / 2)`, otherwise,
        it defaults to 1.0.  Both the approximation error of the kernel and the
        classification quality are sensitive to this parameter. If `trainable`
        is set to `True`, this parameter is learned end-to-end during training
        and the provided value serves as the initial value.
        **Note:** When features from this layer are fed to a linear model,
          by making `scale` trainable, the resulting optimization problem is
          no longer convex (even if the loss function used by the linear model
          is convex).
      trainable: Whether the scaling parameter of the layer should be trainable.
        Defaults to `False`.
      name: String, name to use for this layer.
    r   NFc                    s   |dkrt d| t|tr@| tvr@t d| dt |d ur^|dkr^t d| t jf ||d| || _|| _|| _	d S )Nr   z5`output_dim` should be a positive integer. Received: z"Unsupported `kernel_initializer`: z Expected one of:         z=When provided, `scale` should be a positive float. Received: )	trainablename)

ValueError
isinstancestrlower_SUPPORTED_RBF_KERNEL_TYPESsuper__init__
output_dimkernel_initializerscale)selfr   r   r   r
   r   kwargs	__class__ S/var/www/html/django/DPS/env/lib/python3.9/site-packages/keras/layers/kernelized.pyr      s.    	
zRandomFourierFeatures.__init__c                    s  t |}|jdkr*td|j d| |jd jd u rHtd| tjdd|jd jid| _|jd j}t	| j
|| jfd}| jd|| jft j|d	d
| _| jd| jft jtjddtj dd	d
| _| jd u rt| j
|| _| jddt jt jj| jddd| _t | d S )N   zCThe rank of the input tensor should be 2. Received input with rank z% instead. Full input shape received:    cThe last dimension of the input tensor should be defined. Found `None`. Full input shape received: )ndimaxes)shapeunscaled_kernelF)r   r!   dtypeinitializerr
   biasr	   )minvalmaxvalkernel_scale)r   TNonNeg)r   r!   r#   r$   r
   
constraint)tfTensorShaperankr   ndimsdimsvaluer   	InputSpec _get_random_features_initializerr   r   
add_weightfloat32r"   r   RandomUniformnppir%   r   _get_default_scalecompatv1constant_initializerr(   r   build)r   input_shape	input_dimr   r   r   r   r<      sb    




zRandomFourierFeatures.buildc                 C   sV   t j|| jd}t |t j}d| j | j }t j||d}t j	|| j
}t |S )N)r#         ?)ab)r+   convert_to_tensorr#   castr4   r(   r"   matmulnnbias_addr%   cos)r   inputskerneloutputsr   r   r   call   s    zRandomFourierFeatures.callc                 C   sF   t |}|d}|jd jd u r2td| |d d | jS )Nr   r   )r+   r,   	with_rankr/   r0   r   concatenater   )r   r=   r   r   r   compute_output_shape   s    

z*RandomFourierFeatures.compute_output_shapec                    sP   | j }t|tst|}| j|| jd}t  }t	t
| t
|  S )N)r   r   r   )r   r   r   r   	serializer   r   r   
get_configdictlistitems)r   r   configbase_configr   r   r   rQ      s    


z RandomFourierFeatures.get_config)r   NFN)
__name__
__module____qualname____doc__r   r<   rK   rO   rQ   __classcell__r   r   r   r   r      s   q    6
r   c                 C   sj   dd }| }t | trf|  dkr0tjdd}n6|  dkrRt|dd|d}ntd	|  d
t |S )z/Returns Initializer object for random features.c                 S   s.   t jjdd|d}| |t t j|d    S )Nr	   r?   )lowhighsizeg      ?)r6   randomuniformtanr7   )locr   r!   probsr   r   r   _get_cauchy_samples  s    z=_get_random_features_initializer.<locals>._get_cauchy_samplesr   r?   )stddevr   r	   )rb   r   r!   z#Unsupported `kernel_initializer`: "z" Expected one of: )r   r   r   r   RandomNormalConstantr   r   )r$   r!   rd   Zrandom_features_initializerr   r   r   r2     s    
r2   c                 C   s(   t | tr$|  dkr$t|d S dS )Nr   g       @r?   )r   r   r   r6   sqrt)r$   r>   r   r   r   r8     s    r8   )rZ   numpyr6   tensorflow.compat.v2r9   v2r+   kerasr   keras.enginer   r    tensorflow.python.util.tf_exportr   r   Layerr   r2   r8   r   r   r   r   <module>   s    c