class_docstr: objective function of logistic regression with prejudice remover
  
  Loss Function type 4: Weights for logistic regression are prepared for each
  value of S. Penalty for enhancing is defined as mutual information between
  Y and S.
class_docstr_tok: ["objective","function","of","logistic","regression","with","prejudice","remover","Loss","Function","type","4",":","Weights","for","logistic","regression","are","prepared","for","each","value","of","S.","Penalty","for","enhancing","is","defined","as","mutual","information","between","Y","and","S","."]
docstr: first derivative of loss function
  
  Parameters
  ----------
  `coef_` : array, shape=(`n_sfv_` * n_features)
      coefficients of model
  X : array, shape=(n_samples, n_features)
      feature vectors of samples
  y : array, shape=(n_samples)
      target class of samples
  s : array, shape=(n_samples)
      values of sensitive features
  
  Returns
  grad_loss : float
      first derivative of loss function
docstr_tok: ["first","derivative","of","loss","function","Parameters","--","--","--","--","--","`","coef_","`",":","array",",","shape=","(","`","n_sfv_","`","*","n_features",")","coefficients","of","model","X",":","array",",","shape=","(","n_samples",",","n_features",")","feature","vectors","of","samples","y",":","array",",","shape=","(","n_samples",")","target","class","of","samples","s",":","array",",","shape=","(","n_samples",")","values","of","sensitive","features","Returns","grad_loss",":","float","first","derivative","of","loss","function"]
code: def grad_loss(self, coef_, X, y, s):
      """first derivative of loss function
  
      Parameters
      ----------
      `coef_` : array, shape=(`n_sfv_` * n_features)
          coefficients of model
      X : array, shape=(n_samples, n_features)
          feature vectors of samples
      y : array, shape=(n_samples)
          target class of samples
      s : array, shape=(n_samples)
          values of sensitive features
  
      Returns
      grad_loss : float
          first derivative of loss function
      """
  
      coef = coef_.reshape(self.n_sfv_, self.n_features_)
      l_ = np.empty(self.n_sfv_ * self.n_features_)
      l = l_.reshape(self.n_sfv_, self.n_features_)
      #        print >> sys.stderr, "grad_loss:", coef[0, :], coef[1, :]
  
      ### constants
      # prefix "d_": derivertive by w(s)
  
      # sigma = Pr[y=0|x,s] = sigmoid(w(s)^T x)
      # d_sigma(x,s) = d sigma / d w(s) = sigma (1 - sigma) x
      p = np.array(
          [
              sigmoid(X[i, :], coef[s[i], :])
              for i in range(self.n_samples_)
          ]
      )
      dp = (p * (1.0 - p))[:, np.newaxis] * X
  
      # rho(s) = Pr[y=0|s] = \sum_{(xi,si)in D st si=s} sigma(xi,si) / #D[s]
      # d_rho(s) = \sum_{(xi,si)in D st si=s} d_sigma(xi,si) / #D[s]
      q = (
          np.array([np.sum(p[s == si]) for si in range(self.n_sfv_)])
          / self.c_s_
      )
      dq = (
          np.array(
              [
                  np.sum(dp[s == si, :], axis=0)
                  for si in range(self.n_sfv_)
              ]
          )
          / self.c_s_[:, np.newaxis]
      )
  
      # pi = Pr[y=0] = \sum_{(xi,si)in D} sigma(xi,si) / #D
      # d_pi = \sum_{(xi,si)in D} d_sigma(xi,si) / #D
      r = np.sum(p) / self.n_samples_
      dr = np.sum(dp, axis=0) / self.n_samples_
  
      # likelihood
      # l(si) = \sum_{x,y in D st s=si} (y - sigma(x, si)) x
      for si in range(self.n_sfv_):
          l[si, :] = np.sum(
              (y - p)[s == si][:, np.newaxis] * X[s == si, :], axis=0
          )
  
      # fairness-aware regularizer
      # differentialy by w(s)
      # \sum_{x,s in {D st s=si} \
      #     [(log(rho(si)) - log(pi)) - (log(1 - rho(si)) - log(1 - pi))] \
      #     * d_sigma
      # + \sum_{x,s in {D st s=si} \
      #     [ {sigma(xi, si) - rho(si)} / {rho(si) (1 - rho(si))} ] \
      #     * d_rho
      # - \sum_{x,s in {D st s=si} \
      #     [ {sigma(xi, si) - pi} / {pi (1 - pi)} ] \
      #     * d_pi
  
      f1 = (np.log(q[s]) - np.log(r)) - (
          np.log(1.0 - q[s]) - np.log(1.0 - r)
      )
      f2 = (p - q[s]) / (q[s] * (1.0 - q[s]))
      f3 = (p - r) / (r * (1.0 - r))
      f4 = (
          f1[:, np.newaxis] * dp
          + f2[:, np.newaxis] * dq[s, :]
          - np.outer(f3, dr)
      )
      f = np.array(
          [np.sum(f4[s == si, :], axis=0) for si in range(self.n_sfv_)]
      )
  
      # l2 regularizer
      reg = coef
  
      # sum
      l[:, :] = -l + self.eta * f + self.C * reg
      #        print >> sys.stderr, "l =", l
  
      return l_
  
imports: from __future__ import print_function
  from __future__ import division
  from __future__ import unicode_literals
  import logging
  import numpy
  from scipy.optimize import fmin_cg
  from sklearn.linear_model import LogisticRegression
  from sklearn.base import BaseEstimator, ClassifierMixin
label_desc: Use image node_id 2 for calling the LRwPRObjetiveType4Mixin obj's underlying member method code with example usage: obj.grad_loss(coef_, X, y, s) and returns: l_