o
    Nes                     @   s,  d dl mZ d dl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
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mZ d dlmZmZ d dlmZm Z  dgZ!dZ"dZ#dZ$dZ%dZ&dZ'dZ(dd Z)dd Z*dd Z+dd Z,d d! Z-d"d# Z.ed$d% Z/ed&d' Z0d(d) Z1ed*d+ Z2d,d- Z3dTd.d/Z4ed0d1 Z5d2d3 Z6G d4d5 d5e7Z8	dUd6d7Z9d8d9 Z:d:d; Z;dUd<d=Z<	>dVd?d@Z=dAdB Z>dCdD Z?dEdF Z@dGdH ZA	dUdIdJZB	dUdKdLZCdMdN ZDdOdP ZE	dTdQdRZFG dSd dejGZHdS )W    )print_functionN)compat)core)	framework)backward)unique_name)layers)nn)_hash_with_id)switch_to_static_graph)_non_static_mode)_is_enable_standalone_executor$_is_dy2st_enable_standalone_executor)add_build_strategy_forLazyInitialized)_C_ops_legacy_C_opsTranslatedLayerz.pdmodelz
.pdiparamsz.pdiparams.infoz.metaloadparambufferc                 C   s^   t | d}| }W d    n1 sw   Y  t|}t| s-td|  |S )Nrbz Unsupported program version: %d
)openreadr   ProgramDescZ_is_program_version_supported_version
ValueError)model_file_pathfZprogram_desc_strprogram_desc r    GD:\Projects\ConvertPro\env\Lib\site-packages\paddle/fluid/dygraph/io.py_load_program_desc7   s   


r"   c                 C   sT   |   tjjjks$|   tjjjks$|   tjjjks$|   tjjjkr&dS |  S )NF)	typer   VarDescVarTypeZFEED_MINIBATCHZ
FETCH_LISTZREADERRAWpersistable)var_descr    r    r!   _is_persistableE   s   r)   c                 C   s   g }t j| D ]$}||}t j| D ]}||}|  | v r-|	| qq
t j| D ](}||}t j| D ]}||}|  |
 v r^||v rZqF  dS qFq7dS NFT)sixmovesrange
num_blocksblockop_sizeopnameinput_arg_namesappendoutput_arg_names)Zpersistable_var_descr   Z	input_ops	block_idxr/   op_idxr1   r    r    r!   _is_parameterP   s(   




r8   c                 C   s@   g }t j|  D ]}| |}|ttt|	  q
|S N)
r+   r,   r-   r.   r/   extendlistfilterr)   all_vars)r   persistable_varsir/   r    r    r!   _get_persistable_varsh   s
   
r@   c                 C   s(   g }t | }|D ]	}||  q|S )z<
    Get all persistable variable names in ProgramDesc.
    )r@   r4   r2   )r   Z	var_namesr>   varr    r    r!   _get_persistable_var_namesp   s
   rB   c                 C   sF   t  }tj|  D ]}| |}| D ]	}||  qq|S r9   )	setr+   r,   r-   r.   r/   r=   addr2   )r   all_var_namesr?   r/   rA   r    r    r!   _get_all_var_names{   s   
rF   c                 C   s&   t }t| } td| |f}|S )zo
    Append loaded suffix to the given variable name
    e.g. x ==> x.load_0, x.load_0 ==> x.load_0.load_0
    .)LOADED_VAR_SUFFIXcptZto_textr   generate_with_ignorable_keyjoin)r2   suffixnew_namer    r    r!   _append_loaded_suffix   s   
rN   c                 C   
   t | S r9   )r   rJ   prefixr    r    r!   _generate_unique_var_name      
rR   c           
      C   s   t  }t| }|D ]M}| }t| }|||< || tj|  D ]/}| 	|}|
t|t| tj| D ]}||}	|	|| |	|| qAq&q	|S r9   )dictr@   r2   rN   set_namer+   r,   r-   r.   r/   _rename_varrI   to_bytesr0   r1   _rename_input_rename_output)
r   Zsuffix_varname_dictr>   r(   Zold_namerM   r6   r/   r7   r1   r    r    r!   _append_loaded_suffix_to_var   s"   


rZ   c                 C   rO   r9   )r   generaterP   r    r    r!   0_generate_unique_var_name_sync_with_main_program   rS   r\   c                 C   s0   t  }t| }|D ]}| }|| ||< q	|S r9   )rT   r@   r2   )r   Zall_new_old_dict_allZnew_old_dictr>   r(   name_newr    r    r!   _get_loaded_var_new_old   s   r^   c              
   C   s&  t  }t  }g }tj|  D ]}| |}| D ]	}||  qqd}	tj|  D ]}| |}t	| D ]v\}
}| }d|v }|	pL|}	|du sU||v o_|du p\||vo_| }|r|
d}t|dkr}|d  r}d|dd }n|}	 t|}||d|
 ||
d d  vrnqn|}||kr|t|t| |s|||< |||< q=q0|	ri }|D ]5}tj|  D ]*}| |}t	| D ]\}
}| }d|v r||v r|||| }|||< qqq|D ]}|| ||< |||| < qtj|  D ]}| |}tj| D ]n}||}| D ].}||v rR||| krR||||  |t|rR|t|t||  q%| D ].}||v r||| kr||||  |t|r|t|t||  qXqq|   ||fS )a  
    Change the name of the loaded variables.Use 'unique_name.generate' to avoid duplication.
    It is used when loading multiple program during inference.

    e.g. linear_0.tmp_3 ==> linear_0.tmp_1, x ==> x_0. For double grad, x@GRAD ==> x_0@GRAD
    If 'include' is not `None`,variables in include and the corresponding
      double grad variables (if exist) are renamed.
    If 'exclude' is not `None`,variables that are in exclude and the
      corresponding double grad variables (if exist) are not renamed.

    Args:
        program_desc(ProgramDesc):the variables in it will be modified.
        include(List):list of names of variables.
        exclude(List):list of names of variables.

    Returns:
        tuple of (dict_rename_var_new_old, dict_rename_var_old_new)
        dict_rename_var_new_old is a dict mapping from new name to old name
        dict_rename_var_old_new is a dict mapping from old name to new name
    F@GRADN_   )rT   r+   r,   r-   r.   r/   r=   r4   r2   	enumeratesplitlen	isnumericrK   r\   rV   rI   rW   replacer0   r1   r3   rX   has_varr5   rY   flush)r   includeexcludedict_rename_var_old_newZdict_rename_var_new_oldZ	old_namesZb_idxZ	cur_blockrA   Zhas_double_gradZvar_idxZname_oldZis_double_grad_varZshould_renameZ	temp_namer]   Zdouble_grad_rename_dictvar_nameZnew_var_namer7   r1   Zinput_arg_nameZoutput_arg_namer    r    r!   _rename_var_program_desc   s   


#
	



$rn   c                    s<   t   |  _ fddtj j D  _    S )Nc                    s   g | ]}t  |qS r    )r   Block).0r?   progr    r!   
<listcomp>>  s    
z*_build_program_by_desc.<locals>.<listcomp>)	r   Programdescr+   r,   r-   r.   blocks_sync_with_cpp)r   r    rq   r!   _build_program_by_desc:  s   
rx   c                 C   sZ   t j|  D ]"}| |}t j| D ]}||}|dr)|d| qqd S )Nis_test)	r+   r,   r-   r.   r/   r0   r1   has_attr	_set_attr)r   ry   r?   r/   jr1   r    r    r!   _change_is_test_statusF  s   


r}   c                       s   e Zd ZdZ fddZedd Zedd Zedd	 Z	ed
d Z
edd Zedd Zedd Zedd Zedd Zedd Zedd Zedd Zedd Zdd Zed d! Zed"d# Zed$d% Z  ZS )&_ProgramHolderz
    Holds the execution information of a Program.

    _ProgramHolder is the execution unit of TranslatedLayer,
    if TranslatedLayer contains multiple _ProgramHolder,
    it can execute multiple methods

    _ProgramHolder is an internal concept.
    c                    sT   t t|   g | _g | _g | _g | _t | _	d | _
| || _| | j| _d S r9   )superr~   __init___input_descs_output_descs_double_grad_descs_persistable_namesr   ZScope_inner_scope_suffix_varname_dict_preprocess_infer_program_desc_append_backward_desc_train_program_desc)selfr   	__class__r    r!   r   [  s   

z_ProgramHolder.__init__c                 C   s2   t | j}| jd }|dkrt|d|S |S )Nr   )rx   r   r   r/   r0   r   )r   whole_programend_op_indexr    r    r!   _create_forward_train_programq  s
   
z,_ProgramHolder._create_forward_train_programc                 C   
   |   jS r9   )r   ru   r   r    r    r!   _forward_program_descz  rS   z$_ProgramHolder._forward_program_descc                 C   sV   t | j}| jd dt| j  }|jd }||k r&t|||S t	j
 S )Nr      )rx   r   r   r/   r0   re   r   ru   r   paddlestaticrt   )r   r   start_op_indexr   r    r    r!   _create_backward_train_program  s   

z-_ProgramHolder._create_backward_train_programc                 C   r   r9   )r   ru   r   r    r    r!   _backward_program_desc  rS   z%_ProgramHolder._backward_program_descc                 C      | j S r9   )r   r   r    r    r!   infer_program     z_ProgramHolder.infer_programc                 C   r   r9   )r   r   r    r    r!   train_program  r   z_ProgramHolder.train_programc                 C   r   r9   )r   r   r    r    r!   forward_program  r   z_ProgramHolder.forward_programc                 C   r   r9   )r   r   r    r    r!   backward_program  r   z_ProgramHolder.backward_programc                 C   r   r9   )r   r   r    r    r!   input_descs  r   z_ProgramHolder.input_descsc                 C   r   r9   )r   r   r    r    r!   output_descs  r   z_ProgramHolder.output_descsc                 C   r   r9   )r   r   r    r    r!   persistable_names  r   z _ProgramHolder.persistable_namesc                 C   r   r9   )r   r   r    r    r!   double_grad_descs  r   z _ProgramHolder.double_grad_descsc                 C   r   r9   )r   r   r    r    r!   scope  r   z_ProgramHolder.scopec              
   C   s  t |}t||\}}g }|d}tj| D ]}||}| dkrM|	| t
|dd }	||	 | j	|t
|dd  q| dkr|dd dr|	| t
|dd }
||
 | j	|t
|dd  q| dkr|	| t
|dd }|| |dd ds| j	|t
|dd  q|dr|d qt|D ]
}|||d	  qt| D ]}||}| D ]}d
| v r| j	| qq| j  t|}| | t||| _t || _ |S )Nr   feedXOutscalezsave_infer_model/scale_fetchZop_callstackra   r_   )!rB   rn   r/   r+   r,   r-   r0   r1   r#   r4   rI   rW   inputZ_remove_varr   find_varoutput
startswithr   rz   Zremove_attrreversedZ
_remove_opr.   r=   r2   r   reverserx   _append_scale_to_outputr^   r   r   )r   r   Zlist_persistable_varZrename_new_old_dictr`   Zops_to_removeZ
root_blockr?   r1   Zfeed_var_nameZout_var_nameZfetch_var_namer7   Z
block_descr(   Ztmp_programr    r    r!   r     sj   













z_ProgramHolder._preprocessc                 C   s   g }t |+ t| jD ]\}}| | }tj|dd	|d}|
| qW d    n1 s5w   Y  t|D ]
\}}|j| j|< q>d S )Ng      ?ztranslated_layer/scale_{}r2   )r   Zprogram_guardrc   r   global_blockrA   r2   r	   r   formatr4   ru   )r   programZscale_output_varsr?   outrA   r    r    r!   r     s   z&_ProgramHolder._append_scale_to_outputc              	   C   s   t |}t|d t|}tj|jD ]G}||}|j	D ]<}|j
dkr[d|jvs4t|ddkr[|jtdddg||dd jt jjjdd	d
}|jd|jg qq|S )NFZ
batch_normZReserveSpacer   rG   reserve_spacetmpr   T)r2   dtyper#   r'   stop_gradient)r   r   r}   rx   r+   r,   r-   r.   r/   opsr#   output_namesre   r   
create_varr   rJ   rK   rA   r   r   r$   r%   
LOD_TENSORru   Z
set_outputr2   )r   infer_program_descZprogram_desc_copyr   r6   r/   r1   r   r    r    r!   _get_train_forward_program  s,   





	z)_ProgramHolder._get_train_forward_programc                 C   sF   |  |}g }| jD ]}|| |  q
tj|g d |jS )N)targetsinputs)	r   r   r4   r   rA   r2   r   Z	gradientsru   )r   r   r   r   r   r    r    r!   r   @  s   

z$_ProgramHolder._append_backward_desc)__name__
__module____qualname____doc__r   r   r   r   r   r   r   propertyr   r   r   r   r   r   r   r   r   r   r   r   r   __classcell__r    r    r   r!   r~   P  sH    













Y

"r~   c              
   C   s  t |j}i }|D ]l}|j|  }t||jrBt r/tj| |	 | |
 dd}n%tj| |	 | |
 dd}ntj|
 | | |	 dd}|d u rlt jdi d|idtj| |id d|_||| < q	|d urg }d	d
 |j D }	t|	 D ]}
|||	|
   qt jdi d|idtj| |id |D ]}t||jsq||  }d|_qt|j}|D ]}|t  }||vrd|| _q|S )NT)shaper   r2   r#   r'   )r#   r2   r   r   r'   r   r   	file_pathr#   r   outputsattrsFc                 S      i | ]\}}||qS r    r    )rp   kvr    r    r!   
<dictcomp>      
z5_load_persistable_vars_by_program.<locals>.<dictcomp>load_combine)r@   r   r   r2   r8   r   _in_eager_without_dygraph_checkEagerParamBaser   r   r#   	ParamBase_varbase_creator_dygraph_tracertrace_opospathrK   r   itemssortedkeysr4   rF   r   r   grad_var_suffix)
model_pathprogram_holderparams_filenamer>   load_var_dictZeach_varZorig_each_namenew_varload_var_listZdict_name_old_newr2   r   rE   rm   grad_var_namer    r    r!   !_load_persistable_vars_by_programj  sz   


r   c                 C   s`  t |d}t|}W d    n1 sw   Y  t }g }dd |j D }t|D ]P}	|	|vr8td|	||	 }
||	 dd d urft	
 rXt	jdgtjjj|
dd}nt	jdgtjjj|
dd}nt	j|
dd	}||	 d
 |_|||
< || q-|d usJ dtj| |}tj|st|dkrtd|S t	 jdi d|id|id |S )Nr   c                 S   r   r    r    )rp   keyvaluer    r    r!   r     r   z*_load_persistable_vars.<locals>.<dictcomp>zdThe model to be loaded is not complete.The variable `%s` of program cannot be found in loaded model.Z	trainablera   T)r   r   r2   r'   )r2   r'   r   z#params_filename should not be None.r   z%The model to be loaded is incomplete.r   r   r   r   )r   pickler   rT   r   r   r   RuntimeErrorgetr   r   r   r   r$   r%   FP32r   r   r   r4   r   r   rK   existsre   r   r   r   )r   var_info_pathr   r   r   Zextra_var_infor   r   Zinv_suffix_varname_dictr2   rM   r   Zvar_file_pathr    r    r!   _load_persistable_vars  sd   			r   c                 C   s*   t  }| D ]}|j| }| | ||< q|S r9   )rT   r   )var_dictr   Zno_suffix_var_dictrm   Zno_suffix_namer    r    r!   _remove_varname_suffix  s
   
r   c                 C   sT  t  }|d urstj|}tj| |}|d tt  }t| D ]N}||kr2d}tj| |}n6|trg|	|rg|t|tt d  
d}t|dkrft|d dkrf|d }tj| |}nq"q"tt|||< q"|S t| D ]/\}}}	|	D ]'}
d|
v rtj| |
}|
d}|dkrd}n|dd tt|||< qqx|S )	Nforwardra   rG      r   modelr`    )rT   r   r   basenamerK   re   INFER_MODEL_SUFFIXlistdirendswithr   rd   r~   r"   walkstriprg   )r   model_filenameZprogram_holder_dictr   
model_namefilename	func_nameparsing_namesr`   Z
file_namesr2   method_namer    r    r!   _construct_program_holders  sP   

r  Tc                 C   s2  t |d }tj| |}tj| t |}tj|ryt| ||d |}|d tt  }t| D ]D}	|		|rc|	
trc|	t|tt d  d}
t|
dkrbt|
d dkrb|
d }nq3q3tj| |}|t| ||| |	 q3n|d urtj|st S t| |d |}|st||d }|S )Nz.infor   ra   rG   r   r   )strr   r   rK   r   r   re   INFER_PARAMS_SUFFIXr   r   r   rd   updaterT   r   r   )r   programsr   Zappend_suffixZvar_info_filenamer   Zparams_pathr   r   	file_namer   r   r    r    r!   _construct_params_and_buffers:  sH   

r  c                 C   sR   | r| S t  rtjtjjjg dtjjjdgS t	tjjjg dtjjjdgS )NZFake_varF)
r   r   r   eagerTensorr$   r%   r   r&   VarBase)varsr    r    r!   _valid_varsh  s&   r  c                 C   s  g }t |D ]V\}}t|tjtjtjjfstdt	| t|tjrMt
 r;tjj||j|  dt
 dd}ntj||j|  dt
 dd}n
|}|j|  |_|| q| jd u rkdd |jD | _g }|jD ](}| j| }	|	| jv r|| j|	  qp|	| jv r|| j|	  qptd| g }
|jD ]0}t
 rtjj| | | |	 dd}nt| | | |	 d}|
| qt
 r|jg}nttjjjg d	tjjjd}| |j g }|j D ]1}t
 rtjj| | | |	 dd}nt| | | |	 d}|| q| j!r-|j"n|j#}| j!r7|j$n|j%}|j"&d
' }d|&d
dd
d|d| j!dt(|| g
}t) o[t* }|+d|f |rv|+d|&d
d|j,&d
f t-j.t/|t/|t/|
|t/|d g|R   |D ]#}|jt0  }|&d
1t23|}|d u rq|4|	  q|
}t5|
dkr|
d
 }|S )Nz_The type of input in TranslatedLayer must be numpy array or Variable(VarBase), but received %s.FT)r   r2   r'   ZplaceZ	zero_copyc                 S      g | ]}|  qS r    r   rp   Zinsr    r    r!   rs         z _run_dygraph.<locals>.<listcomp>zFThe persistable variable %s does not exist in current TranslatedLayer.)r   dimsr2   r#   r'   Zprogram_out_scoper   r   r   r   ry   Z
program_iduse_interpretorcoreZforward_global_blockZbackward_global_blockra   )6rc   
isinstancenpZndarrayr   r  r	  r
  	TypeErrorr#   r   r   r   r2   Z_current_expected_placer4   _input_args_namesr   _persistable_var_name_dict_parameters_buffersr   r   r   r   r   r$   r%   r   ZSTEP_SCOPESr   Z	set_scoper   _is_testr   r   r   r   r/   r0   r
   r   r   r:   r   r   Zrun_programr  r   r   rI   rW   Z_set_grad_typere   )instancer   r   Z
input_varsr?   r   rA   r>   rm   Zdy_var_nameZoutput_varsr(   Ztmp_scope_vecZdouble_grad_varstrace_programr   r   r   r  Zpersistable_varr   Zgrad_varoutsr    r    r!   _run_dygraph  s  











	
r  c           	      C   st   t  }t|}t||d\}}|  dd |jD }t|||| | |  t|||}t	|dkr8|d }|S )Nrk   c                 S   r  r    r   )rp   rA   r    r    r!   rs   ;      z%_run_static_graph.<locals>.<listcomp>ra   r   )
r   Zdefault_main_programrB   rn   ri   r   _append_blockrw   _get_output_from_programre   )	r   r   r  Zmain_programparam_var_namesr`   rl   r   r  r    r    r!   _run_static_graph4  s*   
r$  c                 C   sR   g }|dk r|S |  |jD ]}|| q|  |j}|dkr'|t| |7 }|S )z
    Get variables in current block and its parent block.

    Args:
        program(Program): The program containing the current block.
        block_idx(int): index of current block.

    Returns:
        List: list of variables.
    r   rb   )r/   r  r4   
parent_idx_collect_current_and_parent_var)r   r6   r  rA   r%  r    r    r!   r&  M  s   r&  c                 C   s  | j }t| |}t| ||d|d dd |jD }dd |D }t|t|kr8tdt|t|t|D ]\}	}
|rF||
 }
| |j	dd||	 gid	|
gid
 q<t
| ||d}|   | jd }| dkrtd| D ])}||}|j}|dkr|| }n|}| j|d}t|||d |t
||7 }q{|   |D ]*}|dr|d}t|tjjr|j}t|tjr|j}|d| ||  q|   || _ dS )a,  
    Append Variables and Operators in 'src_program_desc' to dest_program.

    Args:
        dest_program(Program): Variables and Operators are appended to it.
        src_program_desc(ProgramDesc): Variables in it will be appended to 'dest_program'.
        program_holder(_ProgramHolder): program_holder of TranslatedLayer
        input_variables(list): list of input variables
        dict_rename_var_old_new(None|dict): When using '_rename_var_program_desc',
        use it to map the name of the variable before it was modified and the new name.
    r   r  c                 S   r  r    r   rp   inpr    r    r!   rs     r   z!_append_block.<locals>.<listcomp>c                 S   s   g | ]}|j qS r    r   r'  r    r    r!   rs     s    z=The number of input is invalid, expected {}, but received {}.Zassignr   r   )r#   r   r   ra   )r%  Z	sub_blockN)Zcurrent_block_idxr&  !append_var_from_block_desc_staticr/   r   re   r   r   rc   	append_op append_op_from_block_desc_staticrw   r.   r-   parentZ_create_blockrz   attrr  r   r   Z	BlockDescidro   idxr{   )Zdest_programZsrc_program_descr   Zinput_variablesrl   Zorigin_block_idxr#  Zname_inp_descZinput_namesr?   Zout_nameZ
append_opsZoffset_block_idxZsrc_block_idxZ	src_blockZsrc_parent_idxr%  Z
dest_blockr1   subZ	origin_idr    r    r!   r!  c  st   






r!  c           	      C   sh   t  }|jD ]+}t| jD ]#}| |j}| }|r|| }||v r0|| }||vr0|| qq|S )zB
    Get output name of 'program' according to program_holder
    )r;   r   r-   r.   r/   r  r2   r4   )	r   r   rl   r  rA   r/  r  rm   r   r    r    r!   r"    s   

	r"  c                 C   s0   g }t | D ]}|t| || q|S )a  
    Append Operators of 'src_block_desc' to current block.

    Args:
        block(Block): append OP of  'src_block_desc' to it.
        src_block_desc(BlockDesc): append var of  'src_block_desc'

    Returns:
        List: list of the OP that are append to current block.
    )r-   r0   r4   append_op_from_desc_staticr1   )r/   src_block_descr   r?   r    r    r!   r+    s   r+  c                 C   sB   |  }| j }|| tj| ||dddd}| j| |S )z
    Append Operators to 'block' according to 'op_desc'.

    Args:
        block(Block): append OP of  'src_block_desc' to it.
        op_desc(OpDesc): create OP according to it.

    Returns:
        Operator: OP appended to 'block'.
    N)r/   ru   r#   r   r   r   )r#   ru   r*  Z	copy_fromr   Operatorr   r4   )r/   Zop_descZop_typeZ	op_appendr1   r    r    r!   r1    s   

r1  c                 C   s   g }|  D ]r}| }|du s||v o|du p||v}| |sx|rx| }|tjjjtjjjtjjj	fv r@|
 }	| }
nd}	d}
|tjjjtjjj	fv rU| }nd}| ra| j }n| }||j| |	||
|| | d q|S )a*  
    Append Variables of 'src_block_desc' to current block.
    If 'include' is not `None`,variables that are not in include are not append.
    If 'exclude' is not `None`,variables that are in exclude will are not append.

    Args:
        block(Block): append Variables of  'src_block_desc' to it.
        src_block_desc(BlockDesc): append var of  'src_block_desc'
        include(List):list of names of variables
        exclude(List):list of names of variables

    Returns:
        List: list of the variables that are append to current block.
    N)r2   r   r#   r   	lod_levelr'   Zset_need_check_feed)r=   r2   rh   r#   r   r$   r%   ZSELECTED_ROWSr   ZLOD_TENSOR_ARRAYr   r   r4  r'   r   r   r4   r   Zneed_check_feed)r/   r2  rj   rk   Zvars_appendr(   Zvar_desc_nameZshould_appendZvar_typeZ	data_typeZ	var_shaper4  Zcurrent_blockr    r    r!   r)    sN   

r)  c                       sx   e Zd ZdZ fddZeejdddZedd Z	d	d
 Z
dd ZdddZdddZdddZdddZ  ZS )r   a  
    TranslatedLayer is a ``paddle.nn.Layer`` for holding the model
    loaded by :ref:`api_paddle_jit_load` . It can be used like a
    general Layer object in eval or train mode.

    .. note:
        The TranslatedLayer objects should not be created by constructor, it only can be loaded and constructed by :ref:`api_paddle_jit_load` .

    Examples:
        .. code-block:: python

            import numpy as np
            import paddle
            import paddle.nn as nn
            import paddle.optimizer as opt

            BATCH_SIZE = 16
            BATCH_NUM = 4
            EPOCH_NUM = 4

            IMAGE_SIZE = 784
            CLASS_NUM = 10

            # define a random dataset
            class RandomDataset(paddle.io.Dataset):
                def __init__(self, num_samples):
                    self.num_samples = num_samples

                def __getitem__(self, idx):
                    image = np.random.random([IMAGE_SIZE]).astype('float32')
                    label = np.random.randint(0, CLASS_NUM - 1, (1, )).astype('int64')
                    return image, label

                def __len__(self):
                    return self.num_samples

            class LinearNet(nn.Layer):
                def __init__(self):
                    super(LinearNet, self).__init__()
                    self._linear = nn.Linear(IMAGE_SIZE, CLASS_NUM)

                @paddle.jit.to_static
                def forward(self, x):
                    return self._linear(x)

            def train(layer, loader, loss_fn, opt):
                for epoch_id in range(EPOCH_NUM):
                    for batch_id, (image, label) in enumerate(loader()):
                        out = layer(image)
                        loss = loss_fn(out, label)
                        loss.backward()
                        opt.step()
                        opt.clear_grad()
                        print("Epoch {} batch {}: loss = {}".format(
                            epoch_id, batch_id, np.mean(loss.numpy())))

            # 1. train & save model.

            # create network
            layer = LinearNet()
            loss_fn = nn.CrossEntropyLoss()
            adam = opt.Adam(learning_rate=0.001, parameters=layer.parameters())

            # create data loader
            dataset = RandomDataset(BATCH_NUM * BATCH_SIZE)
            loader = paddle.io.DataLoader(dataset,
                batch_size=BATCH_SIZE,
                shuffle=True,
                drop_last=True,
                num_workers=2)

            # train
            train(layer, loader, loss_fn, adam)

            # save
            model_path = "linear.example.model"
            paddle.jit.save(layer, model_path)

            # 2. load model as TranslatedLayer

            # load
            translated_layer = paddle.jit.load(model_path)

            # inference
            translated_layer.eval()
            x = paddle.randn([1, IMAGE_SIZE], 'float32')
            pred = translated_layer(x)

            # fine-tune
            translated_layer.train()
            adam = opt.Adam(learning_rate=0.001, parameters=translated_layer.parameters())
            train(translated_layer, loader, loss_fn, adam)

    c                    s   t t|   t|tstdt|tstd|| _t | _t	 G |
 D ]:\}}t|tjtjfrFtt}|| j|< | || q)t|tjtjjfr`tt}|| j|< | || q)tdW d    n1 snw   Y  d| _d | _d S )NzETranslatedLayer need to use _ProgramHolder's dict for initialization.zITranslatedLayer need to use persistable variable dict for initialization.z?Adding persistent variable which  to layer is not supported nowT)r   r   r   r  rT   r  _program_holder_dictr  r   guardr   r   r   r   rR   PARAMETER_NAME_PREFIXZadd_parameterr   r  r	  r
  BUFFER_NAME_PREFIXZregister_bufferr  r  )r   r  r>   r2   rA   Zdy_namer   r    r!   r     s<   

	



zTranslatedLayer.__init__Nc           	      C   s   t j| } t j| std|  d }d }|d ur |j}|j}t| |}t| ||}t	||}|
 D ]\}}|jd u rFdd |jD |_tt	|t	|| q4|  |S )Nz There is no directory named '%s'c                 S   r  r    r   r  r    r    r!   rs     r  z.TranslatedLayer._construct.<locals>.<listcomp>)r   r   normpathisdirr   r   r   r  r  r   r   r  r   setattr_execution_method_creatoreval)	r   Zconfigsr   r   r  r>   Ztranslated_layerr  r   r    r    r!   
_construct  s6   


	zTranslatedLayer._constructc                    s    fdd |  _  S )Nc                    s@   | j  j }t rt| ||S tjt|j	}t
|||jS r9   )r5  r   r   r  r   rt   Z_construct_from_descr   r   r   r$  ru   )r   r   r   p__i_m_p_l__r    r!   rA    s   
z>TranslatedLayer._execution_method_creator.<locals>.__i_m_p_l__)r   )r  r   r    r@  r!   r<    s   z)TranslatedLayer._execution_method_creatorc                 C      d| _ d| _d S r*   r  Ztrainingr   r    r    r!   train     
zTranslatedLayer.trainc                 C   rB  )NTFrC  r   r    r    r!   r=    rE  zTranslatedLayer.evalr   c                 C   s   |  |}|j}t|}|S )a  
        Gets translated program of specified method.

        Args:
            - method_name (string): mehtod name corresponding to the program
                to be obtained. Default: 'forward'.

        Returns:
            Program

        Examples:
            .. code-block:: python

                import numpy as np
                import paddle
                import paddle.nn as nn
                import paddle.optimizer as opt

                BATCH_SIZE = 16
                BATCH_NUM = 4
                EPOCH_NUM = 4

                IMAGE_SIZE = 784
                CLASS_NUM = 10

                # define a random dataset
                class RandomDataset(paddle.io.Dataset):
                    def __init__(self, num_samples):
                        self.num_samples = num_samples

                    def __getitem__(self, idx):
                        image = np.random.random([IMAGE_SIZE]).astype('float32')
                        label = np.random.randint(0, CLASS_NUM - 1, (1, )).astype('int64')
                        return image, label

                    def __len__(self):
                        return self.num_samples

                class LinearNet(nn.Layer):
                    def __init__(self):
                        super(LinearNet, self).__init__()
                        self._linear = nn.Linear(IMAGE_SIZE, CLASS_NUM)

                    @paddle.jit.to_static
                    def forward(self, x):
                        return self._linear(x)

                def train(layer, loader, loss_fn, opt):
                    for epoch_id in range(EPOCH_NUM):
                        for batch_id, (image, label) in enumerate(loader()):
                            out = layer(image)
                            loss = loss_fn(out, label)
                            loss.backward()
                            opt.step()
                            opt.clear_grad()
                            print("Epoch {} batch {}: loss = {}".format(
                                epoch_id, batch_id, np.mean(loss.numpy())))

                # create network
                layer = LinearNet()
                loss_fn = nn.CrossEntropyLoss()
                adam = opt.Adam(learning_rate=0.001, parameters=layer.parameters())

                # create data loader
                dataset = RandomDataset(BATCH_NUM * BATCH_SIZE)
                loader = paddle.io.DataLoader(dataset,
                    batch_size=BATCH_SIZE,
                    shuffle=True,
                    drop_last=True,
                    num_workers=2)

                # train
                train(layer, loader, loss_fn, adam)

                # save
                model_path = "linear.example.model"
                paddle.jit.save(layer, model_path)

                # load
                translated_layer = paddle.jit.load(model_path)

                # get program
                program = translated_layer.program()
        )_get_program_holderr   rx   )r   r  r   r   r   r    r    r!   r     s   
VzTranslatedLayer.programc                 C   s&   | j |d }|d u rtd| |S )Nz9The method `%s` does not exist in loaded TranslatedLayer.)r5  r   r   )r   r  r   r    r    r!   rF  f  s   z#TranslatedLayer._get_program_holderc                 C   F   |  |}g }|jD ]}tjj| | | d}|| q
|S N)r   r   r2   )	rF  r   r   r   	InputSpecr   r   r2   r4   )r   r  r   Z
input_specr(   specr    r    r!   _input_speco  s   

zTranslatedLayer._input_specc                 C   rG  rH  )	rF  r   r   r   rI  r   r   r2   r4   )r   r  r   Zoutput_specr(   rJ  r    r    r!   _output_spec  s   

zTranslatedLayer._output_specr9   )r   )r   r   r   r   r   staticmethodr   Zdygraph_onlyr>  r<  rD  r=  r   rF  rK  rL  r   r    r    r   r!   r   4  s    _+)


_
	)NNr9   )NT)I
__future__r   r   r+   r   numpyr  r   r   rI   Zpaddle.fluidr   r   r   r   Zpaddle.fluid.dygraphr   Zpaddle.fluid.layersr	   Zpaddle.fluid.layers.utilsr
   Zpaddle.fluid.dygraph.baser   Zpaddle.fluid.frameworkr   Zpaddle.fluid.executorr   r   Z6paddle.fluid.dygraph.dygraph_to_static.partial_programr   r   r   r   __all__r   r  ZINFER_PARAMS_INFO_SUFFIXZINFER_PROPERTY_SUFFIXrH   r7  r8  r"   r)   r8   r@   rB   rF   rN   rR   rZ   r\   r^   rn   rx   r}   objectr~   r   r   r   r  r  r  r  r$  r&  r!  r"  r+  r1  r)  ZLayerr   r    r    r    r!   <module>   s   	



	 

  
OJ
0
. 4
U

>