a
    Sic"                     @   s   d 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lmZ ddlmZ ejZejZed	G d
d dejZdS )z*Keras hashed crossing preprocessing layer.    N)backend)
base_layer)base_preprocessing_layer)preprocessing_utils)layer_utils)keras_exportz6keras.layers.experimental.preprocessing.HashedCrossingc                       sV   e Zd ZdZd fdd	Zdd Zdd	 Zd
d Z fddZdd Z	dd Z
  ZS )HashedCrossinga  A preprocessing layer which crosses features using the "hashing trick".

    This layer performs crosses of categorical features using the "hasing
    trick".  Conceptually, the transformation can be thought of as:
    hash(concatenation of features) % `num_bins`.

    This layer currently only performs crosses of scalar inputs and batches of
    scalar inputs. Valid input shapes are `(batch_size, 1)`, `(batch_size,)` and
    `()`.

    For an overview and full list of preprocessing layers, see the preprocessing
    [guide](https://www.tensorflow.org/guide/keras/preprocessing_layers).

    Args:
      num_bins: Number of hash bins.
      output_mode: Specification for the output of the layer. Defaults to
        `"int"`.  Values can be `"int"`, or `"one_hot"` configuring the layer as
        follows:
          - `"int"`: Return the integer bin indices directly.
          - `"one_hot"`: Encodes each individual element in the input into an
            array the same size as `num_bins`, containing a 1 at the input's bin
            index.
      sparse: Boolean. Only applicable to `"one_hot"` mode. If True, returns a
        `SparseTensor` instead of a dense `Tensor`. Defaults to False.
      **kwargs: Keyword arguments to construct a layer.

    Examples:

    **Crossing two scalar features.**

    >>> layer = tf.keras.layers.experimental.preprocessing.HashedCrossing(
    ...     num_bins=5)
    >>> feat1 = tf.constant(['A', 'B', 'A', 'B', 'A'])
    >>> feat2 = tf.constant([101, 101, 101, 102, 102])
    >>> layer((feat1, feat2))
    <tf.Tensor: shape=(5,), dtype=int64, numpy=array([1, 4, 1, 1, 3])>

    **Crossing and one-hotting two scalar features.**

    >>> layer = tf.keras.layers.experimental.preprocessing.HashedCrossing(
    ...     num_bins=5, output_mode='one_hot')
    >>> feat1 = tf.constant(['A', 'B', 'A', 'B', 'A'])
    >>> feat2 = tf.constant([101, 101, 101, 102, 102])
    >>> layer((feat1, feat2))
    <tf.Tensor: shape=(5, 5), dtype=float32, numpy=
      array([[0., 1., 0., 0., 0.],
             [0., 0., 0., 0., 1.],
             [0., 1., 0., 0., 0.],
             [0., 1., 0., 0., 0.],
             [0., 0., 0., 1., 0.]], dtype=float32)>
    intFc                    s   d|vs|d d u r.|t kr"tjnt |d< t jf i | tj	d
d |t kr~t| jjs~|d }td| tj|t tf| jjdd || _|| _|| _d S )Ndtyper   TzMWhen `output_mode='int'`, `dtype` should be an integer type. Received: dtype=output_mode)allowable_strings
layer_namearg_name)INTtfint64r   floatxsuper__init__r   keras_kpl_gaugeget_cellsetas_dtypecompute_dtype
is_integer
ValueErrorr   validate_string_argONE_HOT	__class____name__num_binsr   sparse)selfr    r   r!   kwargsinput_dtyper    f/var/www/html/django/DPS/env/lib/python3.9/site-packages/keras/layers/preprocessing/hashed_crossing.pyr   W   s4    zHashedCrossing.__init__c                 C   s   |  | dd |D }| | |d jj}|dk rDdd |D }|dk rZdd |D }tj|| j}tj|}|dkrt	|ddg}n,|dkrt	|dg}n|dkrt	|g }t
j|| j| j| j| jd	S )
Nc                 S   s   g | ]}t |qS r&   )utilsensure_tensor.0xr&   r&   r'   
<listcomp>~       z'HashedCrossing.call.<locals>.<listcomp>r      c                 S   s   g | ]}t |d qS r(   expand_dimsr*   r&   r&   r'   r-      r.      c                 S   s   g | ]}t |d qS r0   r2   r*   r&   r&   r'   r-      r.   r1   )r   depthr!   r
   )_check_at_least_two_inputs_check_input_shape_and_typeshaperankr   r!   cross_hashedr    to_densereshaper(   encode_categorical_inputsr   r   )r"   inputsr9   outputsr&   r&   r'   callz   s.    

zHashedCrossing.callc                 C   s   |  | t|d S )Nr   )r6   r(   $compute_shape_for_encode_categorical)r"   input_shapesr&   r&   r'   compute_output_shape   s    
z#HashedCrossing.compute_output_shapec                 C   sP   dd |D }|  |}| js0tdd |D r@tj|| jdS tj|| jdS )Nc                 S   s   g | ]}|j  qS r&   r8   as_listr*   r&   r&   r'   r-      r.   z;HashedCrossing.compute_output_signature.<locals>.<listcomp>c                 s   s   | ]}t |tjV  qd S N)
isinstancer   SparseTensorSpecr*   r&   r&   r'   	<genexpr>   s   z:HashedCrossing.compute_output_signature.<locals>.<genexpr>)r8   r
   )rC   r!   anyr   rH   r   
TensorSpec)r"   input_specsrB   output_shaper&   r&   r'   compute_output_signature   s    
z'HashedCrossing.compute_output_signaturec                    s&   t   }|| j| j| jd |S )N)r    r   r!   )r   
get_configupdater    r   r!   )r"   configr%   r&   r'   rO      s    
zHashedCrossing.get_configc                 C   s:   t |ttfstd| t|dk r6td| d S )NzQ`HashedCrossing` should be called on a list or tuple of inputs. Received: inputs=r/   zK`HashedCrossing` should be called on at least two inputs. Received: inputs=)rG   listtupler   len)r"   r>   r&   r&   r'   r6      s    z)HashedCrossing._check_at_least_two_inputsc                    s   |d j   t }|dks2|dkr@ d dkr@td| t fdd|dd  D sltd| td	d |D rtd
| tdd |D std| d S )Nr   r/   r1   r4   zjAll `HashedCrossing` inputs should have shape `[]`, `[batch_size]` or `[batch_size, 1]`. Received: inputs=c                 3   s   | ]}|j   kV  qd S rF   rD   r*   first_shaper&   r'   rI      r.   z=HashedCrossing._check_input_shape_and_type.<locals>.<genexpr>zFAll `HashedCrossing` inputs should have equal shape. Received: inputs=c                 s   s    | ]}t |tjtjfV  qd S rF   )rG   r   RaggedTensorSparseTensorr*   r&   r&   r'   rI      s   zFAll `HashedCrossing` inputs should be dense tensors. Received: inputs=c                 s   s"   | ]}|j jp|j tjkV  qd S rF   )r
   r   r   stringr*   r&   r&   r'   rI      r.   zUAll `HashedCrossing` inputs should have an integer or string dtype. Received: inputs=)r8   rE   rT   r   allrJ   )r"   r>   r9   r&   rU   r'   r7      s8    z*HashedCrossing._check_input_shape_and_type)r	   F)r   
__module____qualname____doc__r   r@   rC   rN   rO   r6   r7   __classcell__r&   r&   r%   r'   r   !   s   4#&r   )r]   tensorflow.compat.v2compatv2r   kerasr   keras.enginer   r   Zkeras.layers.preprocessingr   r(   keras.utilsr    tensorflow.python.util.tf_exportr   r   r   Layerr   r&   r&   r&   r'   <module>   s   