code: def non_negative_factorization(
      X,
      W=None,
      H=None,
      n_components=None,
      init="random",
      update_H=True,
      solver="cd",
      tol=1e-4,
      max_iter=200,
      alpha=0.0,
      l1_ratio=0.0,
      regularization=None,
      random_state=None,
      verbose=0,
      shuffle=False,
      nls_max_iter=2000,
      sparseness=None,
      beta=1,
      eta=0.1,
  ):
      """Compute Non-negative Matrix Factorization (NMF)
  
      Find two non-negative matrices (W, H) whose product approximates the non-
      negative matrix X. This factorization can be used for example for
      dimensionality reduction, source separation or topic extraction.
  
      The objective function is::
  
          0.5 * ||X - WH||_Fro^2
          + alpha * l1_ratio * ||vec(W)||_1
          + alpha * l1_ratio * ||vec(H)||_1
          + 0.5 * alpha * (1 - l1_ratio) * ||W||_Fro^2
          + 0.5 * alpha * (1 - l1_ratio) * ||H||_Fro^2
  
      Where::
  
          ||A||_Fro^2 = \sum_{i,j} A_{ij}^2 (Frobenius norm)
          ||vec(A)||_1 = \sum_{i,j} abs(A_{ij}) (Elementwise L1 norm)
  
      The objective function is minimized with an alternating minimization of W
      and H. If H is given and update_H=False, it solves for W only.
  
      Parameters
      ----------
      X : array-like, shape (n_samples, n_features)
          Constant matrix.
  
      W : array-like, shape (n_samples, n_components)
          If init='custom', it is used as initial guess for the solution.
  
      H : array-like, shape (n_components, n_features)
          If init='custom', it is used as initial guess for the solution.
          If update_H=False, it is used as a constant, to solve for W only.
  
      n_components : integer
          Number of components, if n_components is not set all features
          are kept.
  
      init :  None | 'random' | 'nndsvd' | 'nndsvda' | 'nndsvdar' | 'custom'
          Method used to initialize the procedure.
          Default: 'nndsvd' if n_components < n_features, otherwise random.
          Valid options:
  
          - 'random': non-negative random matrices, scaled with:
              sqrt(X.mean() / n_components)
  
          - 'nndsvd': Nonnegative Double Singular Value Decomposition (NNDSVD)
              initialization (better for sparseness)
  
          - 'nndsvda': NNDSVD with zeros filled with the average of X
              (better when sparsity is not desired)
  
          - 'nndsvdar': NNDSVD with zeros filled with small random values
              (generally faster, less accurate alternative to NNDSVDa
              for when sparsity is not desired)
  
          - 'custom': use custom matrices W and H
  
      update_H : boolean, default: True
          Set to True, both W and H will be estimated from initial guesses.
          Set to False, only W will be estimated.
  
      solver : 'pg' | 'cd'
          Numerical solver to use:
          'pg' is a (deprecated) Projected Gradient solver.
          'cd' is a Coordinate Descent solver.
  
      tol : float, default: 1e-4
          Tolerance of the stopping condition.
  
      max_iter : integer, default: 200
          Maximum number of iterations before timing out.
  
      alpha : double, default: 0.
          Constant that multiplies the regularization terms.
  
      l1_ratio : double, default: 0.
          The regularization mixing parameter, with 0 <= l1_ratio <= 1.
          For l1_ratio = 0 the penalty is an elementwise L2 penalty
          (aka Frobenius Norm).
          For l1_ratio = 1 it is an elementwise L1 penalty.
          For 0 < l1_ratio < 1, the penalty is a combination of L1 and L2.
  
      regularization : 'both' | 'components' | 'transformation' | None
          Select whether the regularization affects the components (H), the
          transformation (W), both or none of them.
  
      random_state : integer seed, RandomState instance, or None (default)
          Random number generator seed control.
  
      verbose : integer, default: 0
          The verbosity level.
  
      shuffle : boolean, default: False
          If true, randomize the order of coordinates in the CD solver.
  
      nls_max_iter : integer, default: 2000
          Number of iterations in NLS subproblem.
          Used only in the deprecated 'pg' solver.
  
      sparseness : 'data' | 'components' | None, default: None
          Where to enforce sparsity in the model.
          Used only in the deprecated 'pg' solver.
  
      beta : double, default: 1
          Degree of sparseness, if sparseness is not None. Larger values mean
          more sparseness. Used only in the deprecated 'pg' solver.
  
      eta : double, default: 0.1
          Degree of correctness to maintain, if sparsity is not None. Smaller
          values mean larger error. Used only in the deprecated 'pg' solver.
  
      Returns
      -------
      W : array-like, shape (n_samples, n_components)
          Solution to the non-negative least squares problem.
  
      H : array-like, shape (n_components, n_features)
          Solution to the non-negative least squares problem.
  
      n_iter : int
          Actual number of iterations.
  
      References
      ----------
      C.-J. Lin. Projected gradient methods for non-negative matrix
      factorization. Neural Computation, 19(2007), 2756-2779.
      http://www.csie.ntu.edu.tw/~cjlin/nmf/
  
      Cichocki, Andrzej, and P. H. A. N. Anh-Huy. "Fast local algorithms for
      large scale nonnegative matrix and tensor factorizations."
      IEICE transactions on fundamentals of electronics, communications and
      computer sciences 92.3: 708-721, 2009.
      """
  
      X = check_array(X, accept_sparse=("csr", "csc"))
      check_non_negative(X, "NMF (input X)")
      _check_string_param(sparseness, solver)
  
      n_samples, n_features = X.shape
      if n_components is None:
          n_components = n_features
  
      if (
          not isinstance(n_components, INTEGER_TYPES)
          or n_components <= 0
      ):
          raise ValueError(
              "Number of components must be a positive integer;"
              " got (n_components=%r)" % n_components
          )
      if not isinstance(max_iter, INTEGER_TYPES) or max_iter < 0:
          raise ValueError(
              "Maximum number of iterations must be a positive integer;"
              " got (max_iter=%r)" % max_iter
          )
      if not isinstance(tol, numbers.Number) or tol < 0:
          raise ValueError(
              "Tolerance for stopping criteria must be "
              "positive; got (tol=%r)" % tol
          )
  
      # check W and H, or initialize them
      if init == "custom" and update_H:
          _check_init(H, (n_components, n_features), "NMF (input H)")
          _check_init(W, (n_samples, n_components), "NMF (input W)")
      elif not update_H:
          _check_init(H, (n_components, n_features), "NMF (input H)")
          W = np.zeros((n_samples, n_components))
      else:
          W, H = _initialize_nmf(
              X, n_components, init=init, random_state=random_state
          )
  
      if solver == "pg":
          warnings.warn(
              "'pg' solver will be removed in release 0.19."
              " Use 'cd' solver instead.",
              DeprecationWarning,
          )
          if update_H:  # fit_transform
              W, H, n_iter = _fit_projected_gradient(
                  X,
                  W,
                  H,
                  tol,
                  max_iter,
                  nls_max_iter,
                  alpha,
                  l1_ratio,
                  sparseness,
                  beta,
                  eta,
              )
          else:  # transform
              W, H, n_iter = _update_projected_gradient_w(
                  X,
                  W,
                  H,
                  tol,
                  nls_max_iter,
                  alpha,
                  l1_ratio,
                  sparseness,
                  beta,
                  eta,
              )
      elif solver == "cd":
          W, H, n_iter = _fit_coordinate_descent(
              X,
              W,
              H,
              tol,
              max_iter,
              alpha,
              l1_ratio,
              regularization,
              update_H=update_H,
              verbose=verbose,
              shuffle=shuffle,
              random_state=random_state,
          )
      else:
          raise ValueError("Invalid solver parameter '%s'." % solver)
  
      if n_iter == max_iter:
          warnings.warn(
              "Maximum number of iteration %d reached. Increase it to"
              " improve convergence." % max_iter,
              ConvergenceWarning,
          )
  
      return W, H, n_iter
  
imports: from __future__ import division, print_function
  from math import sqrt
  import warnings
  import numbers
  import numpy
  import scipy.sparse
  from ..base import BaseEstimator, TransformerMixin
  from ..utils import check_random_state, check_array
  from ..utils.extmath import randomized_svd, safe_sparse_dot, squared_norm
  from ..utils.extmath import fast_dot
  from ..utils.validation import check_is_fitted, check_non_negative
  from ..utils import deprecated
  from ..exceptions import ConvergenceWarning
  from .cdnmf_fast import _update_cdnmf_fast
label_desc: Use image node_id 15 for calling a global function with example usage: non_negative_factorization(X, W, H, n_components, init, update_H, solver, tol, max_iter, alpha, l1_ratio, regularization, random_state, verbose, shuffle, nls_max_iter, sparseness, beta, eta) and returns: W,  H,  n_iter