o
    }oi@                     @   s`   d dl mZ d dlZd dlmZ d dlmZmZmZ d dl	m
Z
 dgZG dd deeeeZdS )    )contextmanagerN)Module)FileIOSerializationTyping)loggingNeuralModulec                   @   s`   e Zd ZdZedd Zejjdd Z	dddZ
dd
dZdded	dfddZedd ZdS )r   zV
    Abstract class offering interface shared between all PyTorch Neural Modules.
    c                 C   s   |   S )z_
        Utility property that returns the total number of parameters of NeuralModule.
        )_num_weights)self r   L/home/ubuntu/.local/lib/python3.10/site-packages/nemo/core/classes/module.pynum_weights   s   zNeuralModule.num_weightsc                 C   s(   d}|   D ]}|jr|| 7 }q|S )Nr   )
parametersrequires_gradnumel)r
   numpr   r   r   r	   &   s   zNeuralModule._num_weightsNc                 C   s   dS )z
        Override this method if random inputs won't work
        Returns:
            A tuple sample of valid input data.
        Nr   )r
   	max_batchmax_dimr   r   r   input_example.   s   zNeuralModule.input_examplereturnc                 C   sP   i }|   D ]\}}|j||< d|_qt| ds|| _n| j| |   dS )aJ  
        Freeze all params for inference.

        This method sets `requires_grad` to False for all parameters of the module.
        It also stores the original `requires_grad` state of each parameter in a dictionary,
        so that `unfreeze()` can restore the original state if `partial=True` is set in `unfreeze()`.
        F_frozen_grad_mapN)named_parametersr   hasattrr   updateeval)r
   grad_mappnameparamr   r   r   freeze7   s   

zNeuralModule.freezeFpartialc                 C   s   |rt | dstd|  D ]"\}}|sd|_q|| jv r%| j| |_qtd| d d|_qt | dr<t| d |   dS )a1  
        Unfreeze all parameters for training.

        Allows for either total unfreeze or partial unfreeze (if the module was explicitly frozen previously with `freeze()`).
        The `partial` argument is used to determine whether to unfreeze all parameters or only the parameters that were
        previously unfrozen prior `freeze()`.

        Example:
            Consider a model that has an encoder and a decoder module. Assume we want the encoder to be frozen always.

            ```python
            model.encoder.freeze()  # Freezes all parameters in the encoder explicitly
            ```

            During inference, all parameters of the model should be frozen - we do this by calling the model's freeze method.
            This step records that the encoder module parameters were already frozen, and so if partial unfreeze is called,
            we should keep the encoder parameters frozen.

            ```python
            model.freeze()  # Freezes all parameters in the model; encoder remains frozen
            ```

            Now, during fine-tuning, we want to unfreeze the decoder but keep the encoder frozen. We can do this by calling
            `unfreeze(partial=True)`.

            ```python
            model.unfreeze(partial=True)  # Unfreezes only the decoder; encoder remains frozen
            ```

        Args:
            partial: If True, only unfreeze parameters that were previously frozen. If the parameter was already frozen
                when calling `freeze()`, it will remain frozen after calling `unfreeze(partial=True)`.
        r   zKCannot unfreeze partially without first freezing the module with `freeze()`Tz
Parameter zN not found in list of previously frozen parameters. Unfreezing this parameter.N)	r   
ValueErrorr   r   r   r   warningdelattrtrain)r
   r    r   r   r   r   r   unfreezeO   s   "



zNeuralModule.unfreezec              	   c   sf    | j }|   zdV  W | jdd |r|   dS |   dS | jdd |r.|   w |   w )a  
        Context manager which temporarily freezes a module, yields control and finally unfreezes the module partially
        to return to original state.

        Allows for either total unfreeze or partial unfreeze (if the module was explicitly frozen previously with `freeze()`).
        The `partial` argument is used to determine whether to unfreeze all parameters or only the parameters that were
        previously unfrozen prior `freeze()`.

        Example:
            with model.as_frozen():  # by default, partial = True
                # Do something with the model
                pass

            # Model's parameters are now back to original state of requires_grad
        NT)r    )trainingr   r%   r$   r   )r
   training_moder   r   r   	as_frozen   s   

zNeuralModule.as_frozen)NN)r   N)F)__name__
__module____qualname____doc__propertyr   torchjitignorer	   r   r   boolr%   r   r(   r   r   r   r   r      s    



	=)
contextlibr   r.   torch.nnr   nemo.core.classes.commonr   r   r   
nemo.utilsr   __all__r   r   r   r   r   <module>   s   