code: def fit(self, X, y, weights=None):
          
  
          # validate parameters
          self._validate_params()
  
          # validate data
          y = check_y(y, self.link, self.distribution, verbose=self.verbose)
          X = check_X(X, verbose=self.verbose)
          check_X_y(X, y)
  
          if weights is not None:
              weights = np.array(weights).astype('f').ravel()
              weights = check_array(weights, name='sample weights',
                                    ndim=1, verbose=self.verbose)
              check_lengths(y, weights)
          else:
              weights = np.ones_like(y).astype('float64')
  
          # validate data-dependent parameters
          self._validate_data_dep_params(X)
  
          # set up logging
          if not hasattr(self, 'logs_'):
              self.logs_ = defaultdict(list)
  
          # begin capturing statistics
          self.statistics_ = {}
          self.statistics_['n_samples'] = len(y)
          self.statistics_['m_features'] = X.shape[1]
  
          # optimize
          self._pirls(X, y, weights)
          # if self._opt == 0:
          #     self._pirls(X, y, weights)
          # if self._opt == 1:
          #     self._pirls_naive(X, y)
          return self
docs: Fit the generalized additive model.
  
          Parameters
          ----------
          X : array-like, shape (n_samples, m_features)
              Training vectors.
          y : array-like, shape (n_samples,)
              Target values,
              ie integers in classification, real numbers in
              regression)
          weights : array-like shape (n_samples,) or None, optional
              Sample weights.
              if None, defaults to array of ones
  
          Returns
          -------
          self : object
              Returns fitted GAM object