
    i#                        S r SSKrSSKrSSKJrJrJr  SSKr SSK	r	SSK
Jr  SSKJr  SSKJrJr  SrSSKJr  SS	KJr  SS
KJr  SSKJr  \R8                  " \5      r " S S\(       a  \R>                  O\ 5      r! " S S\(       a  \R>                  O\ 5      r" " S S5      r#g! \ a    Sr\R&                  " S5         Nf = f)z3Trainer for contrastive learning with triplet loss.    N)OptionalDictAny)
DataLoaderTensorDatasetTFz9PyTorch not available, PreferenceTrainer will be disabled)PreferenceEncoder)PreferenceDataset)MemoryStore)PatternEmbedderc                      ^  \ rS rSrSrSS\4U 4S jjjrS\R                  S\R                  S\R                  S\R                  4S	 jr	S
r
U =r$ )TripletLoss   zTriplet loss for contrastive learning.

Loss = max(0, d(anchor, positive) - d(anchor, negative) + margin)
where d is Euclidean distance.
marginc                 b   > [         (       d  [        S5      e[        [        U ]  5         Xl        g)zDInitialize triplet loss.

Args:
    margin: Margin for triplet loss
z#PyTorch is required for TripletLossN)TORCH_AVAILABLEImportErrorsuperr   __init__r   selfr   	__class__s     C   /home/ubuntu/codebase/yexijia/保研/iCoLoc/src/learning/trainer.pyr   TripletLoss.__init__!   s(     CDDk4)+    anchorpositivenegativereturnc                    [         R                  R                  R                  X5      n[         R                  R                  R                  X5      n[         R                  " XE-
  U R
                  -   SS9nUR                  5       $ )zCompute triplet loss.

Args:
    anchor: Anchor vectors (batch_size, dim)
    positive: Positive vectors (batch_size, dim)
    negative: Negative vectors (batch_size, dim)
    
Returns:
    Loss value
        min)torchnn
functionalpairwise_distanceclampr   mean)r   r   r   r   d_posd_neglosss          r   forwardTripletLoss.forward-   sa     ##55fG##55fG {{5=4;;6C@yy{r   r   333333?__name__
__module____qualname____firstlineno____doc__floatr   r#   Tensorr,   __static_attributes____classcell__r   s   @r   r   r      sQ    
u 
 
ell ell ,,+0<< r   r   c                      ^  \ rS rSrSrSS\4U 4S jjjrS\R                  S\R                  S\R                  S\R                  4S	 jr	S
r
U =r$ )CosineTripletLossC   zcCosine-based triplet loss.

Loss = max(0, -cos(anchor, positive) + cos(anchor, negative) + margin)
r   c                 b   > [         (       d  [        S5      e[        [        U ]  5         Xl        g)zKInitialize cosine triplet loss.

Args:
    margin: Margin for triplet loss
z)PyTorch is required for CosineTripletLossN)r   r   r   r=   r   r   r   s     r   r   CosineTripletLoss.__init__I   s)     IJJ/1r   r   r   r   r   c                    [         R                  R                  R                  X5      n[         R                  R                  R                  X5      n[         R                  " U* U-   U R
                  -   SS9nUR                  5       $ )zCompute cosine triplet loss.

Args:
    anchor: Anchor vectors (batch_size, dim)
    positive: Positive vectors (batch_size, dim)
    negative: Negative vectors (batch_size, dim)
    
Returns:
    Loss value
r    r!   )r#   r$   r%   cosine_similarityr'   r   r(   )r   r   r   r   cos_poscos_negr+   s          r   r,   CosineTripletLoss.forwardU   sf     ((%%77I((%%77I {{G8g-;Eyy{r   r.   r/   r1   r;   s   @r   r=   r=   C   sQ    

u 
 
ell ell ,,+0<< r   r=   c                       \ rS rSrSr       SS\S\S\\   S\	S\	S	\
S
\
S\S\4S jjr  SS\	S\	S\\   S\\\4   4S jjrS\4S jrS\4S jrSrg)PreferenceTrainerk   z:Trainer for preference encoder using contrastive learning.Nmemory_storeembeddermodel	input_dim
hidden_dimr   learning_rateuse_cosine_lossuser_idc
                 ~   [         (       d  [        S5      eXl        X l        Xl        X`l        Xpl        Uc  [        XES9U l        OX0l        U(       a  [        US9U l
        O[        US9U l
        [        R                  " U R                  R                  5       US9U l        [         R#                  SU SU 35        g)a  Initialize preference trainer.

Args:
    memory_store: Memory store instance
    embedder: Pattern embedder
    model: Optional pre-trained preference encoder
    input_dim: Input embedding dimension
    hidden_dim: Hidden layer dimension
    margin: Margin for triplet loss
    learning_rate: Learning rate
    use_cosine_loss: Whether to use cosine-based triplet loss
    user_id: User identifier
z)PyTorch is required for PreferenceTrainerN)rL   rM   r.   )lrz*PreferenceTrainer initialized with margin=z, lr=)r   r   rI   rJ   rP   r   rN   r   rK   r=   	criterionr   optimAdam
parameters	optimizerloggerinfo)
r   rI   rJ   rK   rL   rM   r   rN   rO   rP   s
             r   r   PreferenceTrainer.__init__n   s    . IJJ( * =*YVDJJ .f=DN(7DN DJJ$9$9$;N@m_]^r   epochs
batch_size	save_pathr   c           	         [        U R                  U R                  U R                  5      nUR	                  5       n[        U5      S:X  a  [        R                  S5        / SS.$ [        R                  " U Vs/ s H  ofS   PM	     sn5      n[        R                  " U Vs/ s H  ofS   PM	     sn5      n[        R                  " U Vs/ s H  ofS   PM	     sn5      n	[        XxU	5      n
[        XSS9nS/ 0n[        R                  S	[        U5       S
U S35        U R                  R                  5         [        U5       GHM  nSnSnU H  u  nnnU R                  U5      nU R                  U5      nU R                  U5      nU R!                  UUU5      nU R"                  R%                  5         UR'                  5         U R"                  R)                  5         UUR+                  5       -  nUS-  nM     US:  a  X-  OSnUS   R-                  U5        SUS-    SU SUS 3n[        R                  U5        [/        SU 35        US:  d  GM  US   US-
     U-
  nUS:  a  SO	US:  a  SOSn[/        SU S[1        U5      S 35        GMP     U(       a  U R3                  U5        XS'   U$ s  snf s  snf s  snf )zTrain the preference encoder.

Args:
    epochs: Number of training epochs
    batch_size: Batch size
    save_path: Path to save the trained model
    
Returns:
    Training history dictionary
r   z"No triplets available for training)r+   r[         T)r\   shuffler+   zStarting training with z triplets, z epochsr    zEpoch /z, Loss: z.4fz  u   ↓u   ↑u   →u       Loss变化:  r[   )r	   rI   rJ   rP   get_tripletslenrX   warningr#   FloatTensorr   r   rY   rK   trainrangerS   rW   	zero_gradbackwardstepitemappendprintabs
save_model)r   r[   r\   r]   datasettripletstanchors	positives	negativestensor_dataset
dataloaderhistoryepoch
epoch_loss	n_batchesbatch_anchorsbatch_positivesbatch_negativesanchor_projpositive_projnegative_projr+   avg_lossprogress_msgloss_changetrends                              r   rh   PreferenceTrainer.train   s    $D$5$5t}}dllS'')x=ANN?@!,, ##8$<8aqT8$<=%%X&>XtX&>?	%%X&>XtX&>?	 'w9EtT
 2,-c(m_KxwWX

6]EJICM?"jj7 $

? ; $

? ; ~~k=-P ((*##%diik)
Q	 DN" 2;Qz-CHFO""8, $E!G9AfXXhs^LLKK%B|n%& qy%foeAg6A!,q{QeTY(q[1A#0FGHC #H OOI&"o %=&>&>s   9J4"J9J>pathc                    [         R                  " [         R                  R                  U5      SS9  [        R
                  " U R                  R                  5       U R                  R                  5       U R                  R                  U R                  R                  U R                  R                  S.U5        [        R                  SU 35        g)z@Save the trained model.

Args:
    path: Path to save the model
T)exist_ok)model_state_dictoptimizer_state_dictrL   rM   
output_dimzModel saved to N)osmakedirsr   dirnamer#   saverK   
state_dictrW   rL   rM   r   rX   rY   )r   r   s     r   rq   PreferenceTrainer.save_model   s     	BGGOOD)D9

 $

 5 5 7$(NN$=$=$?--**//**//
 	 	odV,-r   c                     [         R                  " U5      nU R                  R                  US   5        U R                  R                  US   5        [
        R                  SU 35        g)zCLoad a trained model.

Args:
    path: Path to load the model from
r   r   zModel loaded from N)r#   loadrK   load_state_dictrW   rX   rY   )r   r   
checkpoints      r   
load_modelPreferenceTrainer.load_model   sV     ZZ%


"":.@#AB&&z2H'IJ(/0r   )rS   rJ   rN   r   rI   rK   rW   rP   )Ni     r0   gMbP?Tuser_001)
       N)r2   r3   r4   r5   r6   r
   r   r   r   intr7   boolstrr   r   r   rh   rq   r   r9    r   r   rG   rG   k   s    D
 7;"%#&!$(-)- */_*/_*/_ !!23/_  	/_
 !/_ /_ !&/_ #'/_ /_b 9;)-LC L# L!#L26sCx.L\.s . 	1s 	1r   rG   )$r6   r   numpynptypingr   r   r   loggingr#   torch.nnr$   torch.optimrT   torch.utils.datar   r   r   r   rf   embedding.encoderr   learning.datasetr	   memory.storer
   learning.embedderr   	getLoggerr2   rX   Moduleobjectr   r=   rG   r   r   r   <module>r      s    9 	  & & Q:O
 0 . $ -			8	$&"))F &R%_		& %P[1 [1{  QOOOOPQs   B% %CC