
    i#                     t   d Z ddlZddlZddlmZmZmZ ddlZ	 ddl	Z	ddl
mZ ddlmZ ddlmZmZ dZddlmZ dd	lmZ dd
lmZ ddlmZ  ej8                  e      Z G d derej>                  ne       Z! G d derej>                  ne       Z" G d d      Z#y# e$ r dZ ej&                  d       Y w xY w)z3Trainer for contrastive learning with triplet loss.    N)OptionalDictAny)
DataLoaderTensorDatasetTFz9PyTorch not available, PreferenceTrainer will be disabled)PreferenceEncoder)PreferenceDataset)MemoryStore)PatternEmbedderc                        e Zd ZdZd	def fdZdej                  dej                  dej                  dej                  fdZ xZ	S )
TripletLosszTriplet loss for contrastive learning.
    
    Loss = max(0, d(anchor, positive) - d(anchor, negative) + margin)
    where d is Euclidean distance.
    marginc                 Z    t         st        d      t        t        |           || _        y)zdInitialize triplet loss.
        
        Args:
            margin: Margin for triplet loss
        z#PyTorch is required for TripletLossN)TORCH_AVAILABLEImportErrorsuperr   __init__r   selfr   	__class__s     G   /home/ubuntu/codebase/yexijia/保研/colocation_mvp/learning/trainer.pyr   zTripletLoss.__init__!   s(     CDDk4)+    anchorpositivenegativereturnc                    t         j                  j                  j                  ||      }t         j                  j                  j                  ||      }t        j                  ||z
  | j
                  z   d      }|j                         S )a  Compute 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   forwardzTripletLoss.forward-   sg     ##55fhG##55fhG {{55=4;;6C@yy{r   333333?
__name__
__module____qualname____doc__floatr   r!   Tensorr*   __classcell__r   s   @r   r   r      sG    
u 
ell ell ,,+0<<r   r   c                        e Zd ZdZd	def fdZdej                  dej                  dej                  dej                  fdZ xZ	S )
CosineTripletLosszoCosine-based triplet loss.
    
    Loss = max(0, -cos(anchor, positive) + cos(anchor, negative) + margin)
    r   c                 Z    t         st        d      t        t        |           || _        y)zkInitialize cosine triplet loss.
        
        Args:
            margin: Margin for triplet loss
        z)PyTorch is required for CosineTripletLossN)r   r   r   r7   r   r   r   s     r   r   zCosineTripletLoss.__init__I   s)     IJJ/1r   r   r   r   r   c                    t         j                  j                  j                  ||      }t         j                  j                  j                  ||      }t        j                  | |z   | j
                  z   d      }|j                         S )a  Compute 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*   zCosineTripletLoss.forwardU   sj     ((%%77I((%%77I {{G8g-;Eyy{r   r+   r-   r5   s   @r   r7   r7   C   sG    

u 
ell ell ,,+0<<r   r7   c                       e Zd ZdZ	 	 	 	 	 	 	 ddededee   dedede	d	e	d
e
defdZ	 	 ddededee   deeef   fdZdefdZdefdZy)PreferenceTrainerz:Trainer for preference encoder using contrastive learning.Nmemory_storeembeddermodel	input_dim
hidden_dimr   learning_rateuse_cosine_lossuser_idc
                    t         st        d      || _        || _        |	| _        || _        || _        |t        ||      | _        n|| _        |rt        |      | _
        nt        |      | _
        t        j                  | j                  j                         |      | _        t         j#                  d| d|        y)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)rB   rC   )r   )lrz*PreferenceTrainer initialized with margin=z, lr=)r   r   r?   r@   rF   r   rD   r   rA   r7   	criterionr   optimAdam
parameters	optimizerloggerinfo)
r   r?   r@   rA   rB   rC   r   rD   rE   rF   s
             r   r   zPreferenceTrainer.__init__n   s    . IJJ( * =*Y:VDJDJ .f=DN(7DN DJJ$9$9$;N@m_]^r   epochs
batch_size	save_pathr   c           	      d   t        | j                  | j                  | j                        }|j	                         }t        |      dk(  rt        j                  d       g ddS t        j                  |D cg c]  }|d   	 c}      }t        j                  |D cg c]  }|d   	 c}      }t        j                  |D cg c]  }|d   	 c}      }	t        |||	      }
t        |
|d      }dg i}t        j                  d	t        |       d
| d       | j                  j                          t        |      D ]F  }d}d}|D ]  \  }}}| j                  |      }| j                  |      }| j                  |      }| j!                  |||      }| j"                  j%                          |j'                          | j"                  j)                          ||j+                         z  }|dz  } |dkD  r||z  nd}|d   j-                  |       d|dz    d| d|d}t        j                  |       t/        d|        |dkD  s|d   |dz
     |z
  }|dkD  rdn|dk  rdnd}t/        d| dt1        |      d       I |r| j3                  |       ||d<   |S c c}w c c}w c c}w )a
  Train 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)   rP         T)rQ   shuffler)   zStarting training with z triplets, z epochsr   zEpoch /z, Loss: z.4fz  u   ↓u   ↑u   →u       Loss变化:  rP   )r	   r?   r@   rF   get_tripletslenrN   warningr!   FloatTensorr   r   rO   rA   trainrangerI   rM   	zero_gradbackwardstepitemappendprintabs
save_model)r   rP   rQ   rR   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   r]   zPreferenceTrainer.train   s    $D$5$5t}}dllS'')x=ANN?@!,, ##8$<8aQqT8$<=%%X&>XqtX&>?	%%X&>XqtX&>?	 'w	9E:tT
 2,-c(m_KxwWX

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

? ; $

? ; ~~k=-P ((*##%diik)
Q	 DN" 2;QzI-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   7J#J(J-pathc                    t        j                  t         j                  j                  |      d       t	        j
                  | j                  j                         | j                  j                         | j                  j                  | j                  j                  | j                  j                  d|       t        j                  d|        y)z`Save the trained model.
        
        Args:
            path: Path to save the model
        T)exist_ok)model_state_dictoptimizer_state_dictrB   rC   
output_dimzModel saved to N)osmakedirsr}   dirnamer!   saverA   
state_dictrM   rB   rC   r   rN   rO   )r   r}   s     r   rf   zPreferenceTrainer.save_model   s     	BGGOOD)D9

 $

 5 5 7$(NN$=$=$?--**//**//
 	 	odV,-r   c                     t        j                  |      }| j                  j                  |d          | j                  j                  |d          t
        j                  d|        y)zcLoad a trained model.
        
        Args:
            path: Path to load the model from
        r   r   zModel loaded from N)r!   loadrA   load_state_dictrM   rN   rO   )r   r}   
checkpoints      r   
load_modelzPreferenceTrainer.load_model   sV     ZZ%


"":.@#AB&&z2H'IJ(/0r   )Ni     r,   gMbP?Tuser_001)
       N)r.   r/   r0   r1   r
   r   r   r   intr2   boolstrr   r   r   r]   rf   r    r   r   r>   r>   k   s    D
 7;"%#&!$(-)- */_*/_*/_ !!23/_  	/_
 !/_ /_ !&/_ #'/_ /_b 9;)-LC L# L!#L26sCx.L\.s . 	1s 	1r   r>   )$r1   r   numpynptypingr   r   r   loggingr!   torch.nnr"   torch.optimrJ   torch.utils.datar   r   r   r   r[   embedding.encoderr   learning.datasetr	   memory.storer
   learning.embedderr   	getLoggerr.   rN   Moduleobjectr   r7   r>   r   r   r   <module>r      s    9 	  & & Q:O
 0 . $ -			8	$&"))F &R%_		& %P[1 [1{  QOGOOOPQs   B B76B7