
    c^                     Z   d Z ddlZddlZddlZddlZddlZej        d         dk    rddlm	Z	 nddl	m	Z	 	 ddl
mZ dZn# e$ r dZY nw xY w G d d	          Z G d
 de          Z G d de          Z G d de          Z G d de          Z G d d          Z G d d          ZdS )aV  Callbacks can be used to observe the training process.

Since training in huge corpora can be time consuming, we want to offer the users some insight
into the process, in real time. In this way, convergence issues
or other potential problems can be identified early in the process,
saving precious time and resources.

The metrics exposed through this module can be used to construct Callbacks, which will be called
at specific points in the training process, such as "epoch starts" or "epoch finished".
These metrics can be used to assess mod's convergence or correctness, for example
to save the model, visualize intermediate results, or anything else.

Usage examples
--------------
To implement a Callback, inherit from this base class and override one or more of its methods.

Create a callback to save the training model after each epoch

.. sourcecode:: pycon

    >>> from gensim.test.utils import get_tmpfile
    >>> from gensim.models.callbacks import CallbackAny2Vec
    >>>
    >>>
    >>> class EpochSaver(CallbackAny2Vec):
    ...     '''Callback to save model after each epoch.'''
    ...
    ...     def __init__(self, path_prefix):
    ...         self.path_prefix = path_prefix
    ...         self.epoch = 0
    ...
    ...     def on_epoch_end(self, model):
    ...         output_path = get_tmpfile('{}_epoch{}.model'.format(self.path_prefix, self.epoch))
    ...         model.save(output_path)
    ...         self.epoch += 1
    ...

Create a callback to print progress information to the console:

.. sourcecode:: pycon

    >>> class EpochLogger(CallbackAny2Vec):
    ...     '''Callback to log information about training'''
    ...
    ...     def __init__(self):
    ...         self.epoch = 0
    ...
    ...     def on_epoch_begin(self, model):
    ...         print("Epoch #{} start".format(self.epoch))
    ...
    ...     def on_epoch_end(self, model):
    ...         print("Epoch #{} end".format(self.epoch))
    ...         self.epoch += 1
    ...
    >>>
    >>> epoch_logger = EpochLogger()
    >>> w2v_model = Word2Vec(common_texts, epochs=5, vector_size=10, min_count=0, seed=42, callbacks=[epoch_logger])
    Epoch #0 start
    Epoch #0 end
    Epoch #1 start
    Epoch #1 end
    Epoch #2 start
    Epoch #2 end
    Epoch #3 start
    Epoch #3 end
    Epoch #4 start
    Epoch #4 end

Create and bind a callback to a topic model. This callback will log the perplexity metric in real time:

.. sourcecode:: pycon

    >>> from gensim.models.callbacks import PerplexityMetric
    >>> from gensim.models.ldamodel import LdaModel
    >>> from gensim.test.utils import common_corpus, common_dictionary
    >>>
    >>> # Log the perplexity score at the end of each epoch.
    >>> perplexity_logger = PerplexityMetric(corpus=common_corpus, logger='shell')
    >>> lda = LdaModel(common_corpus, id2word=common_dictionary, num_topics=5, callbacks=[perplexity_logger])

    N   )Queue)VisdomTFc                   $    e Zd ZdZd Zd Zd ZdS )MetricaQ  Base Metric class for topic model evaluation metrics.

    Concrete implementations include:

        * :class:`~gensim.models.callbacks.CoherenceMetric`
        * :class:`~gensim.models.callbacks.PerplexityMetric`
        * :class:`~gensim.models.callbacks.DiffMetric`
        * :class:`~gensim.models.callbacks.ConvergenceMetric`

    c                 V    | j         | j         S t          |           j        dd         S )zGet a string representation of Metric class.

        Returns
        -------
        str
            Human readable representation of the metric.

        Ni)titletype__name__selfs    7lib/python3.11/site-packages/gensim/models/callbacks.py__str__zMetric.__str__x   s.     : 	,:::&ss++    c                 \    |                                 D ]\  }}t          | ||           dS )zSet the metric parameters.

        Parameters
        ----------
        **parameters
            Keyword arguments to override the object's internal attributes.

        N)itemssetattr)r   
parameters	parametervalues       r   set_parameterszMetric.set_parameters   sC     !+ 0 0 2 2 	, 	,IuD)U++++	, 	,r   c                      t          d          )a   Get the metric's value at this point in time.

        Warnings
        --------
        The user **must** provide a concrete implementation for this method for every subclass of
        this class.

        See Also
        --------
        :meth:`gensim.models.callbacks.CoherenceMetric.get_value`
        :meth:`gensim.models.callbacks.PerplexityMetric.get_value`
        :meth:`gensim.models.callbacks.DiffMetric.get_value`
        :meth:`gensim.models.callbacks.ConvergenceMetric.get_value`

        Returns
        -------
        object
            The metric's type depends on what exactly it measures. In the simplest case it might
            be a real number corresponding to an error estimate. It could however be anything else
            that is useful to report or visualize.

        zBPlease provide an implementation for `get_value` in your subclass.)NotImplementedErrorr   s    r   	get_valuezMetric.get_value   s    . ""fgggr   N)r   
__module____qualname____doc__r   r   r    r   r   r   r   m   sP        	 	, , ,
, 
, 
,h h h h hr   r   c                   .     e Zd ZdZ	 	 ddZ fdZ xZS )CoherenceMetriczMetric class for coherence evaluation.

    See Also
    --------
    :class:`~gensim.models.coherencemodel.CoherenceModel`

    N
   c
                     || _         || _        || _        || _        || _        || _        || _        || _        |	| _        dS )a  

        Parameters
        ----------
        corpus : {iterable of list of (int, float), scipy.sparse.csc}, optional
            Stream of document vectors or sparse matrix of shape (`num_documents`, `num_terms`).
        texts : list of char (str of length 1), optional
            Tokenized texts needed for coherence models that use sliding window based probability estimator.
        dictionary : :class:`~gensim.corpora.dictionary.Dictionary`, optional
            Gensim dictionary mapping from integer IDs to words, needed to create corpus. If `model.id2word` is present,
            this is not needed. If both are provided, `dictionary` will be used.
        coherence : {'u_mass', 'c_v', 'c_uci', 'c_npmi'}, optional
            Coherence measure to be used. 'c_uci' is also known as 'c_pmi' in the literature.
            For 'u_mass', the corpus **MUST** be provided. If `texts` is provided, it will be converted
            to corpus using the dictionary. For 'c_v', 'c_uci' and 'c_npmi', `texts` **MUST** be provided.
            Corpus is not needed.
        window_size : int, optional
            Size of the window to be used for coherence measures using boolean
            sliding window as their probability estimator. For 'u_mass' this doesn't matter.
            If 'None', the default window sizes are used which are:

                * `c_v` - 110
                * `c_uci` - 10
                * `c_npmi` - 10
        topn : int, optional
            Number of top words to be extracted from each topic.
        logger : {'shell', 'visdom'}, optional
           Monitor training process using one of the available methods. 'shell' will print the coherence value in
           the active shell, while 'visdom' will visualize the coherence value with increasing epochs using the Visdom
           visualization framework.
        viz_env : object, optional
            Visdom environment to use for plotting the graph. Unused.
        title : str, optional
            Title of the graph plot in case `logger == 'visdom'`. Unused.

        N)	corpus
dictionary	coherencetextswindow_sizetopnloggerviz_envr	   )
r   r#   r&   r$   r%   r'   r(   r)   r*   r	   s
             r   __init__zCoherenceMetric.__init__   sI    L $"
&	


r   c           
      &   d| _         d| _         t          t          |           j        di | t
          j                            | j         | j        | j        | j	        | j
        | j        | j        | j                  }|                                S )a  Get the coherence score.

        Parameters
        ----------
        **kwargs
            Key word arguments to override the object's internal attributes.
            One of the following parameters are expected:

                * `model` - pre-trained topic model of type :class:`~gensim.models.ldamodel.LdaModel`.
                * `topics` - list of tokenized topics.

        Returns
        -------
        float
            The coherence score.

        N)modeltopicsr&   r#   r$   r'   r%   r(   r   )r-   r.   superr    r   gensimmodelsCoherenceModelr&   r#   r$   r'   r%   r(   get_coherence)r   kwargscm	__class__s      r   r   zCoherenceMetric.get_value   s    & 
3ot$$3==f===]))*T[
4;D4Dn49 * 
 
 !!!r   )	NNNNNr!   NNNr   r   r   r   r+   r   __classcell__r6   s   @r   r    r       sa          LPMQ. . . .`" " " " " " " " "r   r    c                   *     e Zd ZdZddZ fdZ xZS )PerplexityMetricz'Metric class for perplexity evaluation.Nc                 >    || _         || _        || _        || _        dS )a  

        Parameters
        ----------
        corpus : {iterable of list of (int, float), scipy.sparse.csc}, optional
            Stream of document vectors or sparse matrix of shape (`num_documents`, `num_terms`).
        logger : {'shell', 'visdom'}, optional
           Monitor training process using one of the available methods. 'shell' will print the perplexity value in
           the active shell, while 'visdom' will visualize the coherence value with increasing epochs using the Visdom
           visualization framework.
        viz_env : object, optional
            Visdom environment to use for plotting the graph. Unused.
        title : str, optional
            Title of the graph plot in case `logger == 'visdom'`. Unused.

        N)r#   r)   r*   r	   )r   r#   r)   r*   r	   s        r   r+   zPerplexityMetric.__init__  s$    " 


r   c                      t          t          |           j        di | t          d | j        D                       }| j                            | j                  |z  }t          j        |           S )a  Get the coherence score.

        Parameters
        ----------
        **kwargs
            Key word arguments to override the object's internal attributes.
            A trained topic model is expected using the 'model' key.
            This must be of type :class:`~gensim.models.ldamodel.LdaModel`.

        Returns
        -------
        float
            The perplexity score.

        c              3   *   K   | ]}|D ]	\  }}|V  
d S Nr   ).0document_cnts       r   	<genexpr>z-PerplexityMetric.get_value.<locals>.<genexpr>-  s3      RR8RRvq#3RRRRRRRr   r   )	r/   r;   r   sumr#   r-   boundnpexp2)r   r4   corpus_wordsperwordboundr6   s       r   r   zPerplexityMetric.get_value  su      	5%%4>>v>>>RRt{RRRRRz''44|Cw}%%%r   )NNNNr7   r9   s   @r   r;   r;     sR        11   ,& & & & & & & & &r   r;   c                   .     e Zd ZdZ	 	 d
dZ fd	Z xZS )
DiffMetricz-Metric class for topic difference evaluation.jaccardd   r!   TFNc
                     || _         || _        || _        || _        || _        || _        || _        || _        |	| _        dS )ac  

        Parameters
        ----------
        distance : {'kullback_leibler', 'hellinger', 'jaccard'}, optional
            Measure used to calculate difference between any topic pair.
        num_words : int, optional
            The number of most relevant words used if `distance == 'jaccard'`. Also used for annotating topics.
        n_ann_terms : int, optional
            Max number of words in intersection/symmetric difference between topics. Used for annotation.
        diagonal : bool, optional
            Whether we need the difference between identical topics (the diagonal of the difference matrix).
        annotation : bool, optional
            Whether the intersection or difference of words between two topics should be returned.
        normed : bool, optional
            Whether the matrix should be normalized or not.
        logger : {'shell', 'visdom'}, optional
           Monitor training process using one of the available methods. 'shell' will print the coherence value in
           the active shell, while 'visdom' will visualize the coherence value with increasing epochs using the Visdom
           visualization framework.
        viz_env : object, optional
            Visdom environment to use for plotting the graph. Unused.
        title : str, optional
            Title of the graph plot in case `logger == 'visdom'`. Unused.

        N	distance	num_wordsn_ann_termsdiagonal
annotationnormedr)   r*   r	   
r   rQ   rR   rS   rT   rU   rV   r)   r*   r	   s
             r   r+   zDiffMetric.__init__4  H    8 !"& $


r   c           	           t          t          |           j        di | | j                            | j        | j        | j        | j        | j	        | j
        | j                  \  }}|S )a@  Get the difference between each pair of topics in two topic models.

        Parameters
        ----------
        **kwargs
            Key word arguments to override the object's internal attributes.
            Two models of type :class:`~gensim.models.ldamodelLdaModel`
            are expected using the keys `model` and `other_model`.

        Returns
        -------
        np.ndarray of shape (`model.num_topics`, `other_model.num_topics`)
            Matrix of differences between each pair of topics.
        np.ndarray of shape (`model.num_topics`, `other_model.num_topics`, 2), optional
            Annotation matrix where for each pair we include the word from the intersection of the two topics,
            and the word from the symmetric difference of the two topics. Only included if `annotation == True`.

        r   )r/   rL   r   r-   diffother_modelrQ   rR   rS   rT   rU   rV   r   r4   diff_diagonalrB   r6   s       r   r   zDiffMetric.get_valueZ  sj    & 	/j$.88888:??dmT^T=MM4?DK
 
q r   	rM   rN   r!   TFTNNNr7   r9   s   @r   rL   rL   2  sY        77SWQU$ $ $ $L        r   rL   c                   .     e Zd ZdZ	 	 d
dZ fd	Z xZS )ConvergenceMetricz)Metric class for convergence evaluation. rM   rN   r!   TFNc
                     || _         || _        || _        || _        || _        || _        || _        || _        |	| _        dS )ab  

        Parameters
        ----------
        distance : {'kullback_leibler', 'hellinger', 'jaccard'}, optional
            Measure used to calculate difference between any topic pair.
        num_words : int, optional
            The number of most relevant words used if `distance == 'jaccard'`. Also used for annotating topics.
        n_ann_terms : int, optional
            Max number of words in intersection/symmetric difference between topics. Used for annotation.
        diagonal : bool, optional
            Whether we need the difference between identical topics (the diagonal of the difference matrix).
        annotation : bool, optional
            Whether the intersection or difference of words between two topics should be returned.
        normed : bool, optional
            Whether the matrix should be normalized or not.
        logger : {'shell', 'visdom'}, optional
           Monitor training process using one of the available methods. 'shell' will print the coherence value in
           the active shell, while 'visdom' will visualize the coherence value with increasing epochs using the Visdom
           visualization framework.
        viz_env : object, optional
            Visdom environment to use for plotting the graph. Unused.
        title : str, optional
            Title of the graph plot in case `logger == 'visdom'`. Unused.

       NrP   rW   s
             r   r+   zConvergenceMetric.__init__w  rX   r   c           	           t          t          |           j        di | | j                            | j        | j        | j        | j        | j	        | j
        | j                  \  }}t          j        |          S )a:  Get the sum of each element in the difference matrix between each pair of topics in two topic models.

        A small difference between the partially trained models produced by subsequent training iterations can indicate
        that the model has stopped significantly improving and has therefore converged to a local or global optimum.

        Parameters
        ----------
        **kwargs
            Key word arguments to override the object's internal attributes.
            Two models of type :class:`~gensim.models.ldamodel.LdaModel`
            are expected using the keys `model` and `other_model`.

        Returns
        -------
        float
            The sum of the difference matrix between two trained topic models (usually the same model after two
            subsequent training iterations).

        r   )r/   r`   r   r-   rZ   r[   rQ   rR   rS   rT   rU   rV   rG   rE   r\   s       r   r   zConvergenceMetric.get_value  su    ( 	6&&5?????:??dmT^T=MM4?DK
 
q vm$$$r   r^   r7   r9   s   @r   r`   r`   u  sY        33SWQU$ $ $ $L% % % % % % % % %r   r`   c                   &    e Zd ZdZd Zd ZddZdS )Callbacka+  A class representing routines called reactively at specific phases during trained.

    These can be used to log or visualize the training progress using any of the metric scores developed before.
    The values are stored at the end of each training epoch. The following metric scores are currently available:

        * :class:`~gensim.models.callbacks.CoherenceMetric`
        * :class:`~gensim.models.callbacks.PerplexityMetric`
        * :class:`~gensim.models.callbacks.DiffMetric`
        * :class:`~gensim.models.callbacks.ConvergenceMetric`

    c                     || _         dS )z

        Parameters
        ----------
        metrics : list of :class:`~gensim.models.callbacks.Metric`
            The list of metrics to be reported by the callback.

        N)metrics)r   rf   s     r   r+   zCallback.__init__  s     r   c                    || _         d| _        t          d | j        D                       r,t	          j        |          | _        t                      | _        t          d | j        D                       r0t          st          d          t                      | _        g | _        t          d | j        D                       rt          j        d          | _        dS dS )aA  Save the model instance and initialize any required variables which would be updated throughout training.

        Parameters
        ----------
        model : :class:`~gensim.models.basemodel.BaseTopicModel`
            The model for which the training will be reported (logged or visualized) by the callback.

        Nc              3   N   K   | ] }t          |t          t          f          V  !d S r?   
isinstancerL   r`   r@   metrics     r   rD   z%Callback.set_model.<locals>.<genexpr>  2      ^^vz&:/@"ABB^^^^^^r   c              3   ,   K   | ]}|j         d k    V  dS )visdomNr)   rk   s     r   rD   z%Callback.set_model.<locals>.<genexpr>  s)      DDVv}(DDDDDDr   z'Please install Visdom for visualizationc              3   ,   K   | ]}|j         d k    V  dS )shellNrp   rk   s     r   rD   z%Callback.set_model.<locals>.<genexpr>  s)      CCFv}'CCCCCCr   zgensim.models.ldamodel)r-   previousanyrf   copydeepcopyr   diff_matVISDOM_INSTALLEDImportErrorr   vizwindowslogging	getLoggerlog_typer   r-   s     r   	set_modelzCallback.set_model  s     
^^QUQ]^^^^^ 	$ M%00DM!GGDMDDt|DDDDD 	# M!"KLLLxxDHDLCCdlCCCCC 	H#-.FGGDMMM	H 	Hr   Nc                 F   i }t          | j                  D ]\  }}t          |          }|                    || j        | j                  }|||<   |j        dk    r*|dk    r%|j        dk    rt          j	        |g          }| j
                            |j        |j        t          d||                    }	| j                            |           | j                            t'          j        |	                     n| j
                            t          j	        |g          t          j	        |g          |j        t          d||                    }	| j                            t'          j        |	                     n|j        dk    rt          j        | j                                        t          j	        |g          f          }| j
                            |j        |j        | j        |         t          d||                     | j                            |           nU| j
                            t          j	        |g          t          j	        |g          |j        | j        |         d	
           |j        dk    rOd                    dt          |          d|dt          |          f          }
| j                            |
           t7          d | j        D                       rt'          j        | j                  | _        |S )a  Report the current epoch's metric value.

        Called at the end of each training iteration.

        Parameters
        ----------
        epoch : int
            The epoch that just ended.
        topics : list of list of str, optional
            List of tokenized topics. This is required for the coherence metric.

        Returns
        -------
        dict of (str, object)
            Mapping from metric names to their values. The type of each value depends on the metric type,
            for example :class:`~gensim.models.callbacks.DiffMetric` computes a matrix while
            :class:`~gensim.models.callbacks.ConvergenceMetric` computes a float.

        )r.   r-   r[   ro   r   Epochs)xlabelylabelr	   )Xenvopts)Yr   r   r   )r   r   winr   append)r   r   r   r   updaterr    zEpoch z: z estimate: c              3   N   K   | ] }t          |t          t          f          V  !d S r?   ri   rk   s     r   rD   z(Callback.on_epoch_end.<locals>.<genexpr>1  rm   r   )	enumeraterf   strr   r-   rs   r)   ndimrG   arrayrz   heatmapTr*   dictrw   putr{   r   ru   rv   lineconcatenategetjoinr~   infort   )r   epochr.   current_metricsirl   labelr   rw   
viz_metric	statements              r   on_epoch_endzCallback.on_epoch_end  s   *  #4<00 ,	. ,	.IAvKKE$$F$*RVR_$``E%*OE"}( "A: !zA~ G#%8UG#4#4%)X%5%5&jfn4x`emrCsCsCs &6 & &
 ))(333++DM*,E,EFFFF%)X]] hw//28UG3D3D&.!%Xe5!Q!Q!Q &3 & &

 ++DM*,E,EFFFFzA~ #%>4=3D3D3F3FRWQXHYHY2Z#[#[((&jfn$,q/!%Xe5!Q!Q!Q )    ))(3333 hw// hw// & $Q#+ &    }' .GGXs5zz4WZ[`WaWa$bcc	""9--- ^^QUQ]^^^^^ 	6 M$*55DMr   r?   )r   r   r   r   r+   r   r   r   r   r   rd   rd     sY        
 
	 	 	H H H4J J J J J Jr   rd   c                   *    e Zd ZdZd Zd Zd Zd ZdS )CallbackAny2Veca  Base class to build callbacks for :class:`~gensim.models.word2vec.Word2Vec` & subclasses.

    Callbacks are used to apply custom functions over the model at specific points
    during training (epoch start, batch end etc.). This is a base class and its purpose is to be inherited by
    custom Callbacks that implement one or more of its methods (depending on the point during training where they
    want some action to be taken).

    See examples at the module level docstring for how to define your own callbacks by inheriting  from this class.

    As of gensim 4.0.0, the following callbacks are no longer supported, and overriding them will have no effect:

    - on_batch_begin
    - on_batch_end

    c                     dS )zMethod called at the start of each epoch.

        Parameters
        ----------
        model : :class:`~gensim.models.word2vec.Word2Vec` or subclass
            Current model.

        Nr   r   s     r   on_epoch_beginzCallbackAny2Vec.on_epoch_beginG  	     	r   c                     dS )zMethod called at the end of each epoch.

        Parameters
        ----------
        model : :class:`~gensim.models.word2vec.Word2Vec` or subclass
            Current model.

        Nr   r   s     r   r   zCallbackAny2Vec.on_epoch_endR  r   r   c                     dS )zMethod called at the start of the training process.

        Parameters
        ----------
        model : :class:`~gensim.models.word2vec.Word2Vec` or subclass
            Current model.

        Nr   r   s     r   on_train_beginzCallbackAny2Vec.on_train_begin]  r   r   c                     dS )zMethod called at the end of the training process.

        Parameters
        ----------
        model : :class:`~gensim.models.word2vec.Word2Vec` or subclass
            Current model.

        Nr   r   s     r   on_train_endzCallbackAny2Vec.on_train_endh  r   r   N)r   r   r   r   r   r   r   r   r   r   r   r   r   7  sZ         	 	 		 	 		 	 		 	 	 	 	r   r   )r   r0   r|   ru   sysnumpyrG   version_infoqueuer   ro   r   rx   ry   r   r    r;   rL   r`   rd   r   r   r   r   <module>r      s  P Pd    



    A!    <h <h <h <h <h <h <h <h~U" U" U" U" U"f U" U" U"p+& +& +& +& +&v +& +& +&\@ @ @ @ @ @ @ @FA% A% A% A% A% A% A% A%H{ { { { { { { {|: : : : : : : : : :s   ? A	A	