U
    5AfD                     @   sH  d Z ddlZddlZddlmZmZmZmZmZm	Z	 erDddl
mZ G dd dejZeee  eee  eee  dd	d
Zeee  ee	ee ee f  ee dddZeee  ee	ee ee f  ee eee ee f dddZG dd dZG dd dZdd Zeeee ee	edf  ee dddZdS )zACollection of utils to be used by backbones and their components.    N)TYPE_CHECKINGIterableListOptionalTupleUnion   )PretrainedConfigc                   @   s   e Zd ZdZdZdS )BackboneTypeZtimmtransformersN)__name__
__module____qualname__TIMMTRANSFORMERS r   r   E/tmp/pip-unpacked-wheel-zw5xktn0/transformers/utils/backbone_utils.pyr
      s   r
   out_featuresout_indicesstage_namesc                    s  dkrt d dk	rt tfs6t dt  tfdd D r`t d d  t tt krt d    fd	d
D  }krt d| d  |dk	rt|tst dt| tfdd|D }tfdd|D rt d d| t|tt|kr^d| }|||krPd| dnd7 }t ||tt|krdd
 tt	||dd dD }t d| d|  dk	r|dk	rt t|krt d fdd
|D krt ddS )zW
    Verify that out_indices and out_features are valid for the given stage_names.
    Nz2Stage_names must be set for transformers backbonesz out_features must be a list got c                 3   s   | ]}| kV  qd S Nr   .0Zfeatr   r   r   	<genexpr>,   s     z2verify_out_features_out_indices.<locals>.<genexpr>z.out_features must be a subset of stage_names: z got z2out_features must not contain any duplicates, got c                    s   g | ]}| kr|qS r   r   r   r   r   r   
<listcomp>0   s      z3verify_out_features_out_indices.<locals>.<listcomp>z@out_features must be in the same order as stage_names, expected z out_indices must be a list, got c                 3   s&   | ]}|d k r|t   n|V  qdS )r   Nlenr   idxr   r   r   r   9   s     c                 3   s"   | ]}|t t kr|V  qd S r   )ranger   r    r   r   r   r   :   s      z2out_indices must be valid indices for stage_names z, got z1out_indices must not contain any duplicates, got z(equivalent to z)) c                 S   s   g | ]\}}|qS r   r   )r   _r!   r   r   r   r   A   s     c                 S   s   | d S )Nr   r   )xr   r   r   <lambda>A       z1verify_out_features_out_indices.<locals>.<lambda>)keyz?out_indices must be in the same order as stage_names, expected zHout_features and out_indices should have the same length if both are setc                    s   g | ]} | qS r   r   r    r   r   r   r   I   s     zQout_features and out_indices should correspond to the same stages if both are set)

ValueError
isinstancelisttypeanyr   settuplesortedzip)r   r   r   Zsorted_featsZpositive_indicesmsgZsorted_negativer   )r   r   r   verify_out_features_out_indices    sB    


 r3   c                    sx   |dkr*| dkr*t  d g} d g} nF|dkrN| dk	rN fdd| D }n"| dkrp|dk	rp fdd|D } | |fS )a  
    Finds the corresponding `out_features` and `out_indices` for the given `stage_names`.

    The logic is as follows:
        - `out_features` not set, `out_indices` set: `out_features` is set to the `out_features` corresponding to the
        `out_indices`.
        - `out_indices` not set, `out_features` set: `out_indices` is set to the `out_indices` corresponding to the
        `out_features`.
        - `out_indices` and `out_features` not set: `out_indices` and `out_features` are set to the last stage.
        - `out_indices` and `out_features` set: input `out_indices` and `out_features` are returned.

    Args:
        out_features (`List[str]`): The names of the features for the backbone to output.
        out_indices (`List[int]` or `Tuple[int]`): The indices of the features for the backbone to output.
        stage_names (`List[str]`): The names of the stages of the backbone.
    N   c                    s   g | ]}  |qS r   )index)r   Zlayerr   r   r   r   f   s     z9_align_output_features_output_indices.<locals>.<listcomp>c                    s   g | ]} | qS r   r   r    r   r   r   r   h   s     r   r   r   r   r   %_align_output_features_output_indicesM   s    r7   )r   r   r   returnc                 C   sJ   |dk	rt |nd}t| ||d t| ||d\}}t|||d ||fS )a`  
    Get the `out_features` and `out_indices` so that they are aligned.

    The logic is as follows:
        - `out_features` not set, `out_indices` set: `out_features` is set to the `out_features` corresponding to the
        `out_indices`.
        - `out_indices` not set, `out_features` set: `out_indices` is set to the `out_indices` corresponding to the
        `out_features`.
        - `out_indices` and `out_features` not set: `out_indices` and `out_features` are set to the last stage.
        - `out_indices` and `out_features` set: they are verified to be aligned.

    Args:
        out_features (`List[str]`): The names of the features for the backbone to output.
        out_indices (`List[int]` or `Tuple[int]`): The indices of the features for the backbone to output.
        stage_names (`List[str]`): The names of the stages of the backbone.
    Nr   )r+   r3   r7   )r   r   r   Zoutput_featuresZoutput_indicesr   r   r   *get_aligned_output_features_output_indicesl   s      
r9   c                       s   e Zd ZU dZee ed< ddddZddddZdddd	Z	e
d
d Zejee dddZe
dd Zejeee ee f dddZe
dd Ze
dd Zdd Zdee ee ee dddZ fddZ  ZS )BackboneMixinNbackbone_type)r8   c                 C   s   t | dddkrtddd | jjjD | _dd | jjjD | _t| jjj}| jj	 }t
||| jd || | _| _dS )zo
        Initialize the backbone model from timm The backbone must already be loaded to self._backbone
        	_backboneNz=self._backbone must be set before calling _init_timm_backbonec                 S   s   g | ]}|d  qS )moduler   r   stager   r   r   r      s     z5BackboneMixin._init_timm_backbone.<locals>.<listcomp>c                 S   s   g | ]}|d  qS )Znum_chsr   r>   r   r   r   r      s     r   )getattrr)   r<   Zfeature_infoinfor   num_featuresr+   r   module_namer3   _out_features_out_indices)selfconfigr   r   r   r   r   _init_timm_backbone   s      z!BackboneMixin._init_timm_backbonec                 C   sH   t |d}t |dd }t |dd }|| _t|||d\| _| _d | _d S )Nr   r   r   r   )r@   r   r9   rD   rE   rB   )rF   rG   r   r   r   r   r   r   _init_transformers_backbone   s    
  z)BackboneMixin._init_transformers_backbonec                 C   sn   || _ t|dd| _| jr tjntj| _| jtjkr@| | n*| jtjkrX| | nt	d| j ddS )z
        Method to initialize the backbone. This method is called by the constructor of the base class after the
        pretrained model weights have been loaded.
        use_timm_backboneFzbackbone_type z not supported.N)
rG   r@   rJ   r
   r   r   r;   rH   rI   r)   )rF   rG   r   r   r   _init_backbone   s    zBackboneMixin._init_backbonec                 C   s   | j S r   rD   rF   r   r   r   r      s    zBackboneMixin.out_featuresr   c                 C   s   t |d| jd\| _| _dS z
        Set the out_features attribute. This will also update the out_indices attribute to match the new out_features.
        Nr   r9   r   rD   rE   rF   r   r   r   r   r      s
      c                 C   s   | j S r   rE   rM   r   r   r   r      s    zBackboneMixin.out_indicesr   c                 C   s   t d|| jd\| _| _dS z
        Set the out_indices attribute. This will also update the out_features attribute to match the new out_indices.
        Nr   rO   rF   r   r   r   r   r      s
      c                    s    fddt  jD S )Nc                    s   i | ]\}}| j | qS r   )rB   )r   ir?   rM   r   r   
<dictcomp>   s      z6BackboneMixin.out_feature_channels.<locals>.<dictcomp>)	enumerater   rM   r   rM   r   out_feature_channels   s    z"BackboneMixin.out_feature_channelsc                    s    fdd j D S )Nc                    s   g | ]} j | qS r   )rX   )r   namerM   r   r   r      s     z*BackboneMixin.channels.<locals>.<listcomp>r   rM   r   rM   r   channels   s    zBackboneMixin.channelsc                    s2   t t| jj  fdd| D }| ||S )Nc                    s   i | ]\}}| kr||qS r   r   )r   kv	signaturer   r   rV      s       z>BackboneMixin.forward_with_filtered_kwargs.<locals>.<dictcomp>)dictinspectr^   forward
parametersitems)rF   argskwargsZfiltered_kwargsr   r]   r   forward_with_filtered_kwargs   s    z*BackboneMixin.forward_with_filtered_kwargs)output_hidden_statesoutput_attentionsreturn_dictc                 C   s   t dd S )Nz7This method should be implemented by the derived class.)NotImplementedError)rF   Zpixel_valuesrg   rh   ri   r   r   r   ra      s    zBackboneMixin.forwardc                    s*   t   }|d|d< |d|d< |S z
        Serializes this instance to a Python dictionary. Override the default `to_dict()` from `PretrainedConfig` to
        include the `out_features` and `out_indices` attributes.
        rD   r   rE   r   superto_dictpoprF   output	__class__r   r   rn      s    
zBackboneMixin.to_dict)NNN)r   r   r   r;   r   r
   __annotations__rH   rI   rK   propertyr   setterr   strr   r   r   intrX   rZ   rf   boolra   rn   __classcell__r   r   rr   r   r:      s4   


 

   	r:   c                       st   e Zd ZdZedd Zejee dddZedd Z	e	je
ee ee f dd	dZ	 fd
dZ  ZS )BackboneConfigMixinzv
    A Mixin to support handling the `out_features` and `out_indices` attributes for the backbone configurations.
    c                 C   s   | j S r   rL   rM   r   r   r   r     s    z BackboneConfigMixin.out_featuresr   c                 C   s   t |d| jd\| _| _dS rN   rO   rP   r   r   r   r   
  s
      c                 C   s   | j S r   rQ   rM   r   r   r   r     s    zBackboneConfigMixin.out_indicesrR   c                 C   s   t d|| jd\| _| _dS rS   rO   rT   r   r   r   r     s
      c                    s*   t   }|d|d< |d|d< |S rk   rl   rp   rr   r   r   rn      s    
zBackboneConfigMixin.to_dict)r   r   r   __doc__ru   r   rv   r   rw   r   r   r   rx   rn   rz   r   r   rr   r   r{     s   

 r{   c           	      C   s^  ddl m}m} t| dd}t| dd}t| dd}t| dd}t| dd}|dkrXi n|}|rp|dk	rptd	|dk	r|dk	r|dk	rtd
|dkr|dkr|dkr|dkr|jf d| i|S |r|dkrtd|j|f||d|}nh|r|dkr
td|j|f|}n@|dkr6|dkr6td|dkrN|j|f|}|j|d}|S )a>  
    Loads the backbone model from a config object.

    If the config is from the backbone model itself, then we return a backbone model with randomly initialized
    weights.

    If the config is from the parent model of the backbone model itself, then we load the pretrained backbone weights
    if specified.
    r   )AutoBackbone
AutoConfigbackbone_configNrJ   use_pretrained_backbonebackbonebackbone_kwargs?You can't specify both `backbone_kwargs` and `backbone_config`.z>Cannot specify both config.backbone_config and config.backbonerG   z8config.backbone must be set if use_timm_backbone is True)rJ   r   z>config.backbone must be set if use_pretrained_backbone is Truez<Either config.backbone_config or config.backbone must be set)rG   )r   r}   r~   r@   r)   Zfrom_configZfrom_pretrained)	rG   r}   r~   r   rJ   r   Zbackbone_checkpointr   r   r   r   r   load_backbone+  sR    


r   r	   rJ   r   r   r   r   c                 C   sL   |dk	r|dk	rt d|dk	r,| r,t d|dk	rH|rH|dk	rHt ddS )zR
    Verify that the config arguments to be passed to load_backbone are valid
    Nz8You can't specify both `backbone` and `backbone_config`.zAYou can't specify both `backbone_config` and `use_timm_backbone`.r   )r)   r   r   r   r    verify_backbone_config_argumentsh  s    
r   )r|   enumr`   typingr   r   r   r   r   r   Zconfiguration_utilsr	   Enumr
   rw   rx   r3   r7   r9   r:   r{   r   ry   r_   r   r   r   r   r   <module>   s8    
 
 
.
 
 u*>