B
    df                 @   s  d Z ddlZddlZddlZddlZddl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 efddZdd Zdd ZG dd dejZdd Zdd Zdd Z dd Z!dd Z"dd Z#dd  Z$d!d" Z%d#d$ Z&d%d& Z'e(d'kre'  dS )(zHPython command line interface for converting TF models to TFLite models.    N)app)lite)register_custom_opdefs)toco_flags_pb2)gen_html)tf2)dtypes)
keras_depsc                s$   | d k	r  fdd|  dD S d S )Nc                s   g | ]}|r |qS  r
   ).0val)type_fnr
   W/var/www/html/venv/lib/python3.7/site-packages/tensorflow/lite/python/tflite_convert.py
<listcomp>&   s    z _parse_array.<locals>.<listcomp>,)split)valuesr   r
   )r   r   _parse_array$   s    r   c             C   s$   | d k	r t dd | dD S d S )Nc             S   s   g | ]}|r|qS r
   r
   )r   itemr
   r
   r   r   ,   s    z_parse_set.<locals>.<listcomp>r   )setr   )r   r
   r
   r   
_parse_set*   s    r   c             C   sF   | dkrt jS | dkrt jS | dks,| dkr2t jS td|| dS )zConverts the inference type to the value of the constant.

  Args:
    value: str representing the inference type.
    flag: str representing the flag name.

  Returns:
    tf.dtype.

  Raises:
    ValueError: Unsupported value.
  FLOATZINT8ZUINT8ZQUANTIZED_UINT8z`Unsupported value for `{}` flag. Expected FLOAT, INT8, UINT8, or QUANTIZED_UINT8 instead got {}.N)r   float32Zint8Zuint8
ValueErrorformat)valueflagr
   r
   r   _parse_inference_type0   s    r   c                   s,   e Zd ZdZd fdd	ZdddZ  ZS )	_ParseBooleanFlagzGHelper class to parse boolean flag that optionally accepts truth value.Nc                s2   |dkrt dtt| j||fd|i| d S )N?zAThis parser only supports nargs='?' (0 or 1 additional arguments)nargs)r   superr   __init__)selfoption_stringsdestr    kwargs)	__class__r
   r   r"   K   s
    
z_ParseBooleanFlag.__init__c             C   sT   |d krd}n4|  dkr d}n"|  dkr2d}ntd| jt|| j| d S )NTtruefalseFzEInvalid argument to --{}. Must use flag alone, or specify true/false.)lowerr   r   r%   setattr)r#   parser	namespacer   option_string
flag_valuer
   r
   r   __call__T   s    
z_ParseBooleanFlag.__call__)N)N)__name__
__module____qualname____doc__r"   r0   __classcell__r
   r
   )r'   r   r   H   s   	r   c             C   s   t | j}d}| jr<dd | jdD }ttt||}t | j}|||d}| jrlt	j
j}| j|d< nT| jrt	j
j}| j|d< t| j|d< | j|d	< n"| jrt	j
j}| j|d
< ntd|f |S )zMakes a TFLiteConverter object based on the flags provided.

  Args:
    flags: argparse.Namespace object containing TFLite flags.

  Returns:
    TFLiteConverter object.

  Raises:
    ValueError: Invalid flags.
  Nc             S   s   g | ]}t |td qS ))r   )r   int)r   shaper
   r
   r   r   x   s   z)_get_tflite_converter.<locals>.<listcomp>:)input_arraysinput_shapesoutput_arraysgraph_def_filesaved_model_dirZtag_setZsignature_keyZ
model_filezM--graph_def_file, --saved_model_dir, or --keras_model_file must be specified.)r   r9   r:   r   dictlistzipr;   r<   r   ZTFLiteConverterZfrom_frozen_graphr=   from_saved_modelr   saved_model_tag_setsaved_model_signature_keykeras_model_fileZfrom_keras_model_filer   )flagsr9   r:   Zinput_shapes_listr;   Zconverter_kwargsZconverter_fnr
   r
   r   _get_tflite_converterg   s.    


rF   c          	   C   s  | j rtt| j  t| }| jr0t| jd|_| jrDt| jd|_| jrZtj	
| j|_| jr| jr| }t| jtd}|jtjkrt| jtd}nt| jtd}tt||}| jst|dkst|t|krtdd|ttt|||_| jdk	r$| jdk	r$| j| jf|_| jr4| j|_| jrD| j|_| j rX| j dk|_ | j!rh| j!|_!| j"rt#j$% }t& |j'_(xH| j")dD ]8}||krtd	d||j'j(*t#$| qW | j+r$t#j$j,|j'j(krtd
t& }x | j+)dD ]}	|*|	 qW t||j'_+| j-rVt#j.j/g|_0|jtjkrVt1d tj|_| j2rztj3g|j'_4| j-szt1d | j5r| j5|_5| j6r| j6|_7| j8r| j8|_8| j9|_9| j:dk	r| j:|_:|; }
t<| j=d}|>|
 W dQ R X dS )zCalls function to convert the TensorFlow 1.X model into a TFLite model.

  Args:
    flags: argparse.Namespace object.

  Raises:
    ValueError: Invalid flags.
  inference_typeinference_input_type)r      a*  Mismatching --input_arrays, --std_dev_values, and --mean_values. The flags must have the same number of items. The current input arrays are '{0}'. --input_arrays must be present when specifying --std_dev_values and --mean_values with multiple input tensors in order to map between names and values.r   NTRUEz,Invalid value for --target_ops. Options: {0}zY--experimental_select_user_tf_ops can only be set if --target_ops contains SELECT_TF_OPS.zg--post_training_quantize quantizes a graph of inference_type FLOAT. Overriding inference_type to FLOAT.z[--quantize_to_float16 will only take effect with the --post_training_quantize flag enabled.wb)?custom_opdefsr   r   rF   rG   r   rH   Zoutput_format_toco_flags_pb2Z
FileFormatValuemean_valuesstd_dev_valuesZget_input_arraysfloatr   r   r6   r?   r@   r9   lenr   r   joinr>   Zquantized_input_statsdefault_ranges_mindefault_ranges_maxZdefault_ranges_statsZdrop_control_dependencyZreorder_across_fake_quantZchange_concat_input_rangesallow_custom_opsZ
target_opsr   OpsSetget_optionsr   Ztarget_specZsupported_opsr   addexperimental_select_user_tf_opsZSELECT_TF_OPSpost_training_quantizeZOptimizeDEFAULTZoptimizationsprintquantize_to_float16Zfloat16Zsupported_typesdump_graphviz_dirdump_graphviz_videoZdump_graphviz_vodeconversion_summary_direxperimental_new_converterexperimental_new_quantizerconvertopenoutput_filewrite)rE   	converterr9   rP   rO   Zquant_statsZops_set_optionsoptionZuser_op_setZop_nameZoutput_datafr
   r
   r   _convert_tf1_model   s    





rk   c          	   C   s   | j r(tjj| j t| jt| jd}n | jrHt	
 | j}tj|}| j|_| jdk	rb| j|_| }t| jd}|| W dQ R X dS )zCalls function to convert the TensorFlow 2.0 model into a TFLite model.

  Args:
    flags: argparse.Namespace object.

  Raises:
    ValueError: Unsupported file format.
  )Zsignature_keystagsNrK   )r=   r   ZTFLiteConverterV2rA   r   rC   r   rB   rD   r	   Zget_load_model_functionZfrom_keras_modelrb   rc   rd   re   rf   rg   )rE   rh   modelZtflite_modelrj   r
   r
   r   _convert_tf2_model  s    

rn   c             C   s  dd }|rzd}x\|D ]T}|||dd7 }|||dd7 }|||dd	7 }|||d
d7 }|||dd7 }qW |rzt || jr| jr| jst d| jr| jst d| jd| jdkrt d| js| jrt| jt| jkrt d| jd| jdkrt d| j	dk| j
dkkr2t d| jrJ| jsJt d| jrb| jsbt d| jrz| jszt d| jr| jst ddS )an  Checks the parsed and unparsed flags to ensure they are valid in 1.X.

  Raises an error if previously support unparsed flags are found. Raises an
  error for parsed flags that don't meet the required conditions.

  Args:
    flags: argparse.Namespace object containing TFLite flags.
    unparsed: List of unparsed flags.

  Raises:
    ValueError: Invalid flags.
  c             S   s   |  |rd||S dS )Nz
  Use {0} instead of {1} )
startswithr   )r   Z	orig_flagZnew_flagr
   r
   r   _get_message_unparsed3  s    
z/_check_tf1_flags.<locals>._get_message_unparsedro   z--input_filez--graph_def_filez--savedmodel_directoryz--saved_model_dirz--std_valuez--std_dev_valuesz--batch_sizez--input_shapesz--dump_graphvizz--dump_graphviz_dirzE--input_arrays and --output_arrays are required with --graph_def_filez/--input_shapes must be used with --input_arraysr8   r   zD--input_shapes and --input_arrays must have the same number of itemsz8--std_dev_values and --mean_values must be used togetherzB--std_dev_values, --mean_values must have the same number of itemsNzC--default_ranges_min and --default_ranges_max must be used togetherz;--dump_graphviz_video must be used with --dump_graphviz_dirz>--custom_opdefs must be used with --experimental_new_converterz4--custom_opdefs must be used with --allow_custom_opszP--experimental_select_user_tf_ops must be used with --experimental_new_converter)r   r<   r9   r;   r:   countrP   rO   boolrT   rU   r`   r_   rL   rb   rV   rZ   )rE   unparsedrq   outputr   r
   r
   r   _check_tf1_flags$  sJ    
rv   c             C   s   | j s| jstddS )zChecks the parsed and unparsed flags to ensure they are valid in 2.X.

  Args:
    flags: argparse.Namespace object containing TFLite flags.

  Raises:
    ValueError: Invalid flags.
  zEone of the arguments --saved_model_dir --keras_model_file is requiredN)rD   r=   r   )rE   r
   r
   r   _check_tf2_flagsm  s    	rw   c          	   C   s  | j dd}|jdtdd |jdtdd |jdtd	d | jd
tjddgdd | jdtjddd | jdtjdd | jdtdd | jdtdd | jdtdd | jdtdd | jdtdd | jdtd d | jd!td"d | jd#td$d | jd%td&d | jd'd(d)tjd* | jd+d(d)d,d* | jd-d.d)d/d* | jd0d)d1d2 | jd3d)d4d2 | jd5tjd6d7gd8d | jd9td:d;d< | jd=td>d | jd?td@dA	t
j d | jdBtdCd | jdDtdEd | jdFd)dGd2 | jdHtdId dJS )KzdReturns ArgumentParser for tflite_convert for TensorFlow 1.X.

  Args:
    parser: ArgumentParser
  T)requiredz--graph_def_filez<Full filepath of file containing frozen TensorFlow GraphDef.)typehelpz--saved_model_dirz5Full filepath of directory containing the SavedModel.z--keras_model_filez5Full filepath of HDF5 file containing tf.Keras model.z--output_formatZTFLITEZGRAPHVIZ_DOTzOutput file format.)ry   choicesrz   z--inference_typer   z_Target data type of real-number arrays in the output file. Must be either FLOAT, INT8 or UINT8.)ry   defaultrz   z--inference_input_typezTarget data type of real-number input arrays. Allows for a different type for input arrays in the case of quantization. Must be either FLOAT, INT8 or UINT8.z--input_arraysz+Names of the input arrays, comma-separated.z--input_shapesz8Shapes corresponding to --input_arrays, colon-separated.z--output_arraysz,Names of the output arrays, comma-separated.z--saved_model_tag_setzComma-separated set of tags identifying the MetaGraphDef within the SavedModel to analyze. All tags must be present. In order to pass in an empty tag set, pass in "". (default "serve")z--saved_model_signature_keyzkKey identifying the SignatureDef containing inputs and outputs. (default DEFAULT_SERVING_SIGNATURE_DEF_KEY)z--std_dev_valueszStandard deviation of training data for each input tensor, comma-separated floats. Used for quantized input tensors. (default None)z--mean_valueszuMean of training data for each input tensor, comma-separated floats. Used for quantized input tensors. (default None)z--default_ranges_minzDefault value for min bound of min/max range values used for all arrays without a specified range, Intended for experimenting with quantization via "dummy quantization". (default None)z--default_ranges_maxzDefault value for max bound of min/max range values used for all arrays without a specified range, Intended for experimenting with quantization via "dummy quantization". (default None)z--quantize_weightsr[   
store_true)r%   actionrz   z--post_training_quantizezBoolean indicating whether to quantize the weights of the converted float model. Model size will be reduced and there will be latency improvements (at the cost of accuracy). (default False)z--quantize_to_float16r^   zBoolean indicating whether to quantize weights to fp16 instead of the default int8 when post-training quantization (--post_training_quantize) is enabled. (default False)z--drop_control_dependencyzBoolean indicating whether to drop control dependencies silently. This is due to TensorFlow not supporting control dependencies. (default True))r~   rz   z--reorder_across_fake_quantaF  Boolean indicating whether to reorder FakeQuant nodes in unexpected locations. Used when the location of the FakeQuant nodes is preventing graph transformations necessary to convert the graph. Results in a graph that differs from the quantized training graph, potentially causing differing arithmetic behavior. (default False)z--change_concat_input_rangesrJ   FALSEzBoolean to change behavior of min/max ranges for inputs and outputs of the concat operator for quantized models. Changes the ranges of concat operator overlap when true. (default False)z--allow_custom_opsr   a  Boolean indicating whether to allow custom operations. When false any unknown operation is an error. When true, custom ops are created for any op that is unknown. The developer will need to provide these to the TensorFlow Lite runtime with a custom resolver. (default False))r~   r    rz   z--custom_opdefszString representing a list of custom ops OpDefs delineated with commas that are included in the GraphDef. Required when using custom operations with --experimental_new_converter.z--target_opszExperimental flag, subject to change. Set of OpsSet options indicating which converter to use. Options: {0}. One or more option may be specified. (default set([OpsSet.TFLITE_BUILTINS]))r   z!--experimental_select_user_tf_opszzExperimental flag, subject to change. Comma separated list of user's defined TensorFlow operators required in the runtime.z--dump_graphviz_dirzFull filepath of folder to dump the graphs at various stages of processing GraphViz .dot files. Preferred over --output_format=GRAPHVIZ_DOT in order to keep the requirements of the output file.z--dump_graphviz_videozMBoolean indicating whether to dump the graph after every graph transformationz--conversion_summary_dirzFull filepath to store the conversion logs, which includes graphviz of the model before/after the conversion, an HTML report and the conversion proto buffers. This will only be generated when passing --experimental_new_converterN)add_mutually_exclusive_groupadd_argumentstrupperrQ   argparseSUPPRESSr   r   rS   r   rW   rX   )r,   input_file_groupr
   r
   r   _get_tf1_flags{  s    

r   c             C   s\   |   }|jdtdd |jdtdd | jdtdd | jdtd	d | jd
ddd dS )zdReturns ArgumentParser for tflite_convert for TensorFlow 2.0.

  Args:
    parser: ArgumentParser
  z--saved_model_dirz5Full path of the directory containing the SavedModel.)ry   rz   z--keras_model_filez5Full filepath of HDF5 file containing tf.Keras model.z--saved_model_tag_setzComma-separated set of tags identifying the MetaGraphDef within the SavedModel to analyze. All tags must be present. In order to pass in an empty tag set, pass in "". (default "serve")z--saved_model_signature_keyzkKey identifying the SignatureDef containing inputs and outputs. (default DEFAULT_SERVING_SIGNATURE_DEF_KEY)z--enable_v1_converterr}   z*Enables the TensorFlow V1 converter in 2.0)r~   rz   N)r   r   r   )r,   r   r
   r
   r   _get_tf2_flags:  s*    r   c             C   s^   t jdd}|jdtddd | r,t| nt| |jdtddd	d
 |jdtddd |S )zReturns an ArgumentParser for tflite_convert.

  Args:
    use_v2_converter: Indicates which converter to return.
  Return: ArgumentParser.
  z3Command line tool to run TensorFlow Lite Converter.)descriptionz--output_filez!Full filepath of the output file.T)ry   rz   rx   z--experimental_new_converterr   znExperimental flag, subject to change. Enables MLIR-based conversion instead of TOCO conversion. (default True))r~   r    r|   rz   z--experimental_new_quantizerzsExperimental flag, subject to change. Enables MLIR-based quantizer instead of flatbuffer conversion. (default True))r~   r    rz   )r   ArgumentParserr   r   r   r   r   )use_v2_converterr,   r
   r
   r   _get_parser^  s,    
r   c             C   s,  t  }t|}|jtjdd d\}}t  r^|jr^d}t|}|jtjdd d\}}y|rnt| n
t|| W n^ t	k
r } z@|
  tjtjd }tjd|t| td W dd}~X Y nX |rt| n@zt| W d|jr&|jrt|j|j|j n
td X dS )zMain in tflite_convert.py.rI   N)argsFr   z{0}: error: {1}
zlConversion summary will only be generated when enabling the new converter via --experimental_new_converter. )r   enabledr   parse_known_argssysargvZenable_v1_converterrw   rv   r   print_usageospathbasenamestderrrg   r   r   exitrn   rk   ra   rb   r   Zgen_conversion_log_htmlr[   rf   warningswarn)_r   r,   Ztflite_flagsrt   e	file_namer
   r
   r   run_main  s6    


r   c               C   s   t jttjd d d d S )NrI   )mainr   )r   runr   r   r   r
   r
   r
   r   r     s    r   __main__))r4   r   r   r   r   Zabslr   Z
tensorflowtfZtensorflow.lite.pythonr   Ztensorflow.lite.python.convertr   Ztensorflow.lite.tocor   rM   Ztensorflow.lite.toco.loggingr   Ztensorflow.pythonr   Ztensorflow.python.frameworkr   Ztensorflow.python.utilr	   r   r   r   r   Actionr   rF   rk   rn   rv   rw   r   r   r   r   r   r1   r
   r
   r
   r   <module>   s<   0oI @$'+
