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 sign of weights in the first layer.
  
  :param unit_vector_scale: Multiplicative scale of the unit vector e_j.
  :param ftol: Tolerance for termination by the change of the cost function.
docstr_tok: ["Recover","the","sign","of","weights","in","the","first","layer",".",":","param","unit_vector_scale",":","Multiplicative","scale","of","the","unit","vector","e_j",".",":","param","ftol",":","Tolerance","for","termination","by","the","change","of","the","cost","function","."]
code: def _sign_recovery(self, unit_vector_scale: int, ftol: float) -> None:
      """
      Recover the sign of weights in the first layer.
  
      :param unit_vector_scale: Multiplicative scale of the unit vector e_j.
      :param ftol: Tolerance for termination by the change of the cost function.
      """
      logger.info("Recover sign of the weights of the first layer.")
  
      if self.num_neurons is None:
          raise ValueError(
              "The value of `num_neurons` is required for critical point search."
          )
  
      a0_pairwise_ratios_inverse = 1.0 / self.a0_pairwise_ratios
      self.b_0 = np.zeros((self.num_neurons, 1), dtype=NUMPY_DTYPE)
  
      for i in range(self.num_neurons):
          x_i = self.critical_points[i].flatten()
          self.b_0[i] = -np.matmul(
              a0_pairwise_ratios_inverse[:, i], x_i
          )
  
      z_0 = np.random.normal(0, 1, (self.num_features,)).astype(
          dtype=NUMPY_DTYPE
      )
  
      def f_z(z_i):
          return np.squeeze(
              np.matmul(
                  a0_pairwise_ratios_inverse.T,
                  np.expand_dims(z_i, axis=0).T,
              )
              + self.b_0
          )
  
      result_z = least_squares(f_z, z_0, ftol=ftol)
  
      for i in range(self.num_neurons):
          e_i = np.zeros((self.num_neurons, 1), dtype=NUMPY_DTYPE)
          e_i[i, 0] = unit_vector_scale
  
          def f_v(v_i):
              # pylint: disable=W0640
              return np.squeeze(
                  np.matmul(
                      -a0_pairwise_ratios_inverse.T,
                      np.expand_dims(v_i, axis=0).T,
                  )
                  - e_i
              )
  
          v_0 = np.random.normal(0, 1, self.num_features)
          result_v_i = least_squares(f_v, v_0, ftol=ftol)
          value_p = np.sum(
              np.abs(
                  self._o_l(np.expand_dims(result_z.x, axis=0))
                  - (
                      self._o_l(
                          np.expand_dims(
                              result_z.x + result_v_i.x, axis=0
                          )
                      )
                  )
              )
          )
          value_m = np.sum(
              np.abs(
                  self._o_l(np.expand_dims(result_z.x, axis=0))
                  - (
                      self._o_l(
                          np.expand_dims(
                              result_z.x - result_v_i.x, axis=0
                          )
                      )
                  )
              )
          )
  
          if value_m < value_p:
              a0_pairwise_ratios_inverse[:, i] *= -1
              self.b_0[i, 0] *= -1
  
      self.w_0 = a0_pairwise_ratios_inverse
  
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 7 for calling the FunctionallyEquivalentExtraction obj's underlying member method code with example usage: obj._sign_recovery(unit_vector_scale, ftol) and returns: np, np