class_docstr: A distribution that samples items based on scores and cosine similarity.
code: def _penalizer_fn(self, logits, features, slots):
      num_items = logits.shape[-1]
      num_slotted = len(slots)
      slot_tensor = tf.stack(slots, axis=-1)
      # The tfd.Categorical distribution will give the sample `num_items` if all
      # the logits are `-inf`. Hence, we need to apply minimum. This happens when
      # `num_actions` is less than `num_slots`. To this end, the action taken by
      # the policy always has to be taken together with the `num_actions`
      # observation, to know how many slots are filled with valid items.
      slotted_features = tf.gather(
          features, tf.minimum(slot_tensor, num_items - 1), batch_dims=1
      )
  
      # Calculate the similarity between all pairs from
      # `slotted_features x all_features`.
      all_sims = (
          tf.keras.losses.cosine_similarity(
              tf.repeat(features, num_slotted, axis=1),
              tf.tile(slotted_features, [1, num_items, 1]),
          )
          - 1
      )
  
      sim_matrix = tf.reshape(
          all_sims, shape=[-1, num_items, num_slotted]
      )
      similarity_boosts = tf.reduce_min(sim_matrix, axis=-1)
      adjusted_logits = logits + (
          self._penalty_mixture_coefficient * similarity_boosts
      )
      return adjusted_logits
  
imports: from typing import Optional, Sequence, Text
  import numpy
  import tensorflow
  import tensorflow_probability
  from tf_agents.policies import tf_policy
  from tf_agents.policies import utils
  from tf_agents.specs import bandit_spec_utils
  from tf_agents.specs import tensor_spec
  from tf_agents.trajectories import policy_step
  from tf_agents.typing import types
label_desc: Use image node_id 1 for calling the CosinePenalizedPlackettLuce obj's underlying member method code with example usage: obj._penalizer_fn(logits, features, slots) and returns: adjusted_logits