class_docstr: Mini-Batch K-Means clustering
  
  Read more in the :ref:`User Guide <mini_batch_kmeans>`.
  
  Parameters
  ----------
  
  n_clusters : int, optional, default: 8
      The number of clusters to form as well as the number of
      centroids to generate.
  
  max_iter : int, optional
      Maximum number of iterations over the complete dataset before
      stopping independently of any early stopping criterion heuristics.
  
  max_no_improvement : int, default: 10
      Control early stopping based on the consecutive number of mini
      batches that does not yield an improvement on the smoothed inertia.
  
      To disable convergence detection based on inertia, set
      max_no_improvement to None.
  
  tol : float, default: 0.0
      Control early stopping based on the relative center changes as
      measured by a smoothed, variance-normalized of the mean center
      squared position changes. This early stopping heuristics is
      closer to the one used for the batch variant of the algorithms
      but induces a slight computational and memory overhead over the
      inertia heuristic.
  
      To disable convergence detection based on normalized center
      change, set tol to 0.0 (default).
  
  batch_size : int, optional, default: 100
      Size of the mini batches.
  
  init_size : int, optional, default: 3 * batch_size
      Number of samples to randomly sample for speeding up the
      initialization (sometimes at the expense of accuracy): the
      only algorithm is initialized by running a batch KMeans on a
      random subset of the data. This needs to be larger than n_clusters.
  
  init : {'k-means++', 'random' or an ndarray}, default: 'k-means++'
      Method for initialization, defaults to 'k-means++':
  
      'k-means++' : selects initial cluster centers for k-mean
      clustering in a smart way to speed up convergence. See section
      Notes in k_init for more details.
  
      'random': choose k observations (rows) at random from data for
      the initial centroids.
  
      If an ndarray is passed, it should be of shape (n_clusters, n_features)
      and gives the initial centers.
  
  n_init : int, default=3
      Number of random initializations that are tried.
      In contrast to KMeans, the algorithm is only run once, using the
      best of the ``n_init`` initializations as measured by inertia.
  
  compute_labels : boolean, default=True
      Compute label assignment and inertia for the complete dataset
      once the minibatch optimization has converged in fit.
  
  random_state : integer or numpy.RandomState, optional
      The generator used to initialize the centers. If an integer is
      given, it fixes the seed. Defaults to the global numpy random
      number generator.
  
  reassignment_ratio : float, default: 0.01
      Control the fraction of the maximum number of counts for a
      center to be reassigned. A higher value means that low count
      centers are more easily reassigned, which means that the
      model will take longer to converge, but should converge in a
      better clustering.
  
  verbose : boolean, optional
      Verbosity mode.
  
  Attributes
  ----------
  
  cluster_centers_ : array, [n_clusters, n_features]
      Coordinates of cluster centers
  
  labels_ :
      Labels of each point (if compute_labels is set to True).
  
  inertia_ : float
      The value of the inertia criterion associated with the chosen
      partition (if compute_labels is set to True). The inertia is
      defined as the sum of square distances of samples to their nearest
      neighbor.
  
  See also
  --------
  
  KMeans
      The classic implementation of the clustering method based on the
      Lloyd's algorithm. It consumes the whole set of input data at each
      iteration.
  
  Notes
  -----
  See http://www.eecs.tufts.edu/~dsculley/papers/fastkmeans.pdf
docstr: Compute the centroids on X by chunking it into mini-batches.
  
  Parameters
  ----------
  X : array-like or sparse matrix, shape=(n_samples, n_features)
      Training instances to cluster.
docstr_tok: ["Compute","the","centroids","on","X","by","chunking","it","into","mini-batches",".","Parameters","--","--","--","--","--","X",":","array-like","or","sparse","matrix",",","shape=","(","n_samples",",","n_features",")","Training","instances","to","cluster","."]
code: def fit(self, X, y=None):
      """Compute the centroids on X by chunking it into mini-batches.
  
      Parameters
      ----------
      X : array-like or sparse matrix, shape=(n_samples, n_features)
          Training instances to cluster.
      """
      random_state = check_random_state(self.random_state)
      X = check_array(
          X,
          accept_sparse="csr",
          order="C",
          dtype=[np.float64, np.float32],
      )
      n_samples, n_features = X.shape
      if n_samples < self.n_clusters:
          raise ValueError(
              "Number of samples smaller than number " "of clusters."
          )
  
      n_init = self.n_init
      if hasattr(self.init, "__array__"):
          self.init = np.ascontiguousarray(self.init, dtype=X.dtype)
          if n_init != 1:
              warnings.warn(
                  "Explicit initial center position passed: "
                  "performing only one init in MiniBatchKMeans instead of "
                  "n_init=%d" % self.n_init,
                  RuntimeWarning,
                  stacklevel=2,
              )
              n_init = 1
  
      x_squared_norms = row_norms(X, squared=True)
  
      if self.tol > 0.0:
          tol = _tolerance(X, self.tol)
  
          # using tol-based early stopping needs the allocation of a
          # dedicated before which can be expensive for high dim data:
          # hence we allocate it outside of the main loop
          old_center_buffer = np.zeros(n_features, dtype=X.dtype)
      else:
          tol = 0.0
          # no need for the center buffer if tol-based early stopping is
          # disabled
          old_center_buffer = np.zeros(0, dtype=X.dtype)
  
      distances = np.zeros(self.batch_size, dtype=X.dtype)
      n_batches = int(np.ceil(float(n_samples) / self.batch_size))
      n_iter = int(self.max_iter * n_batches)
  
      init_size = self.init_size
      if init_size is None:
          init_size = 3 * self.batch_size
      if init_size > n_samples:
          init_size = n_samples
      self.init_size_ = init_size
  
      validation_indices = random_state.randint(0, n_samples, init_size)
      X_valid = X[validation_indices]
      x_squared_norms_valid = x_squared_norms[validation_indices]
  
      # perform several inits with random sub-sets
      best_inertia = None
      for init_idx in range(n_init):
          if self.verbose:
              print(
                  "Init %d/%d with method: %s"
                  % (init_idx + 1, n_init, self.init)
              )
          counts = np.zeros(self.n_clusters, dtype=np.int32)
  
          # TODO: once the `k_means` function works with sparse input we
          # should refactor the following init to use it instead.
  
          # Initialize the centers using only a fraction of the data as we
          # expect n_samples to be very large when using MiniBatchKMeans
          cluster_centers = _init_centroids(
              X,
              self.n_clusters,
              self.init,
              random_state=random_state,
              x_squared_norms=x_squared_norms,
              init_size=init_size,
          )
  
          # Compute the label assignment on the init dataset
          batch_inertia, centers_squared_diff = _mini_batch_step(
              X_valid,
              x_squared_norms[validation_indices],
              cluster_centers,
              counts,
              old_center_buffer,
              False,
              distances=None,
              verbose=self.verbose,
          )
  
          # Keep only the best cluster centers across independent inits on
          # the common validation set
          _, inertia = _labels_inertia(
              X_valid, x_squared_norms_valid, cluster_centers
          )
          if self.verbose:
              print(
                  "Inertia for init %d/%d: %f"
                  % (init_idx + 1, n_init, inertia)
              )
          if best_inertia is None or inertia < best_inertia:
              self.cluster_centers_ = cluster_centers
              self.counts_ = counts
              best_inertia = inertia
  
      # Empty context to be used inplace by the convergence check routine
      convergence_context = {}
  
      # Perform the iterative optimization until the final convergence
      # criterion
      for iteration_idx in range(n_iter):
          # Sample a minibatch from the full dataset
          minibatch_indices = random_state.randint(
              0, n_samples, self.batch_size
          )
  
          # Perform the actual update step on the minibatch data
          batch_inertia, centers_squared_diff = _mini_batch_step(
              X[minibatch_indices],
              x_squared_norms[minibatch_indices],
              self.cluster_centers_,
              self.counts_,
              old_center_buffer,
              tol > 0.0,
              distances=distances,
              # Here we randomly choose whether to perform
              # random reassignment: the choice is done as a function
              # of the iteration index, and the minimum number of
              # counts, in order to force this reassignment to happen
              # every once in a while
              random_reassign=(
                  (iteration_idx + 1) % (10 + self.counts_.min()) == 0
              ),
              random_state=random_state,
              reassignment_ratio=self.reassignment_ratio,
              verbose=self.verbose,
          )
  
          # Monitor convergence and do early stopping if necessary
          if _mini_batch_convergence(
              self,
              iteration_idx,
              n_iter,
              tol,
              n_samples,
              centers_squared_diff,
              batch_inertia,
              convergence_context,
              verbose=self.verbose,
          ):
              break
  
      self.n_iter_ = iteration_idx + 1
  
      if self.compute_labels:
          self.labels_, self.inertia_ = self._labels_inertia_minibatch(
              X
          )
  
      return self
  
imports: import warnings
  import numpy
  import scipy.sparse
  from ..base import BaseEstimator, ClusterMixin, TransformerMixin
  from ..metrics.pairwise import euclidean_distances
  from ..metrics.pairwise import pairwise_distances_argmin_min
  from ..utils.extmath import row_norms, squared_norm
  from ..utils.sparsefuncs_fast import assign_rows_csr
  from ..utils.sparsefuncs import mean_variance_axis
  from ..utils.fixes import astype
  from ..utils import check_array
  from ..utils import check_random_state
  from ..utils import as_float_array
  from ..utils import gen_batches
  from ..utils.validation import check_is_fitted
  from ..utils.validation import FLOAT_DTYPES
  from ..utils.random import choice
  from ..externals.joblib import Parallel
  from ..externals.joblib import delayed
  from ..externals.six import string_types
  from .None import _k_means
  from ._k_means_elkan import k_means_elkan
label_desc: Use image node_id 2 for calling the MiniBatchKMeans obj's underlying member method code with example usage: obj.fit(X, y) and returns: self