<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def fit_quantile(self, X, y, quantile, max_iter=20, tol=0.01, weights=None):
 """fit ExpectileGAM to a desired quantile via binary search Parameters X : array-like, shape (n_samples, m_features) Training vectors, where n_samples is the number of samples and m_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. quantile : float on (0, 1) desired quantile to fit. max_iter : int, default: 20 maximum number of binary search iterations to perform tol : float > 0, default: 0.01 maximum distance between desired quantile and fitted quantile weights : array-like shape (n_samples,) or None, default: None containing sample weights if None, defaults to array of ones Returns ------- self : fitted GAM object """

        def _within_tol(a, b, tol):
            return np.abs(a - b) <= tol

        # validate arguments
        if quantile <= 0 or quantile >= 1:
            raise ValueError('quantile must be on (0, 1), but found {}'.format(quantile))

        if tol <= 0:
            raise ValueError('tol must be float > 0 {}'.format(tol))

        if max_iter <= 0:
            raise ValueError('max_iter must be int > 0 {}'.format(max_iter))

        # perform a first fit if necessary
        if not self._is_fitted:
            self.fit(X, y, weights=weights)

        # do binary search
        max_ = 1.0
        min_ = 0.0
        n_iter = 0
        while n_iter < max_iter:
            ratio = self._get_quantile_ratio(X, y)

            if _within_tol(ratio, quantile, tol):
                break

            if ratio < quantile:
                min_ = self.expectile
            else:
                max_ = self.expectile

            expectile = (max_ + min_) / 2.
            self.set_params(expectile=expectile)
            self.fit(X, y, weights=weights)

            n_iter += 1

        # print diagnostics
        if not _within_tol(ratio, quantile, tol) and self.verbose:
            warnings.warn('maximum iterations reached')

        return self