code: def intrinsic_causal_influence(
      causal_model: StructuralCausalModel,
      target_node: Any,
      prediction_model: Union[
          PredictionModel, ClassificationModel, str
      ] = "approx",
      attribution_func: Optional[
          Callable[[np.ndarray, np.ndarray], float]
      ] = None,
      num_training_samples: int = 100000,
      num_samples_randomization: int = 1000,
      num_samples_baseline: int = 2000,
      max_batch_size: int = 250,
      auto_assign_quality: auto.AssignmentQuality = auto.AssignmentQuality.GOOD,
      shapley_config: Optional[ShapleyConfig] = None,
  ) -> Dict[Any, float]:
      """Computes the causal contribution of each upstream noise term of the target node (including the noise of the
      target itself) to the statistical property (e.g. mean, variance) of the target. We call this contribution
      *intrinsic* as noise terms, by definition, do not inherit properties of observed parents. The contribution of each
      noise term is then the *intrinsic* causal contribution of the corresponding node. For more scientific details,
      please refer to the paper below.
  
      **Research Paper**:
      Janzing et al. *Quantifying causal contributions via structure preserving interventions*. arXiv:2007.00714, 2021.
  
      :param causal_model: The structural causal model for whose target node we compute the intrinsic causal influence
                           of its ancestors.
      :param target_node: Target node whose statistical property is to be attributed.
      :param prediction_model: Prediction model for estimating the functional relationship between subsets of ancestor
                               noise terms and the target node. This can be an instance of a PredictionModel, the string
                               'approx' or the string 'exact'. With 'exact', the underlying causal models in the graph
                               are utilized directly by propagating given noise inputs through the graph, which ensures
                               that generated samples follow the fitted models. In contrast, the 'approx' method involves
                               selecting and training a suitable model based on data sampled from the graph. This might
                               lead to deviations from the outcomes of the fitted models, but is faster and can be more
                               robust in certain settings.
      :param attribution_func: Optional attribution function to measure the statistical property of the target node. This
                               function expects two inputs; predictions after the randomization of certain features (i.e.
                               samples from noise nodes) and a baseline where no features were randomized. The baseline
                               predictions can be typically ignored if one is interested in uncertainty measures such as
                               entropy or variance, but they might be relevant if, for instance, these shall be estimated
                               based on the residuals. By default, entropy is used if prediction model is a classifier,
                               variance otherwise.
      :param num_training_samples: Number of samples drawn from the graphical causal model that are used for fitting the
                                   prediction_model (if necessary).
      :param num_samples_randomization: Number of noise samples drawn from the graphical causal model that are used for
                                        evaluating the set function. Here, these samples are samples from
                                        the noise distributions used for randomizing features that are not in the subset.
      :param num_samples_baseline: Number of noise samples drawn from the graphical causal model that are used for
                                   evaluating the set function. Here, these samples are used as fixed observations for
                                   features that are in the subset.
      :param max_batch_size: Maximum batch size for estimating the predictions from evaluation samples. This has a
                             significant impact on the overall memory usage. If set to -1, all samples are used in one
                             batch.
      :param auto_assign_quality: Auto assign quality for the 'approx' prediction_model option.
      :param shapley_config: :class:`~dowhy.gcm.shapley.ShapleyConfig` for the Shapley estimator.
      :return: Intrinsic causal contribution of each ancestor node to the statistical property defined by the
               attribution_func of the target node.
      """
      validate_causal_dag(causal_model.graph)
  
      # Creating a smaller subgraph, which only contains upstream nodes that are connected to the target node.
      sub_causal_model = StructuralCausalModel(
          node_connected_subgraph_view(causal_model.graph, target_node)
      )
  
      data_samples, noise_samples = noise_samples_of_ancestors(
          sub_causal_model, target_node, num_training_samples
      )
      node_names = noise_samples.columns
      noise_samples, target_samples = shape_into_2d(
          noise_samples.to_numpy(), data_samples[target_node].to_numpy()
      )
  
      target_is_categorical = is_categorical(
          data_samples[target_node].to_numpy()
      )
  
      prediction_method = _get_icc_noise_function(
          causal_model,
          target_node,
          prediction_model,
          noise_samples,
          node_names,
          target_samples,
          auto_assign_quality,
          target_is_categorical,
      )
  
      if attribution_func is None:
          if target_is_categorical:
  
              def attribution_func(x, _):
                  return -estimate_entropy_of_probabilities(x)
  
          else:
  
              def attribution_func(x, _):
                  return estimate_variance(x)
  
      _, noise_samples = noise_samples_of_ancestors(
          sub_causal_model,
          target_node,
          num_samples_randomization + num_samples_baseline,
      )
      noise_samples = shape_into_2d(noise_samples.to_numpy())
  
      iccs = _estimate_iccs(
          attribution_func,
          prediction_method,
          noise_samples[:num_samples_randomization],
          noise_samples[
              num_samples_randomization : num_samples_randomization
              + num_samples_baseline
          ],
          max_batch_size,
          ShapleyConfig() if shapley_config is None else shapley_config,
      )
  
      return {node: iccs[i] for i, node in enumerate(node_names)}
  
imports: import logging
  import warnings
  from typing import Any, Callable, Dict, Iterator, List, Optional, Tuple, Union, cast
  import numpy
  import pandas
  from joblib import Parallel, delayed
  from numpy.matlib import repmat
  import dowhy.gcm.auto
  from dowhy.gcm import feature_relevance_sample
  from dowhy.gcm._noise import compute_data_from_noise, compute_noise_from_data, noise_samples_of_ancestors
  from dowhy.gcm.causal_mechanisms import ClassifierFCM, ConditionalStochasticModel, ProbabilityEstimatorModel
  from dowhy.gcm.causal_models import InvertibleStructuralCausalModel, ProbabilisticCausalModel, StructuralCausalModel, validate_causal_dag, validate_node
  from dowhy.gcm.divergence import estimate_kl_divergence_of_probabilities
  from dowhy.gcm.fitting_sampling import draw_samples
  from dowhy.gcm.ml import ClassificationModel, PredictionModel
  from dowhy.gcm.shapley import ShapleyConfig, estimate_shapley_values
  from dowhy.gcm.stats import marginal_expectation
  from dowhy.gcm.uncertainty import estimate_entropy_of_probabilities, estimate_variance
  from dowhy.gcm.util.general import has_categorical, is_categorical, means_difference, set_random_seed, shape_into_2d
  from dowhy.graph import get_ordered_predecessors, is_root_node, node_connected_subgraph_view
label_desc: Use image node_id 4 for calling a global function with example usage: intrinsic_causal_influence(causal_model, target_node, prediction_model, attribution_func, num_training_samples, num_samples_randomization, num_samples_baseline, max_batch_size, auto_assign_quality, shapley_config) and returns: unknown, unknown, estimate_variance