
    BVhH                     4   d Z ddlmZmZmZmZmZ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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   e d       G d dejB                               Z"y)z?Mid level API for TPU Embeddings without Embedding Accelerator.    )AnyDictIterableOptionalTextUnion)distribute_lib)tpu_strategy)dtypes)ops)sparse_tensor)tensor)	array_ops)embedding_ops)math_ops)
sparse_ops)	variables)ragged_tensor)tpu_embedding_base)tpu_embedding_v2_utils)tpu_replication)nest)	tf_exportz)tpu.experimental.embedding.TPUEmbeddingV0c            
           e Zd ZdZdeej                  ef   deej                     f fdZ
edeej                  ej                  f   fd       Zdeeeeej                  f   f   fdZd Z	 dd	ej*                  d
ej*                  dee   dej*                  fdZd	ej*                  dedej*                  fdZ	 ddedee   defdZdej8                  d
eej8                     dej                  dej                  dej*                  f
dZdej>                  d
eej>                     dej                  dej                  dej*                  f
dZ  xZ!S )TPUEmbeddingV0a  The TPUEmbedding mid level API running on TPU without Embedding accelerator.

  NOTE: This mid level API is not intended for large embedding table lookup.
  Embedding tables will be replicated across devices rather than sharding
  across them. To do large embedding table lookup, please use the
  `tpu.experimental.embedding.TPUEmbedding` class. This class is an alternative
  way to do embedding lookups when the TPU doesn't support any version of
  embedding feature. See
  `tpu.experimental.tpu_hardware_feature.embedding_feature` for a detailed
  explanation.

  This class has to be created under the `TPUStrategy`, Otherwise a RuntimeError
  will be raised.
  ```python
  strategy = tf.distribute.TPUStrategy(...)
  with strategy.scope():
    embedding = tf.tpu.experimental.embedding.TPUEmbeddingV0(
        feature_config=feature_config,
        optimizer=tf.tpu.experimental.embedding.SGD(0.1))
  ```
  When creating a distributed dataset that is to be passed to the lookup
  operation a special input option must be specified:

  ```python
  distributed_dataset = (
      strategy.distribute_datasets_from_function(
          dataset_fn=...,
          options=tf.distribute.InputOptions(
              experimental_fetch_to_device=False))
  dataset_iterator = iter(distributed_dataset)
  ```

  Below is an example of a training and evaluation step:

  ```python
  optimizer = tf.keras.optimizers.SGD(0.1)

  @tf.function
  def training_step(dataset_iterator, num_steps):
    def tpu_step(embedding_features):
      with tf.GradientTape() as tape:
        tape.watch(embedding.embedding_table.values())
        activation = embedding(embedding_features)
        model_output = model(activations)
        loss = ...  # some function of labels and model_output

      embedding_gradients = tape.gradient(loss,
                                          embedding.embedding_table.values())
      optimizer.apply_gradients(list(zip(gradients,
                                mid_level_api.embedding_tables.values())))
      # Insert your model gradient and optimizer application here

    for _ in tf.range(num_steps):
      strategy.run(tpu_step, args=(next(dataset_iterator), ))

  @tf.function
  def evalution_step(dataset_iterator, num_steps):
    def tpu_step(embedding_features):
      activations = embedding(embedding_features)
      model_output = model(activations)
      # Insert your evaluation code here.

    for _ in tf.range(num_steps):
      strategy.run(tpu_step, args=(next(dataset_iterator), ))
  ```

  NOTE: The optimizer used here is a Keras optimizer. In order to make the slot
  variable creation stay consistent between Keras optimizers and
  embedding optimizers, the `slot_variable_creation_fn` argument of the
  embedding optimizers has to be passed with the Keras `add_slot` function. Also
  note that the slot names might be slightly different between them.

  ```python
  optimizer = tf.keras.optimizers.Adagrad(learning_rate=0.1)

  def slot_variable_creation_fn(table, slot_names, slot_initializers):
      slots = {}
      for slot, initializer in zip(slot_names, slot_initializers):
        slots[slot] = optimizer.add_slot(table, slot, initializer)
      return slots

  embedding_optimizer = tf.experimental.embedding.Adagrad(
      learning_rate=0.1,
      slot_variable_creation_fn=slot_variable_creation_fn)

  # Use the embedding optimizer to create mid level api and keras optimizer to
  # apply gradients.
  ```
  feature_config	optimizerc                    t         t        |   ||       t        j                         | _        t        | j
                  t        j                  t        j                  f      s$t        dj                  | j
                              d| _        y )Nz@TPUEmbeddingV0 should be created under TPUStrategy but found {}.F)superr   __init__r	   get_strategy	_strategy
isinstancer
   TPUStrategyTPUStrategyV2RuntimeErrorformat_built)selfr   r   	__class__s      V/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/tpu/tpu_embedding_v1.pyr    zTPUEmbeddingV0.__init__   sp     
.$(C#002DNdnn#//1K1KLN
L6$..!# # DK    returnc                     | j                          | j                  D ci c]  }|| j                  |j                     d   ! c}S c c}w )z;Returns a dict of embedding tables, keyed by `TableConfig`.
parameters)_maybe_build_table_config
_variablesname)r)   tables     r+   embedding_tableszTPUEmbeddingV0.embedding_tables   sO     	 '' 	tuzz*<88  s   $Ac                 l    i }| j                   D ]"  }| j                  |d      ||j                  <   $ |S )a)  Create variables for TPU embeddings.

    Note that this will always ensure that the variable is created under the
    TPUStrategy.

    Returns:
      A dict of dicts. The outer dict is keyed by the table names and the inner
      dicts are keyed by 'parameters' and the slot variable names.
    T)	trainable)r1   _create_variablesr3   )r)   r   r4   s      r+   _create_variables_and_slotsz*TPUEmbeddingV0._create_variables_and_slots   sF     I## L"44Ud4Ki

L r,   c                     | j                   s.t        j                         5  | j                          d d d        y y # 1 sw Y   y xY wN)r(   r   
init_scopebuild)r)   s    r+   r0   zTPUEmbeddingV0._maybe_build   s=    ;; >> 

   s	   <A
embeddingsweightcombinerc                    |d}|dk(  rt        j                  |d      }|S |dk(  rFt        j                  |d      }t        j                  |d      }t        j                  ||      }|S |dk(  rqt        j                  |d      }t        j                  |d      }t        j                  |d      }t        j                  |      }t        j                  ||      }|S t        d|       )a  Apply the combiner to the embedding look up result on second to last axis.

    Args:
      embeddings: A Tensor of the embedding lookup result.
      weight: A Tensor of weight which has the same shape of the embeddings.
      combiner: One of "mean", "sum", "sqrtn". Defaults to "mean".

    Raises:
      ValueError: If the combiner is not one of 'mean', 'sqrtn' or 'sum'.
    Returns:
      A Tensor.
    meansum)axissqrtn   z6combiner must be one of 'mean', 'sqrtn' or 'sum', got )r   
reduce_sum
div_no_nanpowsqrt
ValueError)r)   r>   r?   r@   
weight_sumweight_squaredweight_sum_sqrts          r+   _apply_combiner_to_embeddingsz,TPUEmbeddingV0._apply_combiner_to_embeddings   s    " h5&&z;j  
V	&&z;j&&vB7j&&z:>j  
W	&&z;j||FA.n&&~B?j j1o&&z?Cj  B8*
MO Or,   sequence_lengthc                     |j                   d   }||kD  rt        j                  |g dd|dg      }|S t        j                  |ddgd||z
  gddgg      }|S )a?  Pad or truncate the embedding lookup result based on the sequence length.

    Args:
      embeddings: A rank 3 Tensor of the embedding lookup result.
      sequence_length: number of the max sequence length set in the feature
        config.

    Returns:
      A Tensor with second last axis padded or truncated.
       )r   r   r   )beginsizer   )paddings)shaper   slicepad)r)   r>   rQ   original_sequence_lengths       r+   %_pad_or_truncate_with_sequence_lengthz4TPUEmbeddingV0._pad_or_truncate_with_sequence_length   s}      *//2/1??
IR",EGj 	 ==
FQ2J JKFj r,   featuresweightsc           
      `   | j                   s| j                          t        j                  || j                         t        j
                  |      }dgt        |      z  }|+t        j                  ||       t        j
                  |      }t        j                  | j                        }g }t        |||      D ]  \  }}\  }	}
| j                  |
j                     }|t        |t        j                        rt        dj                  |	            t!        |      t!        |      ur.t        dj                  |	t!        |      t!        |                  |
j"                  dkD  rt        dj                  |	            t        |t        j                        rP|
j"                  dkD  rt        dj                  |	            |j%                  t'        j(                  ||             1t        |t*        j,                        r%|j%                  | j/                  ||||
             pt        |t0        j2                        r%|j%                  | j5                  ||||
             t        dj                  |	t!        |                   t        j6                  | j                  |      S )a  Apply embedding lookup on TPUs using Tensorcore.

    Note that all the sparse and ragged tensors will be converted to dense
    tensors on CPU and then passed to the TPU to do embedding look up. Large
    embedding lookup is not supported by this API, use the TPUEmbedding mid
    level api instead.

    Args:
      features: a nested structure of Tensors, SparseTensors or RaggedTensors.
      weights: a nested structure of Tensors, SparseTensors or RaggedTensors or
        None for no weights. If not None, structure must match that of inputs,
        but entries are allowed to be None.

    Returns:
      A nested structure of Tensors with the same structure as inputs.
    Nz,Weight specified for {}, but input is dense.zPWeight for {} is of type {} but it does not match type of the input which is {}.r   z8Weight specified for {}, but this is a sequence feature.z?Feature {} is a sequence feature but a dense tensor was passed.zCInput {} is type {}. Tensor, SparseTensor or RaggedTensor expected.)r(   r=   r   assert_same_structure_feature_configflattenlen flatten_with_joined_string_pathszipr5   r4   r#   r   TensorrL   r'   typemax_sequence_lengthappendr   embedding_lookup_v2r   SparseTensor#_embedding_lookup_for_sparse_tensorr   RaggedTensor#_embedding_lookup_for_ragged_tensorpack_sequence_as)r)   r]   r^   flat_inputsflat_weightsflat_featuresoutputsinpr?   pathfeaturer4   s               r+   embedding_lookupzTPUEmbeddingV0.embedding_lookup   sY   & ;;
jjlx)=)=>,,x(K6C,,L
  73\\'*l99$:N:NOMG(+K,9); !K$V_dG##GMM2e		c6==)<CCDIK K&\c*##)6$Vd3i#HJ J ((1, &&,fTl4 4 
C	'&&*"F4L* * 	}88DEc=55644S&%5<>	? c=55644S&%5<>	?  228&tCy2IK 	KA!KD   !5!5w??r,   rt   r4   rv   c                 d   d }t        j                  |||      \  }}t        j                  ||      }t	        j
                  |d      }||z  }|j                  s-|j                  dkD  r| j                  ||j                        }|S | j                  |||j                  j                        }|S )a.  Embedding lookup for sparse tensor based on its feature config.

    Args:
      inp: a single SparseTensor input.
      weight: None or SparseTensor which has the same shape of the input.
      table: a table variable.
      feature: a feature config.

    Returns:
      Embedding lookup result.
    c                    |Yt        j                  | j                  t        j                  | j
                  t        j                        | j                        }t        j                  |       } t        j                  |      }| |fS )Ndtype)dense_shape)r   rk   indicesr   	ones_likevaluesr   float32r|   r   sparse_tensor_to_densert   r?   s     r+   sparse_to_dense_computationzWTPUEmbeddingV0._embedding_lookup_for_sparse_tensor.<locals>.sparse_to_dense_computationH  si    	++KK

&..A)
 --c2c008f&[r,   r   rT   r   )r   outside_compilationr   rj   r   expand_dimsoutput_shaperh   r\   rP   r4   r@   )r)   rt   r?   r4   rv   r   r>   s          r+   rl   z2TPUEmbeddingV0._embedding_lookup_for_sparse_tensor4  s    (	 "55#V=KC 225#>J""62.F&JG$?$?!$C==
g113j
  55j&6=mm6L6LNjr,   c                 R   |j                   j                  dk7  r.t        dj                  |j                   j                              |j                   d   }d }t	        j
                  |||||      \  }}t        j                  ||      }t        j                  |d      }||z  }|j                  rt        j                         5  t        j                  |j                        j                         }ddd       |k(  r'| j!                  |||j"                  j$                        }t        j&                  ||j                  |j"                  j(                  gz         }|S |j*                  dk(  r'| j!                  |||j"                  j$                        }|S # 1 sw Y   xY w)	a  Embedding lookup for ragged tensor based on its feature config.

    Args:
      inp: a single rank 2 RaggedTensor input.
      weight: None or RaggedTensor which has the same shape of the input.
      table: a table variable.
      feature: a feature config.

    Returns:
      Embedding lookup result.

    Raises:
      ValueError: if input ragged tensor is not rank 2 or output shape set in
      the feature config doesn't match with the first dim size of the input.
    rG   z7Only rank 2 ragged tensor is supported, but got rank {}r   c                    |Wt         j                  j                  t        j                  | j
                  t        j                        | j                        }|j                  sV|j                  dkD  rG| j                  ||j                  f      } t        j                  | t        j                        }| |fS |j                  rt        j                         5  t        j                  |j                        j!                         }d d d        |k(  r$| j                         |j                         }} | |fS ||kD  rJ||z  dk(  rB||z  }| j                  ||f      } t        j                  | t        j                        }| |fS t#        dj%                  |j                  |            | j                         |j                         }} | |fS # 1 sw Y   xY w)Nrz   r   rX   zOutput shape set in the FeatureConfig should be the factor of the input data batch size. But instead got output shape {}, input data batch size {})r   rm   from_row_splitsr   r~   r   r   r   
row_splitsr   rh   	to_tensorr   r<   r   reduce_prodnumpyrL   r'   )rt   r?   
batch_sizerv   output_batch_size
seq_lengths         r+   #ragged_to_dense_outside_compilationz_TPUEmbeddingV0._embedding_lookup_for_ragged_tensor.<locals>.ragged_to_dense_outside_compilation~  s   	++;;

&..ANN !!g&A&AA&Emm:w/J/J"KmL$$S?< &[;  ^^ 	Q&2273G3GHNNP
	Q 
*)9)9);v#* &[! 
*!J.!3 )J6*Z$<=#&&s&..A& &[ ))/0D0D0:*<= = mmov'7'7'9V&[5	Q 	Qs   .GG)rt   r?   r   rv   rT   Nr   )rX   rankrL   r'   r   r   r   rj   r   r   r   r   r<   r   r   r   rP   r4   r@   reshapedimrh   )	r)   rt   r?   r4   rv   r   r   r>   r   s	            r+   rn   z2TPUEmbeddingV0._embedding_lookup_for_ragged_tensora  s   ( yy~~
C
J
Jiinn  1J
&P "55+KC 225#>J""62.F&J>> O$001E1EFLLNO	j	(77
F8?8N8NP
$$
G00GMM4E4E3FFHj  
	$	$	)77
F8?8N8NP
O Os   .FF&r;   )"__name__
__module____qualname____doc__r   r   FeatureConfigr   r   
_Optimizerr    propertyr   TableConfigtf_variablesVariabler5   r   r9   r0   r   rf   rP   intr\   r   rw   r   rk   rl   r   rm   rn   __classcell__)r*   s   @r+   r   r   &   s   Xt2@@(JK 0;;< *668M8MMN D$t\%:%::;;<" "&	"--" mm" 	" +1--	"H8;}}4 15A@!$A@ (A@9<A@F++++}112+ ""+ &33	+ 9?	+Z\++\}112\ ""\ &33	\ 9?	\r,   r   N)#r   typingr   r   r   r   r   r   tensorflow.python.distributer	   r
   tensorflow.python.frameworkr   r   r   r   tensorflow.python.opsr   r   r   r   r   r   tensorflow.python.ops.raggedr   tensorflow.python.tpur   r   r   tensorflow.python.utilr    tensorflow.python.util.tf_exportr   TPUEmbeddingBaser    r,   r+   <module>r      so    F = = 7 5 . + 5 . + / * , ; 6 4 8 1 ' 6 67V'88 V 8Vr,   