Ë
    éÓ^j	u  ã                   ó¨  — d Z ddlZddlmZmZmZmZ ddlZddlm	Z	 ddl
m	c mZ ddlmZmZ ddlmZ ddlmZ  ej(                  e«      Z G d„ d	e	j.                  «      Zd
eee	j.                  ef   de	j.                  dee   deej4                     deej6                     defd„Z G d„ de«      Z G d„ de	j.                  «      Z G d„ de«      Zy)z5Knowledge distillation training tasks and components.é    N)ÚDictÚOptionalÚTupleÚUnion)Úcreate_modelÚgroup_parameters)Úunwrap_modelé   )ÚTrainingTaskc                   óÄ  ‡ — e Zd ZdZ	 	 	 	 	 ddeeej                  f   dee	   de	dee   dee
j                     dee
j                     fˆ fd„Zd	e
j                  d
e
j                  fd„Z	 	 	 	 ddedee   deded
d f
d„Z	 dd	e
j                  ded
e
j                  fd„Z	 	 dd	e
j                  dee
j                     dee
j                     d
e
j                  fd„Zˆ xZS )ÚDistillationTeacherae  Wrapper for a teacher model used in knowledge distillation.

    Creates and manages a pre-trained teacher model for knowledge distillation,
    handling model creation and normalization differences between teacher and student.

    Can be created from:
    - A model name string (creates the model internally with pretrained weights)
    - An existing nn.Module (wraps it with the necessary interface)

    Args:
        model_name_or_module: Either a model name string or an nn.Module
        num_classes: Number of output classes (required if model_name_or_module is a string)
        in_chans: Number of input channels (used if model_name_or_module is a string)
        pretrained_path: Optional path to pretrained weights (used if model_name_or_module is a string)
        device: Device to place the model on
        dtype: Model dtype (uses float32 if None)
    Úmodel_name_or_moduleÚnum_classesÚin_chansÚpretrained_pathÚdeviceÚdtypec           	      ó  •— t         ‰| �  «        t        |t        «      rAt        j                  d|› d�«       ddi}|rt        ||¬«      |d<   t        d|||||dœ|¤Ž}n>t        |t        j                  «      r|}n!t        dt        |«      j                  › �«      ‚|j                  «        || _        t        |«      }	t!        |	d	«      r9|	j"                  j%                  d
d«      }
|	j"                  j%                  dd«      }nd}
d}t'        j(                  |
||¬«      j+                  dddd«      }t'        j(                  |||¬«      j+                  dddd«      }| j-                  d|d¬«       | j-                  d|d¬«       d | _        y )NzCreating KD teacher model: 'ú'Ú
pretrainedT)Úfiler   Úpretrained_cfg_overlay)Ú
model_namer   r   r   r   z8model_name_or_module must be a string or nn.Module, got Úpretrained_cfgÚmean)g
×£p=
ß?gÉv¾Ÿ/Ý?g–C‹lçûÙ?Ústd)gZd;ßOÍ?gyé&1¬Ì?gÍÌÌÌÌÌÌ?©r   r   r
   éÿÿÿÿÚmean_kdF©Ú
persistentÚstd_kd© )ÚsuperÚ__init__Ú
isinstanceÚstrÚ_loggerÚinfoÚdictr   ÚnnÚModuleÚ	TypeErrorÚtypeÚ__name__ÚevalÚmodelr	   Úhasattrr   ÚgetÚtorchÚtensorÚviewÚregister_bufferÚ_compiled_forward_features)Úselfr   r   r   r   r   r   Úpretrained_kwargsr1   Úmodel_unwrappedr   r   r   r"   Ú	__class__s                 €úa/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/timm/task/distillation.pyr%   zDistillationTeacher.__init__%   sš  ø€ ô 	‰ÑÔäÐ*¬CÔ0Ü�L‰LÐ7Ð8LÐ7MÈQÐOÔPà!-¨tÐ 4ÐÙÜ>BØ(Ø +ô?Ð!Ð":Ñ;ô
 !ð Ø/Ø'Ø!ØØñð $ñ‰Eô Ð,¬b¯i©iÔ8Ø(‰EäØJÌ4ÐPdÓKe×KnÑKnÐJoÐpóð ð 	�
‰
ŒØˆŒ
ô ' uÓ-ˆÜ�?Ð$4Ô5Ø"×1Ñ1×5Ñ5°fÐ>SÓTˆDØ!×0Ñ0×4Ñ4°UÐ<QÓR‰Cà(ˆDØ'ˆCä—,‘,˜t¨F¸%Ô@×EÑEÀaÈÈQÐPQÓRˆÜ—‘˜c¨&¸Ô>×CÑCÀAÀrÈ1ÈaÓPˆØ×Ñ˜Y¨¸EÐÔBØ×Ñ˜X v¸%ÐÔ@Ø*.ˆÕ'ó    ÚinputÚreturnc                 ó$  — t        | j                  d«      rt        | j                  d«      s-t        d| j                  j                  j                  › d�«      ‚| j                  j                  |«      }| j                  j                  |d¬«      S )NÚforward_featuresÚforward_headzModel zi does not support feature extraction. Ensure the model has 'forward_features' and 'forward_head' methods.T©Ú
pre_logits)r2   r1   Ú
ValueErrorr<   r/   rB   rC   )r9   r?   Úfeature_maps      r=   Ú_forward_featuresz%DistillationTeacher._forward_features[   s€   € Ü�t—z‘zÐ#5Ô6¼gÀdÇjÁjÐR`Ô>aÜØ˜Ÿ™×-Ñ-×6Ñ6Ð7ð 8Vð Vóð ð —j‘j×1Ñ1°%Ó8ˆØ�z‰z×&Ñ& {¸tÐ&ÓDÐDr>   ÚbackendÚmodeÚcompile_modelÚcompile_featuresc                 ó®   — |r(t        j                  | j                  f||dœ|¤Ž| _        |r(t        j                  | j                  f||dœ|¤Ž| _        | S )z;Compile teacher inference paths used by distillation tasks.©rI   rJ   )r4   Úcompiler1   rH   r8   )r9   rI   rJ   rK   rL   Úcompile_kwargss         r=   rO   zDistillationTeacher.compiled   sa   € ñ ÜŸ™ t§z¡zÐ`¸7ÈÑ`ÐQ_Ñ`ˆDŒJÙÜ.3¯m©mØ×&Ñ&ð/àØñ/ð !ñ	/ˆDÔ+ð ˆr>   Úreturn_featuresc                 ó„   — |r.| j                   �| j                  |«      S | j                  |«      S | j                  |«      S )aG  Forward pass through teacher model.

        Args:
            input: Input tensor (should already be normalized for teacher)
            return_features: Whether to return pooled pre-logits features instead of logits

        Returns:
            Logits or pooled pre-logits features depending on return_features flag
        )r8   rH   r1   )r9   r?   rQ   s      r=   ÚforwardzDistillationTeacher.forwardx   sD   € ñ Ø×.Ñ.Ð:Ø×6Ñ6°uÓ=Ð=Ø×)Ñ)¨%Ó0Ð0à—:‘:˜eÓ$Ð$r>   Ústudent_meanÚstudent_stdc                 óÖ   — |�|€|S t        j                  || j                  «      r"t        j                  || j                  «      r|S ||z  |z   | j                  z
  | j                  z  S )ao  Normalize input to match teacher's expected normalization.

        Args:
            input: Input tensor (already normalized for student)
            student_mean: Student normalization mean buffer [1, 3, 1, 1]
            student_std: Student normalization std buffer [1, 3, 1, 1]

        Returns:
            Input tensor normalized for the teacher model
        )r4   Úequalr   r"   )r9   r?   rT   rU   s       r=   Únormalize_inputz#DistillationTeacher.normalize_input�   sa   € ð  Ð ;Ð#6ØˆLÜ�;‰;�| T§\¡\Ô2´u·{±{À;ÐPT×P[ÑP[Ô7\ØˆLØ˜Ñ# lÑ2°T·\±\ÑAÀTÇ[Á[ÑPÐPr>   )Né   NNN)ÚinductorNTF©F)NN)r/   Ú
__module__Ú__qualname__Ú__doc__r   r'   r+   r,   r   Úintr4   r   r   r%   ÚTensorrH   ÚboolrO   rS   rX   Ú__classcell__©r<   s   @r=   r   r      se  ø„ ñð* *.ØØ-1Ø-1Ø+/ñ4/à"'¨¨R¯Y©Y¨Ñ"7ð4/ð " #™ð4/ð ð	4/ð
 & c™]ð4/ð ˜UŸ\™\Ñ*ð4/ð ˜EŸK™KÑ(õ4/ðlE u§|¡|ð E¸¿¹ó Eð &Ø"&Ø"&Ø%*ñàðð ˜3‘-ðð  ð	ð
 #ðð 
óð. %*ñ%à—<‘<ð%ð "ð%ð 
�‰ó	%ð0 48Ø26ñ	Qà—<‘<ðQð # 5§<¡<Ñ0ðQð " %§,¡,Ñ/ð	Qð
 
�‰÷Qr>   r   ÚteacherÚstudent_modelr   r   r   r@   c                 óŽ   — t        | t        «      r| S t        |«      }|j                  }|j                  }t        | |||||¬«      S )a’  Resolve teacher input to a DistillationTeacher instance.

    Args:
        teacher: Model name string, nn.Module, or DistillationTeacher
        student_model: Student model to infer num_classes/in_chans from
        pretrained_path: Optional path to teacher pretrained weights
        device: Device for teacher
        dtype: Dtype for teacher

    Returns:
        DistillationTeacher instance
    )r   r   r   r   r   r   )r&   r   r	   r   r   )rd   re   r   r   r   Ústudent_unwrappedr   r   s           r=   Ú_resolve_teacherrh   ¤   sV   € ô& �'Ô.Ô/Øˆô % ]Ó3ÐØ#×/Ñ/€KØ ×)Ñ)€HäØ$ØØØ'ØØôð r>   c                   ó   ‡ — e Zd ZdZ	 	 	 	 	 	 	 	 	 ddej
                  deeej
                  ef   de	ej
                     de	e   dede	e
   de	e
   d	e
d
e	ej                     de	ej                     defˆ fd„Z	 dde	e   dd fd„Z	 	 ddede	e   dej
                  fd„Zdej&                  dej&                  deeej&                  f   fd„Zˆ xZS )ÚLogitDistillationTaska  Logit-based knowledge distillation task.

    Performs distillation by matching student and teacher output logits using
    KL divergence with temperature scaling.

    Loss weighting supports two modes:
    1. Independent weights: loss = task_loss_weight * task_loss + distill_loss_weight * distill_loss
    2. Complementary mode: loss = task_loss_weight * task_loss + (1 - task_loss_weight) * distill_loss
       (used when only task_loss_weight is specified)

    Args:
        student_model: Student model to train
        teacher_model: Teacher model - can be a model name string, nn.Module, or DistillationTeacher
        criterion: Task loss function (default: CrossEntropyLoss)
        teacher_pretrained_path: Path to teacher pretrained weights (used when teacher_model is a string)
        loss_type: Type of distillation loss (currently only 'kl' supported)
        distill_loss_weight: Weight for distillation loss
        task_loss_weight: Weight for task loss
        temperature: Softmax temperature for distillation (typical values: 1-4)
        device: Device for task tensors/buffers
        dtype: Dtype for task tensors/buffers
        verbose: Enable info logging

    Example:
        >>> # With model name string (num_classes/in_chans inferred from student)
        >>> task = LogitDistillationTask(
        ...     student_model=model, teacher_model='resnet50',
        ...     criterion=nn.CrossEntropyLoss(),
        ...     task_loss_weight=0.3, temperature=4.0,
        ...     device=torch.device('cuda'),
        ... )
        >>> # With raw model
        >>> task = LogitDistillationTask(
        ...     student_model=model, teacher_model=my_teacher_model,
        ...     criterion=nn.CrossEntropyLoss(),
        ...     task_loss_weight=0.3, temperature=4.0,
        ... )
    re   Úteacher_modelÚ	criterionÚteacher_pretrained_pathÚ	loss_typeÚdistill_loss_weightÚtask_loss_weightÚtemperaturer   r   Úverbosec                 ó”  •— t         ‰| �  |	|
|¬«       t        |||| j                  | j                  «      }|| _        || _        |�|nt        j                  «       | _	        || _
        || _        |dk7  rt        d|› d�«      ‚t        |«      }t        j                  |j                   d   | j                  | j                  ¬«      j#                  dddd«      }t        j                  |j                   d	   | j                  | j                  ¬«      j#                  dddd«      }| j%                  d
|d¬«       | j%                  d|d¬«       |�D|| _        |�|nd| _        | j*                  r´t,        j/                  d| j(                  › d|› �«       nŽ|�C|| _        d|z
  | _        | j*                  rot,        j/                  d|› d| j&                  › �«       nId| _        d| _        | j*                  r/t,        j/                  d| j(                  › d| j&                  › �«       | j*                  rt,        j/                  d|› d|› �«       y y )N©r   r   rr   ÚklzUnsupported loss_type 'z$'. Currently only 'kl' is supported.r   r   r
   r   r   rT   Fr    rU   ç      ð?z9LogitDistillationTask: Independent weights - task_weight=ú, distill_weight=z8LogitDistillationTask: Complementary mode - task_weight=z;LogitDistillationTask: Default equal weights - task_weight=z!LogitDistillationTask: loss_type=z, temperature=)r$   r%   rh   r   r   Útrainable_modulerd   r+   ÚCrossEntropyLossrl   rn   rq   rF   r	   r4   r5   r   r6   r7   ro   rp   rr   r(   r)   )r9   re   rk   rl   rm   rn   ro   rp   rq   r   r   rr   rd   rg   rT   rU   r<   s                   €r=   r%   zLogitDistillationTask.__init__ñ   sb  ø€ ô 	‰Ñ ¨e¸WÐÔEô #ØØØ#Ø�K‰KØ�J‰Jó
ˆð !.ˆÔØˆŒØ&/Ð&;™Ä×ATÑATÓAVˆŒØ"ˆŒØ&ˆÔà˜ÒÜÐ6°y°kÐAeÐfÓgÐgô )¨Ó7ÐÜ—|‘|Ø×,Ñ,¨VÑ4Ø—;‘;Ø—*‘*ô
÷ ‰$ˆq�"�a˜Ó
ð	 	ô
 —l‘lØ×,Ñ,¨UÑ3Ø—;‘;Ø—*‘*ô
÷ ‰$ˆq�"�a˜Ó
ð	 	ð
 	×Ñ˜^¨\ÀeÐÔLØ×Ñ˜]¨KÀEÐÔJð Ð*à':ˆDÔ$Ø8HÐ8TÑ$4ÐZ]ˆDÔ!Ø�|Š|Ü—‘ð#Ø#'×#8Ñ#8Ð"9Ð9JÐK^ÐJ_ðaõð Ð)à$4ˆDÔ!Ø'*Ð-=Ñ'=ˆDÔ$Ø�|Š|Ü—‘ð#Ø#3Ð"4Ð4EÀd×F^ÑF^ÐE_ðaõð (+ˆDÔ$Ø$'ˆDÔ!Ø�|Š|Ü—‘ð#Ø#'×#8Ñ#8Ð"9Ð9JÈ4×KcÑKcÐJdðfôð
 �<Š<Ü�L‰LØ3°I°;¸nÈ[ÈMÐZõð r>   Ú
device_idsr@   c                 ó’   — ddl m} | j                  j                  «       D ]	  }d|_        Œ  || j
                  fd|i|¤Ž| _        | S )aŒ  Prepare task for distributed training.

        Wraps the student model in DistributedDataParallel (DDP) while leaving
        the frozen teacher model unwrapped.

        Args:
            device_ids: List of device IDs for DDP (e.g., [local_rank])
            **ddp_kwargs: Additional arguments passed to DistributedDataParallel

        Returns:
            self (for method chaining)
        r   ©ÚDistributedDataParallelFrz   ©Útorch.nn.parallelr}   rd   Ú
parametersÚrequires_gradrx   ©r9   rz   Ú
ddp_kwargsÚDDPÚparams        r=   Úprepare_distributedz)LogitDistillationTask.prepare_distributedD  óQ   € õ" 	Eà—\‘\×,Ñ,Ó.ò 	(ˆEØ"'ˆEÕð	(ñ !$ D×$9Ñ$9Ñ _ÀjÐ _ÐT^Ñ _ˆÔØˆr>   rI   rJ   c                 óÎ   — t        j                  | j                  f||dœ|¤Ž| _        | j                  | _         | j                  j                  d||dddœ|¤Ž | j                  S )z=Compile student eval/train forward and teacher logit forward.rN   TF©rI   rJ   rK   rL   r#   )r4   rO   rx   Ú
eval_modelrd   )r9   rI   rJ   rP   s       r=   rO   zLogitDistillationTask.compile]  ss   € ô !&§¡¨d×.CÑ.CÐ rÈWÐ[_Ñ rÐcqÑ rˆÔà×/Ñ/ˆŒØˆ�‰×Ñð 	
ØØØØ"ñ		
ð
 ò	
ð ×$Ñ$Ð$r>   r?   Útargetc                 ól  — | j                  |«      }| j                  ||«      }t        j                  «       5  | j                  j                  || j                  | j                  «      }| j	                  |j                  «       d¬«      }ddd«       t        j                  || j                  z  d¬«      }t        j                  | j                  z  d¬«      }t        j                  ||dd¬«      | j                  d	z  z  }	| j                  |z  | j                  |	z  z   }
|
|||	d
œS # 1 sw Y   Œ xY w)aÁ  Forward pass with logit distillation.

        Args:
            input: Input tensor [B, C, H, W]
            target: Target labels [B]

        Returns:
            Dictionary containing:
                - 'loss': Combined training loss (task + distillation)
                - 'output': Student logits (for metrics)
                - 'task_loss': Classification loss component
                - 'kd_loss': Logit distillation loss component
        F©rQ   Nr   )ÚdimÚ	batchmeanT)Ú	reductionÚ
log_targeté   ©ÚlossÚoutputÚ	task_lossÚkd_loss)rx   rl   r4   Úno_gradrd   rX   rT   rU   ÚdetachÚFÚlog_softmaxrq   Úkl_divrp   ro   )r9   r?   r‹   Ústudent_logitsr–   Úinput_kdÚteacher_logitsÚprob_sÚprob_tr—   Ú
total_losss              r=   rS   zLogitDistillationTask.forwardp  s  € ð$ ×.Ñ.¨uÓ5ˆØ—N‘N >°6Ó:ˆ	ä�]‰]‹_ñ 	TØ—|‘|×3Ñ3°E¸4×;LÑ;LÈd×N^ÑN^Ó_ˆHØ!Ÿ\™\¨(¯/©/Ó*;ÈU˜\ÓSˆN÷	Tô —‘˜~°×0@Ñ0@Ñ@ÀbÔIˆÜ—‘˜~°×0@Ñ0@Ñ@ÀbÔIˆÜ—(‘(˜6 6°[ÈTÔRÐVZ×VfÑVfÐjkÑVkÑlˆà×*Ñ*¨YÑ6¸×9QÑ9QÐT[Ñ9[Ñ[ˆ
ð Ø$Ø"Øñ	
ð 	
÷	Tð 	Tús   ¸AD*Ä*D3)	NNru   NNrv   NNT©N©rZ   N)r/   r\   r]   r^   r+   r,   r   r'   r   r   Úfloatr4   r   r   ra   r%   Úlistr†   rO   r`   r   rS   rb   rc   s   @r=   rj   rj   É   sh  ø„ ñ%ðV .2Ø59Ø!Ø37Ø04Ø!$Ø-1Ø+/Ø ñQàŸ9™9ðQð !  b§i¡iÐ1DÐ!DÑEðQð   §	¡	Ñ*ð	Qð
 &.¨c¡]ðQð ðQð "*¨%¡ðQð ' u™oðQð ðQð ˜UŸ\™\Ñ*ðQð ˜EŸK™KÑ(ðQð õQðj *.ñà  ™ðð 
!ó	ð6 &Ø"&ñ%àð%ð ˜3‘-ð%ð
 
�‰ó%ð&$
à—<‘<ð$
ð —L‘Lð$
ð 
ˆc�5—<‘<ÐÑ	 ÷	$
r>   rj   c                   óÈ   ‡ — e Zd ZdZ	 ddej
                  deej
                     fˆ fd„Zd„ Zdde	fd„Z
dej                  d	eej                  ej                  f   fd
„Zˆ xZS )Ú"FeatureDistillationTrainableModulea  Trainable module for feature distillation.

    Wraps student model and projection layer into a single module where all
    trainable forward operations happen inside forward(). This ensures proper
    DDP wrapping when the module is used with DistributedDataParallel.
    re   Ú
projectionc                 ó>   •— t         ‰| �  «        || _        || _        y)zÍ Create trainable module wrapper for feature distillation.

        Args:
            student_model: Student model to train
            projection: Optional projection layer (Linear layer or None)
        N)r$   r%   Ústudentr©   )r9   re   r©   r<   s      €r=   r%   z+FeatureDistillationTrainableModule.__init__Ÿ  s   ø€ ô 	‰ÑÔØ$ˆŒØ$ˆ�r>   c                 ó¤   — t        | j                  «      }t        |d«      s
t        «       S |j	                  «       D �ch c]  }d|z   ’Œ	 c}S c c}w )NÚno_weight_decayústudent.)r	   r«   r2   Úsetr­   )r9   r«   Únames      r=   r­   z2FeatureDistillationTrainableModule.no_weight_decay®  sD   € Ü˜tŸ|™|Ó,ˆÜ�wÐ 1Ô2Ü“5ˆLØ.5×.EÑ.EÓ.GÖH d�
˜TÓ!ÒHÐHùÒHs   ¾AÚcoarsec                 óÎ   ‡‡— t        | j                  «      }t        |d«      si S t        ||j	                  |¬«      d¬«      Št        ‰j                  «       d¬«      Šˆˆfd„}|S )NÚgroup_matcher)r±   T)Úreverser   )Údefaultc                 óf   •— | j                  d«      r‰j                  | t        d«      d  ‰«      S ‰S )Nr®   )Ú
startswithr3   Úlen)r°   Ústudent_layer_mapÚ
task_layers    €€r=   Ú_matcherzBFeatureDistillationTrainableModule.group_matcher.<locals>._matcher¼  s4   ø€ Ø�‰˜zÔ*Ø(×,Ñ,¨T´#°j³/Ð2BÐ-CÀZÓPÐPØÐr>   )r	   r«   r2   r   r³   ÚmaxÚvalues)r9   r±   r«   r»   r¹   rº   s       @@r=   r³   z0FeatureDistillationTrainableModule.group_matcher´  sa   ù€ Ü˜tŸ|™|Ó,ˆÜ�w Ô0ØˆIä,¨W°g×6KÑ6KÐSYÐ6KÓ6ZÐdhÔiÐÜÐ*×1Ñ1Ó3¸QÔ?ˆ
õ	ð
 ˆr>   r?   r@   c                 óê   — | j                   j                  |«      }| j                   j                  |«      }| j                   j                  |d¬«      }| j                  �| j                  |«      }||fS )a  Forward pass through student and projection.

        Args:
            input: Input tensor [B, C, H, W]

        Returns:
            Tuple of (student_logits, student_features) where features are
            optionally projected to match teacher dimension.
        TrD   )r«   rB   rC   r©   )r9   r?   rG   r�   Ústudent_featuress        r=   rS   z*FeatureDistillationTrainableModule.forwardÃ  sl   € ð —l‘l×3Ñ3°EÓ:ˆØŸ™×2Ñ2°;Ó?ˆØŸ<™<×4Ñ4°[ÈTÐ4ÓRÐà�?‰?Ð&Ø#Ÿ™Ð/?Ó@ÐàÐ/Ð/Ð/r>   r£   r[   )r/   r\   r]   r^   r+   r,   r   r%   r­   ra   r³   r4   r`   r   rS   rb   rc   s   @r=   r¨   r¨   —  sl   ø„ ñð /3ñ%àŸ9™9ð%ð ! §¡Ñ+õ%òIñ Dó ð0˜UŸ\™\ð 0¨e°E·L±LÀ%Ç,Á,Ð4NÑ.O÷ 0r>   r¨   c                   óþ  ‡ — e Zd ZdZ	 	 	 	 	 	 	 	 	 d#dej
                  deeej
                  ef   de	ej
                     de	e   de	e
   de	e
   d	e	e   d
e	e   de	ej                     de	ej                     defˆ fd„Zedej
                  defd„«       Z	 d$de	e   dd fd„Z	 	 d%dede	e   dej
                  fd„Zd&de	ej
                     dede	ej
                     fˆ fd„Z	 	 d&de	ej
                     dedeeeeej0                  f   f   fd„Zd'defd„Z	 	 	 d(de	eeeeej0                  f   f      dede	ej
                     deddf
d„Zd ej0                  d!ej0                  deeej0                  f   fd"„Zˆ xZS ))ÚFeatureDistillationTaska�  Feature-based knowledge distillation task.

    Performs distillation by matching student and teacher intermediate features
    (pooled pre-logits) using MSE loss. Automatically creates a projection layer
    if student and teacher feature dimensions differ.

    Loss weighting supports two modes:
    1. Independent weights: loss = task_loss_weight * task_loss + distill_loss_weight * distill_loss
    2. Complementary mode: loss = task_loss_weight * task_loss + (1 - task_loss_weight) * distill_loss
       (used when only task_loss_weight is specified)

    Args:
        student_model: Student model to train
        teacher_model: Teacher model - can be a model name string, nn.Module, or DistillationTeacher
        criterion: Task loss function (default: CrossEntropyLoss)
        teacher_pretrained_path: Path to teacher pretrained weights (used when teacher_model is a string)
        distill_loss_weight: Weight for distillation loss
        task_loss_weight: Weight for task loss
        student_feature_dim: Student pre-logits dimension (auto-detected if None)
        teacher_feature_dim: Teacher pre-logits dimension (auto-detected if None)
        device: Device for task tensors/buffers
        dtype: Dtype for task tensors/buffers
        verbose: Enable info logging

    Example:
        >>> # With model name string (num_classes/in_chans inferred from student)
        >>> task = FeatureDistillationTask(
        ...     student_model=model, teacher_model='resnet50',
        ...     criterion=nn.CrossEntropyLoss(),
        ...     distill_loss_weight=5.0, task_loss_weight=1.0,
        ...     device=torch.device('cuda'),
        ... )
    Nre   rk   rl   rm   ro   rp   Ústudent_feature_dimÚteacher_feature_dimr   r   rr   c                 ó¾  •— t         ‰| �  |	|
|¬«       t        |||| j                  | j                  «      }|| _        |�|nt        j                  «       | _        |�D|| _	        |�|nd| _
        | j                  r´t        j                  d| j                  › d|› �«       nŽ|�C|| _
        d|z
  | _	        | j                  rot        j                  d|› d| j                  › �«       nId| _	        d| _
        | j                  r/t        j                  d| j                  › d| j                  › �«       |€| j                  |«      }|€| j                  |j                  «      }d }||k7  rU| j                  rt        j                  d|› d|› �«       t        j                   ||| j                  | j                  ¬	«      }n!| j                  rt        j                  d
«       t#        ||«      | _        t'        |«      }t)        j*                  |j,                  d   | j                  | j                  ¬	«      j/                  dddd«      }t)        j*                  |j,                  d   | j                  | j                  ¬	«      j/                  dddd«      }| j1                  d|d¬«       | j1                  d|d¬«       | j                  rt        j                  d|› d|› �«       y y )Nrt   rv   z;FeatureDistillationTask: Independent weights - task_weight=rw   z:FeatureDistillationTask: Complementary mode - task_weight=z=FeatureDistillationTask: Default equal weights - task_weight=zCreating projection layer: z -> r   z.Feature dimensions match, no projection neededr   r
   r   r   rT   Fr    rU   z%FeatureDistillationTask: student_dim=z, teacher_dim=)r$   r%   rh   r   r   rd   r+   ry   rl   ro   rp   rr   r(   r)   Ú_detect_feature_dimr1   ÚLinearr¨   rx   r	   r4   r5   r   r6   r7   )r9   re   rk   rl   rm   ro   rp   rÂ   rÃ   r   r   rr   rd   r©   rg   rT   rU   r<   s                    €r=   r%   z FeatureDistillationTask.__init__ú  sé  ø€ ô 	‰Ñ ¨e¸WÐÔEô #ØØØ#Ø�K‰KØ�J‰Jó
ˆð ˆŒØ&/Ð&;™Ä×ATÑATÓAVˆŒð Ð*à':ˆDÔ$Ø8HÐ8TÑ$4ÐZ]ˆDÔ!Ø�|Š|Ü—‘ð#Ø#'×#8Ñ#8Ð"9Ð9JÐK^ÐJ_ðaõð Ð)à$4ˆDÔ!Ø'*Ð-=Ñ'=ˆDÔ$Ø�|Š|Ü—‘ð#Ø#3Ð"4Ð4EÀd×F^ÑF^ÐE_ðaõð (+ˆDÔ$Ø$'ˆDÔ!Ø�|Š|Ü—‘ð#Ø#'×#8Ñ#8Ð"9Ð9JÈ4×KcÑKcÐJdðfôð Ð&Ø"&×":Ñ":¸=Ó"IÐØÐ&Ø"&×":Ñ":¸7¿=¹=Ó"IÐð ˆ
ØÐ"5Ò5Ø�|Š|Ü—‘Ø1Ð2EÐ1FÀdÐK^ÐJ_Ð`ôô Ÿ™Ð#6Ð8KÐTX×T_ÑT_Ðgk×gqÑgqÔr‰Jà�|Š|Ü—‘ÐMÔNä BÀ=ÐR\Ó ]ˆÔô )¨Ó7ÐÜ—|‘|Ø×,Ñ,¨VÑ4Ø—;‘;Ø—*‘*ô
÷ ‰$ˆq�"�a˜Ó
ð	 	ô
 —l‘lØ×,Ñ,¨UÑ3Ø—;‘;Ø—*‘*ô
÷ ‰$ˆq�"�a˜Ó
ð	 	ð
 	×Ñ˜^¨\ÀeÐÔLØ×Ñ˜]¨KÀEÐÔJà�<Š<Ü�L‰LðØ2Ð3°>ÐBUÐAVðXõð r>   r1   r@   c                 óŽ   — t        | «      } t        | d«      r| j                  S t        | d«      r| j                  S t	        d«      ‚)z)Auto-detect feature dimension from model.Úhead_hidden_sizeÚnum_featuresz±Cannot auto-detect feature dimension. Model must have 'head_hidden_size' or 'num_features' attribute, or you must specify student_feature_dim and teacher_feature_dim explicitly.)r	   r2   rÈ   rÉ   rF   )r1   s    r=   rÅ   z+FeatureDistillationTask._detect_feature_dim\  sN   € ô ˜UÓ#ˆä�5Ð,Ô-Ø×)Ñ)Ð)Ü�U˜NÔ+Ø×%Ñ%Ð%äðRóð r>   rz   c                 ó’   — ddl m} | j                  j                  «       D ]	  }d|_        Œ  || j
                  fd|i|¤Ž| _        | S )a¦  Prepare task for distributed training.

        Wraps the trainable module (student + projection) in DistributedDataParallel
        (DDP) while leaving the frozen teacher model unwrapped.

        Args:
            device_ids: List of device IDs for DDP (e.g., [local_rank])
            **ddp_kwargs: Additional arguments passed to DistributedDataParallel

        Returns:
            self (for method chaining)
        r   r|   Frz   r~   r‚   s        r=   r†   z+FeatureDistillationTask.prepare_distributedl  r‡   r>   rI   rJ   c                 ó   — t        j                  | j                  j                  f||dœ|¤Ž}|| _        t        j                  | j                  f||dœ|¤Ž| _         | j
                  j                  d||dddœ|¤Ž |S )z9Compile feature-distillation train and eval entry points.rN   FTr‰   r#   )r4   rO   rx   r«   rŠ   rd   )r9   rI   rJ   rP   rŠ   s        r=   rO   zFeatureDistillationTask.compile…  s›   € ô —]‘] 4×#8Ñ#8×#@Ñ#@ÐoÈ'ÐX\ÑoÐ`nÑoˆ
Ø$ˆŒÜ %§¡Ø×!Ñ!ð!
àØñ!
ð ñ	!
ˆÔð 	ˆ�‰×Ñð 	
ØØØØ!ñ		
ð
 ò	
ð Ðr>   ÚmoduleÚemac                 ó¦   •— t         ‰| �  ||¬«      }|}|�:t        |t        «      r|j                  S t        |d«      s	 |S |j                  }|�Œ:|S )N)rÌ   rÍ   rÌ   )r$   Úget_eval_modelr&   r¨   r«   r2   rÌ   )r9   rÌ   rÍ   ÚresolvedÚcurrentr<   s        €r=   rÏ   z&FeatureDistillationTask.get_eval_model�  sc   ø€ Ü‘7Ñ)°¸SÐ)ÓAˆØˆØÐ!Ü˜'Ô#EÔFØ—‘Ð&Ü˜7 HÔ-Øàˆð —n‘nˆGð Ñ!ð ˆr>   c                 ó    — |�|n| j                  |¬«      }|€i S t        |«      }|j                  €i S d|j                  j                  «       iS )N©rÍ   r©   )Úget_trainable_moduler	   r©   Ú
state_dict)r9   rÌ   rÍ   Ú	trainables       r=   Úget_task_statez&FeatureDistillationTask.get_task_state¨  s^   € ð
 "Ð-‘°4×3LÑ3LÐQTÐ3LÓ3UˆØˆ>ØˆIÜ  Ó(ˆ	Ø×ÑÐ'ØˆIØ˜i×2Ñ2×=Ñ=Ó?Ð@Ð@r>   Úexclude_headc                 óî   — t        | j                  «      }t        |j                  j	                  «       «      }|r|d d }|j
                  �)|j                  |j
                  j	                  «       «       |S )Néþÿÿÿ)r	   rx   r¦   r«   r€   r©   Úextend)r9   rØ   rÖ   r€   s       r=   Úget_clip_parametersz+FeatureDistillationTask.get_clip_parametersµ  sh   € Ü  ×!6Ñ!6Ó7ˆ	Ü˜)×+Ñ+×6Ñ6Ó8Ó9ˆ
ÙØ# C R˜ˆJØ×ÑÐ+Ø×Ñ˜i×2Ñ2×=Ñ=Ó?Ô@ØÐr>   ÚstateÚstrictc                 ó  — |sy |�|n| j                  |¬«      }|€|rt        d«      ‚t        d«      ‚t        |«      }|j                  d«      }|€y |j                  €|rt        d«      ‚y |j                  j                  ||¬«       y )NrÓ   z.Cannot load EMA task state before setup_ema().z2Cannot load task state without a trainable module.r©   z@Checkpoint has projection task state but task has no projection.)rÞ   )rÔ   ÚRuntimeErrorr	   r3   r©   Úload_state_dict)r9   rÝ   rÞ   rÌ   rÍ   rÖ   Úprojection_states          r=   Úload_task_statez'FeatureDistillationTask.load_task_state¾  sŸ   € ñ ØØ!Ð-‘°4×3LÑ3LÐQTÐ3LÓ3UˆØˆ>ÙÜ"Ð#SÓTÐTÜÐSÓTÐTÜ  Ó(ˆ	Ø Ÿ9™9 \Ó2ÐØÐ#ØØ×ÑÐ'ÙÜ"Ð#eÓfÐfØØ×Ñ×,Ñ,Ð-=ÀfÐ,ÕMr>   r?   r‹   c                 ó¼  — | j                  |«      \  }}| j                  ||«      }t        j                  «       5  | j                  j                  || j                  | j                  «      }| j	                  |j                  «       d¬«      }ddd«       t        j                  |«      }| j                  |z  | j                  |z  z   }	|	|||dœS # 1 sw Y   ŒExY w)aÅ  Forward pass with feature distillation.

        Args:
            input: Input tensor [B, C, H, W]
            target: Target labels [B]

        Returns:
            Dictionary containing:
                - 'loss': Combined training loss (task + distillation)
                - 'output': Student logits (for metrics)
                - 'task_loss': Classification loss component
                - 'kd_loss': Feature distillation loss component
        Tr�   Nr“   )rx   rl   r4   r˜   rd   rX   rT   rU   r™   rš   Úmse_lossrp   ro   )
r9   r?   r‹   r�   r¿   r–   rž   Úteacher_featuresr—   r¢   s
             r=   rS   zFeatureDistillationTask.forwardÖ  s×   € ð$ ,0×+@Ñ+@ÀÓ+GÑ(ˆÐ(Ø—N‘N >°6Ó:ˆ	ä�]‰]‹_ñ 	UØ—|‘|×3Ñ3°E¸4×;LÑ;LÈd×N^ÑN^Ó_ˆHØ#Ÿ|™|¨H¯O©OÓ,=Èt˜|ÓTÐ÷	Uô —*‘*Ð-Ð/?Ó@ˆØ×*Ñ*¨YÑ6¸×9QÑ9QÐT[Ñ9[Ñ[ˆ
ð Ø$Ø"Øñ	
ð 	
÷	Uð 	Uús   »ACÃC)	NNNNNNNNTr£   r¤   )NFr[   )TNF)r/   r\   r]   r^   r+   r,   r   r'   r   r   r¥   r_   r4   r   r   ra   r%   ÚstaticmethodrÅ   r¦   r†   rO   rÏ   r   r`   r×   rÜ   rã   rS   rb   rc   s   @r=   rÁ   rÁ   ×  sŒ  ø„ ñ ðL .2Ø59Ø37Ø04Ø15Ø15Ø-1Ø+/Ø ñ`àŸ9™9ð`ð !  b§i¡iÐ1DÐ!DÑEð`ð   §	¡	Ñ*ð	`ð
 &.¨c¡]ð`ð "*¨%¡ð`ð ' u™oð`ð "*¨#¡ð`ð "*¨#¡ð`ð ˜UŸ\™\Ñ*ð`ð ˜EŸK™KÑ(ð`ð õ`ðD ð 2§9¡9ð °ò ó ðð" *.ñà  ™ðð 
#ó	ð6 &Ø"&ñàðð ˜3‘-ðð
 
�‰óñ0	 X¨b¯i©iÑ%8ð 	Àdð 	ÐW_Ð`b×`iÑ`iÑWjõ 	ð +/ØñAà˜RŸY™YÑ'ðAð ðAð 
ˆc�4˜˜UŸ\™\Ð)Ñ*Ð*Ñ	+ó	Añ°ó ð  Ø*.ØñNà˜D  d¨3°·±Ð+<Ñ&=Ð!=Ñ>Ñ?ðNð ðNð ˜RŸY™YÑ'ð	Nð
 ðNð 
óNð0!
à—<‘<ð!
ð —L‘Lð!
ð 
ˆc�5—<‘<ÐÑ	 ÷	!
r>   rÁ   ) r^   ÚloggingÚtypingr   r   r   r   r4   Útorch.nnr+   Útorch.nn.functionalÚ
functionalrš   Útimm.modelsr   r   Ú
timm.utilsr	   Útaskr   Ú	getLoggerr/   r(   r,   r   r'   r   r   rh   rj   r¨   rÁ   r#   r>   r=   ú<module>rñ      sæ   ðÙ ;Û ß /Ó /ã Ý ß Ð ç 6Ý #å ð ˆ'×
Ñ
˜HÓ
%€ôOQ˜"Ÿ)™)ô OQðd"Ø�s˜BŸI™IÐ':Ð:Ñ;ð"à—y‘yð"ð " #™ð"ð ˜Ÿ™Ñ&ð	"ð
 ˜Ÿ™Ñ$ð"ð ó"ôJK
˜Lô K
ô\=0¨¯©ô =0ô@`
˜lõ `
r>   