code: def _grad_neg_log_likelihood_and_fim(
      model_matrix, linear_response, response, model
  ):
      """Computes the neg-log-likelihood gradient and Fisher information for a GLM.
  
      Note that Fisher information is related to the Hessian of the log-likelihood
      by the equation
  
      ```none
      FisherInfo = E[Hessian with respect to model_coefficients of -LogLikelihood(
          Y | model_matrix, model_coefficients)]
      ```
  
      where `LogLikelihood` is the log-likelihood of a generalized linear model
      parameterized by `model_matrix` and `model_coefficients`, and the expectation
      is taken over Y, distributed according to the same GLM with the same parameter
      values.
  
      Args:
        model_matrix: (Batch of) matrix-shaped, `float` `Tensor` or `SparseTensor`
          where each row represents a sample's features.  Has shape `[N, n]` where
          `N` is the number of data samples and `n` is the number of features per
          sample.
        linear_response: (Batch of) vector-shaped `Tensor` with the same dtype as
          `model_matrix`, equal to `model_matix @ model_coefficients` where
          `model_coefficients` are the coefficients of the linear component of the
          GLM.
        response: (Batch of) vector-shaped `Tensor` with the same dtype as
          `model_matrix` where each element represents a sample's observed response
          (to the corresponding row of features).
        model: `tfp.glm.ExponentialFamily`-like instance, which specifies the link
          function and distribution of the GLM, and thus characterizes the negative
          log-likelihood. Must have sufficient statistic equal to the response, that
          is, `T(y) = y`.
  
      Returns:
        grad_neg_log_likelihood: (Batch of) vector-shaped `Tensor` with the same
          shape and dtype as a single row of `model_matrix`, representing the
          gradient of the negative log likelihood of `response` given linear
          response `linear_response`.
        fim_middle: (Batch of) vector-shaped `Tensor` with the same shape and dtype
          as a single column of `model_matrix`, satisfying the equation
          `Fisher information =
          Transpose(model_matrix)
          @ diag(fim_middle)
          @ model_matrix`.
      """
      # TODO(b/111926503): Determine whether there are some practical cases where it
      # is computationally favorable to compute the full FIM.
      mean, variance, grad_mean = model(linear_response)
  
      is_valid = (
          tf.math.is_finite(grad_mean)
          & tf.not_equal(grad_mean, 0.0)
          & tf.math.is_finite(variance)
          & (variance > 0.0)
      )
  
      def _mask_if_invalid(x, mask):
          return tf.where(
              is_valid,
              x,
              np.array(mask, dtype_util.as_numpy_dtype(x.dtype)),
          )
  
      # TODO(b/111923449): Link to derivation once it's available.
      v = (
          (response - mean)
          * _mask_if_invalid(grad_mean, 1)
          / _mask_if_invalid(variance, np.inf)
      )
      grad_log_likelihood = sparse_or_dense_matvecmul(
          model_matrix, v, adjoint_a=True
      )
      fim_middle = _mask_if_invalid(
          grad_mean, 0.0
      ) ** 2 / _mask_if_invalid(variance, np.inf)
      return -grad_log_likelihood, fim_middle
  
file_path: probability/tensorflow_probability/python/glm/proximal_hessian.py
imports: import numpy
  import tensorflow.compat.v2
  from tensorflow_probability.python.glm import fisher_scoring
  from tensorflow_probability.python.internal import dtype_util
  from tensorflow_probability.python.math.linalg import sparse_or_dense_matvecmul
  from tensorflow_probability.python.optimizer import proximal_hessian_sparse
label_desc: Use image node_id 1 for calling a global function with example usage: _grad_neg_log_likelihood_and_fim(model_matrix, linear_response, response, model) and returns: unknown,  fim_middle, tf