class_docstr: Local Interpretable Model-agnostic Explanations (LIME).
class_docstr_tok: ["Local","Interpretable","Model-agnostic","Explanations","(","LIME",")","."]
docstr: Run this component, given a model and input(s).
docstr_tok: ["Run","this","component",",","given","a","model","and","input","(","s",")","."]
code: def run(
      self,
      inputs: list[JsonDict],
      model: lit_model.Model,
      dataset: lit_dataset.Dataset,
      model_outputs: Optional[list[JsonDict]] = None,
      config: Optional[JsonDict] = None,
  ) -> Optional[list[JsonDict]]:
      """Run this component, given a model and input(s)."""
      config_defaults = {
          k: v.default for k, v in self.config_spec().items()
      }
      config = dict(
          config_defaults, **(config or {})
      )  # update and return
  
      kernel_width = int(config[KERNEL_WIDTH_KEY])
      num_samples = int(config[NUM_SAMPLES_KEY])
      mask_string = config[MASK_KEY]
      # pylint: disable=g-explicit-bool-comparison
      seed = int(config[SEED_KEY]) if config[SEED_KEY] != "" else None
      # pylint: enable=g-explicit-bool-comparison
  
      # Find keys of input (text) segments to explain.
      # Search in the input spec, since it's only useful to look at ones that are
      # used by the model.
      text_keys = utils.find_spec_keys(
          model.input_spec(), types.TextSegment
      )
      if not text_keys:
          logging.warning("LIME requires text inputs.")
          return None
      logging.info(
          "Found text fields for LIME attribution: %s", str(text_keys)
      )
  
      available_pred_keys = utils.find_spec_keys(
          model.output_spec(), _SUPPORTED_PRED_TYPES
      )
      if not available_pred_keys:
          logging.warning(
              "LIME did not find any supported output fields."
          )
          return None
  
      if (field := config[TARGET_HEAD_KEY]) and (
          cls_idx := int(config[CLASS_KEY])
      ) != -1:
          # TODO(b/205996131): remove this case
          pred_key = field
          provided_class_to_explain = cls_idx
      elif target_config := config.get(TARGET_INFO_KEY):
          pred_key = target_config["field"]
          if pred_key not in available_pred_keys:
              logging.warning(
                  "LIME is not compatible with field '%s'", pred_key
              )
              return None
          # May be None, if there's no label vocab.
          provided_class_to_explain = target_config.get("index")
      else:
          pred_key = available_pred_keys[0]
          provided_class_to_explain = None  # use model prediction
  
      pred_type_info = model.output_spec()[pred_key]
      all_results = []
  
      # Explain each input.
      for example in inputs:
          # dict[field name -> interpretations]
          result = {}
          predict_fn = functools.partial(
              _predict_fn,
              model=model,
              original_example=example,
              pred_key=pred_key,
              pred_type_info=pred_type_info,
          )
  
          class_to_explain = get_class_to_explain(
              model, pred_key, example, provided_class_to_explain
          )
  
          # Explain each text segment in the input, keeping the others constant.
          for text_key in text_keys:
              input_string = example[text_key]
              logging.info("Explaining: %s", input_string)
  
              # Perturbs the input string, gets model predictions, fits linear model.
              explanation = lime.explain(
                  sentence=input_string,
                  predict_fn=functools.partial(
                      predict_fn, text_key=text_key
                  ),
                  # `class_to_explain` is ignored when predict_fn output is a scalar.
                  class_to_explain=class_to_explain,
                  num_samples=num_samples,
                  tokenizer=str.split,
                  mask_token=mask_string,
                  kernel=functools.partial(
                      lime.exponential_kernel, kernel_width=kernel_width
                  ),
                  seed=seed,
              )
  
              # Turn the LIME explanation into a list following original word order.
              scores = explanation.feature_importance
              # TODO(lit-dev): Move score normalization to the UI.
              scores = citrus_util.normalize_scores(scores)
              result[text_key] = dtypes.TokenSalience(
                  explanation.features, scores
              )
  
          all_results.append(result)
  
      return all_results
  
imports: from collections.abc import Iterable
  import functools
  from typing import Any, Optional
  from absl import logging
  from lit_nlp.api import components
  from lit_nlp.api import dataset
  from lit_nlp.api import dtypes
  from lit_nlp.api import model
  from lit_nlp.api import types
  from lit_nlp.components.citrus import lime
  from lit_nlp.components.citrus import utils
  from lit_nlp.lib import utils
  import numpy
label_desc: Use image node_id 2 for calling the LIME obj's underlying member method code with example usage: obj.run(inputs, model, dataset, model_outputs, config) and returns: all_results, None, None, None