o
    ?e1                     @   s  d 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 Zd*ddZdd Zd+ddZd,ddZdd Zd+ddZdd Zd d! Z d"d# Z!d$d% Z"d&d' Z#d(d) Z$dS )-z$Utils related to keras model saving.    N)def_function)backend)losses)optimizer_v1)
optimizers)base_layer_utils)generic_utils)version_utils)ask_to_proceed_with_overwrite)
tf_logging)nestc                 C   s    t | ddrdd | jD S dS )aB  Convert metrics from a Keras model `compile` API to dictionary.

  This is used for converting Keras models to Estimators and SavedModels.

  Args:
    model: A `tf.keras.Model` object.

  Returns:
    Dictionary mapping metric names to metric instances. May return `None` if
    the model does not contain any metrics.
  Z_compile_metricsNc                 S   s   i | ]}|j |qS  )name).0mr   r   l/home/www/facesmatcher.com/pyenv/lib/python3.10/site-packages/tensorflow/python/keras/saving/saving_utils.py
<dictcomp>2   s    z)extract_model_metrics.<locals>.<dictcomp>)getattrZ_compile_metric_functionsmodelr   r   r   extract_model_metrics"   s   r   Fc                 C   sF   | j | d}|du rdS t|}t|tjjr t|dkr |S |gS )aM  Inspect model to get its input signature.

  The model's input signature is a list with a single (possibly-nested) object.
  This is due to the Keras-enforced restriction that tensor inputs must be
  passed in as the first argument.

  For example, a model with input {'feature1': <Tensor>, 'feature2': <Tensor>}
  will have input signature: [{'feature1': TensorSpec, 'feature2': TensorSpec}]

  Args:
    model: Keras Model object.
    keep_original_batch_size: A boolean indicating whether we want to keep using
      the original batch size or set it to None. Default is `False`, which means
      that the batch dim of the returned input signature will always be set to
      `None`.

  Returns:
    A list containing either a single TensorSpec or an object with nested
    TensorSpecs. This list does not contain the `training` argument.
  )Zdynamic_batchN   )Z_get_save_spec_enforce_names_consistency
isinstancecollectionsabcSequencelen)r   Zkeep_original_batch_sizeZinput_specsr   r   r   model_input_signature6   s   
r   c                 C   s   t d| )NzModel {} cannot be saved because the input shapes have not been set. Usually, input shapes are automatically determined from calling `.fit()` or `.predict()`. To manually set the shapes, call `model.build(input_shape)`.)
ValueErrorformatr   r   r   r   raise_model_input_errorY   s   r!   c                    s\    du rt jtjrjj  du rt  du rt tj d fdd}|S )a  Trace the model call to create a tf.function for exporting a Keras model.

  Args:
    model: A Keras model.
    input_signature: optional, a list of tf.TensorSpec objects specifying the
      inputs to the model.

  Returns:
    A tf.function wrapping the model's call function with input signatures set.

  Raises:
    ValueError: if input signature cannot be inferred from the model.
  N)input_signaturec                     s   t  dkr
| d nt| }t j|dddd |dd}W d   n1 s+w   Y  j}|du rBddlm} ||}t	
|}d	d
 t||D S )z<A concrete tf.function that wraps the model's call function.r   r   FT)inputsZbuild_graphtrainingZsaving)r$   N)compile_utilsc                 S   s   i | ]\}}||qS r   r   )r   r   outputr   r   r   r          z<trace_model_call.<locals>._wrapped_model.<locals>.<dictcomp>)r   listr   Zcall_contextZenteroutput_namestensorflow.python.keras.enginer%   Zcreate_pseudo_output_namesr   flattenzip)argsr#   outputsr)   r%   r"   r   r   r   _wrapped_modely   s   


z(trace_model_call.<locals>._wrapped_model)r   callr   Functionr"   r   r!   function)r   r"   r0   r   r/   r   trace_model_calla   s   
r4   Tc           
   
   C   s  ddl m} ddlm} d| jji}z|  |d< W n ty0 } z
|r&|W Y d}~nd}~ww tt	|t
 |d}| jr|rt| jtjrOtd |S | jr| jd	d
}|dd t||d< t| j|jrotdt| jj| j d}	|	|d d< |S )z3Returns a dictionary containing the model metadata.r   )__version__)optimizer_v2
class_nameconfigN)keras_versionr   model_configa<  TensorFlow optimizers do not make it possible to access optimizer attributes or optimizer state after instantiation. As a result, we cannot save the optimizer as part of the model save file. You will have to compile your model again after loading it. Prefer using a Keras optimizer instead (see keras.io/optimizers).F)Zuser_metrics	optimizertraining_configzAs of now, Optimizers loaded from SavedModel cannot be saved. If you're calling `model.save` or `tf.keras.models.save_model`, please set the `include_optimizer` option to `False`. For `tf.saved_model.save`, delete the optimizer from the model.)r7   r8   optimizer_config)tensorflow.python.kerasr5   Z$tensorflow.python.keras.optimizer_v2r6   	__class____name__Z
get_configNotImplementedErrordictstrKr   r;   r   r   ZTFOptimizerloggingwarningZ_compile_was_calledZ_get_compile_argspop_serialize_nested_configZRestoredOptimizerr   Zget_registered_name)
r   Zinclude_optimizerZrequire_configr9   r6   r:   emetadatar<   r=   r   r   r   model_metadata   sF   
rK   c                 C   s   |st j| rt| S dS )z3Returns whether the filepath should be overwritten.T)ospathisfiler
   )filepath	overwriter   r   r   should_overwrite   s   rQ   c                 C   s   |du ri }t |T | d }t|}d}| dd}|dur'ttj|}d}| dd}|dur8tt|}d}| dd}	|	durItt|	}t| drR| d nd}
| d }W d   n1 sbw   Y  t	||||||
dS )	z4Return model.compile arguments from training config.Nr=   lossmetricsweighted_metricssample_weight_modeloss_weights)r;   rR   rS   rT   rV   rU   )
r   ZCustomObjectScoper   deserializeget_deserialize_nested_configr   _deserialize_metrichasattrrB   )r<   Zcustom_objectsr=   r;   rR   Zloss_configrS   Zmetrics_configrT   Zweighted_metrics_configrU   rV   r   r   r   !compile_args_from_training_config   sD   


r\   c                    sl   dd }|du r
dS ||r |S t |tr" fdd| D S t |ttfr2 fdd|D S td)	z=Deserializes arbitrary Keras `config` using `deserialize_fn`.c                 S   s(   t | trd| v rdS t | trdS dS )Nr7   TF)r   rB   rC   objr   r   r   _is_single_object   s
   
z5_deserialize_nested_config.<locals>._is_single_objectNc                    s   i | ]
\}}|t  |qS r   rY   )r   kvdeserialize_fnr   r   r      s    
z._deserialize_nested_config.<locals>.<dictcomp>c                    s   g | ]}t  |qS r   r`   )r   r^   rc   r   r   
<listcomp>  r'   z._deserialize_nested_config.<locals>.<listcomp>z#Saved configuration not understood.)r   rB   itemstupler(   r   )rd   r8   r_   r   rc   r   rY      s   

rY   c                 C   s   dd }t || S )z/Serialized a nested structure of Keras objects.c                 S   s   t | r	t| S | S N)callabler   Zserialize_keras_objectr]   r   r   r   _serialize_fn  s   
z/_serialize_nested_config.<locals>._serialize_fn)r   map_structure)r8   rj   r   r   r   rH   
  s   rH   c                 C   s"   ddl m} | dv r| S || S )z7Deserialize metrics, leaving special strings untouched.r   )rS   )ZaccuracyaccZcrossentropyZce)r>   rS   rW   )Zmetric_configZmetrics_moduler   r   r   rZ     s   
rZ   c                    s\   dd  dd }t | }t fdd|D o#t fdd|D  }|r,t || } | S )z5Enforces that either all specs have names or none do.c                 S   s   t | do	| jd uS Nr   )r[   r   specr   r   r   	_has_name"  s   z-_enforce_names_consistency.<locals>._has_namec                 S   s   t | } t| drd | _| S rm   )copydeepcopyr[   _namern   r   r   r   _clear_name%  s   

z/_enforce_names_consistency.<locals>._clear_namec                 3       | ]} |V  qd S rh   r   r   srp   r   r   	<genexpr>-      z-_enforce_names_consistency.<locals>.<genexpr>c                 3   ru   rh   r   rv   rx   r   r   ry   .  rz   )r   r+   anyallrk   )specsrt   Z
flat_specsZname_inconsistencyr   rx   r   r     s   
r   c                 C   sp   t | s4| jd ur6z| jjs| j| j | jjs&| j| j| j W d S W d S    td Y d S d S d S )NzCompiled the loaded model, but the compiled metrics have yet to be built. `model.compile_metrics` will be empty until you train or evaluate the model.)	r	   Zis_v1_layer_or_modelr.   Zcompiled_lossZbuiltbuildZcompiled_metricsrE   rF   r   r   r   r   try_build_compiled_arguments5  s   

r   c                 C   s   |  dp|  dp|  dS )Nz.h5z.kerasz.hdf5)endswith)rO   r   r   r   is_hdf5_filepathD  s   r   )Frh   )TT)%__doc__r   rq   rL   Ztensorflow.python.eagerr   r>   r   rD   r   r   r   r*   r   Ztensorflow.python.keras.utilsr   r	   Z&tensorflow.python.keras.utils.io_utilsr
   Ztensorflow.python.platformr   rE   Ztensorflow.python.utilr   r   r   r!   r4   rK   rQ   r\   rY   rH   rZ   r   r   r   r   r   r   r   <module>   s8   
#

.1
)
