class_docstr: Abstract base class for implementing different cluster centroid initialisation algorithms.
  
  Must be initialised with a reference to the
  weights and implement the single method below.
  
  Optionally, zero-centroid initialization (used for sparsity-aware clustering)
  can be enforced by setting the preserve_sparsity option in the clustering
  parameters.
  The procedure is the following:
  1. First, one centroid is set to zero explicitly
  2. The zero-point centroid divides the weights into two intervals: positive
  and negative.
  3. The remaining centroids are proportionally allocated to the two intervals
  4. For each interval (positive and negative), the standard initialization is
  used.
class_docstr_tok: ["Abstract","base","class","for","implementing","different","cluster","centroid","initialisation","algorithms",".","Must","be","initialised","with","a","reference","to","the","weights","and","implement","the","single","method","below",".","Optionally",",","zero-centroid","initialization","(","used","for","sparsity-aware","clustering",")","can","be","enforced","by","setting","the","preserve_sparsity","option","in","the","clustering","parameters",".","The","procedure","is","the","following",":","1",".","First",",","one","centroid","is","set","to","zero","explicitly","2",".","The","zero-point","centroid","divides","the","weights","into","two","intervals",":","positive","and","negative",".","3",".","The","remaining","centroids","are","proportionally","allocated","to","the","two","intervals","4",".","For","each","interval","(","positive","and","negative",")",",","the","standard","initialization","is","used","."]
docstr: The zero-centroid sparsity preservation technique works as follows.
  
  1. First, one centroid is set to zero explicitly
  2. The zero-point centroid divides the weights into two intervals:
     positive and negative
  3. The remaining centroids are proportionally allocated to the two
     intervals
  4. For each interval (positive and negative), the standard initialization
     is used
  This method is also referred to as sparsity-aware centroid initialization.
  
  Args:
    weights_to_cluster: Optional list of weights.
  
  Returns:
    centroids.
docstr_tok: ["The","zero-centroid","sparsity","preservation","technique","works","as","follows",".","1",".","First",",","one","centroid","is","set","to","zero","explicitly","2",".","The","zero-point","centroid","divides","the","weights","into","two","intervals",":","positive","and","negative","3",".","The","remaining","centroids","are","proportionally","allocated","to","the","two","intervals","4",".","For","each","interval","(","positive","and","negative",")",",","the","standard","initialization","is","used","This","method","is","also","referred","to","as","sparsity-aware","centroid","initialization",".","Args",":","weights_to_cluster",":","Optional","list","of","weights",".","Returns",":","centroids","."]
code: def _zero_centroid_initialization(self, weights_to_cluster=None):
      """The zero-centroid sparsity preservation technique works as follows.
  
      1. First, one centroid is set to zero explicitly
      2. The zero-point centroid divides the weights into two intervals:
         positive and negative
      3. The remaining centroids are proportionally allocated to the two
         intervals
      4. For each interval (positive and negative), the standard initialization
         is used
      This method is also referred to as sparsity-aware centroid initialization.
  
      Args:
        weights_to_cluster: Optional list of weights.
  
      Returns:
        centroids.
      """
      # In the case of per-channel clustering, set weights
      # to be clustered to channel weights.
      weights = (
          weights_to_cluster
          if weights_to_cluster is not None
          else self.weights
      )
  
      # Zero-point centroid
      zero_centroid = tf.zeros(shape=(1,))
  
      # Get the negative weights
      negative_weights = tf.boolean_mask(
          weights, tf.math.less(weights, 0)
      )
      negative_weights_count = tf.size(negative_weights)
  
      # Get the positive weights
      positive_weights = tf.boolean_mask(
          weights, tf.math.greater(weights, 0)
      )
      positive_weights_count = tf.size(positive_weights)
  
      # Get the number of non-zero weights
      non_zero_weights_count = (
          negative_weights_count + positive_weights_count
      )
  
      if tf.math.equal(non_zero_weights_count, 0):
          # No non-zero weights available, simply return the zero-centroid
          return zero_centroid
  
      # Reduce the number of clusters by one to allow room for the zero-point
      # centroid.
      number_of_non_zero_clusters = self.number_of_clusters - 1
  
      # Split the non-zero clusters proportionally among negative and positive
      # weights.
      negative_weights_ratio = (
          negative_weights_count / non_zero_weights_count
      )
      number_of_negative_clusters = tf.cast(
          tf.math.round(
              number_of_non_zero_clusters * negative_weights_ratio
          ),
          dtype=tf.int64,
      )
      number_of_positive_clusters = (
          number_of_non_zero_clusters - number_of_negative_clusters
      )
  
      # Calculate the negative centroids
      negative_cluster_centroids = (
          self._calculate_centroids_for_interval(
              negative_weights, number_of_negative_clusters
          )
      )
  
      # Calculate the positive centroids
      positive_cluster_centroids = (
          self._calculate_centroids_for_interval(
              positive_weights, number_of_positive_clusters
          )
      )
  
      # Put all the centroids together: negative, zero, positive
      centroids = tf.concat(
          [
              negative_cluster_centroids,
              zero_centroid,
              positive_cluster_centroids,
          ],
          axis=0,
      )
  
      return centroids
  
imports: import abc
  import six
  import tensorflow
  from tensorflow.python.ops import clustering_ops
  from tensorflow_model_optimization.python.core.clustering.keras import cluster_config
label_desc: Use image node_id 5 for calling the AbstractCentroidsInitialisation obj's underlying member method code with example usage: obj._zero_centroid_initialization(weights_to_cluster) and returns: centroids, zero_centroid