o
    –hØ  ã                   @   s¸   d dl mZmZ d dl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Z d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ eƒ Ze d	¡ZG d
d„ deƒZdS )é    )ÚABCÚabstractmethodN)ÚListÚTupleÚAnyÚMapping)Údefault_device)Úutils)ÚDEFAULT_BATCH_SIZE)Úevaluate_model)Úget_tqdmzstanza.lemmaclassifierc                   @   sL   e Zd Zdedefdd„Zedd„ ƒZdeded	ed
ededdfdd„Z	dS )ÚBaseLemmaClassifierTrainerÚlabel_decoderÚcountsc                 C   sn   dd„ |  ¡ D ƒ}t| ¡ ƒ}|D ]}||| t|ƒ  ||< qt |¡}t d|› d¡ tj	|d| _
dS )an  
        If applicable, this function will update the loss function of the LemmaClassifierLSTM model to become BCEWithLogitsLoss.
        The weights are determined by the counts of the classes in the dataset. The weights are inversely proportional to the
        frequency of the class in the set. E.g. classes with lower frequency will have higher weight.
        c                 S   s   g | ]}d ‘qS )r   © )Ú.0Ú_r   r   úf/var/www/html/env_mimamsha/lib/python3.10/site-packages/stanza/models/lemma_classifier/base_trainer.pyÚ
<listcomp>   s    zFBaseLemmaClassifierTrainer.configure_weighted_loss.<locals>.<listcomp>zUsing weights z for weighted loss.)ÚweightN)ÚkeysÚsumÚvaluesÚlenÚtorchÚtensorÚloggerÚinfoÚnnÚBCEWithLogitsLossÚ	criterion)Úselfr   r   ÚweightsÚtotal_samplesÚ	class_idxr   r   r   Úconfigure_weighted_loss   s   
z2BaseLemmaClassifierTrainer.configure_weighted_lossc                 C   s   dS )z`
        Build a model using pieces of the dataset to determine some of the model shape
        Nr   )r!   r   Ú
upos_to_idÚknown_wordsÚtarget_wordsÚtarget_uposr   r   r   Úbuild_model#   s    z&BaseLemmaClassifierTrainer.build_modelÚ
num_epochsÚ	save_nameÚargsÚ	eval_fileÚ
train_fileÚreturnNc              
   C   sÆ  t ƒ }|s	tdƒ‚tj|| j| dt¡d}|j}|j}	t	|ƒ| _
t d|› ¡ t d|› d| j
› ¡ t d|j› ¡ |  ||	|j|jt|jƒ¡| _tj| j ¡ | jd| _| j |¡ t d	|› d
t| j ¡ ƒj› ¡ tj |¡r„| dd¡s„td|› dƒ‚| jrŽ|  ||j ¡ t !dt| j ¡ ƒj› ¡ | j" t| j ¡ ƒj¡| _"dt#dƒ}
}t$|ƒD ]¬}t%|ƒD ]_\}}}}t	|ƒt	|ƒ  krÐt	|ƒksân J dt	|ƒt	|ƒt	|ƒf› dƒ‚| j &¡  |  |||¡}| jrt' (dd„ |D ƒ¡jt'j)d |¡}n| |¡}|  "||¡}| *¡  | j +¡  qºt d|d › d|› d| ,¡ › ¡ |rZt-| j|dd\}}}}t d|› ¡ ||krY|}| j .|¡ t d|› d¡ q´| j .|¡ q´dS ) a  
        Trains a model on batches of texts, position indices of the target token, and labels (lemma annotation) for the target token.

        Args:
            num_epochs (int): Number of training epochs
            save_name (str): Path to file where trained model should be saved.
            eval_file (str): Path to the dev set file for evaluating model checkpoints each epoch.
            train_file (str): Path to data file, containing tokenized text sentences, token index and true label for token lemma on each line.
        z,Cannot train model - no train_file supplied!Ú
batch_size)Ú
get_countsr1   z!Loaded dataset successfully from zUsing label decoder: z  Output dimension: zTarget words: )ÚlrzTraining model on device: z. ÚforceFz
Save name zM already exists; training would overwrite previous file contents. Aborting...zCriterion on Nz-infz>Input sentences, positions, and labels are of unequal length (ú)c                 S   s0   g | ]}|d krt  dd g¡nt  d dg¡‘qS )r   é   )r   r   )r   Úlabelr   r   r   r   ]   s   0 z4BaseLemmaClassifierTrainer.train.<locals>.<listcomp>)ÚdtypezEpoch [r6   ú/z	], Loss: T)Úis_trainingzWeighted f1 for model: z%New best model: weighted f1 score of Ú.)/r   Ú
ValueErrorr	   ÚDatasetÚweighted_lossÚgetr
   r   r&   r   Ú
output_dimr   r   r(   r*   r'   Úsetr)   ÚmodelÚoptimÚAdamÚ
parametersr3   Ú	optimizerÚtoÚnextÚdeviceÚosÚpathÚexistsÚFileExistsErrorr%   r   Údebugr    ÚfloatÚrangeÚtqdmÚ	zero_gradr   ÚstackÚfloat32ÚbackwardÚstepÚitemr   Úsave)r!   r+   r,   r-   r.   r/   rI   Údatasetr   r&   Ú
best_modelÚbest_f1ÚepochÚ	sentencesÚ	positionsÚ	upos_tagsÚlabelsÚoutputsÚtargetsÚlossr   Úf1r   r   r   Útrain)   sV   
"D
&
$
€áz BaseLemmaClassifierTrainer.train)
Ú__name__Ú
__module__Ú__qualname__r   r%   r   r*   ÚintÚstrre   r   r   r   r   r      s
    
&r   )Úabcr   r   ÚloggingrJ   Útypingr   r   r   r   r   Útorch.nnr   Útorch.optimrC   Ústanza.models.common.utilsr   Ústanza.models.lemma_classifierr	   Ú(stanza.models.lemma_classifier.constantsr
   Ú.stanza.models.lemma_classifier.evaluate_modelsr   Ústanza.utils.get_tqdmr   rQ   Ú	getLoggerr   r   r   r   r   r   Ú<module>   s   
