class_docstr: `FeatureScaled` kernel for continuous and categorical data.
  
  This kernel is an extension of `FeatureScaled` that handles categorical data
  (encoded as integers, not one-hot) in addition to continuous (float) data.
  `ContinuousAndCategoricalValues` structures, containing arrays of continuous
  and categorical data, are passed to the `apply`, `matrix` and `tensor`
  methods. The continuous inputs are scaled and then passed to the distance
  function, like in `FeatureScaled`. Categorical data is compared for equality,
  and features in the same category are assigned distance 0 and features in
  different categories are assigned distance 1. The scaling factors are then
  applied to the categorical distances.
  
  #### Examples
  
  Compute the kernel matrix on synthetic data.
  
  ```python
  import numpy as np
  
  continuous_dim = 3
  categorical_dim = 5
  
  # Define an ARD kernel that takes a structure of continuous and categorical
  # data as inputs, with randomly-sampled length scales. The `categorical`
  # field of `scale_diag` contains a float Tensor because it represents a
  # scaling multiplier for the categorical distance, not the categorical data
  # itself.
  base_kernel = tfpk.MaternFiveHalves()
  kernel = tfpks.FeatureScaledWithCategorical(
      base_kernel,
      scale_diag=tfpks.ContinuousAndCategoricalValues(
          continuous=np.random.uniform(size=[continuous_dim]),
          categorical=np.random.uniform(size=[categorical_dim])),
      validate_args=True)
  
  # Create `num_points` examples in the continuous/categorical feature space.
  num_points = 12
  num_categories = 10
  x1 = tfpks.ContinuousAndCategoricalValues(
      continuous=np.random.normal(size=(num_points, continuous_dim)),
      categorical=np.random.randint(
          num_categories, size=(num_points, categorical_dim)))
  x2 = tfpks.ContinuousAndCategoricalValues(
      continuous=np.random.normal(size=(num_points, continuous_dim)),
      categorical=np.random.randint(
          num_categories, size=(num_points, categorical_dim)))
  
  # Evaluate the kernel matrix for `x1` and `x2`.
  kernel.matrix(x1, x2)  # has shape `[num_points, num_points]`
  
  ```
docstr: Construct an `FeatureScaledWithCategorical` kernel instance.
  
  Args:
    kernel: `PositiveSemidefiniteKernel` instance. Parameters to `kernel` must
      be broadcastable with `scale_diag`. `kernel` must be isotropic and
      implement an `_apply_with_distance` method.
    scale_diag: `ContinuousAndCategoricalValues` instance containing floating
      point arrays that control the sharpness/width of the kernel shape. Each
      component of `scale_diag` must have dimensionality of at least
      the corresponding (continuous or categorical) element of
      `kernel.feature_ndims`, and extra dimensions must be broadcastable with
      parameters of `kernel`. This is a "diagonal" in the sense that if all
      the feature dimensions were flattened, `scale_diag` acts as the inverse
      of a diagonal matrix.
      Default value: None.
    inverse_scale_diag: `ContinuousAndCategoricalValues` instance containing
      non-negative floating point arrays that are treated as the reciprocals
      of the corresponding components of `scale_diag`.  Only one of
      `scale_diag` or `inverse_scale_diag` should be provided.
      Default value: None
    feature_ndims: `ContinuousAndCategoricalValues` instance containing
      integers indicating the rank of the continuous and categorical feature
      space. Default value: None, i.e. `kernel.feature_ndims` for both
      components of the feature space.
    validate_args: If `True`, parameters are checked for validity despite
      possibly degrading runtime performance.
    name: Python `str` name prefixed to Ops created by this class.
docstr_tok: ["Construct","an","`","FeatureScaledWithCategorical","`","kernel","instance",".","Args",":","kernel",":","`","PositiveSemidefiniteKernel","`","instance",".","Parameters","to","`","kernel","`","must","be","broadcastable","with","`","scale_diag","`",".","`","kernel","`","must","be","isotropic","and","implement","an","`","_apply_with_distance","`","method",".","scale_diag",":","`","ContinuousAndCategoricalValues","`","instance","containing","floating","point","arrays","that","control","the","sharpness\/width","of","the","kernel","shape",".","Each","component","of","`","scale_diag","`","must","have","dimensionality","of","at","least","the","corresponding","(","continuous","or","categorical",")","element","of","`","kernel.feature_ndims","`",",","and","extra","dimensions","must","be","broadcastable","with","parameters","of","`","kernel","`",".","This","is","a","``","diagonal","''","in","the","sense","that","if","all","the","feature","dimensions","were","flattened",",","`","scale_diag","`","acts","as","the","inverse","of","a","diagonal","matrix",".","Default","value",":","None",".","inverse_scale_diag",":","`","ContinuousAndCategoricalValues","`","instance","containing","non-negative","floating","point","arrays","that","are","treated","as","the","reciprocals","of","the","corresponding","components","of","`","scale_diag","`",".","Only","one","of","`","scale_diag","`","or","`","inverse_scale_diag","`","should","be","provided",".","Default","value",":","None","feature_ndims",":","`","ContinuousAndCategoricalValues","`","instance","containing","integers","indicating","the","rank","of","the","continuous","and","categorical","feature","space",".","Default","value",":","None",",","i.e",".","`","kernel.feature_ndims","`","for","both","components","of","the","feature","space",".","validate_args",":","If","`","True","`",",","parameters","are","checked","for","validity","despite","possibly","degrading","runtime","performance",".","name",":","Python","`","str","`","name","prefixed","to","Ops","created","by","this","class","."]
code: def __init__(
      self,
      kernel,
      scale_diag=None,
      inverse_scale_diag=None,
      feature_ndims=None,
      validate_args=False,
      name="FeatureScaledWithCategorical",
  ):
      """Construct an `FeatureScaledWithCategorical` kernel instance.
  
      Args:
        kernel: `PositiveSemidefiniteKernel` instance. Parameters to `kernel` must
          be broadcastable with `scale_diag`. `kernel` must be isotropic and
          implement an `_apply_with_distance` method.
        scale_diag: `ContinuousAndCategoricalValues` instance containing floating
          point arrays that control the sharpness/width of the kernel shape. Each
          component of `scale_diag` must have dimensionality of at least
          the corresponding (continuous or categorical) element of
          `kernel.feature_ndims`, and extra dimensions must be broadcastable with
          parameters of `kernel`. This is a "diagonal" in the sense that if all
          the feature dimensions were flattened, `scale_diag` acts as the inverse
          of a diagonal matrix.
          Default value: None.
        inverse_scale_diag: `ContinuousAndCategoricalValues` instance containing
          non-negative floating point arrays that are treated as the reciprocals
          of the corresponding components of `scale_diag`.  Only one of
          `scale_diag` or `inverse_scale_diag` should be provided.
          Default value: None
        feature_ndims: `ContinuousAndCategoricalValues` instance containing
          integers indicating the rank of the continuous and categorical feature
          space. Default value: None, i.e. `kernel.feature_ndims` for both
          components of the feature space.
        validate_args: If `True`, parameters are checked for validity despite
          possibly degrading runtime performance.
        name: Python `str` name prefixed to Ops created by this class.
      """
      parameters = dict(locals())
      if (scale_diag is None) == (inverse_scale_diag is None):
          raise ValueError(
              "Must specify exactly one of `scale_diag` and `inverse_scale_diag`."
          )
      with tf.name_scope(name):
          float_dtype = dtype_util.common_dtype(
              [kernel, scale_diag, inverse_scale_diag],
              dtype_hint=tf.float32,
          )
          dtype = ContinuousAndCategoricalValues(float_dtype, None)
          if scale_diag is None:
              self._scale_diag = scale_diag
              self._inverse_scale_diag = (
                  nest_util.convert_to_nested_tensor(
                      inverse_scale_diag,
                      dtype_hint=dtype,
                      name="inverse_scale_diag",
                      convert_ref=False,
                  )
              )
          else:
              self._scale_diag = nest_util.convert_to_nested_tensor(
                  scale_diag,
                  dtype_hint=dtype,
                  name="scale_diag",
                  convert_ref=False,
              )
              self._inverse_scale_diag = inverse_scale_diag
          self._kernel = kernel
  
          if feature_ndims is None:
              feature_ndims = ContinuousAndCategoricalValues(
                  kernel.feature_ndims, kernel.feature_ndims
              )
  
          super(FeatureScaledWithCategorical, self).__init__(
              feature_ndims=feature_ndims,
              dtype=dtype,
              name=name,
              validate_args=validate_args,
              parameters=parameters,
          )
  
imports: import collections
  import tensorflow.compat.v2
  from tensorflow_probability.python.internal import assert_util
  from tensorflow_probability.python.internal import dtype_util
  from tensorflow_probability.python.internal import nest_util
  from tensorflow_probability.python.internal import parameter_properties
  from tensorflow_probability.python.internal import tensor_util
  from tensorflow_probability.python.math.psd_kernels import positive_semidefinite_kernel
  from tensorflow_probability.python.math.psd_kernels.internal import util
label_desc: Use image node_id 1 to create a new FeatureScaledWithCategorical object from inherited base classes: psd_kernel with example: obj = FeatureScaledWithCategorical(kernel, scale_diag, inverse_scale_diag, feature_ndims, validate_args, name)