'Fit the gradient boosting model.
Parameters
X : array-like, shape = [n_samples, n_features]
Training vectors, where n_samples is the number of samples
and n_features is the number of features.
y : array-like, shape = [n_samples]
Target values (integers in classification, real numbers in
regression)
For classification, labels must correspond to classes.
sample_weight : array-like, shape = [n_samples] or None
Sample weights. If None, then samples are equally weighted. Splits
that would create child nodes with net zero or negative weight are
ignored while searching for a split in each node. In the case of
classification, splits are also ignored if they would result in any
single class carrying a negative weight in either child node.
monitor : callable, optional
The monitor is called after each iteration with the current
iteration, a reference to the estimator and the local variables of
``_fit_stages`` as keyword arguments ``callable(i, self,
locals())``. If the callable returns ``True`` the fitting procedure
is stopped. The monitor can be used for various things such as
computing held-out estimates, early stopping, model introspect, and
snapshoting.
Returns
self : object
Returns self.'

def fit(self, X, y, sample_weight=None, monitor=None):

    if (not self.warm_start):
        self._clear_state()
    (X, y) = check_X_y(X, y, accept_sparse=['csr', 'csc', 'coo'], dtype=DTYPE)
    (n_samples, self.n_features_) = X.shape
    if (sample_weight is None):
        sample_weight = np.ones(n_samples, dtype=np.float32)
    else:
        sample_weight = column_or_1d(sample_weight, warn=True)
    check_consistent_length(X, y, sample_weight)
    y = self._validate_y(y)
    if (self.n_iter_no_change is not None):
        (X, X_val, y, y_val, sample_weight, sample_weight_val) = train_test_split(X, y, sample_weight, random_state=self.random_state, test_size=self.validation_fraction)
    else:
        X_val = y_val = sample_weight_val = None
    self._check_params()
    if (not self._is_initialized()):
        self._init_state()
        self.init_.fit(X, y, sample_weight)
        y_pred = self.init_.predict(X)
        begin_at_stage = 0
        self._rng = check_random_state(self.random_state)
    else:
        if (self.n_estimators < self.estimators_.shape[0]):
            raise ValueError(('n_estimators=%d    must    be    larger    or    equal    to    estimators_.shape[0]=%d    when    warm_start==True' % (self.n_estimators, self.estimators_.shape[0])))
        begin_at_stage = self.estimators_.shape[0]
        y_pred = self._decision_function(X)
        self._resize_state()
    X_idx_sorted = None
    presort = self.presort
    if ((presort == 'auto') and issparse(X)):
        presort = False
    elif (presort == 'auto'):
        presort = True
    if (presort == True):
        if issparse(X):
            raise ValueError('Presorting    is    not    supported    for    sparse    matrices.')
        else:
            X_idx_sorted = np.asfortranarray(np.argsort(X, axis=0), dtype=np.int32)
    n_stages = self._fit_stages(X, y, y_pred, sample_weight, self._rng, X_val, y_val, sample_weight_val, begin_at_stage, monitor, X_idx_sorted)
    if (n_stages != self.estimators_.shape[0]):
        self.estimators_ = self.estimators_[:n_stages]
        self.train_score_ = self.train_score_[:n_stages]
        if hasattr(self, 'oob_improvement_'):
            self.oob_improvement_ = self.oob_improvement_[:n_stages]
    self.n_estimators_ = n_stages
    return self
