code: def compute_noise_matrix_from_inverse(
      ps, inverse_noise_matrix, *, py=None
  ) -> np.ndarray:
      """Compute the noise matrix ``P(label=k_s|true_label=k_y)``.
  
      Parameters
      ----------
      py : np.ndarray
          Array of shape ``(K, 1)`` containing the fraction (prior probability) of each TRUE class label, ``P(true_label = k)``.
  
      inverse_noise_matrix : np.ndarray
          A conditional probability matrix (of shape ``(K, K)``) of the form P(true_label=k_y|label=k_s) representing
          the estimated fraction observed examples in each class k_s, that are
          mislabeled examples from every other class k_y. If None, the
          inverse_noise_matrix will be computed from pred_probs and labels.
          Assumes columns of inverse_noise_matrix sum to 1.
  
      ps : np.ndarray
          Array of shape ``(K, 1)`` containing the fraction (prior probability) of each observed NOISY label, P(labels = k).
          `ps` is easily computable from `py` and should only be provided if it has already been precomputed, to increase code efficiency.
  
      Returns
      -------
      noise_matrix : np.ndarray
          Array of shape ``(K, K)``, where `K` = number of classes, whose columns sum to 1.
          A conditional probability matrix of the form ``P(label=k_s|true_label=k_y)`` containing
          the fraction of examples in every class, labeled as every other class.
  
      Examples
      --------
      For loop based implementation:
  
      .. code:: python
  
          # Number of classes labels
          K = len(ps)
  
          # 'py' is p(true_label=k) = inverse_noise_matrix * p(true_label=k)
          # because in *vector computation*: P(true_label=k|label=k) * p(label=k) = P(true_label=k)
          if py is None:
              py = inverse_noise_matrix.dot(ps)
  
          # Estimate the (K, K) noise matrix P(labels = k_s | true_labels = k_y)
          noise_matrix = np.empty(shape=(K,K))
          # k_s is the class value k of noisy label `labels == k`
          for k_s in range(K):
              # k_y is the (guessed) class value k of true label y
              for k_y in range(K):
                  # P(labels|y) = P(true_label|labels) * P(labels) / P(true_label)
                  noise_matrix[k_s][k_y] = inverse_noise_matrix[k_y][k_s] * \
                                           ps[k_s] / py[k_y]
  
      """
  
      joint = (inverse_noise_matrix * ps).T
      py = joint.sum(axis=0) if py is None else py
      noise_matrix = joint / np.clip(py, a_min=TINY_VALUE, a_max=None)
  
      # Clip inverse noise rates P(true_label=k_y|true_label=k_s) into proper range [0,1)
      return clip_noise_rates(noise_matrix)
  
file_path: cleanlab/cleanlab/internal/latent_algebra.py
imports: import warnings
  import numpy
  from typing import Tuple
  from cleanlab.internal.util import value_counts, clip_values, clip_noise_rates
  from cleanlab.internal.constants import TINY_VALUE, CLIPPING_LOWER_BOUND
label_desc: Use image node_id 4 for calling a global function with example usage: compute_noise_matrix_from_inverse(ps, inverse_noise_matrix) and returns: clip_noise_rates