class_docstr: Vector Cross Network can be refered as
  `DCN-V1 <https://arxiv.org/pdf/1708.05123.pdf>`_.
  
  It is also a specialized low rank cross net, where rank=1. In this version, on each
  layer, instead of keeping two kernels W and V, we only keep one vector kernel W
  (Nx1). We use the dot operation to compute the "crossing" effect of the features,
  thus saving two matrix multiplications to further reduce computational cost and cut
  the number of learnable parameters.
  
  On each layer l, the tensor is transformed into
  
  .. math::    x_{l+1} = x_0 * (W_l . x_l + b_l) + x_l
  
  where :math:`W_l` is either a vector, :math:`*` means element-wise multiplication;
  :math:`.` means dot operations.
  
  Args:
      in_features (int): the dimension of the input.
      num_layers (int): the number of layers in the module.
  
  Example::
  
      batch_size = 3
      num_layers = 2
      in_features = 10
      input = torch.randn(batch_size, in_features)
      dcn = VectorCrossNet(num_layers=num_layers)
      output = dcn(input)
class_docstr_tok: ["Vector","Cross","Network","can","be","refered","as","`","DCN-V1","<","https",":","\/\/arxiv.org\/pdf\/1708.05123.pdf",">","`","_",".","It","is","also","a","specialized","low","rank","cross","net",",","where","rank=1",".","In","this","version",",","on","each","layer",",","instead","of","keeping","two","kernels","W","and","V",",","we","only","keep","one","vector","kernel","W","(","Nx1",")",".","We","use","the","dot","operation","to","compute","the","``","crossing","''","effect","of","the","features",",","thus","saving","two","matrix","multiplications","to","further","reduce","computational","cost","and","cut","the","number","of","learnable","parameters",".","On","each","layer","l",",","the","tensor","is","transformed","into","..","math",":",":","x_","{","l+1","}","=","x_0","*","(","W_l",".","x_l","+","b_l",")","+","x_l","where",":","math",":","`","W_l","`","is","either","a","vector",",",":","math",":","`","*","`","means","element-wise","multiplication",";",":","math",":","`",".","`","means","dot","operations",".","Args",":","in_features","(","int",")",":","the","dimension","of","the","input",".","num_layers","(","int",")",":","the","number","of","layers","in","the","module",".","Example",":",":","batch_size","=","3","num_layers","=","2","in_features","=","10","input","=","torch.randn","(","batch_size",",","in_features",")","dcn","=","VectorCrossNet","(","num_layers=num_layers",")","output","=","dcn","(","input",")"]
docstr: Args:
      input (torch.Tensor): tensor with shape [batch_size, in_features].
  
  Returns:
      torch.Tensor: tensor with shape [batch_size, in_features].
docstr_tok: ["Args",":","input","(","torch.Tensor",")",":","tensor","with","shape","[","batch_size",",","in_features","]",".","Returns",":","torch.Tensor",":","tensor","with","shape","[","batch_size",",","in_features","]","."]
code: def forward(self, input: torch.Tensor) -> torch.Tensor:
      """
      Args:
          input (torch.Tensor): tensor with shape [batch_size, in_features].
  
      Returns:
          torch.Tensor: tensor with shape [batch_size, in_features].
      """
  
      x_0 = input.unsqueeze(2)  # (B, N, 1)
      x_l = x_0
  
      for layer in range(self._num_layers):
          xl_w = torch.tensordot(
              x_l,
              self.kernels[layer],
              dims=([1], [0]),
          )  # (B, 1, 1)
          x_l = (
              torch.matmul(x_0, xl_w) + self.bias[layer] + x_l
          )  # (B, N, 1)
  
      return torch.squeeze(x_l, dim=2)
  
file_path: torchrec/torchrec/modules/crossnet.py
imports: from typing import Callable, Optional, Union
  import torch
label_desc: Use image node_id 2 for calling the VectorCrossNet obj's underlying member method code with example usage: obj.forward(input) and returns: torch