class_docstr: Base class for MLP classification and regression.
  
  Warning: This class should not be used directly.
  Use derived classes instead.
  
  .. versionadded:: 0.18
code: def _fit_stochastic(
      self,
      X,
      y,
      activations,
      deltas,
      coef_grads,
      intercept_grads,
      layer_units,
      incremental,
  ):
      params = self.coefs_ + self.intercepts_
      if not incremental or not hasattr(self, "_optimizer"):
          if self.solver == "sgd":
              self._optimizer = SGDOptimizer(
                  params,
                  self.learning_rate_init,
                  self.learning_rate,
                  self.momentum,
                  self.nesterovs_momentum,
                  self.power_t,
              )
          elif self.solver == "adam":
              self._optimizer = AdamOptimizer(
                  params,
                  self.learning_rate_init,
                  self.beta_1,
                  self.beta_2,
                  self.epsilon,
              )
  
      # early_stopping in partial_fit doesn't make sense
      if self.early_stopping and incremental:
          raise ValueError(
              "partial_fit does not support early_stopping=True"
          )
      early_stopping = self.early_stopping
      if early_stopping:
          # don't stratify in multilabel classification
          should_stratify = is_classifier(self) and self.n_outputs_ == 1
          stratify = y if should_stratify else None
          X, X_val, y, y_val = train_test_split(
              X,
              y,
              random_state=self._random_state,
              test_size=self.validation_fraction,
              stratify=stratify,
          )
          if is_classifier(self):
              y_val = self._label_binarizer.inverse_transform(y_val)
      else:
          X_val = None
          y_val = None
  
      n_samples = X.shape[0]
      sample_idx = np.arange(n_samples, dtype=int)
  
      if self.batch_size == "auto":
          batch_size = min(200, n_samples)
      else:
          if self.batch_size > n_samples:
              warnings.warn(
                  "Got `batch_size` less than 1 or larger than "
                  "sample size. It is going to be clipped"
              )
          batch_size = np.clip(self.batch_size, 1, n_samples)
  
      try:
          self.n_iter_ = 0
          for it in range(self.max_iter):
              if self.shuffle:
                  # Only shuffle the sample indices instead of X and y to
                  # reduce the memory footprint. These indices will be used
                  # to slice the X and y.
                  sample_idx = shuffle(
                      sample_idx, random_state=self._random_state
                  )
  
              accumulated_loss = 0.0
              for batch_slice in gen_batches(n_samples, batch_size):
                  if self.shuffle:
                      X_batch = _safe_indexing(
                          X, sample_idx[batch_slice]
                      )
                      y_batch = y[sample_idx[batch_slice]]
                  else:
                      X_batch = X[batch_slice]
                      y_batch = y[batch_slice]
  
                  activations[0] = X_batch
                  (
                      batch_loss,
                      coef_grads,
                      intercept_grads,
                  ) = self._backprop(
                      X_batch,
                      y_batch,
                      activations,
                      deltas,
                      coef_grads,
                      intercept_grads,
                  )
                  accumulated_loss += batch_loss * (
                      batch_slice.stop - batch_slice.start
                  )
  
                  # update weights
                  grads = coef_grads + intercept_grads
                  self._optimizer.update_params(params, grads)
  
              self.n_iter_ += 1
              self.loss_ = accumulated_loss / X.shape[0]
  
              self.t_ += n_samples
              self.loss_curve_.append(self.loss_)
              if self.verbose:
                  print(
                      "Iteration %d, loss = %.8f"
                      % (self.n_iter_, self.loss_)
                  )
  
              # update no_improvement_count based on training loss or
              # validation score according to early_stopping
              self._update_no_improvement_count(
                  early_stopping, X_val, y_val
              )
  
              # for learning rate that needs to be updated at iteration end
              self._optimizer.iteration_ends(self.t_)
  
              if self._no_improvement_count > self.n_iter_no_change:
                  # not better than last `n_iter_no_change` iterations by tol
                  # stop or decrease learning rate
                  if early_stopping:
                      msg = (
                          "Validation score did not improve more than "
                          "tol=%f for %d consecutive epochs."
                          % (self.tol, self.n_iter_no_change)
                      )
                  else:
                      msg = (
                          "Training loss did not improve more than tol=%f"
                          " for %d consecutive epochs."
                          % (self.tol, self.n_iter_no_change)
                      )
  
                  is_stopping = self._optimizer.trigger_stopping(
                      msg, self.verbose
                  )
                  if is_stopping:
                      break
                  else:
                      self._no_improvement_count = 0
  
              if incremental:
                  break
  
              if self.n_iter_ == self.max_iter:
                  warnings.warn(
                      "Stochastic Optimizer: Maximum iterations (%d) "
                      "reached and the optimization hasn't converged yet."
                      % self.max_iter,
                      ConvergenceWarning,
                  )
      except KeyboardInterrupt:
          warnings.warn("Training interrupted by user.")
  
      if early_stopping:
          # restore best weights
          self.coefs_ = self._best_coefs
          self.intercepts_ = self._best_intercepts
          self.validation_scores_ = self.validation_scores_
  
imports: import warnings
  from abc import ABCMeta, abstractmethod
  from itertools import chain
  from numbers import Integral, Real
  import numpy
  import scipy.optimize
  from ..base import BaseEstimator, ClassifierMixin, RegressorMixin, _fit_context, is_classifier
  from ..exceptions import ConvergenceWarning
  from ..metrics import accuracy_score, r2_score
  from ..model_selection import train_test_split
  from ..preprocessing import LabelBinarizer
  from ..utils import _safe_indexing, check_random_state, column_or_1d, gen_batches, shuffle
  from ..utils._param_validation import Interval, Options, StrOptions
  from ..utils.extmath import safe_sparse_dot
  from ..utils.metaestimators import available_if
  from ..utils.multiclass import _check_partial_fit_first_call, type_of_target, unique_labels
  from ..utils.optimize import _check_optimize_result
  from ..utils.validation import check_is_fitted
  from ._base import ACTIVATIONS, DERIVATIVES, LOSS_FUNCTIONS
  from ._stochastic_optimizers import AdamOptimizer, SGDOptimizer
label_desc: Use image node_id 12 for calling the BaseMultilayerPerceptron obj's underlying member method code with example usage: obj._fit_stochastic(X, y, activations, deltas, coef_grads, intercept_grads, layer_units, incremental) without return types