class_docstr: Quantized counterpart of nn.Conv2d module. Stores the centroid, the assignments
  and the non-quantized biases. The full weight is re-instantiated at each forward
  pass and autograd automatically computes the gradients with respect to the
  centroids.
  
  Args:
      - centroids: centroids of size n_centroids x block_size
      - assignments: assignments of the centroids to the subvectors
        of size self.out_channels x n_blocks
      - bias: the non-quantized bias, must be either torch.Tensor or None
  
  Remarks:
      - We refer the reader to the official documentation of the nn.Conv2d module
        for the other arguments and the behavior of the module.
      - Performance tests on GPU show that this implementation is 10% slower than
        the non-quantized nn.Conv2d module for a standard training loop.
      - During the backward, the gradients are averaged by cluster and not summed.
        This explains the hook registered to the centroids.
class_docstr_tok: ["Quantized","counterpart","of","nn.Conv2d","module",".","Stores","the","centroid",",","the","assignments","and","the","non-quantized","biases",".","The","full","weight","is","re-instantiated","at","each","forward","pass","and","autograd","automatically","computes","the","gradients","with","respect","to","the","centroids",".","Args",":","-","centroids",":","centroids","of","size","n_centroids","x","block_size","-","assignments",":","assignments","of","the","centroids","to","the","subvectors","of","size","self.out_channels","x","n_blocks","-","bias",":","the","non-quantized","bias",",","must","be","either","torch.Tensor","or","None","Remarks",":","-","We","refer","the","reader","to","the","official","documentation","of","the","nn.Conv2d","module","for","the","other","arguments","and","the","behavior","of","the","module",".","-","Performance","tests","on","GPU","show","that","this","implementation","is","10","%","slower","than","the","non-quantized","nn.Conv2d","module","for","a","standard","training","loop",".","-","During","the","backward",",","the","gradients","are","averaged","by","cluster","and","not","summed",".","This","explains","the","hook","registered","to","the","centroids","."]
code: def __init__(
      self,
      centroids,
      assignments,
      bias,
      in_channels,
      out_channels,
      kernel_size,
      stride=1,
      padding=0,
      dilation=1,
      groups=1,
      padding_mode="zeros",
  ):
      super(PQConv2d, self).__init__()
      self.block_size = centroids.size(1)
      self.n_centroids = centroids.size(0)
      self.in_channels = in_channels
      self.out_channels = out_channels
      self.kernel_size = _pair(kernel_size)
      self.stride = _pair(stride)
      self.padding = _pair(padding)
      self.dilation = _pair(dilation)
      self.groups = groups
      self.padding_mode = padding_mode
      # check compatibility
      if (
          in_channels
          // groups
          * np.prod(self.kernel_size)
          % self.block_size
          != 0
      ):
          raise ValueError("Wrong PQ sizes")
      if len(assignments) % out_channels != 0:
          raise ValueError("Wrong PQ sizes")
      if in_channels % groups != 0:
          raise ValueError("in_channels must be divisible by groups")
      if out_channels % groups != 0:
          raise ValueError("out_channels must be divisible by groups")
      # define parameters
      self.centroids = nn.Parameter(centroids, requires_grad=True)
      self.register_buffer("assignments", assignments)
      self.register_buffer(
          "counts", torch.bincount(assignments).type_as(centroids)
      )
      if bias is not None:
          self.bias = nn.Parameter(bias)
      else:
          self.register_parameter("bias", None)
      # register hook for averaging gradients per centroids instead of summing
      self.centroids.register_hook(lambda x: x / self.counts[:, None])
  
file_path: fairseq/fairseq/modules/quantization/pq/modules/qconv.py
imports: import numpy
  import torch
  import torch.nn
  import torch.nn.functional
  from torch.nn.modules.utils import _pair
label_desc: Use image node_id 1 to create a new PQConv2d object from inherited base classes: nn with example: obj = PQConv2d(centroids, assignments, bias, in_channels, out_channels, kernel_size, stride, padding, dilation, groups, padding_mode)