class_docstr: Logistic Rule Regression is a directly interpretable supervised learning
  method that performs logistic regression on rule-based features.
docstr: Fit model to training data.
  
  Args:
      X (DataFrame): Binarized features with MultiIndex column labels
      y (array): Target variable
      Xstd (DataFrame, optional): Standardized numerical features
  Returns:
      LogisticRuleRegression: Self
docstr_tok: ["Fit","model","to","training","data",".","Args",":","X","(","DataFrame",")",":","Binarized","features","with","MultiIndex","column","labels","y","(","array",")",":","Target","variable","Xstd","(","DataFrame",",","optional",")",":","Standardized","numerical","features","Returns",":","LogisticRuleRegression",":","Self"]
code: def fit(self, X, y, Xstd=None):
      """Fit model to training data.
  
      Args:
          X (DataFrame): Binarized features with MultiIndex column labels
          y (array): Target variable
          Xstd (DataFrame, optional): Standardized numerical features
      Returns:
          LogisticRuleRegression: Self
      """
      # Initialization
      # Number of samples
      n = X.shape[0]
      if self.init0:
          # Initialize with empty feature indicator and conjunction matrices
          z = pd.DataFrame([], index=X.columns)
          A = np.empty((X.shape[0], 0))
      else:
          # Initialize with X itself i.e. singleton conjunctions
          # Feature indicator and conjunction matrices
          z = pd.DataFrame(
              np.eye(X.shape[1], dtype=int), index=X.columns
          )
          # Remove negations
          indPos = X.columns.get_level_values(1).isin(["", "<=", "=="])
          z = z.loc[:, indPos]
          A = X.loc[:, indPos].values
          # Scale conjunction matrix to account for non-uniform penalties
          A = (
              A
              * self.lambda0
              / (self.lambda0 + self.lambda1 * z.sum().values)
          )
      if self.useOrd:
          self.namesOrd = Xstd.columns
          numOrd = Xstd.shape[1]
          # Scale ordinal features to have similar std as "average" binary feature
          Astd = 0.4 * Xstd.values
      # Iteration counter
      self.it = 0
      # Logistic regression object
      lr = LogisticRegression(
          penalty="l1",
          C=1 / (n * self.lambda0),
          solver="saga",
          multi_class="ovr",
          max_iter=self.maxSolverIter,
      )
  
      self.p = y.mean()
      if self.init0:
          # Initial residual
          r = (self.p - y) / n
          # Derivative w.r.t. intercept term
          UB = min(r.sum(), 0)
      else:
          # Fit logistic regression model
          if self.useOrd:
              B = np.concatenate((Astd, A), axis=1)
              lr.fit(B, y)
              # Initial residual
              r = (lr.predict_proba(B)[:, 1] - y) / n
          else:
              lr.fit(A, y)
              # Initial residual
              r = (lr.predict_proba(A)[:, 1] - y) / n
          # Most "negative" subderivative among current variables (undo scaling)
          UB = -np.abs(np.dot(r, A))
          UB *= (
              self.lambda0 + self.lambda1 * z.sum().values
          ) / self.lambda0
          UB += self.lambda0 + self.lambda1 * z.sum().values
          UB = min(UB.min(), 0)
  
      # Beam search for conjunctions with subdifferentials that exclude zero
      vp, zp, Ap = beam_search_K1(
          r,
          X,
          self.lambda0,
          self.lambda1,
          UB=UB,
          B=self.B,
          wLB=self.wLB,
          eps=self.eps,
          stopEarly=self.stopEarly,
      )
      vn, zn, An = beam_search_K1(
          -r,
          X,
          self.lambda0,
          self.lambda1,
          UB=UB,
          B=self.B,
          wLB=self.wLB,
          eps=self.eps,
          stopEarly=self.stopEarly,
      )
      v = np.append(vp, vn)
  
      while (v < UB).any() and (self.it < self.iterMax):
          # Subdifferentials excluding zero exist, continue
          self.it += 1
          zNew = pd.concat([zp, zn], axis=1, ignore_index=True)
          Anew = np.concatenate((Ap, An), axis=1)
  
          # K conjunctions with largest subderivatives in absolute value
          idxLargest = np.argsort(v)[: self.K]
          v = v[idxLargest]
          zNew = zNew.iloc[:, idxLargest]
          Anew = Anew[:, idxLargest]
          # Scale new conjunction matrix to account for non-uniform penalties
          Anew = (
              Anew
              * self.lambda0
              / (self.lambda0 + self.lambda1 * zNew.sum().values)
          )
  
          # Add to existing conjunctions
          z = pd.concat([z, zNew], axis=1, ignore_index=True)
          A = np.concatenate((A, Anew), axis=1)
          # Fit logistic regression model
          if self.useOrd:
              B = np.concatenate((Astd, A), axis=1)
              lr.fit(B, y)
              # Residual
              r = (lr.predict_proba(B)[:, 1] - y) / n
          else:
              lr.fit(A, y)
              # Residual
              r = (lr.predict_proba(A)[:, 1] - y) / n
  
          # Most "negative" subderivative among current variables (undo scaling)
          UB = -np.abs(np.dot(r, A))
          UB *= (
              self.lambda0 + self.lambda1 * z.sum().values
          ) / self.lambda0
          UB += self.lambda0 + self.lambda1 * z.sum().values
          UB = min(UB.min(), 0)
  
          # Beam search for conjunctions with subdifferentials that exclude zero
          vp, zp, Ap = beam_search_K1(
              r,
              X,
              self.lambda0,
              self.lambda1,
              UB=UB,
              B=self.B,
              wLB=self.wLB,
              eps=self.eps,
              stopEarly=self.stopEarly,
          )
          vn, zn, An = beam_search_K1(
              -r,
              X,
              self.lambda0,
              self.lambda1,
              UB=UB,
              B=self.B,
              wLB=self.wLB,
              eps=self.eps,
              stopEarly=self.stopEarly,
          )
          v = np.append(vp, vn)
  
      # Restrict model to conjunctions with nonzero coefficients
      try:
          idxNonzero = np.where(np.abs(lr.coef_) > self.eps)[1]
          if self.useOrd:
              # Nonzero indices of standardized and rule features
              self.idxNonzeroOrd = idxNonzero[idxNonzero < numOrd]
              nnzOrd = len(self.idxNonzeroOrd)
              idxNonzeroRules = (
                  idxNonzero[idxNonzero >= numOrd] - numOrd
              )
              if self.debias and len(idxNonzero):
                  # Re-fit logistic regression model with effectively no regularization
                  z = z.iloc[:, idxNonzeroRules]
                  lr.C = 1 / self.eps
                  lr.fit(B[:, idxNonzero], y)
                  idxNonzero = np.where(np.abs(lr.coef_) > self.eps)[1]
                  # Nonzero indices of standardized and rule features
                  idxNonzeroOrd2 = idxNonzero[idxNonzero < nnzOrd]
                  self.idxNonzeroOrd = self.idxNonzeroOrd[
                      idxNonzeroOrd2
                  ]
                  idxNonzeroRules = (
                      idxNonzero[idxNonzero >= nnzOrd] - nnzOrd
                  )
              self.z = z.iloc[:, idxNonzeroRules]
              lr.coef_ = lr.coef_[:, idxNonzero]
          else:
              if self.debias and len(idxNonzero):
                  # Re-fit logistic regression model with effectively no regularization
                  z = z.iloc[:, idxNonzero]
                  lr.C = 1 / self.eps
                  lr.fit(A[:, idxNonzero], y)
                  idxNonzero = np.where(np.abs(lr.coef_) > self.eps)[1]
              self.z = z.iloc[:, idxNonzero]
              lr.coef_ = lr.coef_[:, idxNonzero]
      except AttributeError:
          # Model has no coefficients except intercept
          self.z = z
      self.lr = lr
  
file_path: AIX360/aix360/algorithms/rbm/logistic_regression.py
imports: import matplotlib.pyplot
  import numpy
  import pandas
  from sklearn.linear_model import LogisticRegression
  from sklearn.base import BaseEstimator, ClassifierMixin
  from .beam_search import beam_search_K1
label_desc: Use image node_id 2 for calling the LogisticRuleRegression obj's underlying member method code with example usage: obj.fit(X, y, Xstd) without return types