
    2Vh                     >   d dl Z d dlZd dlZd dl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  G d dej@                        Z! G d de      Z"d Z#d Z$ddZ%d Z&d Z'd Z(d Z)d Z*d Z+d Z,d Z-d Z.y)    N)context)	callbacks)metrics)
optimizers)tree)config)loss)trainer)array_slicing)data_adapter_utils)EpochIterator)traceback_utilsc                       e Zd Z fdZed        Zed        Zej                  d        Zd Zd Z	d Z
d Zdd	Zdd
ZddZej                   	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dd       Zej                   	 	 	 	 	 	 	 	 dd       Zej                   	 dd       Z	 	 	 	 ddZ	 	 	 ddZd Zed        ZddZ	 ddZddZddZ fdZ xZS ) TensorFlowTrainerc                     t         |           d | _        d | _        d | _        d| _        t        j                  j                         r$t        j                  j                         | _
        y d | _
        y N   )super__init__train_functiontest_functionpredict_functionunrolled_steps_per_executiontf
distributehas_strategyget_strategy_distribute_strategyself	__class__s    T/home/dcms/DCMS/lib/python3.12/site-packages/keras/src/backend/tensorflow/trainer.pyr   zTensorFlowTrainer.__init__   s_    "! $
 -.) ==%%'(*(B(B(DD%(,D%    c                 Z    | j                   xs t        j                  j                         S N)r   r   r   r   r    s    r"   distribute_strategyz%TensorFlowTrainer.distribute_strategy(   s     ((HBMM,F,F,HHr#   c                 "    | j                   xs dS )Nauto_distribute_reduction_methodr&   s    r"   distribute_reduction_methodz-TensorFlowTrainer.distribute_reduction_method,   s    00:F:r#   c                     || _         y r%   r*   )r    values     r"   r,   z-TensorFlowTrainer.distribute_reduction_method0   s
    ,1)r#   c           	         t        j                  |      \  }}}t        j                         5 }| j                  r | |d      }n | |      }| j                  ||||d      }| j                  j                  t        j                  |      t        j                  t        j                  |      d         d          | j                  | j                  j                  |      }d d d        | j                  rD| j                  }j!                  |      }	| j                  j#                  t%        |	|             nt'        j(                  d       | j+                  |||      S # 1 sw Y   xY w)NTtrainingxyy_predsample_weightr1   r   r6   z.The model does not have any trainable weights.)r   unpack_x_y_sample_weightr   GradientTape_call_has_training_arg_compute_loss_loss_trackerupdate_stateloss_moduleunscale_loss_for_distributionshaper   flatten	optimizer
scale_losstrainable_weightsgradientapply_gradientszipwarningswarncompute_metrics)
r    datar3   r4   r6   taper5   r	   rD   	gradientss
             r"   
train_stepzTensorFlowTrainer.train_step4   sP   0II$O1m __ 	7$**a$/a%%+ & D ++99$? hht||Aq'9:1= ,  ~~)~~006#	7( !! $ 6 6d,=>I NN**3y:K+LMMMJK##Aq&#NN;	7 	7s   B9E))E2c                    t        j                  |      \  }}}| j                  r | |d      }n | |      }| j                  ||||d      }| j                  j                  t        j                  |      t        j                  t        j                  |      d         d          | j                  ||||      S )NFr0   r2   r   r7   )r   r8   r:   r;   r<   r=   r>   r?   r   r@   r   rA   rJ   )r    rK   r3   r4   r6   r5   r	   s          r"   	test_stepzTensorFlowTrainer.test_stepW   s    0II$O1m&&!e,F!WF!!1V=5 " 
 	''55d;((4<<?1#56q9 	( 	
 ##Aq&#NNr#   c                 x    t        j                  |      \  }}}| j                  r | |d      }|S  | |      }|S )NFr0   )r   r8   r:   )r    rK   r3   _r5   s        r"   predict_stepzTensorFlowTrainer.predict_stepf   sD    $==dC1a&&!e,F  !WFr#   c                 r    t         j                  j                  j                   fd        j                  s"t        j
                  d j                        t         j                  j                  j                   fd        j                  st        j
                  d       fd}|S )Nc                 t    j                   j                  | f      }t        |j                   d      }|S )z/Runs a single training step on a batch of data.argsr)   	reductionr'   runreduce_per_replica)rK   outputsr    step_functions     r"   one_step_on_dataz:TensorFlowTrainer._make_function.<locals>.one_step_on_datao   sB     ..22=w2OG((( G
 Nr#   Treduce_retracingjit_compilec                     
j                   dk(  r=t        j                  j                  j	                   	 j                                     S t        j                  j                  j                  d       
fd} 	
fd
fd}t        j                  d      } j                         }t        j                  ||||g      \  }}}j                  |_        |S )Nr   c                     t        j                  t        j                  | j                        |j	                               S r%   )r   logical_andlesssteps_per_execution	has_value)execution_stepoptional_outputsnext_optional_inputsr    s      r"   condzNTensorFlowTrainer._make_function.<locals>.multi_step_on_iterator.<locals>.cond   s4    ~~GGND,D,DE(224 r#   c                 X   fd}fd}t        j                  t        j                  t        j                  | 	j                        j                               ||      }| dz   |t        j                  t        j                  | dz   	j                        fdfd      fS )Nc                      t         j                  j                  j                   j	                                     } | j
                  _        | S r%   )r   experimentalOptional
from_value	get_valueelement_spec_element_spec)next_optional_outputsempty_outputsrk   r_   s    r"   has_nextzfTensorFlowTrainer._make_function.<locals>.multi_step_on_iterator.<locals>.inner_body.<locals>.has_next   sK    ,.OO,D,D,O,O()=)G)G)IJ-) .:: "/ 10r#   c                  *     j                   _         S r%   )rt   )rv   rj   s   r"   no_has_nextziTensorFlowTrainer._make_function.<locals>.multi_step_on_iterator.<locals>.inner_body.<locals>.no_has_next   s    5B5P5P$2++r#   r   c                  $     j                         S r%   )get_next_as_optionaliterators   r"   <lambda>zfTensorFlowTrainer._make_function.<locals>.multi_step_on_iterator.<locals>.inner_body.<locals>.<lambda>   s     = = ? r#   c                       S r%    )rk   s   r"   r~   zfTensorFlowTrainer._make_function.<locals>.multi_step_on_iterator.<locals>.inner_body.<locals>.<lambda>   s     4 r#   )r   rl   re   rf   rg   rh   )
ri   rj   rk   rw   ry   ru   rv   r}   r_   r    s
    ``   r"   
inner_bodyzTTensorFlowTrainer._make_function.<locals>.multi_step_on_iterator.<locals>.inner_body   s    1, )+NN0H0HI,668 )% #Q&) GG 2D4L4LM?4
 
r#   c                     t        t        j                  j                              D ]  } | ||      \  } }} | ||fS r%   )rangeminr   rg   )ri   rj   rk   rR   r   r    s       r"   bodyzNTensorFlowTrainer._make_function.<locals>.multi_step_on_iterator.<locals>.body   sc    9900 A #*,0 KN$46J '(8:NOOr#   r   )	loop_vars)rg   r   ro   rp   rq   get_nextemptyconstantr{   
while_looprs   rt   )r}   rl   r   ri   rk   rR   final_optional_outputsrv   r   r_   r    s   `      @@r"   multi_step_on_iteratorz@TensorFlowTrainer._make_function.<locals>.multi_step_on_iterator   s    ''1,//::$X%6%6%89 
 OO44::4@M#JP"  [[^N#+#@#@#B  ,.==)=:NO,(A%q
 4A3M3M"0))r#   ra   c                 >   t        | t        j                  j                  t        j                  j
                  f      r. |       }|j                         st        |j                         S t        t        j                        |       D ]  \  }} |      } S r%   )
isinstancer   rK   Iteratorr   DistributedIteratorrh   StopIterationrr   rG   r   rg   )r}   opt_outputssteprK   r]   r   r_   r    s        r"   functionz2TensorFlowTrainer._make_function.<locals>.function   s    277++R]]-N-NO 5X>",,.''",,.."%$223X# 5JD$ /t4G5 r#   )r   	autographro   do_not_convertrun_eagerlyr   rb   )r    r^   r   r   r_   s   `` @@r"   _make_functionz TensorFlowTrainer._make_functionn   s    		"	"	1	1	 
2	 !{{ !% ,,  
	"	"	1	1O	* 
2O	*b %'[[&&"	 r#   c                 x    | j                   |s| j                   S | j                  | j                        | _         y r%   )r   r   rN   r    forces     r"   make_train_functionz%TensorFlowTrainer.make_train_function   s3    *5&&&"11$//Br#   c                 x    | j                   |s| j                   S | j                  | j                        | _         y r%   )r   r   rP   r   s     r"   make_test_functionz$TensorFlowTrainer.make_test_function   s3    )%%%%!00@r#   c                 $     j                   |s j                   S t        j                  j                  j                   fd        j
                  s$ j                  rt        j                  dd      t        j                  j                  j                   fd       t        j                  j                  j                  fd       } j                  dkD  r|}n} j
                  st        j                  |d      }| _         y )Nc                 &    j                  |       S )z,Runs a predict test step on a batch of data.)rS   )rK   r    s    r"   r_   zATensorFlowTrainer.make_predict_function.<locals>.one_step_on_data   s     $$T**r#   Tr`   c                 ~    | d   } j                   j                  | f      }t        |j                   d      }|S )Nr   rV   concatrX   rZ   )rK   r]   r_   r    s     r"   one_step_on_data_distributedzMTensorFlowTrainer.make_predict_function.<locals>.one_step_on_data_distributed  sP    7D..22 w 3 G )(("G
 Nr#   c                 t     | d d       }| dd  D ]#  } |g      }t        j                  d ||      }% |S )Nr   c                     t        | |g      S r%   )r   )t1t2s     r"   r~   zUTensorFlowTrainer.make_predict_function.<locals>.multi_step_on_data.<locals>.<lambda>  s    62r(#3 r#   )r   map_structure)rK   r]   single_step_datastep_outputsr   s       r"   multi_step_on_datazCTensorFlowTrainer.make_predict_function.<locals>.multi_step_on_data  sU    248<G$(H  ;=M<NO,,3Wl
 Nr#   r   r   )	r   r   r   ro   r   r   rb   r   rg   )r    r   r   r   r_   r   s   `   @@r"   make_predict_functionz'TensorFlowTrainer.make_predict_function   s      ,U(((		"	"	1	1	+ 
2	+ D$4$4!{{ 4T  
	"	"	1	1
	 
2
	 
	"	"	1	1	 
2	 ##a'1;!{{ 4  !1r#   c                    | j                  d       t        j                         }|r||k  rt        j                  d|z         |}d | _        |r#|!t        j                  |||f|      \  \  }}}}|t        j                  |      \  }}}t        ||||||	|
| j                  | j                  	      }| j                  |       |j                          t        |t         j"                        s)t!        j"                  |d|dk7  |||j$                  |       }d	| _        | j)                          |j+                          d }i }| j,                  xs |}t/        ||      D ]j  }| j1                          |j3                  |       |j5                         5  |D ]G  \  }}|j7                  |       | j9                  |      }|j;                  ||       | j&                  sG n d d d        t=        | j?                  |            }|| jA                  ||      rtC        | d
d       0t        |xs || j                  | j                  |d	      | _        | jE                  |xs |||dd      }|jG                         D ci c]  \  }}d|z   | }}}|jI                  |       |jK                  ||       |}| j&                  sk n t        | jL                  tN        jP                        r*|dkD  r%| jL                  jS                  | jT                         tC        | d
d       | `|jW                  |       | jX                  S # 1 sw Y   ixY wc c}}w )NfitzLimiting epochs to %d)validation_split)	r3   r4   r6   
batch_sizesteps_per_epochshuffleclass_weightr'   rg   r|   Tr   )add_historyadd_progbarverboseepochsstepsmodelF_eval_epoch_iterator)r3   r4   r6   r   r'   rg   r   r   )r3   r4   r6   r   r   r   return_dict_use_cached_eval_datasetval_)logs)-_assert_compile_calledr   
max_epochsrH   rI   r   r   train_validation_splitr   r8   TFEpochIteratorr'   rg   _maybe_symbolic_buildresetr   callbacks_moduleCallbackListnum_batchesstop_trainingr   on_train_begin_initial_epochr   reset_metricson_epoch_begincatch_stop_iterationon_train_batch_beginr   on_train_batch_enddict_get_metrics_result_or_logs_should_evalgetattrevaluateitemsupdateon_epoch_endrB   optimizers_module	Optimizerfinalize_variable_valuesrD   on_train_endhistory)r    r3   r4   r   r   r   r   r   validation_datar   r   r6   initial_epochr   validation_stepsvalidation_batch_sizevalidation_freqr   val_xval_yval_sample_weightepoch_iteratortraining_logsr   epochr   r}   
epoch_logsval_logsnamevals                                  r"   r   zTensorFlowTrainer.fit$  s   ( 	##E*&&(
*v-MM1J>?F$(! 7 44A}%8H%A}
 &
 #;;OL	! )'!+% $ 8 8 $ 8 8

 	""N"; )%5%B%BC(55 #qL$00I #  "  "++<}=&1 0	E $$U+446 &4 ND(2248..x8D00t<)) d>>tDEJ *t/@/@0 4!7>F0?&7#8#FJ,0,D,D,0,D,D(8 %	1D-  =="34B
*' $-1 ) 	 9A8H+44FTM3&  !!(+""5*5&M!!a0	f t~~'8'B'BC
NN33D4J4JK 4/6B)M2||s Js   A	M!MMM	c	           
      ^   | j                  d       |	j                  dd      }
|	rt        d|	       |
r| j                  }n't	        |||||d| j
                  | j                        }| j                  |       |j                          t        |t        j                        s(t        j                  ||dk7  |d|j                  | 	      }| j                          d| _        |j                          i }| j!                          |j#                         5  |D ]G  \  }}|j%                  |       | j'                  |      }|j)                  ||       | j                  sG n d d d        | j+                  |      }|j-                  |       |r|S | j/                  |      S # 1 sw Y   @xY w)
Nr   r   FzArguments not recognized: )r3   r4   r6   r   r   r   r'   rg   r|   r   r   r   r   r   r   r   )r   pop
ValueErrorr   r   r'   rg   r   r   r   r   r   r   r   stop_evaluatingon_test_beginr   r   on_test_batch_beginr   on_test_batch_endr   on_test_end_flatten_metrics_in_order)r    r3   r4   r   r   r6   r   r   r   kwargsuse_cached_eval_datasetr   r   r   r}   s                  r"   r   zTensorFlowTrainer.evaluate  s    	##J/"(**-G"O9&BCC"!66N -+% %$($<$<$($<$<	N 	""N"; )%5%B%BC(55#qL$00I 	!$!002 	"0 h--d3))(3++D$7''	 //5d#K--d33	 	s   A	F#!F##F,c                     t        |||d j                   j                        }t        |t        j
                        s(t	        j
                  ||dk7  |d|j                         }d } fd} j                          d _        |j                          d }	|j                         5  |D ]Z  \  }
}|j                  |
        ||      } j                  |      } |||	      }	|j                  |
d|i        j                  sZ n d d d        |j                          t        j                   t"        |	      }	t        j$                  t&        |	      S # 1 sw Y   NxY w)	NF)r3   r   r   r   r'   rg   r   r   r   c                 n    |t        j                  d |       }|S t        j                  | d ||        |S )Nc                     | gS r%   r   )batch_outputs    r"   r~   zFTensorFlowTrainer.predict.<locals>.append_to_outputs.<locals>.<lambda>  s    , r#   c                 $    | j                  |      S r%   )append)outputr   s     r"   r~   zFTensorFlowTrainer.predict.<locals>.append_to_outputs.<locals>.<lambda>  s    |1L r#   )r   r   map_structure_up_to)batch_outputsr]   s     r"   append_to_outputsz4TensorFlowTrainer.predict.<locals>.append_to_outputs  sG    ,,7! N ((!L!	 Nr#   c                    g }t        j                        D ]  }	 t        |       }|j                  |       ! |S # t        t        j
                  j                  f$ r*}t        |d      rt        |      dkD  r	|cY d}~c S |d}~ww xY w)z$Returns data for the next execution.__len__r   N)
r   rg   nextr   r   errorsOutOfRangeErrorhasattrlenr   )r}   rK   rR   r   er    s        r"   get_dataz+TensorFlowTrainer.predict.<locals>.get_data  s    D4334 .
 '+H~$ ,-. K &ryy'@'@A  tY/CIM#
   s!   =#B
 B;B
BB
r]   )r   r'   rg   r   r   r   r   r   stop_predictingon_predict_beginr   on_predict_batch_beginr   on_predict_batch_endon_predict_endr   r   potentially_ragged_concatr   convert_to_np_if_not_ragged)r    r3   r   r   r   r   r   r  r  r]   r   r}   rK   r  s   `             r"   predictzTensorFlowTrainer.predict  sb   
 )!! $ 8 8 $ 8 8
 )%5%B%BC(55#qL$00I		$ 	""$$""$002 	"0 h006) $ 5 5d ;+M7C..ti5OP''	 	  "**4g
 !!"=wGG	 	s   *AEEE c                 \   | j                  d       |)t        d d|       t        j                  |      | j	                  f       | j                          fd}| j                   |             }t        j                  d |      }|r|S | j                  |      S )Ntrain_on_batchzkArguments `sample_weight` and `class_weight` cannot be specified at the same time. Received: sample_weight=z, class_weight=
data_batchc               3      K    f y wr%   r   r6   r3   r4   s   r"   rK   z.TensorFlowTrainer.train_on_batch.<locals>.dataZ       a''   	c                 ,    t        j                  |       S r%   nparrayr3   s    r"   r~   z2TensorFlowTrainer.train_on_batch.<locals>.<lambda>^      BHHQK r#   )
r   r   r   class_weight_to_sample_weightsr   r   r   r   r   r   )r    r3   r4   r6   r   r   rK   r   s    ```    r"   r  z TensorFlowTrainer.train_on_batchA  s     	##$45#( //<o >$$0>3  /MM<M
 	""q!].C"D  "	( ""46*!!"7>K--d33r#   c                    | j                  d       fd}| j                  f       | j                          | j                   |             }t	        j
                  d |      }|r|S | j                  |      S )Ntest_on_batchc               3      K    f y wr%   r   r  s   r"   rK   z-TensorFlowTrainer.test_on_batch.<locals>.datal  r  r  r  c                 ,    t        j                  |       S r%   r  r   s    r"   r~   z1TensorFlowTrainer.test_on_batch.<locals>.<lambda>t  r!  r#   )r   r   r   r   r   r   r   )r    r3   r4   r6   r   rK   r   s    ```   r"   r$  zTensorFlowTrainer.test_on_batchc  s|     	##O4	( 	""q!].C"D!!!$&)!!"7>K--d33r#   c                     | j                          | j                  |fg      }t        j                  t        |      }|S r%   )r   r   r   r   r  )r    r3   r  s      r"   predict_on_batchz"TensorFlowTrainer.predict_on_batchy  s?    ""$--tf5**'
 r#   c                 *      G  fdd      } |       S )Nc                       e Zd Zd fd	Zy)DTensorFlowTrainer.compiled_metrics.<locals>.DeprecatedCompiledMetricNc                 ,    j                  |||      S )Nr7   )_compiled_metrics_update_state)rR   r4   r5   r6   r    s       r"   r=   zQTensorFlowTrainer.compiled_metrics.<locals>.DeprecatedCompiledMetric.update_state  s"    ::v] ;  r#   r%   )__name__
__module____qualname__r=   r&   s   r"   DeprecatedCompiledMetricr+    s    r#   r1  r   )r    r1  s   ` r"   compiled_metricsz"TensorFlowTrainer.compiled_metrics  s    	 	 ())r#   c                     t        j                  dd       | j                  D ]D  }t        |t        j
                        r|j                  ||       1|j                  |||       F y )Nz`model.compiled_metrics()` is deprecated. Instead, use e.g.:
```
for metric in self.metrics:
    metric.update_state(y, y_pred)
```
   )
stacklevelr7   )rH   rI   r   r   metrics_moduleMeanr=   )r    r4   r5   r6   metrics        r"   r-  z0TensorFlowTrainer._compiled_metrics_update_state  sg     	
 ll 	LF&."5"56##F-#H##Av]#K		Lr#   c                 V    t        j                  d       | j                  d |||      S )Nzp`model.compiled_loss()` is deprecated. Instead, use `model.compute_loss(x, y, y_pred, sample_weight, training)`.r3   r4   r5   r6   rH   rI   compute_loss)r    r4   r5   r6   regularization_lossess        r"   compiled_losszTensorFlowTrainer.compiled_loss  s9     	K	
   am ! 
 	
r#   c                 V    t        j                  d       | j                  d |||      S )Nzg`model.loss()` is deprecated. Instead, use `model.compute_loss(x, y, y_pred, sample_weight, training)`.r:  r;  )r    r4   r5   r6   s       r"   r	   zTensorFlowTrainer.loss  s7    K	
   am ! 
 	
r#   c                 |   | j                   y |l|D ]g  \  }}t        |      }t        j                  d |      }t	        t        j
                  |            r| j                  j                  d|d       }n|} n | j                  j                         5  | j                  |       d d d        y # 1 sw Y   y xY w)Nc                 J    t        | t        j                  j                        S r%   )r   r   r   DistributedValuesr   s    r"   r~   z9TensorFlowTrainer._maybe_symbolic_build.<locals>.<lambda>  s    jBMM,K,KL r#   MEANaxisr  )
r   r  r   r   allrA   r'   reducescope_symbolic_build)r    r}   r  rR   itmaybe_distributed_data_batchhas_distributed_valuess          r"   r   z'TensorFlowTrainer._maybe_symbolic_build  s    $$,  ! 2/3Bx,)-););L0*& t||$:;<!%!9!9!@!@4! "A "J ">J %%++- 	8  J 7	8 	8 	8s   B22B;c                 L    t         |   |      }t        j                  |      S r%   )r   _aggregate_additional_lossr>   scale_loss_for_distribution)r    r	   r!   s     r"   rN  z,TensorFlowTrainer._aggregate_additional_loss  s#    w1$766t<<r#   )F)NNNr   r)   Ng        NTNNr   NNNr   )NNNr)   NNNF)Nr)   NN)NNNF)NNFr%   )NN)r.  r/  r0  r   propertyr'   r,   setterrN   rP   rS   r   r   r   r   r   filter_tracebackr   r   r  r  r$  r(  r2  r-  r>  r	   r   rN  __classcell__r!   s   @r"   r   r      s   -$ I I ; ; !''2 (2!OFOyvC
A
/1b %% 
"#J &JX %% 
@4 &@4D %%HLJH &JH^  4J 4, * *L" DH	

8:= =r#   r   c                   Z     e Zd Zd fd	Zd Zd Zd Zej                   fd       Z	 xZ
S )r   c                     t        |   |i | || _        | j                  j	                         }t        |t        j                  j                        s| j                  j                  |      }|| _
        y r%   )r   r   r   data_adapterget_tf_datasetr   r   r   DistributedDatasetexperimental_distribute_dataset_distributed_dataset)r    r'   rW   r   datasetr!   s        r"   r   zTFEpochIterator.__init__  sh    $)&)$7!##224'2==#C#CD//OOG %,!r#   c                     | j                   S r%   )r[  r&   s    r"   _get_iteratorzTFEpochIterator._get_iterator  s    (((r#   c                 ,    t        j                          y r%   )
tf_context
async_waitr&   s    r"   tf_synczTFEpochIterator.tf_sync  s    r#   c                 ,    t        | j                        S r%   )r  _epoch_iteratorr&   s    r"   __next__zTFEpochIterator.__next__  s    D(())r#   c              #      K   t         |          5  	 d | j                          	 ddd       y# t        j                  j
                  $ r t        w xY w# 1 sw Y   yxY ww)z1Catches errors when an iterator runs out of data.N)r   r   rb  r   r  r  r   r   s    r"   r   z$TFEpochIterator.catch_stop_iteration  s_      W)+ 	$$	$ 	$ 99,, $##$		$ 	$s*   A%A2	A%$AAA"A%r%   )r.  r/  r0  r   r^  rb  re  
contextlibcontextmanagerr   rS  rT  s   @r"   r   r     s1    ,) * $ $r#   r   c                     dk(  r)t        t        j                  j                        rdndfd}t	        j
                  ||       S )a	  Attempt to reduce the structure `values` to single values.

    Given `values` (a `tf.Tensor` or a `PerReplica` structure),
    which represents the values across all the replicas, `reduce_per_replica`
    attempts to "reduce" those values and returns the corresponding structure
    that represents only single values.

    Currently, `reduce_per_replica` is only used for reducing the metric results
    from `tf.distribute.Strategy.run()`. Depending on the underlying
    `Strategy` implementation, `values` may be a `PerReplica` object,
    which can be thought of as a collection of values across the replicas,
    or a `tf.Tensor`, if the strategy has already conducted the reduction
    for the downstream library.

    There are five possible outcomes of reduction:

    1) if the `values` is a structure of simple `tf.Tensor`s, meaning that
       reduction is not actually needed, `reduce_per_replica` returns the
       structure as-is.
    2) else, if `reduction="auto"`, then the best reduction strategy is
       chosen based on the current environment. This should only be used
       for training cases (`fit()`).
    3) else, if `reduction="first"`, then `reduce_per_replica`
       returns the values of the first replica. This is used in the case of
       training and evaluation, where `values` is expected to hold the same
       value across the replicas as a result of `Strategy`'s synchronization
       across the replicas.
       `reduce_per_replica` does not synchronize the values.
    4) else, if `reduction="sum"`, then `reduce_per_replica` returns the sum
       of values for all replicas. This may be used in the custom training loop
       case, where each replica contain different values which are not
       synchronized.
    5) else, if `reduction="concat"`, then `reduce_per_replica`
       returns the concatenation of the values across the replicas, along the
       axis of dimension 0. This is used in the inference case (`predict()`).

    Args:
        values: Structure of `PerReplica` objects or `tf.Tensor`s.
            `tf.Tensor`s are returned as-is.
        strategy: `tf.distribute.Strategy` object.
        reduction: One of `"auto"`, `"first"`, `"concat"`, `"mean"`, or `"sum"`.
            `"auto"` will select `"first"` when used under a TPUStrategy, or
            `"mean"` otherwise.

    Returns:
        Structure of `Tensor`s, representing the result of reduction.
    r)   firstmeanc                    t              rAdk(  rt        |       S dk(  rj                  d|       S dk(  rj                  d| d      S t        |       s| S dk(  rj	                  |       d   S dk(  r1t              rt        |       S t        j	                  |             S dk(  r$t        j                  j	                  |             S dk(  r&t        j                  j	                  |       d      S t        d	 d
      )z$Reduce a single `PerReplica` object.r   sumSUMrk  rC  r   rD  rj  z\`reduction` must be one of "first", "concat", "mean", "sum", or "auto". Received: reduction=.)#_collective_all_reduce_multi_worker_multi_worker_concatrG  _is_per_replica_instanceexperimental_local_results_is_tpu_multi_host_tpu_multi_host_concatr   r   
reduce_sumreduce_meanr   )vrY   strategys    r"   _reducez#reduce_per_replica.<locals>._reduce(  s   .x8H$+Ax88e#ua00f$vqq99'*H'!66q9!<<("!(+-a::hAA!DEE%==!D!DQ!GHH& >>33A6Q  ''0k4 r#   )r   r   r   TPUStrategyr   r   )valuesry  rY   rz  s    `` r"   r\   r\     sG    b Fh 9 9:II@ gv..r#   c           
      r   |j                  | d      }t        |       rnt        j                  | j                  D cg c]/  }t        j
                  t        j                  |      d   d      1 c}d      }|j                  |d      }n>|j                  t        j
                  t        j                  |       d   d      d      }t        j                  |||j                        }g }t        |j                  j                        }t        |      D ]  }|||d|   z  } t        |      S c c}w )zDOrder PerReplica objects for CollectiveAllReduceStrategy and concat.r   rD  )num_or_size_splitsnumN)gatherrr  r   r   r|  expand_dimsr@   splitnum_replicas_in_syncr	  extendedworker_devicesr   )	rx  ry  replicassingle_valueshapes
all_shapesordered_replicasnum_replicas_per_worker
replica_ids	            r"   rq  rq  K  s(   qq)H" %&HH  rxx5a8qA 
 __V!_4
 __NN288A;q>2 % 

 xx%))H
 !("3"3"B"BC34 J
HZ%H1H%HIIJ"##-s   4D4c                     t        | d   t        j                        r!t        j                  j	                  ||       S t        | d         rt        j                  | |      S t        j                  | |      S )zConcats `tensor`s along `axis`.r   rE  	sp_inputsrD  )r   r   SparseTensorsparser   
_is_scalarstack)tensorsrE  s     r"   r   r   j  s\    '!*boo.yyTW==	GAJ	xxd++yyt,,r#   c                     |j                  |       }|j                  j                  }g }t        |      D ]  }|||d|   z  } t	        |      S )z'Correctly order TPU PerReplica objects.N)rs  r  num_replicas_per_hostr   r   )rx  ry  r  r  r  r  s         r"   ru  ru  t  sh    2215H
 %--CC12 H
HZ%F1F%FGGH"##r#   c                     t        | t        j                  j                        xr | j                  j                         S r%   )r   r   r   MultiWorkerMirroredStrategyr  _in_multi_worker_modery  s    r"   rp  rp    s2    8R]]FFG4



1
1
34r#   c                     t        | t        j                  j                        xr$ t        | t        j                  j
                        S r%   )r   r   r   rB  __internal__CompositeTensor)objs    r"   rr  rr    s7    c2==::; 
R__,,A r#   c                     t        | t        j                  t        j                  f      xr | j                  j
                  dk(  S )Nr   )r   r   TensorVariabler@   rankr   s    r"   r  r    s.    a"))R[[12Hqww||q7HHr#   c                 N    t        |       xr | j                  j                  dkD  S r   )_is_tpu_strategyr  	num_hostsr  s    r"   rt  rt    s#    H%I(*;*;*E*E*IIr#   c                 ,    t        | j                        S r%   )_is_tpu_strategy_classr!   r  s    r"   r  r    s    !("4"455r#   c                 `    d } ||       ryt        t        t        | j                              S )Nc                 8    | j                   j                  d      S )Nr{  )r.  
startswith)ks    r"   is_tpu_stratz,_is_tpu_strategy_class.<locals>.is_tpu_strat  s    zz$$]33r#   T)anymapr  	__bases__)clzr  s     r"   r  r    s+    4 Cs)3==9::r#   c                     t        | t        j                        r| S t        | t        j                        r| S | j	                         S r%   )r   r   RaggedTensorr  numpyr   s    r"   r  r    s4    !R__%	Ar	'779r#   c                    t        |       dk(  r| d   S t        | d   t        j                        r!t        j                  j                  d|       S t        | d   t        j                        rt        j
                  | d      S t        j                  | D cg c]  }t        j                  |      dd  c}      }t        j                  j                  ||dd k(  d      }t        j                  j                  |      j                         j                         r<t        | d         rt        j                  | d      S t        j
                  | d      S |j                         j                         ddd   j                  d      }|dk(  rd}n| d   j                  | d }t        j                   j#                  | D cg c]  }|j                          c}|      j%                  dd      S c c}w c c}w )	a  Concats `Tensor`s along their first dimension.

    Args:
        tensors: List of `Tensor`s.

    Returns:
        Concatenation of the inputs along the first dimension -- of type
        `np.ndarray` if all input shapes are compatible, or `tf.RaggedTensor`
        if not.
    r   r   r  rD  NF)inner_shape)r	  r   r   r  r  r   r  r  r@   math
reduce_allr  itemr  tolistindexraggedr   
merge_dims)r  tensornon_batch_shapesconstant_dimsconstant_inner_dimensionsconstant_inner_shapes         r"   r  r    s    7|qqz	GAJ	0yyQ'::	GAJ	0yyq))xxG L&&!1!"!5 LMGG&&,Ra00q ' M 
ww-(..0557gaj!88G!,,99W1--
 	$$&tt,2259  !A%#&qz//1J0J0KL99&-.F.<P  jA+ !M, 	/s   G8G=)r   )/rg  rH   r  r  
tensorflowr   tensorflow.python.eagerr   r`  	keras.srcr   r   r   r6  r   r   r   keras.src.backendr   keras.src.lossesr	   r>   keras.src.trainersr
   base_trainer keras.src.trainers.data_adaptersr   r   !keras.src.trainers.epoch_iteratorr   keras.src.utilsr   Trainerr   r   r\   rq  r   ru  rp  rr  r  rt  r  r  r  r  r   r#   r"   <module>r     s        9 3 / 5  $ 0 6 : ? ; +z
=,, z
=z$m $>W/t$>-$4IJ6;)r#   