o
    iX                     @   s.   d Z ddlZddlZddlZG dd dZdS )z|
Used for EMA tracking a given pytorch module. The user is responsible for calling step()
and setting the appropriate decay
    Nc                   @   sV   e Zd ZdZdddZdddZdd	d
Zdd Zdd Zdd Z	dd Z
dd ZdS )	EMAModulez,Exponential Moving Average of Fairseq ModelsH.?FNc                 C   sv   || _ || _t|| _| jd |pt | _i | _|dur/t	
d|  | jj|d| _| jr6|   d| _dS )a,  
        @param model model to initialize the EMA with
        @param config EMAConfig object with configuration like
        ema_decay, ema_update_freq, ema_fp32
        @param device If provided, copy EMA to this device (e.g. gpu).
        Otherwise EMA is in the same device as the model.
        FNzCopying EMA model to device )devicer   )decayema_fp32copydeepcopymodelrequires_grad_set	skip_keysfp32_paramslogginginfotobuild_fp32_paramsupdate_freq_counter)selfr	   	ema_decayr   r   r    r   U/home/ubuntu/.local/lib/python3.10/site-packages/funasr/models/data2vec/ema_module.py__init__   s   	
zEMAModule.__init__c                 C   sh   | j std|du r| j }dd }|D ]}|| jv r(| j| ||  q||| | j|< qdS )z
        Store a copy of the EMA params in fp32.
        If state dict is passed, the EMA params is copied from
        the provided state dict. Otherwise, it is copied from the
        current EMA model parameters.
        zgbuild_fp32_params should not be called if ema_fp32=False. Use ema_fp32=True if this is really intended.Nc                 S   s   t | r	|  S | S N)torchis_floating_pointfloat)tr   r   r   	_to_float=   s   z.EMAModule.build_fp32_params.<locals>._to_float)r   RuntimeErrorr	   
state_dictr   copy_)r   r   r   	param_keyr   r   r   r   -   s   

zEMAModule.build_fp32_paramsc                 C   s&   | j j|dd |r| | dS dS )z*Load data from a model spec into EMA modelFstrictN)r	   load_state_dictr   )r   r   r   r   r   r   restoreF   s   zEMAModule.restorec                 C   s
   || _ d S r   r   )r   r   r   r   r   	set_decayL   s   
zEMAModule.set_decayc                 C   s   | j S r   r&   )r   r   r   r   	get_decayO   s   zEMAModule.get_decayc              	   C   s0  | j }i }| jr| jn| j }|  D ]x\}}t|tr qz|| }W n ty?   |j	dkr8|
  nt|}Y nw |j|jkrRtdd|j|j d|v rWq|| jv sfd|v rw|jtjkrw|j|jd }|| | n|| |j|j|jdd| d |||< q| j|dd	 d
S )z6One update of the EMA model based on new model weights   z<incompatible tensor shapes between model param and ema paramz	{} vs. {}versionnum_batches_tracked)dtype)alphaF)r   N)r   r   r   r	   r   items
isinstancedictKeyErrorndimr   cloner   r   shape
ValueErrorformatr   r,   r   int64r   r    mul_add_r%   )r   	new_modelr   ema_state_dict
ema_paramskeyparam	ema_paramr   r   r   _step_internalR   s6   
$


zEMAModule._step_internalc                 C   s   |  | d S r   )r@   )r   r:   r   r   r   stepu   s   zEMAModule.stepc                 C   s*   | j  }d|v r|d= |j|dd |S )z{
        Load the model parameters from EMA model.
        Useful for inference or fine-tuning from the EMA model.
        _emaFr"   )r	   r   r$   )r   r	   dr   r   r   reversex   s
   
zEMAModule.reverse)r   FNNr   )F)__name__
__module____qualname____doc__r   r   r%   r'   r(   r@   rA   rD   r   r   r   r   r      s    


#r   )rH   r   r   r   r   r   r   r   r   <module>   s
   