class_docstr: This module implements the Functionally Equivalent Extraction attack for neural networks with two dense layers,
  ReLU activation at the first layer and logits output after the second layer.
  
  | Paper link: https://arxiv.org/abs/1909.01838
class_docstr_tok: ["This","module","implements","the","Functionally","Equivalent","Extraction","attack","for","neural","networks","with","two","dense","layers",",","ReLU","activation","at","the","first","layer","and","logits","output","after","the","second","layer",".","|","Paper","link",":","https",":","\/\/arxiv.org\/abs\/1909.01838"]
docstr: Recover the weights and biases of the first layer.
  
  :param delta_init_value: Initial delta of weight value search.
  :param delta_value_max: Maximum delta  of weight value search.
  :param d2_min: Minimum acceptable value of sum of absolute second derivatives.
  :param d_step:  Step size of delta increase.
  :param delta_sign: Delta of weight sign search.
docstr_tok: ["Recover","the","weights","and","biases","of","the","first","layer",".",":","param","delta_init_value",":","Initial","delta","of","weight","value","search",".",":","param","delta_value_max",":","Maximum","delta","of","weight","value","search",".",":","param","d2_min",":","Minimum","acceptable","value","of","sum","of","absolute","second","derivatives",".",":","param","d_step",":","Step","size","of","delta","increase",".",":","param","delta_sign",":","Delta","of","weight","sign","search","."]
code: def _weight_recovery(
      self,
      delta_init_value: float,
      delta_value_max: float,
      d2_min: float,
      d_step: float,
      delta_sign: float,
  ) -> None:
      """
      Recover the weights and biases of the first layer.
  
      :param delta_init_value: Initial delta of weight value search.
      :param delta_value_max: Maximum delta  of weight value search.
      :param d2_min: Minimum acceptable value of sum of absolute second derivatives.
      :param d_step:  Step size of delta increase.
      :param delta_sign: Delta of weight sign search.
      """
      logger.info("Recovering weights of first layer.")
  
      if self.num_neurons is None:
          raise ValueError(
              "The value of `num_neurons` is required for critical point search."
          )
  
      # Absolute Value Recovery
      d2_ol_d2ej_xi = np.zeros(
          (self.num_features, self.num_neurons), dtype=NUMPY_DTYPE
      )
  
      for i in range(self.num_neurons):
          for j in range(self.num_features):
              delta = delta_init_value
              e_j = np.zeros((1, self.num_features))
              d2_ol_d2ej_xi_ok = False
  
              while not d2_ol_d2ej_xi_ok:
                  e_j[0, j] = delta
  
                  d_ol_dej_xi_p_cej = (
                      self._o_l(self.critical_points[i], e_j=e_j)
                      - self._o_l(self.critical_points[i])
                  ) / delta
                  d_ol_dej_xi_m_cej = (
                      self._o_l(self.critical_points[i])
                      - self._o_l(self.critical_points[i], e_j=-e_j)
                  ) / delta
  
                  d2_ol_d2ej_xi[j, i] = (
                      np.sum(
                          np.abs(d_ol_dej_xi_p_cej - d_ol_dej_xi_m_cej)
                      )
                      / delta
                  )
  
                  if (
                      d2_ol_d2ej_xi[j, i] < d2_min
                      and delta < delta_value_max
                  ):
                      delta = delta + d_step
                  else:
                      d2_ol_d2ej_xi_ok = True
  
      self.a0_pairwise_ratios = np.zeros(
          (self.num_features, self.num_neurons), dtype=NUMPY_DTYPE
      )
  
      for i in range(self.num_neurons):
          for k in range(self.num_features):
              self.a0_pairwise_ratios[k, i] = (
                  d2_ol_d2ej_xi[0, i] / d2_ol_d2ej_xi[k, i]
              )
  
      # Weight Sign Recovery
  
      for i in range(self.num_neurons):
          d2_ol_dejek_xi_0 = None
          for j in range(self.num_features):
              e_j = np.zeros((1, self.num_features), dtype=NUMPY_DTYPE)
  
              e_j[0, 0] += delta_sign
              e_j[0, j] += delta_sign
  
              d_ol_dejek_xi_p_cejek = (
                  self._o_l(self.critical_points[i], e_j=e_j)
                  - self._o_l(self.critical_points[i])
              ) / delta_sign
              d_ol_dejek_xi_m_cejek = (
                  self._o_l(self.critical_points[i])
                  - self._o_l(self.critical_points[i], e_j=-e_j)
              ) / delta_sign
  
              d2_ol_dejek_xi = (
                  d_ol_dejek_xi_p_cejek - d_ol_dejek_xi_m_cejek
              )
  
              if j == 0:
                  d2_ol_dejek_xi_0 = d2_ol_dejek_xi / 2.0
  
              co_p = np.sum(
                  np.abs(
                      d2_ol_dejek_xi_0
                      * (1 + 1 / self.a0_pairwise_ratios[j, i])
                      - d2_ol_dejek_xi
                  )
              )
              co_m = np.sum(
                  np.abs(
                      d2_ol_dejek_xi_0
                      * (1 - 1 / self.a0_pairwise_ratios[j, i])
                      - d2_ol_dejek_xi
                  )
              )
  
              if co_m < co_p * np.max(
                  1 / self.a0_pairwise_ratios[:, i]
              ):
                  self.a0_pairwise_ratios[j, i] *= -1
  
file_path: adversarial-robustness-toolbox/art/attacks/extraction/functionally_equivalent_extraction.py
imports: import logging
  import os
  from typing import List, Optional, TYPE_CHECKING
  import numpy
  from scipy.optimize import least_squares
  from art.attacks.attack import ExtractionAttack
  from art.estimators.estimator import BaseEstimator, NeuralNetworkMixin
  from art.estimators.classification.classifier import ClassifierMixin
  from art.estimators.classification.keras import KerasClassifier
  from art.estimators.classification.blackbox import BlackBoxClassifier
label_desc: Use image node_id 6 for calling the FunctionallyEquivalentExtraction obj's underlying member method code with example usage: obj._weight_recovery(delta_init_value, delta_value_max, d2_min, d_step, delta_sign) without return types