class_docstr: Differential privacy (DP) epsilon lower bound.
  
  This class computes a statistical epsilon lower bound by looking at the log
  ratio of tpr and fpr. The tpr / fpr ratio bound is from `RatioBound` class.
  
  For example, in membership inference attack, the attacker sets a threshold and
  predicts samples with top probability larger than the thresholds as member.
  If the model is trained withs DP guarantee, then we should expect
  log(tpr / fpr) <= epsilon, where tpr and fpr are the true positive and false
  positive rates of the attacker. Therefore, we can use log(tpr / fpr) to derive
  an epsilon lower bound.
  
  The idea of using Clopper Pearson for estimating epsilon lower bound is from
  https://arxiv.org/pdf/2006.07709.pdf.
  The idea of using log Katz is from https://arxiv.org/pdf/2210.08643.pdf.
  
  Examples:
    >>> lb = elb.EpsilonLowerBound(train_top_probs, test_top_probs, alpha=0.05)
    >>> methods = [BoundMethod.BAILEY, BoundMethod.KATZ_LOG]
    >>> lb.compute_epsilon_lower_bounds(methods, k=5)
class_docstr_tok: ["Differential","privacy","(","DP",")","epsilon","lower","bound",".","This","class","computes","a","statistical","epsilon","lower","bound","by","looking","at","the","log","ratio","of","tpr","and","fpr",".","The","tpr","\/","fpr","ratio","bound","is","from","`","RatioBound","`","class",".","For","example",",","in","membership","inference","attack",",","the","attacker","sets","a","threshold","and","predicts","samples","with","top","probability","larger","than","the","thresholds","as","member",".","If","the","model","is","trained","withs","DP","guarantee",",","then","we","should","expect","log","(","tpr","\/","fpr",")","<","=","epsilon",",","where","tpr","and","fpr","are","the","true","positive","and","false","positive","rates","of","the","attacker",".","Therefore",",","we","can","use","log","(","tpr","\/","fpr",")","to","derive","an","epsilon","lower","bound",".","The","idea","of","using","Clopper","Pearson","for","estimating","epsilon","lower","bound","is","from","https",":","\/\/arxiv.org\/pdf\/2006.07709.pdf",".","The","idea","of","using","log","Katz","is","from","https",":","\/\/arxiv.org\/pdf\/2210.08643.pdf",".","Examples",":",">",">",">","lb","=","elb.EpsilonLowerBound","(","train_top_probs",",","test_top_probs",",","alpha=0.05",")",">",">",">","methods","=","[","BoundMethod.BAILEY",",","BoundMethod.KATZ_LOG","]",">",">",">","lb.compute_epsilon_lower_bounds","(","methods",",","k=5",")"]
docstr: Initializes the epsilon lower bound class.
  
  Args:
    pos_scores: per-example scores for the positive class.
    neg_scores: per-example scores for the negative class.
    alpha: the confidence level, must be < 0.5.
    two_sided_threshold: if False, will consider thresholds such that elements
      **above** are predicted as positive, i.e., tpr / fpr and tnr / fnr. If
      True, will also consider fpr / tpr and fnr / tnr.
    thresholds: an array of thresholds to consider. If not provided, will
      enumerate through all possible thresholds.
docstr_tok: ["Initializes","the","epsilon","lower","bound","class",".","Args",":","pos_scores",":","per-example","scores","for","the","positive","class",".","neg_scores",":","per-example","scores","for","the","negative","class",".","alpha",":","the","confidence","level",",","must","be","<","0.5.","two_sided_threshold",":","if","False",",","will","consider","thresholds","such","that","elements","*","*","above","*","*","are","predicted","as","positive",",","i.e.",",","tpr","\/","fpr","and","tnr","\/","fnr",".","If","True",",","will","also","consider","fpr","\/","tpr","and","fnr","\/","tnr",".","thresholds",":","an","array","of","thresholds","to","consider",".","If","not","provided",",","will","enumerate","through","all","possible","thresholds","."]
code: def __init__(
      self,
      pos_scores: np.ndarray,
      neg_scores: np.ndarray,
      alpha: float,
      two_sided_threshold: bool = True,
      thresholds: Optional[np.ndarray] = None,
  ):
      """Initializes the epsilon lower bound class.
  
      Args:
        pos_scores: per-example scores for the positive class.
        neg_scores: per-example scores for the negative class.
        alpha: the confidence level, must be < 0.5.
        two_sided_threshold: if False, will consider thresholds such that elements
          **above** are predicted as positive, i.e., tpr / fpr and tnr / fnr. If
          True, will also consider fpr / tpr and fnr / tnr.
        thresholds: an array of thresholds to consider. If not provided, will
          enumerate through all possible thresholds.
      """
      if pos_scores.ndim != 1:
          raise ValueError(
              "pos_score should be a 1-dimensional array, "
              f"but got {pos_scores.ndim}."
          )
      if neg_scores.ndim != 1:
          raise ValueError(
              "pos_score should be a 1-dimensional array, "
              f"but got {neg_scores.ndim}."
          )
      if alpha >= 0.5:
          raise ValueError(
              "alpha should be < 0.5, e.g. alpha=0.05, "
              f"but got {alpha}."
          )
  
      pos_size, neg_size = pos_scores.size, neg_scores.size
      tp, fp = _get_tp_fp_for_thresholds(
          pos_scores, neg_scores, thresholds
      )
      fn, tn = pos_size - tp, neg_size - fp
  
      # We consider both tpr / fpr and tnr / fnr.
      self._rbs = [
          RatioBound(tp, fp, pos_size, neg_size, alpha),
          RatioBound(tn, fn, neg_size, pos_size, alpha),
      ]
      if two_sided_threshold:
          self._rbs.extend(
              [
                  # pylint: disable-next=arguments-out-of-order
                  RatioBound(fp, tp, neg_size, pos_size, alpha),
                  RatioBound(fn, tn, pos_size, neg_size, alpha),
              ]
          )
  
imports: import enum
  import numbers
  from typing import Dict, Iterable, Optional, Sequence, Union
  import immutabledict
  import numpy
  import numpy.typing
  import scipy.integrate
  import scipy.optimize
  import scipy.stats
  import sklearn.metrics
  from statsmodels.stats import proportion
label_desc: Use image node_id 1 to create a new EpsilonLowerBound object  with example: obj = EpsilonLowerBound(pos_scores, neg_scores, alpha, two_sided_threshold, thresholds)