# Buggy code
def _fit_stages(
    self, X, y, y_pred, sample_weight, random_state, begin_at_stage=0, monitor=None
):
    """Iteratively fits the stages.

    For each stage it computes the progress (OOB, train score)
    and delegates to ``_fit_stage``.
    Returns the number of stages fit; might differ from ``n_estimators``
    due to early stopping.
    """
    n_samples = X.shape[0]
    do_oob = self.subsample < 1.0
    sample_mask = np.ones((n_samples,), dtype=np.bool)
    n_inbag = max(1, int(self.subsample * n_samples))
    loss_ = self.loss_

    # init criterion and splitter
    criterion = FriedmanMSE(1)
    splitter = PresortBestSplitter(
        criterion,
        self.max_features_,
        self.min_samples_leaf,
        self.min_weight_fraction_leaf,
        random_state,
    )

    if self.verbose:
        verbose_reporter = VerboseReporter(self.verbose)
        verbose_reporter.init(self, begin_at_stage)

    # perform boosting iterations
    i = begin_at_stage
    for i in range(begin_at_stage, self.n_estimators):
        # subsampling
        if do_oob:
            sample_mask = _random_sample_mask(n_samples, n_inbag, random_state)
            # OOB score before adding this stage
            old_oob_score = loss_(
                y[~sample_mask], y_pred[~sample_mask], sample_weight[~sample_mask]
            )

        # fit next stage of trees
        y_pred = self._fit_stage(
            i,
            X,
            y,
            y_pred,
            sample_weight,
            sample_mask,
            criterion,
            splitter,
            random_state,
        )

        # track deviance (= loss)
        if do_oob:
            self.train_score_[i] = loss_(
                y[sample_mask], y_pred[sample_mask], sample_weight[sample_mask]
            )
            self.oob_improvement_[i] = old_oob_score - loss_(
                y[~sample_mask], y_pred[~sample_mask], sample_weight[~sample_mask]
            )
        else:
            # no need to fancy index w/ no subsampling
            self.train_score_[i] = loss_(y, y_pred, sample_weight)

        if self.verbose > 0:
            verbose_reporter.update(i, self)

        if monitor is not None:
            early_stopping = monitor(i, self, locals())
            if early_stopping:
                break
    return i + 1


# Traceback (AssertionError)
======================================================================
FAIL: Tests that class_weight and sample_weight are multiplicative
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/buildd/scikit-learn-0.16.0~b1+git1-gab4d07d/debian/python-sklearn/usr/lib/python2.7/dist-packages/sklearn/linear_model/tests/test_sgd.py", line 633, in test_weights_multiplied
assert_array_equal(clf1.coef_, clf2.coef_)
File "/usr/lib/python2.7/dist-packages/numpy/testing/utils.py", line 718, in assert_array_equal
verbose=verbose, header='Arrays are not equal')
File "/usr/lib/python2.7/dist-packages/numpy/testing/utils.py", line 644, in assert_array_compare
raise AssertionError(msg)
AssertionError:
Arrays are not equal

(mismatch 16.6666666667%)
x: array([[-0.34681637, -0.32240913, -0.31335029,  0.34920789,  0.3658206 ,
0.38752489]])
y: array([[-0.34681637, -0.32240913, -0.31335029,  0.34920789,  0.3658206 ,
0.38752489]])

# Fixed code
def _fit_stages(
    self, X, y, y_pred, sample_weight, random_state, begin_at_stage=0, monitor=None
):
    """Iteratively fits the stages.

    For each stage it computes the progress (OOB, train score)
    and delegates to ``_fit_stage``.
    Returns the number of stages fit; might differ from ``n_estimators``
    due to early stopping.
    """
    n_samples = X.shape[0]
    do_oob = self.subsample < 1.0
    sample_mask = np.ones((n_samples,), dtype=np.bool)
    n_inbag = max(1, int(self.subsample * n_samples))
    loss_ = self.loss_

    # Set min_weight_leaf from min_weight_fraction_leaf
    if self.min_weight_fraction_leaf != 0.0 and sample_weight is not None:
        min_weight_leaf = self.min_weight_fraction_leaf * np.sum(sample_weight)
    else:
        min_weight_leaf = 0.0

    # init criterion and splitter
    criterion = FriedmanMSE(1)
    splitter = PresortBestSplitter(
        criterion,
        self.max_features_,
        self.min_samples_leaf,
        min_weight_leaf,
        random_state,
    )

    if self.verbose:
        verbose_reporter = VerboseReporter(self.verbose)
        verbose_reporter.init(self, begin_at_stage)

    # perform boosting iterations
    i = begin_at_stage
    for i in range(begin_at_stage, self.n_estimators):
        # subsampling
        if do_oob:
            sample_mask = _random_sample_mask(n_samples, n_inbag, random_state)
            # OOB score before adding this stage
            old_oob_score = loss_(
                y[~sample_mask], y_pred[~sample_mask], sample_weight[~sample_mask]
            )

        # fit next stage of trees
        y_pred = self._fit_stage(
            i,
            X,
            y,
            y_pred,
            sample_weight,
            sample_mask,
            criterion,
            splitter,
            random_state,
        )

        # track deviance (= loss)
        if do_oob:
            self.train_score_[i] = loss_(
                y[sample_mask], y_pred[sample_mask], sample_weight[sample_mask]
            )
            self.oob_improvement_[i] = old_oob_score - loss_(
                y[~sample_mask], y_pred[~sample_mask], sample_weight[~sample_mask]
            )
        else:
            # no need to fancy index w/ no subsampling
            self.train_score_[i] = loss_(y, y_pred, sample_weight)

        if self.verbose > 0:
            verbose_reporter.update(i, self)

        if monitor is not None:
            early_stopping = monitor(i, self, locals())
            if early_stopping:
                break
    return i + 1