o
    pi                     @   sX   d dl mZmZmZmZmZ d dlmZmZ d dl	m
Z
 d dlmZ G dd deZdS )    )ListMappingOptionalTextUnion)CallbackTrainer)ModelSummary)Modelc                       sx   e Zd ZdZ		ddeeeef eeee ef  f de	e f fddZ
dedefd	d
ZdedefddZ  ZS )GraduallyUnfreezeaR  Gradually unfreeze layers

    1. Start training with all layers frozen, but those that depends on the task
       (i.e. those instantiated in model.build() and task.setup_loss_func()
    2. Train for a few epochs and unfreeze a few more layers
    3. Repeat

    Parameters
    ----------
    schedule:
        See examples for supported format.
    epochs_per_stage : int, optional
        Number of epochs between each stage. Defaults to 1.
        Has no effect if schedule is provided as a {layer_name: epoch} dictionary.

    Usage
    -----
    >>> callback = GraduallyUnfreeze()
    >>> Trainer(callbacks=[callback]).fit(model)

    Examples
    --------
    # for a model with PyanNet architecture (sincnet > lstm > linear > task_specific),
    # those are equivalent and will unfreeze 'linear' at epoch 1, 'lstm' at epoch 2,
    # and 'sincnet' at epoch 3.
    GraduallyUnfreeze()
    GraduallyUnfreeze(schedule=['linear', 'lstm', 'sincnet'])
    GraduallyUnfreeze(schedule={'linear': 1, 'lstm': 2, 'sincnet': 3})

    # the following syntax is also possible (with its dict-based equivalent just below):
    GraduallyUnfreeze(schedule=['linear', ['lstm', 'sincnet']], epochs_per_stage=10)
    GraduallyUnfreeze(schedule={'linear': 10, 'lstm': 20, 'sincnet': 20})
    # will unfreeze 'linear' at epoch 10, and both 'lstm' and 'sincnet' at epoch 20.
    Nscheduleepochs_per_stagec                    s8   t    |d u st|tr|d u rd}|| _|| _d S )N   )super__init__
isinstancer   r   r   )selfr   r   	__class__ P/home/ubuntu/.local/lib/python3.10/site-packages/pyannote/audio/core/callback.pyr   C   s   

zGraduallyUnfreeze.__init__trainermodelc           	         s   | j }|j  fddtt|ddjD }|d u r|}t|trGt }t|D ]\}}t|tr3|n|g}|D ]}|d | j	 ||< q8q(|}|| _ |D ]}|
| qLd S )Nc                    s   g | ]
\}}| vr|qS r   r   ).0layer_task_specific_layersr   r   
<listcomp>V   s
    z2GraduallyUnfreeze.on_fit_start.<locals>.<listcomp>r   )	max_depth)r   task_dependentreversedr	   named_modulesr   r   dict	enumerater   freeze_by_name)	r   r   r   r   backbone_layers	_scheduledepthlayersr   r   r   r   on_fit_startR   s&   

zGraduallyUnfreeze.on_fit_startc                 C   s,   | j  D ]\}}||jkr|| qd S )N)r   itemscurrent_epochunfreeze_by_name)r   r   r   r   epochr   r   r   on_train_epoch_startm   s
   

z&GraduallyUnfreeze.on_train_epoch_start)NN)__name__
__module____qualname____doc__r   r   r   intr   r   r   r   r
   r*   r/   __classcell__r   r   r   r   r      s    %"r   N)typingr   r   r   r   r   	lightningr   r   )lightning.pytorch.utilities.model_summaryr	   pyannote.audior
   r   r   r   r   r   <module>   s
   