예제 #1
0
    def _infer_metadata_entries_from_model(self, signature_name):
        """Infers metadata inputs and outputs."""
        loaded_sig = self._loaded_model.signatures[signature_name]
        _, input_sig = loaded_sig.structured_input_signature
        output_sig = loaded_sig.structured_outputs
        input_mds = {}
        for name, tensor_spec in input_sig.items():
            if tensor_spec.dtype.is_floating:
                input_mds[name] = explain_metadata.InputMetadata(name, name)
            else:
                input_mds[name] = explain_metadata.InputMetadata(
                    name, name, modality=explain_metadata.Modality.CATEGORICAL)

        if not self._explain_output and len(output_sig) > 1:
            raise ValueError(
                "Signature has multiple outputs. You must specify which"
                " output to explain via 'outputs_to_explain' parameter.")
        for name in output_sig:
            if not self._explain_output or self._explain_output[0] == name:
                output_mds = {
                    name: explain_metadata.OutputMetadata(name, name)
                }
                break
        else:
            raise ValueError("Specified output name cannot be found in given"
                             " signature outputs.")
        return input_mds, output_mds
  def _create_input_metadata(
      self,
      features_dict: Dict[Text, List[monkey_patch_utils.FeatureTensors]],
      crossed_columns: Set[Text],
      desired_columns: List[Text],
      drop_duplicate_features: bool = False,
      group_duplicate_features: bool = False):
    """Creates and returns a list of InputMetadata.

    Args:
      features_dict: Dictionary from feature name to FeatureTensors class.
      crossed_columns: A set of crossed column names.
      desired_columns: A list of feature column names. Only the columns in
        this list will be added to input metadata.
      drop_duplicate_features: If there are multiple inputs for the same
        feature column, then we will drop all but one if drop_duplicate_features
        is True. If False, we will include them all with unique suffix added
        to the input names to disambiguate.
      group_duplicate_features: If there are multiple inputs for the same
        feature column, then we will group them all as one feature group
        if this parameter is set to True.

    Returns:
      A list of InputMetadata.
    """
    input_mds = []
    for fc_name, tensor_groups in features_dict.items():
      if fc_name in desired_columns:
        for tensor_group in tensor_groups:
          input_md = self._get_input_tensor_names_for_metadata(tensor_group)
          if fc_name not in crossed_columns:
            input_md.update(
                self._get_encoded_tensor_names_for_metadata(tensor_group))
          input_md['name'] = fc_name
          if self._baselines:
            input_md['input_baselines'] = self._baselines.get(fc_name, None)
          if len(tensor_groups) == 1 or drop_duplicate_features:
            input_mds.append(explain_metadata.InputMetadata(**input_md))
            break  # Skip other tensor_groups.
          # There are multiple inputs for the same feature column.
          # Append part of the tensor name until the first '/'. This usually
          # specifies what kind of model it is: linear or dnn.
          input_tensor_name = str(input_md['input_tensor_name'])
          suffix = input_tensor_name.split('/')[0]
          input_md['name'] = '%s_%s' % (fc_name, suffix)
          if group_duplicate_features:
            input_md['group_name'] = fc_name
          input_mds.append(explain_metadata.InputMetadata(**input_md))
    return input_mds
    def _create_input_metadata(
            self, features_dict: Dict[Text,
                                      List[monkey_patch_utils.FeatureTensors]],
            crossed_columns: Set[Text], desired_columns: List[Text]):
        """Creates and returns a list of InputMetadata.

    Args:
      features_dict: Dictionary from feature name to FeatureTensors class.
      crossed_columns: A set of crossed column names.
      desired_columns: A list of feature column names. Only the columns in
        this list will be added to input metadata.

    Returns:
      A list of InputMetadata.
    """
        input_mds = []
        if self._input_mds is not None:
            input_mds = self._input_mds
        input_names_processed = set([i.name for i in input_mds])
        for fc_name, tensor_groups in features_dict.items():
            if fc_name in desired_columns and fc_name not in input_names_processed:
                for tensor_group in tensor_groups:
                    input_md = self._get_input_tensor_names_for_metadata(
                        tensor_group)
                    if fc_name not in crossed_columns:
                        input_md.update(
                            self._get_encoded_tensor_names_for_metadata(
                                tensor_group))
                    input_md['name'] = fc_name
                    if self._baselines:
                        input_md['input_baselines'] = self._baselines.get(
                            fc_name, None)
                    if (len(tensor_groups) == 1
                            or self._duplicate_action == DuplicateAction.DROP):
                        input_mds.append(
                            explain_metadata.InputMetadata(**input_md))
                        break  # Skip other tensor_groups.
                    # There are multiple inputs for the same feature column.
                    # Append part of the tensor name until the first '/'. This usually
                    # specifies what kind of model it is: linear or dnn.
                    input_tensor_name = str(input_md['input_tensor_name'])
                    suffix = input_tensor_name.split('/')[0]
                    input_md['name'] = '%s_%s' % (fc_name, suffix)
                    if self._duplicate_action == DuplicateAction.GROUP:
                        input_md['group_name'] = fc_name
                    input_mds.append(
                        explain_metadata.InputMetadata(**input_md))
        return input_mds
예제 #4
0
    def set_numeric_metadata(self,
                             input_name,
                             new_name=None,
                             input_baselines=None,
                             index_feature_mapping=None):
        """Sets an existing metadata identified by input as numeric with params.

    Args:
      input_name: Input name in the metadata to be set as numeric.
      new_name: Optional (unique) new name for this feature.
      input_baselines: A list of baseline values. Each baseline value can be a
        single entity or of the same shape as the model_input (except for the
        batch dimension).
      index_feature_mapping: A list of feature names for each index in the input
        tensor.

    Raises:
      ValueError: If input_name cannot be found in the metadata.
    """
        if input_name not in self._inputs:
            raise ValueError("Input with with name '%s' does not exist." %
                             input_name)
        name = new_name if new_name else input_name
        tensor_name = self._inputs.pop(input_name).input_tensor_name

        if index_feature_mapping:
            encoding = explain_metadata.Encoding.BAG_OF_FEATURES
        else:
            encoding = explain_metadata.Encoding.IDENTITY
        self._inputs[name] = explain_metadata.InputMetadata(
            name=name,
            input_tensor_name=tensor_name,
            input_baselines=input_baselines,
            index_feature_mapping=index_feature_mapping,
            encoding=encoding)
예제 #5
0
    def set_image_metadata(self,
                           input_name,
                           new_name=None,
                           input_baselines=None,
                           visualization=None):
        """Sets an existing metadata identified by input as image with params.

    Args:
      input_name: Input name in the metadata to be set as numeric.
      new_name: Optional (unique) new name for this feature.
      input_baselines: A list of baseline values. Each baseline value can be a
        single entity or of the same shape as the model_input (except for the
        batch dimension).
      visualization: A dictionary specifying visualization parameters. Check out
        original documentation for possible keys and values:
        https://cloud.google.com/ai-platform/prediction/docs/ai-explanations/visualizing-explanations

    Raises:
      ValueError: If input_name cannot be found in the metadata.
    """
        if input_name not in self._inputs:
            raise ValueError("Input with with name '%s' does not exist." %
                             input_name)
        name = new_name if new_name else input_name
        tensor_name = self._inputs.pop(input_name).input_tensor_name
        self._inputs[name] = explain_metadata.InputMetadata(
            name=name,
            input_tensor_name=tensor_name,
            input_baselines=input_baselines,
            modality=explain_metadata.Modality.IMAGE,
            visualization=visualization)
    def _add_input_metadata(
            self,
            input_tensor: tf.Tensor,
            name: Optional[Text] = None,
            encoded_tensor: Optional[tf.Tensor] = None,
            encoding: Optional[Text] = explain_metadata.Encoding.IDENTITY,
            input_baselines: Optional[List[Any]] = None,
            encoded_baselines: Optional[List[Any]] = None,
            modality: Optional[Text] = None,
            visualization: Optional[Union[Dict[
                str, str], parameters.VisualizationParameters]] = None,
            index_feature_mapping: Optional[List[Any]] = None,
            domain: Optional[parameters.DomainInfo] = None):
        """Creates an InputMetadata object.

    Args:
      input_tensor: Input tensor for the metadata.
      name: Metadata name for the given input.
      encoded_tensor: Encoded tensor if a tensor representing categorical input
        is encoded to another tensor.
      encoding: Encoding type. One of the values in explain_metadata.Encoding.
      input_baselines: A list of baselines for the input tensor.
      encoded_baselines: A list of baselines for the encoded tensor.
      modality: Modality of the input. One of the values in
        explain_metadata.Modality.
      visualization: Visualization parameters for image inputs. It can either be
        a dictionary of inputs or VisualizationParameters.
      index_feature_mapping: A list of feature names for each index in the input
        tensor.
      domain: DomainInfo object specifying the range of the input feature.
    """
        input_name = name if name else input_tensor.op.name
        encoded_tensor_name = (encoded_tensor.name
                               if encoded_tensor is not None else None)
        if input_tensor.name in self._inputs:
            raise ValueError('Input tensor %s already exists' % input_name)
        if input_name in [input_md.name for input_md in self._inputs.values()]:
            raise ValueError('Input name %s already exists' % input_name)
        domain_dict = domain.asdict() if domain else None
        if (visualization and isinstance(visualization,
                                         parameters.VisualizationParameters)):
            visualization = visualization.asdict()
        self._inputs[input_tensor.name] = explain_metadata.InputMetadata(
            name=input_name,
            input_tensor_name=input_tensor.name,
            encoded_tensor_name=encoded_tensor_name,
            encoding=encoding,
            input_baselines=input_baselines,
            encoded_baselines=encoded_baselines,
            modality=modality,
            visualization=visualization,
            index_feature_mapping=index_feature_mapping,
            domain=domain_dict)
    def set_categorical_metadata(
        self,
        input_name: str,
        new_name: Optional[str] = None,
        encoded_name: Optional[str] = None,
        encoding: str = explain_metadata.Encoding.IDENTITY,
        input_baselines: Optional[List[Union[types.TensorValue,
                                             types.Tensor]]] = None,
        encoded_baselines: Optional[List[Union[types.TensorValue,
                                               types.Tensor]]] = None
    ) -> None:
        """Sets an existing metadata identified by input as categorical with params.

    Args:
      input_name: Input name in the metadata to be set as numeric.
      new_name: Optional (unique) new name for this feature.
      encoded_name: Optional name of the tensor, which is the encoded version of
        the input tensor. It is potentially an output of an encoding function
        such as embedding. Each encoded_name should map to a unique input.
      encoding: Encoding type if encoded_tensor is provided. Possible values are
        {identity, bag_of_features, bag_of_features_sparse, indicator,
        combined_embedding, concat_embedding}.
      input_baselines: A list of baseline values. Each baseline value can be a
        single entity or of the same shape as the model_input (except for the
        batch dimension).
      encoded_baselines: A list of baseline values for the encoded tensor.

    Raises:
      ValueError: If input_name cannot be found in the metadata.
    """
        if input_name not in self._inputs:
            raise ValueError("Input with with name '%s' does not exist." %
                             input_name)
        name = new_name if new_name else input_name
        tensor_name = self._inputs.pop(input_name).input_tensor_name

        self._inputs[name] = explain_metadata.InputMetadata(
            name=name,
            input_tensor_name=tensor_name,
            input_baselines=input_baselines,
            encoded_tensor_name=encoded_name,
            encoded_baselines=encoded_baselines,
            modality=explain_metadata.Modality.CATEGORICAL,
            encoding=encoding)
예제 #8
0
    def _add_input_metadata(self,
                            input_tensor,
                            name=None,
                            encoded_tensor=None,
                            encoding=explain_metadata.Encoding.IDENTITY,
                            input_baselines=None,
                            encoded_baselines=None,
                            modality=None,
                            visualization=None,
                            index_feature_mapping=None):
        """Internal add metadata function that creates an InputMetadata object.

    Args:
      input_tensor: Input tensor for the metadata.
      name: Metadata name for the given input.
      encoded_tensor: Encoded tensor if a tensor representing categorical input
        is encoded to another tensor.
      encoding: Encoding type. One of the values in explain_metadata.Encoding.
      input_baselines: A list of baselines for the input tensor.
      encoded_baselines: A list of baselines for the encoded tensor.
      modality: Modality of the input. One of the values in
        explain_metadata.Modality.
      visualization: Visualization parameters for image inputs.
      index_feature_mapping: A list of feature names for each index in the input
        tensor.
    """
        input_name = name if name else input_tensor.op.name
        encoded_tensor_name = (encoded_tensor.name
                               if encoded_tensor is not None else None)
        if input_tensor.name in self._inputs:
            raise ValueError('Input tensor %s already exists' % input_name)
        if input_name in [input_md.name for input_md in self._inputs.values()]:
            raise ValueError('Input name %s already exists' % input_name)
        self._inputs[input_tensor.name] = explain_metadata.InputMetadata(
            name=input_name,
            input_tensor_name=input_tensor.name,
            encoded_tensor_name=encoded_tensor_name,
            encoding=encoding,
            input_baselines=input_baselines,
            encoded_baselines=encoded_baselines,
            modality=modality,
            visualization=visualization,
            index_feature_mapping=index_feature_mapping)
    def set_image_metadata(
            self,
            input_name: str,
            new_name: Optional[str] = None,
            input_baselines: Optional[List[Union[types.TensorValue,
                                                 types.Tensor]]] = None,
            visualization: Optional[Union[Dict[
                str, str], parameters.VisualizationParameters]] = None,
            domain: Optional[parameters.DomainInfo] = None) -> None:
        """Sets an existing metadata identified by input as image with params.

    Args:
      input_name: Input name in the metadata to be set as numeric.
      new_name: Optional (unique) new name for this feature.
      input_baselines: A list of baseline values. Each baseline value can be a
        single entity or of the same shape as the model_input (except for the
        batch dimension).
      visualization: Either a dictionary of visualization parameters or
        VisualizationParameters instance. Using VisualizationParameters is
        recommended. If None, a default visualization will be selected based on
        the explanation method (IG/XRAI).
      domain: DomainInfo object specifying the range of the input feature.

    Raises:
      ValueError: If input_name cannot be found in the metadata.
    """
        if input_name not in self._inputs:
            raise ValueError("Input with with name '%s' does not exist." %
                             input_name)
        name = new_name if new_name else input_name
        tensor_name = self._inputs.pop(input_name).input_tensor_name
        if (visualization and isinstance(visualization,
                                         parameters.VisualizationParameters)):
            visualization = visualization.asdict()
        domain_dict = domain.asdict() if domain else None
        self._inputs[name] = explain_metadata.InputMetadata(
            name=name,
            input_tensor_name=tensor_name,
            input_baselines=input_baselines,
            modality=explain_metadata.Modality.IMAGE,
            visualization=visualization,
            domain=domain_dict)
예제 #10
0
    def _create_input_metadata(
            self, features_dict: Dict[Text,
                                      List[monkey_patch_utils.FeatureTensors]],
            crossed_columns: Set[Text], desired_columns: List[Text]):
        """Creates and returns a list of InputMetadata.

    Args:
      features_dict: Dictionary from feature name to FeatureTensors class.
      crossed_columns: A set of crossed column names.
      desired_columns: A list of feature column names. Only the columns in
        this list will be added to input metadata.

    Returns:
      A list of InputMetadata.
    """
        input_mds = []
        for fc_name, tensor_groups in features_dict.items():
            if fc_name in desired_columns:
                for tensor_group in tensor_groups:
                    input_md = self._get_input_tensor_names_for_metadata(
                        tensor_group)

                    if fc_name not in crossed_columns:
                        input_md.update(
                            self._get_encoded_tensor_names_for_metadata(
                                tensor_group))

                    if len(tensor_groups) == 1:
                        input_name = fc_name
                    else:
                        # If there are multiple inputs for the same feature column, append
                        # part of the tensor name until the first '/'. This usually
                        # specifies what kind of model it is: linear or dnn.
                        input_name = '%s_%s' % (
                            fc_name,
                            input_md['input_tensor_name'].split('/')[0])
                    input_md['name'] = input_name
                    input_mds.append(
                        explain_metadata.InputMetadata(**input_md))
        return input_mds
def _create_input_metadata_from_signature(
    signature_inputs: Dict[str, tf.Tensor]
    ) -> Dict[str, explain_metadata.InputMetadata]:
  """Creates InputMetadata from signature inputs."""
  return {key: explain_metadata.InputMetadata(key, tensor.name)
          for key, tensor in signature_inputs.items()}