class_docstr: Encoding stage computing Kashin's representation from Hadamard transform.
  
  This class is inspired by the work "Uncertainty Principle and Vector
  Quantization" (https://arxiv.org/pdf/math/0611343.pdf), and the algorithm
  presented therein.
  
  The encoding stage builds upon the `HadamardEncodingStage` and uses the
  overcomplete base to compute representation with a smaller dynamic range of
  coefficients. One of the benefits is that it incurrs a smaller error in
  subsequent uniform quantization, smaller even compared to using the
  `HadamardEncodingStage`.
  
  The idea is that certain overcomplete bases, or tight frames, admit what is
  called "Kashin's representation" for every vector. Kashin's representation is
  such that the dynamic range of coefficients is as small as (asymptotically)
  possible. In this case, the overcomplete base consists of subsampled Hadamard
  matrix.
  
  The algorithm iteratively computes coefficients of input vector in rotated
  space (or projected space), projects onto a L-infinity ball, computes the
  residual error incurred by the projection, and repeats the same procedure with
  the residual and a smaller ball.
  
  For the meaning of the parameters `eta` and `delta`, see Section III.A in the
  referenced paper. The main pseudocode presented there is as follows:
    Input:
      projection, parameters eta, delta (should be derived from the projection).
      vector x of which representation needs to be computed.
    Initialize:
      kashin_coefficients <- [0, 0, ..., 0]
      M <- norm(x) / sqrt(delta * output_dim)  # [initial clipping level]
    Repeat num_iter times:
      b <- frame representation of x
      b <- clip b at level M
      kashin_coefficients <- kashin_coefficients + b
      x' <- recover from frame representation b
      x <- x - x'
      M <- M * eta
    Output:
      kashin_coefficients
  
  The actual implementation of the encoding works as follows:
  The shape of the input `x` to the `encode` method must be either `(dim)` or
  `(b, dim)`, where `dim` is the dimenion of the vector to which the transform
  is to be applied, and must be statically known. `b` represents an optional
  batch dimension, and does not need to be statically known.
  
  If the shape of the input is `(dim)`, it is first expanded to `(1, dim)`. The
  input of shape `(b, dim)` is then padded with zeros to dimension `(b, dim_2)`,
  where `dim_2` is the smallest power of 2 larger than or equal to `dim`. In the
  case of `dim / dim_2 > pad_extra_level_threshold`, an extra factor of 2 is
  added to `dim_2`. Otherwise, the algorithm does not have enough leeway to
  realize benefits over only applying the randomized Hadamard transform.
  
  The Kashin's representation is then computed for each of the `b` vectors of
  shape `dim_2`. The encoded value thus has shape `(b, dim_2)`.
docstr: See base class.
docstr_tok: ["See","base","class","."]
code: def name(self):
      """See base class."""
      return "kashin_hadamard"
  
imports: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  import collections
  import numpy
  import tensorflow
  from tensorflow_model_optimization.python.core.internal.tensor_encoding.core import encoding_stage
  from tensorflow_model_optimization.python.core.internal.tensor_encoding.utils import tf_utils
label_desc: Use image node_id 2 for calling the KashinHadamardEncodingStage obj's underlying member method code with example usage: obj.name() and returns: str