o
    NeC                     @   sr   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 g Zd	ddZe
 d	ddZdS )
    N)	InputSpec)no_grad)OrderedDictc                    s  |du r|du rt d|du ra|durat|rt|j}nBt|ttfr6g }|D ]
}|t|j q*n+t|trOg }|	 D ]}|t|| j qAnt|tj
jjr]t|j}nt dt|trlt|j}nCt|trg }|D ]-}t|tr|f}t|ttfsJ dt|t|tr|t|j qu|| qunt|tr|f}n|}t std d}n| j}|r|   dd d	d
  fdd  |}t| |||\}	}
t|	 |r|   |
S )a  Prints a string summary of the network.

    Args:
        net (Layer): the network which must be a subinstance of Layer.
        input_size (tuple|InputSpec|list[tuple|InputSpec], optional): size of input tensor. if model only 
                    have one input, input_size can be tuple or InputSpec. if model
                    have multiple input, input_size must be a list which contain 
                    every input's shape. Note that input_size only dim of
                    batch_size can be None or -1. Default: None. Note that 
                    input_size and input cannot be None at the same time.
        dtypes (str, optional): if dtypes is None, 'float32' will be used, Default: None.
        input: the input tensor. if input is given, input_size and dtype will be ignored, Default: None.

    Returns:
        Dict: a summary of the network including total params and total trainable params.

    Examples:
        .. code-block:: python

            import paddle
            import paddle.nn as nn

            class LeNet(nn.Layer):
                def __init__(self, num_classes=10):
                    super(LeNet, self).__init__()
                    self.num_classes = num_classes
                    self.features = nn.Sequential(
                        nn.Conv2D(
                            1, 6, 3, stride=1, padding=1),
                        nn.ReLU(),
                        nn.MaxPool2D(2, 2),
                        nn.Conv2D(
                            6, 16, 5, stride=1, padding=0),
                        nn.ReLU(),
                        nn.MaxPool2D(2, 2))

                    if num_classes > 0:
                        self.fc = nn.Sequential(
                            nn.Linear(400, 120),
                            nn.Linear(120, 84),
                            nn.Linear(
                                84, 10))

                def forward(self, inputs):
                    x = self.features(inputs)

                    if self.num_classes > 0:
                        x = paddle.flatten(x, 1)
                        x = self.fc(x)
                    return x

            lenet = LeNet()

            params_info = paddle.summary(lenet, (1, 1, 28, 28))
            print(params_info)

            # multi input demo
            class LeNetMultiInput(LeNet):

                def forward(self, inputs, y):
                    x = self.features(inputs)

                    if self.num_classes > 0:
                        x = paddle.flatten(x, 1)
                        x = self.fc(x + y)
                    return x
            
            lenet_multi_input = LeNetMultiInput()

            params_info = paddle.summary(lenet_multi_input, [(1, 1, 28, 28), (1, 400)], 
                                        dtypes=['float32', 'float32'])
            print(params_info)

            # list input demo
            class LeNetListInput(LeNet):

                def forward(self, inputs):
                    x = self.features(inputs[0])

                    if self.num_classes > 0:
                        x = paddle.flatten(x, 1)
                        x = self.fc(x + inputs[1])
                    return x
            
            lenet_list_input = LeNetListInput()
            input_data = [paddle.rand([1, 1, 28, 28]), paddle.rand([1, 400])]
            params_info = paddle.summary(lenet_list_input, input=input_data)
            print(params_info)

            # dict input demo
            class LeNetDictInput(LeNet):

                def forward(self, inputs):
                    x = self.features(inputs['x1'])

                    if self.num_classes > 0:
                        x = paddle.flatten(x, 1)
                        x = self.fc(x + inputs['x2'])
                    return x

            lenet_dict_input = LeNetDictInput()
            input_data = {'x1': paddle.rand([1, 1, 28, 28]),
                          'x2': paddle.rand([1, 400])}
            params_info = paddle.summary(lenet_dict_input, input=input_data)
            print(params_info)

    Nz4input_size and input cannot be None at the same timezcInput is not tensor, list, tuple and dict, unable to determine input_size, please input input_size.zbWhen input_size is list,             expect item in input_size is a tuple or InputSpec, but got {}zTYour model was created in static mode, this may not get correct summary information!Fc                 S   s"   | D ]}t |ttfr dS qdS NFT
isinstancelisttuple)shapeitem r   ID:\Projects\ConvertPro\env\Lib\site-packages\paddle/hapi/model_summary.py	_is_shape   s
   zsummary.<locals>._is_shapec                 S   s   d}g }t t| D ]3}| | }|d u s|dkr'|d7 }|dkr$tdd}nt|tjr8|dkr8td||| q
t|S )Nr      z?Option input_size only the dim of batch_size can be None or -1.z<Expected element in input size greater than zero, but got {})	rangelen
ValueErrorr   numbersNumberformatappendr	   )r
   Znum_unknownZ	new_shapeir   r   r   r   _check_shape   s&   zsummary.<locals>._check_shapec                    s0   t | ttfr| r| S  fdd| D S )Nc                       g | ]} |qS r   r   .0r   )_check_inputr   r   
<listcomp>       z1summary.<locals>._check_input.<locals>.<listcomp>r   )
input_sizer   r   r   r   r   r      s   zsummary.<locals>._check_input)r   paddleZ	is_tensorr	   r
   r   r   r   dictkeysfluidZ	frameworkVariabler   intr   typein_dynamic_modewarningswarnZtrainingevalsummary_stringprinttrain)netr    dtypesinputxkeyZ_input_sizer   Zin_train_moderesultZparams_infor   r!   r   summary   sv   l






r6   c                    sd  dd   fddt |ttfs||}d}d}tt fddfd	d
	fdd}t |trB|g} fddt 	g | |d ur^|}| n	||}|  D ]}|  qidd }	|		}
|d|
d  d 7 }dd|
d d|
d d|
d d|
d }||d 7 }|d|
d  d 7 }d}d}d}d}	D ]{}d||
d t		| d |
d t		| d  |
d d!	| d" |
d }|	| d" 7 }z|t
t
j	| d  d#d$7 }W n   	| d  D ]}|t
t
j|d#d$7 }qY d%	| v r%	| d% d&kr%|	| d' 7 }||d 7 }q fd(d)|d}td*| d+ d, }t|d+ d, }|| | }|d|
d  d 7 }|d-|d 7 }|d.|d 7 }|d/|| d 7 }|d|
d  d 7 }|d0| d 7 }|d1| d 7 }|d2| d 7 }|d3| d 7 }|d|
d  d 7 }|||d4fS )5Nc                 S   s    | D ]}t |tjs dS qdS r   )r   r   r   )itemsr   r   r   r   _all_is_numper   s
   z&summary_string.<locals>._all_is_numperc                    s<    d u rd t | ttfr| r gS  fdd| D S )NZfloat32c                       g | ]} |qS r   r   r   )_build_dtypesdtyper   r   r          z9summary_string.<locals>._build_dtypes.<locals>.<listcomp>r   )r    r;   )r8   r:   )r;   r   r:      s
   z%summary_string.<locals>._build_dtypesr    c                    sF   t | tjjtjjjfrt| jS t | ttfr! fdd| D S d S )Nc                    r   r   r   )r   xx_get_shape_from_tensorr   r   r     r   zBsummary_string.<locals>._get_shape_from_tensor.<locals>.<listcomp>)	r   r"   r%   r&   coreZVarBaser   r
   r	   )r3   r?   r   r   r@     s
   
z.summary_string.<locals>._get_shape_from_tensorc                    sD   t | ttfr fdd| D }|S t| drt| j}|S g }|S )Nc                    r   r   r   )r   o_get_output_shaper   r   r     r   z=summary_string.<locals>._get_output_shape.<locals>.<listcomp>r
   )r   r   r	   hasattrr
   )outputoutput_shaperC   r   r   rD   	  s   

z)summary_string.<locals>._get_output_shapec                    sx    fdd}t | tjs&t | tjs&| krdk r&| | d S t| dr8| jr:| | d S d S d S )Nc                    s  t | jdd dd }zt| jdd }W n   t}Y d||d f }t |< z
|| d< W n   td	 g | d< Y z
 || d
< W n   td | d
  Y d}t	
 ro| j}n|  }d| d< d}| D ]H\}	}
|t|
j7 }z1tt| |	drtt| |	ds| d  t|
j7  < d| d< d}n|sd| d< W q   d| d< Y q|| d< d S )N.r   'r   _z%s-%ir   input_shapez Get layer {} input shape failed!rG   z!Get layer {} output shape failed!trainable_paramsF	trainableZstop_gradientT	nb_params)str	__class__splitr'   Z
_full_namer   r   r*   r+   r"   r)   _parametersZ
state_dictr7   npprodr
   getattr)layerr2   rF   
class_nameZ	layer_idxZm_keyparamsZlayer_state_dictZtrainable_flagkv)rD   r@   r6   r   r   hook  sL   



z3summary_string.<locals>.register_hook.<locals>.hookr   could_use_cudnn)r   nnZ
SequentialZ	LayerListr   Zregister_forward_post_hookrE   r\   )rV   r[   )rD   r@   depthhooksmodelr6   r   r   register_hook  s   0
z%summary_string.<locals>.register_hookc                    s`   t | ttfr$ | r$t |ttfr|d }n|}ttt| |S fddt| |D S )Nr   c                    s   g | ]	\}} ||qS r   r   )r   r   r;   )build_inputr   r   r   X  s    z7summary_string.<locals>.build_input.<locals>.<listcomp>)r   r   r	   r"   castZrandzip)r    r1   r;   )r8   rb   r   r   rb   P  s   

z#summary_string.<locals>.build_inputc                 S   s   dddddd}| D ]b}|d t t| | d k r&t t| | d |d< |d t t| | d k r@t t| | d |d< |d	 t t|k rRt t||d	< |d
 t t| | d k rlt t| | d |d
< q
d}| D ]\}}|dkr||7 }qs|d |d k r|d |d< |S )N      K   )layer_widthinput_shape_widthoutput_shape_widthparams_widthtable_widthrj   rG   ri   rK   rh   rk   rN   r   rl      )r   rO   r7   )r6   Zhead_lengthrV   Z_temp_widthrY   rZ   r   r   r   _get_str_lengthm  sH   z'summary_string.<locals>._get_str_length-rl   
z{:^{}} {:^{}} {:^{}} {:^{}}zLayer (type)rh   zInput Shaperi   zOutput Shaperj   zParam #rk   =r   rK   rG   z{0:,}rN   r   )ZaxisrM   TrL   c                    sL   t | ttfr| rtt| d d   S t fdd| D   S )N      @      0Ac                    r9   r   r   r   )_get_input_sizesizer   r   r     r<   z;summary_string.<locals>._get_input_size.<locals>.<listcomp>)r   r   r	   absrS   rT   sum)r    ru   )r8   rt   )ru   r   rt     s
   z'summary_string.<locals>._get_input_sizeg       @rr   rs   zTotal params: {0:,}zTrainable params: {0:,}zNon-trainable params: {0:,}zInput size (MB): %0.2fz&Forward/backward pass size (MB): %0.2fzParams size (MB): %0.2fz Estimated Total Size (MB): %0.2f)total_paramsrL   )r   r   r	   r   Z	sublayersr   applyremover   rO   rS   rw   rT   rv   )r`   r    r1   r2   Z
batch_sizeZsummary_strra   r3   hrn   rl   Zline_newrx   Ztotal_outputrL   
max_lengthrV   rG   Ztotal_input_sizeZtotal_output_sizeZtotal_params_size
total_sizer   )
r8   r:   rt   rD   r@   rb   r^   r_   r`   r6   r   r-      s   	
	
;



#




r-   )NNN)r*   numpyrS   r   r"   Z	paddle.nnr]   Zpaddle.staticr   Zpaddle.autogradr   collectionsr   __all__r6   r-   r   r   r   r   <module>   s   
 M