class_docstr: Output layer that produces cos  heta between activation vector x
  and class vector w_j
  
  in_dim:     dimension of input feature vectors
  output_dim: dimension of output feature vectors
              (i.e., number of classes)
  
  Usage example:
    batch_size = 64
    input_dim = 10
    class_num = 5
  
    l_layer = P2SActivationLayer(input_dim, class_num)
    l_loss = P2SGradLoss()
  
    data = torch.rand(batch_size, input_dim, requires_grad=True)
    target = (torch.rand(batch_size) * class_num).clamp(0, class_num-1)
    target = target.to(torch.long)
  
    scores = l_layer(data)
    loss = l_loss(scores, target)
  
    loss.backward()
class_docstr_tok: ["Output","layer","that","produces","cos","heta","between","activation","vector","x","and","class","vector","w_j","in_dim",":","dimension","of","input","feature","vectors","output_dim",":","dimension","of","output","feature","vectors","(","i.e.",",","number","of","classes",")","Usage","example",":","batch_size","=","64","input_dim","=","10","class_num","=","5","l_layer","=","P2SActivationLayer","(","input_dim",",","class_num",")","l_loss","=","P2SGradLoss","(",")","data","=","torch.rand","(","batch_size",",","input_dim",",","requires_grad=True",")","target","=","(","torch.rand","(","batch_size",")","*","class_num",")",".clamp","(","0",",","class_num-1",")","target","=","target.to","(","torch.long",")","scores","=","l_layer","(","data",")","loss","=","l_loss","(","scores",",","target",")","loss.backward","(",")"]
docstr: Compute P2SGrad activation
  
  input:
  ------
    input_feat: tensor (batch_size, input_dim)
  
  output:
  -------
    tensor (batch_size, output_dim)
docstr_tok: ["Compute","P2SGrad","activation","input",":","--","--","--","input_feat",":","tensor","(","batch_size",",","input_dim",")","output",":","--","--","--","-","tensor","(","batch_size",",","output_dim",")"]
code: def forward(self, input_feat):
      """
      Compute P2SGrad activation
  
      input:
      ------
        input_feat: tensor (batch_size, input_dim)
  
      output:
      -------
        tensor (batch_size, output_dim)
  
      """
      # normalize the weight (again)
      # w (feature_dim, output_dim)
      w = self.weight.renorm(2, 1, 1e-5).mul(1e5)
      w = c_f.to_device(w, tensor=input_feat, dtype=input_feat.dtype)
  
      # normalize the input feature vector
      # x_modulus (batch_size)
      # sum input -> x_modules in shape (batch_size)
      x_modulus = input_feat.pow(2).sum(1).pow(0.5)
      # w_modules (output_dim)
      # w_moduls should be 1, since w has been normalized
      # w_modulus = w.pow(2).sum(0).pow(0.5)
  
      # W * x = ||W|| * ||x|| * cos())))))))
      # inner_wx (batch_size, output_dim)
      inner_wx = input_feat.mm(w)
      # cos_theta (batch_size, output_dim)
      cos_theta = inner_wx / x_modulus.view(-1, 1)
      cos_theta = cos_theta.clamp(-1, 1)
  
      # done
      return cos_theta
  
file_path: pytorch-metric-learning/tests/losses/test_p2s_grad_loss.py
imports: import unittest
  import torch
  import torch.nn
  from pytorch_metric_learning.losses import P2SGradLoss
  from pytorch_metric_learning.utils import common_functions
  from ..None import TEST_DEVICE, TEST_DTYPES
label_desc: Use image node_id 2 for calling the TrustedImplementationP2SActivationLayer obj's underlying member method code with example usage: obj.forward(input_feat) and returns: cos_theta