class_docstr: Train and apply a topic model to vectorized texts using scikit-learn's
  implementations of LSA, LDA, and NMF models. Also any other topic model implementations that have
  `component_`, `n_topics` and `transform` attributes. Inspect and visualize results.
  Save and load trained models to and from disk.
  
  Prepare a vectorized corpus (i.e. document-term matrix) and corresponding
  vocabulary (i.e. mapping of term strings to column indices in the matrix).
  See :class:`textacy.representations.vectorizers.Vectorizer` for details. In short:
  
  .. code-block:: pycon
  
      >>> vectorizer = Vectorizer(
      ...     tf_type="linear", idf_type="smooth", norm="l2",
      ...     min_df=3, max_df=0.95, max_n_terms=100000)
      >>> doc_term_matrix = vectorizer.fit_transform(terms_list)
  
  Initialize and train a topic model:
  
  .. code-block:: pycon
  
      >>> model = textacy.tm.TopicModel("nmf", n_topics=20)
      >>> model.fit(doc_term_matrix)
      >>> model
      TopicModel(n_topics=10, model=NMF)
  
  Transform the corpus and interpret our model:
  
  .. code-block:: pycon
  
      >>> doc_topic_matrix = model.transform(doc_term_matrix)
      >>> for topic_idx, top_terms in model.top_topic_terms(vectorizer.id_to_term, topics=[0,1]):
      ...     print("topic", topic_idx, ":", "   ".join(top_terms))
      topic 0 : people   american   go   year   work   think   $   today   money   america
      topic 1 : rescind   quorum   order   unanimous   consent   ask   president   mr.   madam   absence
      >>> for topic_idx, top_docs in model.top_topic_docs(doc_topic_matrix, topics=[0,1], top_n=2):
      ...     print(topic_idx)
      ...     for j in top_docs:
      ...         print(corpus[j]._.meta["title"])
      0
      THE MOST IMPORTANT ISSUES FACING THE AMERICAN PEOPLE
      55TH ANNIVERSARY OF THE BATTLE OF CRETE
      1
      CHEMICAL WEAPONS CONVENTION
      MFN STATUS FOR CHINA
      >>> for doc_idx, topics in model.top_doc_topics(doc_topic_matrix, docs=range(5), top_n=2):
      ...     print(corpus[doc_idx]._.meta["title"], ":", topics)
      JOIN THE SENATE AND PASS A CONTINUING RESOLUTION : (9, 0)
      MEETING THE CHALLENGE : (2, 0)
      DISPOSING OF SENATE AMENDMENT TO H.R. 1643, EXTENSION OF MOST-FAVORED- NATION TREATMENT FOR BULGARIA : (0, 9)
      EXAMINING THE SPEAKER'S UPCOMING TRAVEL SCHEDULE : (0, 9)
      FLOODING IN PENNSYLVANIA : (0, 9)
      >>> for i, val in enumerate(model.topic_weights(doc_topic_matrix)):
      ...     print(i, val)
      0 0.302796022302
      1 0.0635617650602
      2 0.0744927472417
      3 0.0905778808867
      4 0.0521162262192
      5 0.0656303769725
      6 0.0973516532757
      7 0.112907245542
      8 0.0680659204364
      9 0.0725001620636
  
  Visualize the model:
  
  .. code-block:: pycon
  
      >>> model.termite_plot(doc_term_matrix, vectorizer.id_to_term,
      ...                    topics=-1,  n_terms=25, sort_terms_by="seriation")
  
  Persist our topic model to disk:
  
  .. code-block:: pycon
  
      >>> model.save("nmf-10topics.pkl")
  
  Args:
      model: Name or instance of an sklearn decomposition model.
      n_topics: Number of topics in the model to be initialized
      **kwargs:
          variety of parameters used to initialize the model; see individual
          sklearn pages for full details
  
  Raises:
      ValueError: if ``model`` not in ``{"nmf", "lda", "lsa"}`` or is not an
          NMF, LatentDirichletAllocation, or TruncatedSVD instance
  
  See Also:
      * http://scikit-learn.org/stable/modules/generated/sklearn.decomposition.NMF.html
      * http://scikit-learn.org/stable/modules/generated/sklearn.decomposition.LatentDirichletAllocation.html
      * http://scikit-learn.org/stable/modules/generated/sklearn.decomposition.TruncatedSVD.html
class_docstr_tok: ["Train","and","apply","a","topic","model","to","vectorized","texts","using","scikit-learn's","implementations","of","LSA",",","LDA",",","and","NMF","models",".","Also","any","other","topic","model","implementations","that","have","`","component_","`",",","`","n_topics","`","and","`","transform","`","attributes",".","Inspect","and","visualize","results",".","Save","and","load","trained","models","to","and","from","disk",".","Prepare","a","vectorized","corpus","(","i.e",".","document-term","matrix",")","and","corresponding","vocabulary","(","i.e",".","mapping","of","term","strings","to","column","indices","in","the","matrix",")",".","See",":","class",":","`","textacy.representations.vectorizers.Vectorizer","`","for","details",".","In","short",":","..","code-block",":",":","pycon",">",">",">","vectorizer","=","Vectorizer","(","...","tf_type=","''","linear","''",",","idf_type=","''","smooth","''",",","norm=","''","l2","''",",","...","min_df=3",",","max_df=0.95",",","max_n_terms=100000",")",">",">",">","doc_term_matrix","=","vectorizer.fit_transform","(","terms_list",")","Initialize","and","train","a","topic","model",":","..","code-block",":",":","pycon",">",">",">","model","=","textacy.tm.TopicModel","(","``","nmf","''",",","n_topics=20",")",">",">",">","model.fit","(","doc_term_matrix",")",">",">",">","model","TopicModel","(","n_topics=10",",","model=NMF",")","Transform","the","corpus","and","interpret","our","model",":","..","code-block",":",":","pycon",">",">",">","doc_topic_matrix","=","model.transform","(","doc_term_matrix",")",">",">",">","for","topic_idx",",","top_terms","in","model.top_topic_terms","(","vectorizer.id_to_term",",","topics=","[","0,1","]",")",":","...","print","(","``","topic","''",",","topic_idx",",","``",":","''",",","``","``",".join","(","top_terms",")",")","topic","0",":","people","american","go","year","work","think","$","today","money","america","topic","1",":","rescind","quorum","order","unanimous","consent","ask","president","mr.","madam","absence",">",">",">","for","topic_idx",",","top_docs","in","model.top_topic_docs","(","doc_topic_matrix",",","topics=","[","0,1","]",",","top_n=2",")",":","...","print","(","topic_idx",")","...","for","j","in","top_docs",":","...","print","(","corpus","[","j","]","._.meta","[","``","title","''","]",")","0","THE","MOST","IMPORTANT","ISSUES","FACING","THE","AMERICAN","PEOPLE","55TH","ANNIVERSARY","OF","THE","BATTLE","OF","CRETE","1","CHEMICAL","WEAPONS","CONVENTION","MFN","STATUS","FOR","CHINA",">",">",">","for","doc_idx",",","topics","in","model.top_doc_topics","(","doc_topic_matrix",",","docs=range","(","5",")",",","top_n=2",")",":","...","print","(","corpus","[","doc_idx","]","._.meta","[","``","title","''","]",",","``",":","''",",","topics",")","JOIN","THE","SENATE","AND","PASS","A","CONTINUING","RESOLUTION",":","(","9",",","0",")","MEETING","THE","CHALLENGE",":","(","2",",","0",")","DISPOSING","OF","SENATE","AMENDMENT","TO","H.R",".","1643",",","EXTENSION","OF","MOST-FAVORED-","NATION","TREATMENT","FOR","BULGARIA",":","(","0",",","9",")","EXAMINING","THE","SPEAKER","'S","UPCOMING","TRAVEL","SCHEDULE",":","(","0",",","9",")","FLOODING","IN","PENNSYLVANIA",":","(","0",",","9",")",">",">",">","for","i",",","val","in","enumerate","(","model.topic_weights","(","doc_topic_matrix",")",")",":","...","print","(","i",",","val",")","0","0.302796022302","1","0.0635617650602","2","0.0744927472417","3","0.0905778808867","4","0.0521162262192","5","0.0656303769725","6","0.0973516532757","7","0.112907245542","8","0.0680659204364","9","0.0725001620636","Visualize","the","model",":","..","code-block",":",":","pycon",">",">",">","model.termite_plot","(","doc_term_matrix",",","vectorizer.id_to_term",",","...","topics=-1",",","n_terms=25",",","sort_terms_by=","''","seriation","''",")","Persist","our","topic","model","to","disk",":","..","code-block",":",":","pycon",">",">",">","model.save","(","``","nmf-10topics.pkl","''",")","Args",":","model",":","Name","or","instance","of","an","sklearn","decomposition","model",".","n_topics",":","Number","of","topics","in","the","model","to","be","initialized","*","*","kwargs",":","variety","of","parameters","used","to","initialize","the","model",";","see","individual","sklearn","pages","for","full","details","Raises",":","ValueError",":","if","``","model","``","not","in","``","{","``","nmf","''",",","``","lda","''",",","``","lsa","''","}","``","or","is","not","an","NMF",",","LatentDirichletAllocation",",","or","TruncatedSVD","instance","See","Also",":","*","http",":","\/\/scikit-learn.org\/stable\/modules\/generated\/sklearn.decomposition.NMF.html","*","http",":","\/\/scikit-learn.org\/stable\/modules\/generated\/sklearn.decomposition.LatentDirichletAllocation.html","*","http",":","\/\/scikit-learn.org\/stable\/modules\/generated\/sklearn.decomposition.TruncatedSVD.html"]
docstr: Make a "termite" plot for assessing topic models using a tabular layout
  to promote comparison of terms both within and across topics.
  
  Args:
      doc_term_matrix: Corpus represented as a document-term matrix with shape
          (n_docs, n_terms); may have tf- or tfidf-weighting.
      id2term: Object that returns the term string corresponding to term id ``i``
          through ``id2term[i]``. Could be a list of strings where the index
          represents the term id, such as that returned by
          ``sklearn.feature_extraction.text.CountVectorizer.get_feature_names()``,
          or a mapping of term id to term string.
      topics: Topic(s) to include in termite plot; if -1, all topics are included.
      sort_topics_by
      highlight_topics: Indices for up to 6 topics to visually highlight
          in the plot with contrasting colors.
      n_terms: Number of top terms to include in termite plot.
      rank_terms_by: Value used to rank terms; the top-ranked ``n_terms``
          are included in the plot.
      sort_terms_by: Method used to vertically sort the selected top ``n_terms``
          terms; the default ("seriation") groups similar terms together, which
          facilitates cross-topic assessment.
      save: The full /path/to/fname on disk to save figure, or None.
      rc_params: Allow passing parameters to rc_context in matplotlib.plyplot,
          details in https://matplotlib.org/3.1.0/api/_as_gen/matplotlib.pyplot.rc_context.html
  
  Returns:
      ``matplotlib.axes.Axes.axis``: Axis on which termite plot is plotted.
  
  Raises:
      ValueError: if more than 6 topics are selected for highlighting, or
          an invalid value is passed for the sort_topics_by, rank_terms_by,
          and/or sort_terms_by params
  
  References:
      - Chuang, Jason, Christopher D. Manning, and Jeffrey Heer. "Termite:
        Visualization techniques for assessing textual topic models."
        Proceedings of the International Working Conference on Advanced
        Visual Interfaces. ACM, 2012.
      - for sorting by "seriation", see https://arxiv.org/abs/1406.5370
  
  See Also:
      :func:`viz.termite_plot <textacy.viz.termite.termite_plot>`
  
  TODO: `rank_terms_by` other metrics, e.g. topic salience or relevance
docstr_tok: ["Make","a","``","termite","''","plot","for","assessing","topic","models","using","a","tabular","layout","to","promote","comparison","of","terms","both","within","and","across","topics",".","Args",":","doc_term_matrix",":","Corpus","represented","as","a","document-term","matrix","with","shape","(","n_docs",",","n_terms",")",";","may","have","tf-","or","tfidf-weighting",".","id2term",":","Object","that","returns","the","term","string","corresponding","to","term","id","``","i","``","through","``","id2term","[","i","]","``",".","Could","be","a","list","of","strings","where","the","index","represents","the","term","id",",","such","as","that","returned","by","``","sklearn.feature_extraction.text.CountVectorizer.get_feature_names","(",")","``",",","or","a","mapping","of","term","id","to","term","string",".","topics",":","Topic","(","s",")","to","include","in","termite","plot",";","if","-1",",","all","topics","are","included",".","sort_topics_by","highlight_topics",":","Indices","for","up","to","6","topics","to","visually","highlight","in","the","plot","with","contrasting","colors",".","n_terms",":","Number","of","top","terms","to","include","in","termite","plot",".","rank_terms_by",":","Value","used","to","rank","terms",";","the","top-ranked","``","n_terms","``","are","included","in","the","plot",".","sort_terms_by",":","Method","used","to","vertically","sort","the","selected","top","``","n_terms","``","terms",";","the","default","(","``","seriation","''",")","groups","similar","terms","together",",","which","facilitates","cross-topic","assessment",".","save",":","The","full","\/path\/to\/fname","on","disk","to","save","figure",",","or","None",".","rc_params",":","Allow","passing","parameters","to","rc_context","in","matplotlib.plyplot",",","details","in","https",":","\/\/matplotlib.org\/3.1.0\/api\/_as_gen\/matplotlib.pyplot.rc_context.html","Returns",":","``","matplotlib.axes.Axes.axis","``",":","Axis","on","which","termite","plot","is","plotted",".","Raises",":","ValueError",":","if","more","than","6","topics","are","selected","for","highlighting",",","or","an","invalid","value","is","passed","for","the","sort_topics_by",",","rank_terms_by",",","and\/or","sort_terms_by","params","References",":","-","Chuang",",","Jason",",","Christopher","D.","Manning",",","and","Jeffrey","Heer",".","``","Termite",":","Visualization","techniques","for","assessing","textual","topic","models",".","''","Proceedings","of","the","International","Working","Conference","on","Advanced","Visual","Interfaces",".","ACM",",","2012",".","-","for","sorting","by","``","seriation","''",",","see","https",":","\/\/arxiv.org\/abs\/1406.5370","See","Also",":",":","func",":","`","viz.termite_plot","<","textacy.viz.termite.termite_plot",">","`","TODO",":","`","rank_terms_by","`","other","metrics",",","e.g",".","topic","salience","or","relevance"]
code: def termite_plot(
      self,
      doc_term_matrix: np.ndarray | sp.csr_matrix,
      id2term: list[str] | dict[int, str],
      *,
      topics: int | Sequence[int] = -1,
      sort_topics_by: Literal["index", "weight"] = "index",
      highlight_topics: Optional[int | Sequence[int]] = None,
      n_terms: int = 25,
      rank_terms_by: Literal[
          "topic_weight", "corpus_weight"
      ] = "topic_weight",
      sort_terms_by: Literal[
          "seriation", "weight", "index", "alphabetical"
      ] = "seriation",
      save: Optional[str] = None,
      rc_params: Optional[dict] = None,
  ):
      """
      Make a "termite" plot for assessing topic models using a tabular layout
      to promote comparison of terms both within and across topics.
  
      Args:
          doc_term_matrix: Corpus represented as a document-term matrix with shape
              (n_docs, n_terms); may have tf- or tfidf-weighting.
          id2term: Object that returns the term string corresponding to term id ``i``
              through ``id2term[i]``. Could be a list of strings where the index
              represents the term id, such as that returned by
              ``sklearn.feature_extraction.text.CountVectorizer.get_feature_names()``,
              or a mapping of term id to term string.
          topics: Topic(s) to include in termite plot; if -1, all topics are included.
          sort_topics_by
          highlight_topics: Indices for up to 6 topics to visually highlight
              in the plot with contrasting colors.
          n_terms: Number of top terms to include in termite plot.
          rank_terms_by: Value used to rank terms; the top-ranked ``n_terms``
              are included in the plot.
          sort_terms_by: Method used to vertically sort the selected top ``n_terms``
              terms; the default ("seriation") groups similar terms together, which
              facilitates cross-topic assessment.
          save: The full /path/to/fname on disk to save figure, or None.
          rc_params: Allow passing parameters to rc_context in matplotlib.plyplot,
              details in https://matplotlib.org/3.1.0/api/_as_gen/matplotlib.pyplot.rc_context.html
  
      Returns:
          ``matplotlib.axes.Axes.axis``: Axis on which termite plot is plotted.
  
      Raises:
          ValueError: if more than 6 topics are selected for highlighting, or
              an invalid value is passed for the sort_topics_by, rank_terms_by,
              and/or sort_terms_by params
  
      References:
          - Chuang, Jason, Christopher D. Manning, and Jeffrey Heer. "Termite:
            Visualization techniques for assessing textual topic models."
            Proceedings of the International Working Conference on Advanced
            Visual Interfaces. ACM, 2012.
          - for sorting by "seriation", see https://arxiv.org/abs/1406.5370
  
      See Also:
          :func:`viz.termite_plot <textacy.viz.termite.termite_plot>`
  
      TODO: `rank_terms_by` other metrics, e.g. topic salience or relevance
      """
      if highlight_topics is not None:
          if isinstance(highlight_topics, int):
              highlight_topics = (highlight_topics,)
          elif len(highlight_topics) > 6:
              raise ValueError(
                  "no more than 6 topics may be highlighted at once"
              )
  
      # get topics indices
      topic_inds: tuple[int, ...]
      if topics == -1:
          topic_inds = tuple(range(self.n_topics))
      elif isinstance(topics, int):
          topic_inds = (topics,)
      else:
          topic_inds = tuple(topics)
  
      # get topic indices in sorted order
      if sort_topics_by == "index":
          topic_inds = tuple(sorted(topic_inds))
      elif sort_topics_by == "weight":
          topic_inds = tuple(
              topic_ind
              for topic_ind in np.argsort(
                  self.topic_weights(self.transform(doc_term_matrix))
              )[::-1]
              if topic_ind in topic_inds
          )
      else:
          raise ValueError(
              errors.value_invalid_msg(
                  "sort_topics_by",
                  sort_topics_by,
                  {"index", "weight"},
              )
          )
  
      # get column index of any topics to highlight in termite plot
      if highlight_topics is not None:
          highlight_cols = tuple(
              i
              for i in range(len(topic_inds))
              if topic_inds[i] in highlight_topics
          )
      else:
          highlight_cols = None
  
      # get top term indices
      term_inds: list[int]
      if rank_terms_by == "corpus_weight":
          term_inds = np.argsort(np.ravel(doc_term_matrix.sum(axis=0)))[
              : -n_terms - 1 : -1
          ].tolist()
      elif rank_terms_by == "topic_weight":
          term_inds = np.argsort(self.model.components_.sum(axis=0))[
              : -n_terms - 1 : -1
          ].tolist()
      else:
          raise ValueError(
              errors.value_invalid_msg(
                  "rank_terms_by",
                  rank_terms_by,
                  {"corpus_weight", "topic_weight"},
              )
          )
  
      # get top term indices in sorted order
      if sort_terms_by == "weight":
          pass
      elif sort_terms_by == "index":
          term_inds = sorted(term_inds)
      elif sort_terms_by == "alphabetical":
          term_inds = sorted(term_inds, key=lambda x: id2term[x])
      elif sort_terms_by == "seriation":
          topic_term_weights_mat = np.array(
              np.array(
                  [
                      self.model.components_[topic_ind][term_inds]
                      for topic_ind in topic_inds
                  ]
              )
          ).T
          # calculate similarity matrix
          topic_term_weights_sim = np.dot(
              topic_term_weights_mat, topic_term_weights_mat.T
          )
          # substract minimum of sim mat in order to keep sim mat nonnegative
          topic_term_weights_sim = (
              topic_term_weights_sim - topic_term_weights_sim.min()
          )
          # compute Laplacian matrice and its 2nd eigenvector
          L = (
              np.diag(sum(topic_term_weights_sim, 1))
              - topic_term_weights_sim
          )
          D, V = np.linalg.eigh(L)
          D = D[np.argsort(D)]
          V = V[:, np.argsort(D)]
          fiedler = V[:, 1]
          # get permutation corresponding to sorting the 2nd eigenvector
          term_inds = [term_inds[i] for i in np.argsort(fiedler)]
      else:
          raise ValueError(
              errors.value_invalid_msg(
                  "sort_terms_by",
                  sort_terms_by,
                  {"weight", "index", "alphabetical", "seriation"},
              )
          )
  
      # get topic and term labels
      topic_labels = tuple(
          "topic {}".format(topic_ind) for topic_ind in topic_inds
      )
      term_labels = tuple(id2term[term_ind] for term_ind in term_inds)
  
      # get topic-term weights to size dots
      term_topic_weights = np.array(
          [
              self.model.components_[topic_ind][term_inds]
              for topic_ind in topic_inds
          ]
      ).T
  
      return viz.draw_termite_plot(
          term_topic_weights,
          topic_labels,
          term_labels,
          highlight_cols=highlight_cols,
          save=save,
          rc_params=rc_params,
      )
  
imports: from __future__ import annotations
  import logging
  from typing import ClassVar, Iterable, Literal, Optional, Sequence
  import joblib
  import numpy
  import scipy.sparse
  from sklearn.decomposition import NMF, LatentDirichletAllocation, TruncatedSVD
  from ..None import errors, types, viz
label_desc: Use image node_id 15 for calling the TopicModel obj's underlying member method code with example usage: obj.termite_plot(doc_term_matrix, id2term) and returns: viz