code: def nmf(
      input_matrix: Union[pd.Series, pd.DataFrame],
      n_components=2,
      random_state=None,
  ) -> pd.Series:
      """
      Performs non-negative matrix factorization on the given input.
  
      Non-Negative Matrix Factorization (NMF) is often used in
      natural language processing to find clusters of similar
      texts (e.g. some texts in a corpus might be about sports
      and some about music, so they will differ in the usage
      of technical terms; see the example below).
  
      Given a document-term matrix (so in
      texthero usually a Series after applying
      :meth:`texthero.representation.tfidf` or some other first
      representation function that assigns a scalar (a weight) to each
      word), NMF will find n_components many topics (clusters) and
      calculate a vector for each document that places it correctly among
      the topics.
  
      NMF can directly handle sparse input, so when calling nmf on a
      sparse DataFrame, the advantage of sparseness is kept.
  
      Parameters
      ----------
      input_matrix : Pandas Series (VectorSeries) or DataFrame
  
      n_components : int, optinal, default=2
          Number of components to keep (dimensionality of output vectors).
          If n_components is not set or None, all components are kept.
  
      random_state : int, optional, default=None
          Pass an int for reproducible results across multiple function calls.
  
      Returns
      -------
      Pandas Series with the vector calculated by NMF for the document in
      every cell.
  
      Examples
      --------
      >>> import texthero as hero
      >>> import pandas as pd
      >>> s = pd.Series(["Football, Sports, Soccer",
      ...               "Music, Violin, Orchestra", "Football, Music"])
      >>> s = s.pipe(hero.clean).pipe(hero.tokenize).pipe(
      ...                                         hero.term_frequency
      ...                                                 )
      >>> hero.nmf(s) # doctest: +SKIP
      0                    [0.9080190347553924, 0.0]
      1                     [0.0, 0.771931061231598]
      2    [0.3725409073202516, 0.31656880119331093]
      dtype: object
      >>> # As we can see, the third document, which
      >>> # is a mix of sports and music, is placed
      >>> # between the two axes (the topics) while
      >>> # the other documents are placed right on
      >>> # one topic axis each.
  
      See also
      --------
      `NMF on Wikipedia
      <https://en.wikipedia.org/wiki/Non-negative_matrix_factorization>`_
  
      """
      # Default n_components=2 to enable users to easily plot the results.
      nmf = NMF(
          n_components=n_components,
          init="random",
          random_state=random_state,
      )
  
      if isinstance(input_matrix, pd.DataFrame):
          input_matrix_coo = input_matrix.sparse.to_coo()
          input_matrix_for_vectorization = input_matrix_coo.astype(
              "float64"
          )
      else:
          input_matrix_for_vectorization = list(input_matrix)
  
      return pd.Series(
          list(nmf.fit_transform(input_matrix_for_vectorization)),
          index=input_matrix.index,
      )
  
imports: import pandas
  import numpy
  from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer
  from sklearn.manifold import TSNE
  from sklearn.decomposition import PCA, NMF
  from sklearn.cluster import KMeans, DBSCAN, MeanShift
  from sklearn.metrics.pairwise import cosine_similarity
  from sklearn.preprocessing import normalize
  from scipy.sparse import coo_matrix
  from typing import Optional, Union, Any
  from texthero._types import TextSeries, TokenSeries, VectorSeries, DataFrame, InputSeries
  from texthero import preprocessing
  import logging
  import warnings
label_desc: Use image node_id 5 for calling a global function with example usage: nmf(input_matrix, n_components, random_state) and returns: pd