
    6bi!                         S r SSKJs  Jr  SSKJr  SSKJr  SSK	J
r  SSKJr  SSKJr  \R                   r\R"                  r\" SS	/ S
9 " S S\R$                  5      5       rg)z*Keras hashed crossing preprocessing layer.    N)backend)
base_layer)preprocessing_utils)layer_utils)keras_exportzkeras.layers.HashedCrossingz6keras.layers.experimental.preprocessing.HashedCrossing)v1c                   Z   ^  \ rS rSrSrSU 4S jjrS rS rS rU 4S jr	S r
S	 rS
rU =r$ )HashedCrossing    a  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
`()`.

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

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. 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.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.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)>
c                   > SU;  d  US   c2  U[         :X  a  [        R                  O[        R                  " 5       US'   [
        TU ]  " S0 UD6  U[         :X  aB  [        R                  " U R                  5      R                  (       d  US   n[        SU 35      e[        R                  " U[         [        4U R                  R                  SS9  Xl        X l        X0l        g )NdtypezMWhen `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__as_dtypecompute_dtype
is_integer
ValueErrorr   validate_string_argONE_HOT	__class____name__num_binsr   sparse)selfr!   r   r"   kwargsinput_dtyper   s         k/home/james-whalen/.local/lib/python3.13/site-packages/tf_keras/src/layers/preprocessing/hashed_crossing.pyr   HashedCrossing.__init__Z   s    & F7O$;'3.GNN4D 7O 	"6" 3KK 2 23>> /K))47  	''"Gn~~.."		
 !&    c                 ^   U R                  U5        U Vs/ s H  n[        R                  " U5      PM     nnU R                  U5        US   R                  R
                  nUS:  a'  U Vs/ s H  n[        R                  " US5      PM     nnUS:  a'  U Vs/ s H  n[        R                  " US5      PM     nn[        R                  R                  XR                  5      n[        R                  R                  U5      nUS:X  a  [        R                  " USS/5      nO<US:X  a  [        R                  " US/5      nOUS:X  a  [        R                  " U/ 5      n[        R                  " UU R                  U R                  U R                  U R                  S9$ s  snf s  snf s  snf )Nr         )r   depthr"   r   )_check_at_least_two_inputsutilsensure_tensor_check_input_shape_and_typeshaperankexpand_dimsr   r"   cross_hashedr!   to_densereshapeencode_categorical_inputsr   r   )r#   inputsxr3   outputss        r&   callHashedCrossing.callz   sg    	''/289&Q%%%a(&9((0 ay##!88>?1e''2.F?!88>?1e''2.F? ))((?))$$W- 19 jj2q'2GQYjj2$/GQYjj"-G ..((--;;$$
 	
5 : @?s    F ,!F%!F*c                 V    U R                  U5        [        R                  " US   5      $ )Nr   )r.   r/   $compute_shape_for_encode_categorical)r#   input_shapess     r&   compute_output_shape#HashedCrossing.compute_output_shape   s%    ''599,q/JJr(   c                 H   U Vs/ s H  o"R                   R                  5       PM     nnU R                  U5      nU R                  (       d  [	        S U 5       5      (       a  [
        R                  " X@R                  S9$ [
        R                  " X@R                  S9$ s  snf )Nc              3   V   #    U  H  n[        U[        R                  5      v   M!     g 7fN)
isinstancer   SparseTensorSpec.0r:   s     r&   	<genexpr>:HashedCrossing.compute_output_signature.<locals>.<genexpr>   s#      
8C1Jq"--..s   '))r2   r   )	r2   as_listrA   r"   anyr   rG   r   
TensorSpec)r#   input_specsr:   r@   output_shapes        r&   compute_output_signature'HashedCrossing.compute_output_signature   s    3>?;a);?00>;;# 
8C
 
 
 &&"*<*<  }}<7I7IJJ @s   #Bc                    > [         TU ]  5       nUR                  U R                  U R                  U R
                  S.5        U$ )Nr!   r   r"   )r   
get_configupdater!   r   r"   )r#   configr   s     r&   rU   HashedCrossing.get_config   s?    #% MM#//++	
 r(   c                     [        U[        [        45      (       d  [        SU 35      e[	        U5      S:  a  [        SU 35      eg )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=)rF   listtupler   len)r#   r9   s     r&   r.   )HashedCrossing._check_at_least_two_inputs   s]    &4-00,,285  v;?$$*8-  r(   c                   ^ US   R                   R                  5       m[        T5      nUS:  d  US:X  a  TS   S:w  a  [        SU 35      e[	        U4S jUSS   5       5      (       d  [        SU 35      e[        S U 5       5      (       a  [        S	U 35      e[	        S
 U 5       5      (       d  [        SU 35      eg )Nr   r*   r+   r,   zjAll `HashedCrossing` inputs should have shape `[]`, `[batch_size]` or `[batch_size, 1]`. Received: inputs=c              3   \   >#    U  H!  oR                   R                  5       T:H  v   M#     g 7frE   )r2   rL   )rI   r:   first_shapes     r&   rJ   =HashedCrossing._check_input_shape_and_type.<locals>.<genexpr>   s     HZ77??$3Zs   ),zFAll `HashedCrossing` inputs should have equal shape. Received: inputs=c              3   v   #    U  H/  n[        U[        R                  [        R                  45      v   M1     g 7frE   )rF   r   RaggedTensorSparseTensorrH   s     r&   rJ   ra      s*      
GM!Jq2??BOO<==vs   79zFAll `HashedCrossing` inputs should be dense tensors. Received: inputs=c              3      #    U  H>  oR                   R                  =(       d    UR                   [        R                  :H  v   M@     g 7frE   )r   r   r   stringrH   s     r&   rJ   ra      s-     Nv!77%%=BII)==vs   AAzUAll `HashedCrossing` inputs should have an integer or string dtype. Received: inputs=)r2   rL   r\   r   allrM   )r#   r9   r3   r`   s      @r&   r1   *HashedCrossing._check_input_shape_and_type   s    Qioo--/;!8	k"o&:$$*8- 
 HVABZHHH$$*8-   
GM
 
 
 $$*8-  NvNNN228;  Or(   rT   )intF)r    
__module____qualname____firstlineno____doc__r   r<   rA   rQ   rU   r.   r1   __static_attributes____classcell__)r   s   @r&   r
   r
       s5    2h@$
LK	K	
 r(   r
   )rm   tensorflow.compat.v2compatv2r   tf_keras.srcr   tf_keras.src.enginer   !tf_keras.src.layers.preprocessingr   r/   tf_keras.src.utilsr    tensorflow.python.util.tf_exportr   r   r   Layerr
   r   r(   r&   <module>ry      sg    1 " !   * J * :ii
-- !<	
zZ%% z
zr(   