code: def predict_proba(self, L):
          
          self._set_constants(L)
  
          L_aug = self._get_augmented_label_matrix(L)
          mu = np.clip(self.mu.detach().clone().numpy(), 0.01, 0.99)
  
          # Create a "junction tree mask" over the columns of L_aug / mu
          if len(self.deps) > 0:
              jtm = np.zeros(L_aug.shape[1])
  
              # All maximal cliques are +1
              for i in self.c_tree.nodes():
                  node = self.c_tree.node[i]
                  jtm[node["start_index"] : node["end_index"]] = 1
  
              # All separator sets are -1
              for i, j in self.c_tree.edges():
                  edge = self.c_tree[i][j]
                  jtm[edge["start_index"] : edge["end_index"]] = 1
          else:
              jtm = np.ones(L_aug.shape[1])
  
          # Note: We omit abstains, effectively assuming uniform distribution here
          X = np.exp(L_aug @ np.diag(jtm) @ np.log(mu) + np.log(self.p))
          Z = np.tile(X.sum(axis=1).reshape(-1, 1), self.k)
          return X / Z
docs: Returns the [n,k] matrix of label probabilities P(Y | \lambda)
  
          Args:
              L: An [n,m] scipy.sparse label matrix with values in {0,1,...,k}