
    Nj/                        d dl mZ d dlZd dlmZ d dlmZ d dlmZm	Z	m
Z
 d dlZd dl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mZ d dlmZ  ej:                  e      Ze e!   e e e!      z  Z" G d de      Z#y)    )annotationsN)Counter)chain)AnyLiteralcast)	Tokenizer)trange)evaluate_single_or_multi_label)BaseFinetuneable)ClassifierLightningModule#MultiLabelClassifierLightningModule)_DEFAULT_RANDOM_SEEDc                  H    e Zd ZdZdZdddddddd	dd
		 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 d fdZedd       Z	 d	 	 	 	 	 	 	 	 	 ddZdddZ	ddddddddddde
f	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 ddZ	 	 	 	 	 	 d dZ	 d!	 	 	 	 	 	 	 	 	 	 	 d"dZd#dZd$dZ xZS )%StaticModelForClassificationval_accuracymax   i      r   NFT)	n_layers
hidden_dimout_dimpad_idtoken_mappingweightsfreeze	normalizefreeze_weightsc                   t        |      D cg c]  }t        |       c}| _        d| _        t        |   |||||||	|||
|       yc c}w )z'Initialize a standard classifier model.F)vectorsr   r   	tokenizerr   r   r   r   r   r   r   N)rangestrclasses_
multilabelsuper__init__)selfr    r!   r   r   r   r   r   r   r   r   r   x	__class__s                k/Users/ahmed/devFolder/Ultron/claude-voice/.venv/lib/python3.12/site-packages/model2vec/train/classifier.pyr'   z%StaticModelForClassification.__init__   sc    " 5:'N#CNqCFN#C %'!) 	 	
 $Ds   Ac                @    t        j                  | j                        S )z(Return all clasess in the correct order.)nparrayr$   )r(   s    r+   classesz$StaticModelForClassification.classes>   s     xx&&    c           
        g }t        dt        |      ||       D ]  }| j                  ||||z          }| j                  rvt	        j
                  |      }||kD  j                         j                         }	|j                  |	D 
cg c]$  }
| j                  t        j                  |
         & c}
       |j                  |j                  d      j                         D cg c]  }| j                  |    c}        | j                  rt        j                  |t              S t        j                  |      S c c}
w c c}w )a  Predict labels for a set of texts.

        In single-label mode, each prediction is a single class.
        In multilabel mode, each prediction is a list of classes.

        :param X: The texts to predict on.
        :param show_progress_bar: Whether to show a progress bar.
        :param batch_size: The batch size.
        :param threshold: The threshold for multilabel classification.
        :return: The predictions.
        r   disabler   dimdtype)r
   len_encode_single_batchr%   torchsigmoidcpunumpyextendr/   r-   flatnonzeroargmaxtolistr.   object)r(   Xshow_progress_bar
batch_size	thresholdpredbatchlogitsprobsmaskrowidxs               r+   predictz$StaticModelForClassification.predictC   s    As1vz?P;PQE..q9K/LMFf-	)..0668$O$3T\\"..*=>$OP&--A-:N:U:U:WX:W3T\\#.:WXY R ??88D//88D>! PXs   )E 
%E
c                   g }t        dt        |      ||       D ]  }| j                  ||||z          }| j                  rA|j	                  t        j                  |      j                         j                                g|j	                  t        j                  |d      j                         j                                 t        j                  |d      S )zPredict probabilities for each class.

        In single-label mode, returns softmax probabilities.
        In multilabel mode, returns sigmoid probabilities.
        r   r2   r   r4   )axis)r
   r8   r9   r%   appendr:   r;   r<   r=   softmaxr-   concatenate)r(   rC   rD   rE   rG   rH   rI   s          r+   predict_probaz*StaticModelForClassification.predict_proba`   s     As1vz?P;PQE..q9K/LMFEMM&1557==?@EMM&a8<<>DDFG R ~~d++r0   gMbP?   g?autoc                   t        j                  |       t        j                  d       | j	                  |       | j                          |t        |t        j                        rzt        j                  d       t        |      t        | j                        k7  rt        d      t        |j                               D ci c]  \  }}| j                  |   | }}}| j                  ||      }nd}| j!                  |||
||      \  }}| j#                  |t        |            }| j$                  rt'        | ||      }nt)        | ||      }| j+                  ||||||||	|	       | S c c}}w )a  Fit a model.

        This function creates a Lightning Trainer object and fits the model to the data.
        It supports both single-label and multi-label classification.
        We use early stopping. After training, the weights of the best model are loaded back into the model.

        This function seeds everything with a seed of 42, so the results are reproducible.
        It also splits the data into a train and validation set, again with a random seed.

        If `X_val` and `y_val` are not provided, the function will automatically
        split the training data into a train and validation set using `test_size`.

        :param X: The texts to train on.
        :param y: The labels to train on. If the first element is a list, multi-label classification is assumed.
        :param learning_rate: The learning rate.
        :param batch_size: The batch size. If None, a good batch size is chosen automatically.
        :param min_epochs: The minimum number of epochs to train for.
        :param max_epochs: The maximum number of epochs to train for.
            If this is -1, the model trains until early stopping is triggered.
        :param early_stopping_patience: The patience for early stopping.
            If this is None, early stopping is disabled.
        :param test_size: The test size for the train-test split.
        :param device: The device to train on. If this is "auto", the device is chosen automatically.
        :param X_val: The texts to be used for validation.
        :param y_val: The labels to be used for validation.
        :param class_weight: The weight of the classes. If None, all classes are weighted equally. Must
            have the same length as the number of classes.
        :param validation_steps: The number of steps to run validation for. If None, validation steps are estimated from the data.
        :param random_seed: The random seed to use. Defaults to 42.
        :return: The fitted model.
        :raises ValueError: If either X_val or y_val are provided, but not both.
        zRe-initializing model.NzVYou are passing a tensor as class weight. This will be removed in an upcoming version.z@class_weight must have the same length as the number of classes.)learning_rateclass_weight)	moduletrain_datasetval_datasetrE   early_stopping_patience
min_epochs
max_epochsdevicevalidation_steps)plseed_everythingloggerinfo_initialize_on_labels_initialize
isinstancer:   Tensorwarningr8   r$   
ValueError	enumeraterA   _determine_class_weight_create_datasets_determine_batch_sizer%   r   r   _train)r(   rC   yrY   rE   r_   r`   r^   	test_sizera   X_valy_valrZ   rb   random_seedrM   wresolved_class_weightr\   r]   cs                        r+   fitz StaticModelForClassification.fito   sg   b 	;',- 	""1%#,5wx|$DMM(::$%ghhDMlNaNaNcDdeDd&#qc 2A 5Dde$($@$@q$Q!$(!%)%:%:1ay%Y"{//
C<NO
 ??3M@UA *$mZopA'#!$;!!- 	 
	
 9  fs   E/c                   |dk(  r| j                   r=t        t        t        t              |      }t	        t        j                  |            }n"t        t        t           |      }t	        |      }t        |j                               }t        |      }| j                  D cg c]  }||||   z  z   }}n| j                  D cg c]  }||   	 }}t        j                  |t        j                        S c c}w c c}w )z.Determine the class weight for the classifier.balancedr6   )r%   r   listr#   r   r   from_iterablesumvaluesr8   r$   r:   tensorfloat32)r(   rZ   rr   countstotal	n_classesry   r   s           r+   rn   z4StaticModelForClassification._determine_class_weight   s     :%d3i!, !4!4Q!78cA& (EFI@DN1u	F1I 56GN04>1|AG>||G5==99 O>s   #C9C>c                l    | j                          | j                  |d||      }t        |||      }|S )a  Evaluate the classifier on a given dataset using scikit-learn's classification report.

        :param X: The texts to predict on.
        :param y: The ground truth labels.
        :param batch_size: The batch size.
        :param threshold: The threshold for multilabel classification.
        :param output_dict: Whether to output the classification report as a dictionary.
        :return: A classification report.
        T)rD   rE   rF   )predictionsrr   output_dict)evalrN   r   )r(   rC   rr   rE   rF   r   r   reports           r+   evaluatez%StaticModelForClassification.evaluate   s8     			ll1_hli/K1Zefr0   c                   t        |d   t        t        f      rPt        t        t           |      }t        d |D              st        d      d| _        t        t        |            }nit        t        t        t              |      }t        d |D              st        d      d| _        t        t        t        j                  |                  }|| _        t        | j                        | _        y)	zSets the output dimensionality, the classes, and initializes the head.

        :param y: The labels.
        :raises ValueError: If the labels are inconsistent.
        r   c              3  H   K   | ]  }t        |t        t        f        y wN)ri   r#   int.0labels     r+   	<genexpr>zEStaticModelForClassification._initialize_on_labels.<locals>.<genexpr>   s     D!z%#s4!    "zFInconsistent label types in y. All labels must be strings or integers.Fc              3  H   K   | ]  }t        |t        t        f        y wr   )ri   r}   tupler   s     r+   r   zEStaticModelForClassification._initialize_on_labels.<locals>.<genexpr>   s     GQEz%$7Qr   zBInconsistent label types in y. All labels must be lists or tuples.TN)ri   r#   r   r   r}   allrl   r%   sortedsetr   r~   r$   r8   r   )r(   rr   r/   s      r+   rg   z2StaticModelForClassification._initialize_on_labels   s     adS#J'T#Y"AD!DD !ijj#DOSVnGT$s)_a(AGQGG !eff"DOS!4!4Q!789G4==)r0   c                4   | j                   rt        | j                        }t        j                  t        |      |t        j
                        }t        | j                        D ci c]  \  }}||
 }}}t        |      D ]  \  }}|D cg c]  }||   	 }	}d|||	f<     |S t        j                  t        t        t           |      D cg c]  }| j                  j                  |       c}t        j                        }|S c c}}w c c}w c c}w )z5Convert a list or list of list of labels to a tensor.r6   g      ?)r%   r8   r$   r:   zerosfloatrm   r   r   r}   r#   indexlong)
r(   labelsnum_classeslabels_tensorrM   r   mappingisample_labelsindicess
             r+   _labels_to_tensorz.StaticModelForClassification._labels_to_tensor  s    ??dmm,K!KKF[TM4=dmm4LM4Ljc5ucz4LGM$-f$5 =7DE}e75>}E,/aj) %6 	 "LL9=d3i9PQ9P$$U+9PQY^YcYcM  NE Rs   )D
D"D)r    torch.Tensorr!   r	   r   r   r   r   r   r   r   r   r   zlist[int] | Noner   ztorch.Tensor | Noner   boolr   r   r   r   returnNone)r   
np.ndarray)F         ?)
rC   	list[str]rD   r   rE   r   rF   r   r   r   )Fr   )rC   r   rD   r   rE   r   r   r   )rC   r   rr   	LabelTyperY   r   rE   
int | Noner_   r   r`   r   r^   r   rs   r   ra   r#   rt   zlist[str] | Noneru   zLabelType | NonerZ   z<Literal['balanced'] | dict[str, float] | torch.Tensor | Nonerb   r   rv   r   r   r   )rZ   z&dict[str, float] | Literal['balanced']rr   r   r   r   )r   r   F)rC   r   rr   r   rE   r   rF   r   r   r   r   z!str | dict[str, dict[str, float]])rr   r   r   r   )r   r   r   r   )__name__
__module____qualname__
val_metricearly_stopping_directionr'   propertyr/   rN   rT   r   rz   rn   r   rg   r   __classcell__)r*   s   @r+   r   r      s*   J$ *.'+$ 
  
 	 

  
  
  
  
 ( 
 % 
  
  
  
 
 
D ' '
 il""/3"IL"`e"	":,&  $!%!%!#./"&"&UY'+/YY Y 	Y
 Y Y Y ",Y Y Y  Y  Y SY %Y Y  
&!Yv:B:GP:	:( ot(69MRgk	*$*0r0   r   )$
__future__r   loggingcollectionsr   	itertoolsr   typingr   r   r   	lightningrc   r=   r-   r:   
tokenizersr	   tqdmr
   model2vec.inferencer   model2vec.train.baser   !model2vec.train.lightning_modulesr   r   model2vec.train.utilsr   	getLoggerr   re   r}   r#   r   r    r0   r+   <module>r      si    "    % %       > 1 l 6			8	$IT#Y'	~#3 ~r0   