
    2Vh!!                         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  ed	       G d
 de             Zy)    )backend)keras_export)Layer)argument_validation)backend_utils)numerical_utils)tf_utils
tensorflowzkeras.layers.HashedCrossingc                   J     e Zd ZdZ	 	 	 	 d fd	Zd Zd Zd Zd Zd Z	 xZ
S )	HashedCrossinga	  A preprocessing layer which crosses features using the "hashing trick".

    This layer performs crosses of categorical features using the "hashing
    trick". Conceptually, the transformation can be thought of as:
    `hash(concatenate(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
    `()`.

    **Note:** This layer wraps `tf.keras.layers.HashedCrossing`. It cannot
    be used as part of the compiled computation graph of a model with
    any backend other than TensorFlow.
    It can however be used with any backend when running eagerly.
    It can also always be used as part of an input preprocessing pipeline
    with any backend (outside the model itself), which is how we recommend
    to use this layer.

    **Note:** This layer is safe to use inside a `tf.data` pipeline
    (independently of which backend you're using).

    Args:
        num_bins: Number of hash bins.
        output_mode: Specification for the output of the layer. 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. Defaults to `"int"`.
        sparse: Boolean. Only applicable to `"one_hot"` mode and only valid
            when using the TensorFlow backend. 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 = keras.layers.HashedCrossing(
    ...     num_bins=5)
    >>> feat1 = np.array(['A', 'B', 'A', 'B', 'A'])
    >>> feat2 = np.array([101, 101, 101, 102, 102])
    >>> layer((feat1, feat2))
    array([1, 4, 1, 1, 3])

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

    >>> layer = keras.layers.HashedCrossing(
    ...     num_bins=5, output_mode='one_hot')
    >>> feat1 = np.array(['A', 'B', 'A', 'B', 'A'])
    >>> feat2 = np.array([101, 101, 101, 102, 102])
    >>> layer((feat1, feat2))
    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)
    c                 f   t         j                  st        d      |dk(  r|d}t        |   ||       |r"t        j
                         dk7  rt        d      t        j                  |d| j                  j                  d	       || _        || _        || _        d
| _        d| _        d| _        y )NzRLayer HashedCrossing requires TensorFlow. Install it via `pip install tensorflow`.intint64)namedtyper   z;`sparse=True` can only be used with the TensorFlow backend.)r   one_hotoutput_mode)allowable_stringscaller_namearg_nameTF)tf	availableImportErrorsuper__init__r   
ValueErrorr   validate_string_arg	__class____name__num_binsr   sparse!_allow_non_tensor_positional_args_convert_input_argssupports_jit)selfr!   r   r"   r   r   kwargsr   s          ^/home/dcms/DCMS/lib/python3.12/site-packages/keras/src/layers/preprocessing/hashed_crossing.pyr   zHashedCrossing.__init__H   s     ||; 
 %EMEd%0goo'<7M  	//0//"		
 !&15.#( !    c                    t        |      dk(  r&t        |d   t              rt        |d   t              st        d|       |d   d   |d   d   k7  rt        d|       |s| j                  dk(  ry| j
                  fS | j                  dk(  rt        |d         S | j                  d	k(  r'|d   d   dk7  rt        |d         | j
                  fz   S t        |d         d d | j
                  fz   S )
N   r      zBExpected as input a list/tuple of 2 tensors. Received input_shape=zNExpected the two input tensors to have identical shapes. Received input_shape=r    r   )len
isinstancetupler   r   r!   )r&   input_shapes     r(   compute_output_shapez#HashedCrossing.compute_output_shapen   s   K A%k!ne4k!ne4((3}6  q>"Q!33((3}6 
 5(MM##u$Q((y([^B-?1-DQ(DMM+;;;[^$Sb)T]],<<<r)   c                    ddl m} | j                  |       |D cg c]  }t        j                  |       }}| j                  |       t        |d   j                        }t        |      }|dk  r)|D cg c]  }|j                  j                  |d        }}|dk  r)|D cg c]  }|j                  j                  |d        }}t        j                  j                  || j                        }t        j                  j                  |      }|dk(  r|j!                  |       nL|dk(  r,|j!                  |dz          t        j"                  |d      }n|dk(  rt        j$                  |g       }t'        j(                  || j*                  | j                  | j                  | j,                  |      }t/        j0                  || j2                  	      S c c}w c c}w c c}w )
Nr   r
   r+   r-   r,   )r,   )axis)r   depthr"   r   backend_module)r   )keras.src.backendr   _check_at_least_two_inputsr	   ensure_tensor_check_input_shape_and_typer1   shaper/   numpyexpand_dimsr   r"   cross_hashedr!   to_dense	set_shapesqueezereshaper   encode_categorical_inputsr   compute_dtyper   convert_tf_tensorr   )r&   inputs
tf_backendxfirst_shaperankoutputss          r(   callzHashedCrossing.call   s   >''/5;<(((+<<((0 F1IOO,;!8CIJaj&&221b9JFJ!8CIJaj&&221b9JFJ ))((?))$$W- 19k*QYkD01jjq1GQYjj"-G ";;((--;;$$%
 ..wdjjIIE = KJs   G7#G%#G$c                 v    | j                   | j                  | j                  | j                  | j                  dS )Nr!   r   r"   r   r   rO   )r&   s    r(   
get_configzHashedCrossing.get_config   s1    ++kkIIZZ
 	
r)   c                     t        |t        t        f      st        d|       t	        |      dk  rt        d|       y )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=)r0   listr1   r   r/   )r&   rG   s     r(   r9   z)HashedCrossing._check_at_least_two_inputs   sZ    &4-0,,285  v;?$$*8-  r)   c                 V   t        |d   j                        t              }|dkD  s|dk(  rd   dk7  rt        d|       t	        fd|dd  D              st        d|       t        d |D              rt        d	|       t	        d
 |D              st        d|       y )Nr   r+   r-   r,   zjAll `HashedCrossing` inputs should have shape `()`, `(batch_size)` or `(batch_size, 1)`. Received: inputs=c              3   N   K   | ]  }t        |j                        k(    y wN)r1   r<   ).0rI   rJ   s     r(   	<genexpr>z=HashedCrossing._check_input_shape_and_type.<locals>.<genexpr>   s     EQ5>[0Es   "%zFAll `HashedCrossing` inputs should have equal shape. Received: inputs=c              3   p   K   | ].  }t        |t        j                  t        j                  f       0 y wrU   )r0   r   RaggedTensorSparseTensorrV   rI   s     r(   rW   z=HashedCrossing._check_input_shape_and_type.<locals>.<genexpr>   s)      
BCJq2??BOO<=
s   46zFAll `HashedCrossing` inputs should be dense tensors. Received: inputs=c              3      K   | ]L  }t        j                  |j                        j                  xs |j                  t         j                  k(   N y wrU   )r   as_dtyper   
is_integerstringr[   s     r(   rW   z=HashedCrossing._check_input_shape_and_type.<locals>.<genexpr>   s@      
 KK ++Cqww"))/CC
s   AAzUAll `HashedCrossing` inputs should have an integer or string dtype. Received: inputs=)r1   r<   r/   r   allany)r&   rG   rK   rJ   s      @r(   r;   z*HashedCrossing._check_input_shape_and_type   s    F1IOO,;!8	k"o&:$$*8- 
 E&*EE$$*8-   
GM
 
 $$*8-   

 
 228; 	
r)   )r   FNN)r    
__module____qualname____doc__r   r3   rM   rP   r9   r;   __classcell__)r   s   @r(   r   r      s8    9| $"L=8&JP

r)   r   N)	keras.srcr   keras.src.api_exportr   keras.src.layers.layerr   keras.src.utilsr   r   r   r	   keras.src.utils.module_utilsr   r   r   r.   r)   r(   <module>rk      sA     - ( / ) + $ 9 +,WU W -Wr)   