o
    Ne35                     @   s  d Z ddlZddlZddlm  m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 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)backend)losses)
optimizers)base_layer_utils)optimizer_v1)serialization)version_utils)ask_to_proceed_with_overwrite)
tf_loggingc                 C   s    t | ddrdd | jD S dS )aP  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   PD:\Projects\ConvertPro\env\Lib\site-packages\keras/saving/legacy/saving_utils.py
<dictcomp>4   s    z)extract_model_metrics.<locals>.<dictcomp>)getattrZ_compile_metric_functionsmodelr   r   r   extract_model_metrics$   s   r   Fc                 C   s&   | j | d}|du rdS t|}|S )at  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 tuple containing `(args, kwargs)` TensorSpecs of the model call function
      inputs.
      `kwargs` does not contain the `training` argument.
    )Zdynamic_batchN)NN)Z	save_spec_enforce_names_consistency)r   Zkeep_original_batch_sizeZinput_specsr   r   r   model_call_inputs8   s
   r   c                 C   s.   t | tjjrtd|  dtd|  d)NzModel z cannot be saved because the input shape is not available. Please specify an input shape either by calling `build(input_shape)` directly, or by calling the model on actual data using `Model()`, `Model.fit()`, or `Model.predict()`.a   cannot be saved either because the input shape is not available or because the forward pass of the model is not defined.To define a forward pass, please override `Model.call()`. To specify an input shape, either call `build(input_shape)` directly, or call the model on actual data using `Model()`, `Model.fit()`, or `Model.predict()`. If you have a custom training step, please make sure to invoke the forward pass in train step through `Model.__call__`, i.e. `model(inputs)`, as opposed to `model.call()`.)
isinstancekerasmodelsZ
Sequential
ValueErrorr   r   r   r   raise_model_input_errorV   s   
	
r   c                    sn   |du rt  jtjjjr jj}|r|}i }nt \}}|du r&t  tj fdd}|j	|i |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.
    Nc                     s    j jdd| |dd\} }t j ddddd  | i |}W d   n1 s+w   Y   j}|du rBddlm} ||}t	j
|}d	d
 t||D S )z<A concrete tf.function that wraps the model's call function.trainingFT)Zinputs_in_argsN)ZinputsZbuild_graphr   Zsavingr   )compile_utilsc                 S   s   i | ]\}}||qS r   r   )r   r   outputr   r   r   r      s    z<trace_model_call.<locals>._wrapped_model.<locals>.<dictcomp>)Z
_call_specZset_arg_valuer   Zcall_contextZenteroutput_nameskeras.enginer   Zcreate_pseudo_output_namestfnestflattenzip)argskwargsoutputsr   r   r   r   r   _wrapped_model   s   



z(trace_model_call.<locals>._wrapped_model)
r   callr!   Z__internal__functionFunctioninput_signaturer   r   Zget_concrete_function)r   r,   Z
model_argsZmodel_kwargsr(   r   r   r   trace_model_callm   s   r-   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| 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_configzOptimizers loaded from a SavedModel cannot be saved. If you are 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.)r0   r1   optimizer_config)r   r.   Zkeras.optimizers.optimizer_v2r/   	__class____name__Z
get_configNotImplementedErrordictstrr   r4   r   r   ZTFOptimizerloggingwarningZ_compile_was_calledZ_get_compile_argspop_serialize_nested_configZRestoredOptimizerutilsZget_registered_name)
r   Zinclude_optimizerZrequire_configr2   r/   r3   emetadatar5   r6   r   r   r   model_metadata   sN   
"
rC   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   rI   c                 C   s   |du ri }t j|T | d }t|}d}| dd}|dur(ttj|}d}| dd}|dur9tt|}d}| dd}	|	durJtt|	}t	| drS| d nd}
| d }W d   n1 scw   Y  t
||||||
dS )	z4Return model.compile arguments from training config.Nr6   lossmetricsweighted_metricssample_weight_modeloss_weights)r4   rJ   rK   rL   rN   rM   )r   r@   ZCustomObjectScoper   deserializeget_deserialize_nested_configr   _deserialize_metrichasattrr:   )r5   Zcustom_objectsr6   r4   rJ   Zloss_configrK   Zmetrics_configrL   Zweighted_metrics_configrM   rN   r   r   r   !compile_args_from_training_config   sF   


!rT   c                    st   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| 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 )Nr0   TF)r   r:   r;   objr   r   r   _is_single_object  s
   
z5_deserialize_nested_config.<locals>._is_single_objectNc                    s   i | ]
\}}|t  |qS r   rQ   )r   kvdeserialize_fnr   r   r      s    
z._deserialize_nested_config.<locals>.<dictcomp>c                    s   g | ]}t  |qS r   rX   )r   rV   r[   r   r   
<listcomp>%  s    
z._deserialize_nested_config.<locals>.<listcomp>zrSaved configuration not understood. Configuration should be a dictionary, string, tuple or list. Received: config=.)r   r:   itemstuplelistr   )r\   r1   rW   r   r[   r   rQ     s$   


rQ   c                 C   s   dd }t j|| S )z/Serialized a nested structure of Keras objects.c                 S   s   t | r	t| S | S N)callabler   Zserialize_keras_objectrU   r   r   r   _serialize_fn2  s   
z/_serialize_nested_config.<locals>._serialize_fn)r!   r"   map_structure)r1   rd   r   r   r   r?   /  s   r?   c                 C   s"   ddl m} | dv r| S || S )z7Deserialize metrics, leaving special strings untouched.r   )rK   )ZaccuracyaccZcrossentropyZce)r   rK   rO   )Zmetric_configZmetrics_moduler   r   r   rR   :  s   
rR   c                    s`   dd  dd }t j| }t fdd|D o$t fdd|D  }|r.t j|| } | S )z5Enforces that either all specs have names or none do.c                 S   s   | d u pt | do| jd uS Nr   )rS   r   specr   r   r   	_has_nameI  s   z-_enforce_names_consistency.<locals>._has_namec                 S   s   t | } t| drd | _| S rg   )copydeepcopyrS   _namerh   r   r   r   _clear_nameL  s   

z/_enforce_names_consistency.<locals>._clear_namec                 3   s    | ]} |V  qd S rb   r   )r   srj   r   r   	<genexpr>S  s    z-_enforce_names_consistency.<locals>.<genexpr>)r!   r"   r#   anyallre   )specsrn   Z
flat_specsZname_inconsistencyr   rp   r   r   F  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_metricsr<   r=   r   r   r   r   try_build_compiled_arguments\  s   

rv   c                 C   s   |  dp|  dp|  dS )Nz.h5z.kerasz.hdf5)endswith)rG   r   r   r   is_hdf5_filepathn  s
   
rx   )Frb   )TT)%__doc__rk   rD   Ztensorflow.compat.v2compatv2r!   r   r   r   r   r    r   Zkeras.optimizersr   Zkeras.saving.legacyr   Zkeras.utilsr   Zkeras.utils.io_utilsr	   Ztensorflow.python.platformr
   r<   r   r   r   r-   rC   rI   rT   rQ   r?   rR   r   rv   rx   r   r   r   r   <module>   s6   


48
0