class_docstr: A linear regression model for LinUCB.
  Note that instead of being trained by a PyTorch optimizer, we explicitly
      update attributes A and b (according to the LinUCB formulas implemented in
      reagent.training.cb.linucb_trainer.LinUCBTrainer).
  Since computing the regression coefficients inverse matrix inversion (expensive op), we
      save time by only computing the coefficients when necessary (when doing inference).
  
  Args:
      input_dim: Dimension of input data
      l2_reg_lambda: The weight on L2 regularization
      ucb_alpha: The coefficient on the standard deviation in UCB formula.
          Set it to 0 to predict the expected value instead of UCB.
      gamma: per-epoch discount factor (A and b get multiplied by gamma every epoch)
  
  Outputs:
  Dict {"pred_label": pred_label, "pred_sigma": pred_sigma, "ucb": ucb}
class_docstr_tok: ["A","linear","regression","model","for","LinUCB",".","Note","that","instead","of","being","trained","by","a","PyTorch","optimizer",",","we","explicitly","update","attributes","A","and","b","(","according","to","the","LinUCB","formulas","implemented","in","reagent.training.cb.linucb_trainer.LinUCBTrainer",")",".","Since","computing","the","regression","coefficients","inverse","matrix","inversion","(","expensive","op",")",",","we","save","time","by","only","computing","the","coefficients","when","necessary","(","when","doing","inference",")",".","Args",":","input_dim",":","Dimension","of","input","data","l2_reg_lambda",":","The","weight","on","L2","regularization","ucb_alpha",":","The","coefficient","on","the","standard","deviation","in","UCB","formula",".","Set","it","to","0","to","predict","the","expected","value","instead","of","UCB",".","gamma",":","per-epoch","discount","factor","(","A","and","b","get","multiplied","by","gamma","every","epoch",")","Outputs",":","Dict","{","``","pred_label","''",":","pred_label",",","``","pred_sigma","''",":","pred_sigma",",","``","ucb","''",":","ucb","}"]
docstr: Compute current estimate of regression coefficients and A_inv=A**-1
  We save both coefficients and A_inv in case they are needed again to avoid recomputing the inverse.
  The coefficients are computed only when needed because their computation can be expensive
      (involves matrix inversion)
  
  Note the inverse of matrix A is first tried by inv, then pinv if inv fails.
  - Though l2_reg_lambda makes matrix A full rank, when arm energey is huge A may still is close to rank deficient.
  - torch.linalg.pinv is SVD based and allows stable inverse of rank deficient matrix.
  - torch.linalg.inv is calculation more efficent than pinv but may suffer stableness issue.
docstr_tok: ["Compute","current","estimate","of","regression","coefficients","and","A_inv=A","*","*","-1","We","save","both","coefficients","and","A_inv","in","case","they","are","needed","again","to","avoid","recomputing","the","inverse",".","The","coefficients","are","computed","only","when","needed","because","their","computation","can","be","expensive","(","involves","matrix","inversion",")","Note","the","inverse","of","matrix","A","is","first","tried","by","inv",",","then","pinv","if","inv","fails",".","-","Though","l2_reg_lambda","makes","matrix","A","full","rank",",","when","arm","energey","is","huge","A","may","still","is","close","to","rank","deficient",".","-","torch.linalg.pinv","is","SVD","based","and","allows","stable","inverse","of","rank","deficient","matrix",".","-","torch.linalg.inv","is","calculation","more","efficent","than","pinv","but","may","suffer","stableness","issue","."]
code: def _calculate_coefs(self) -> None:
      """
      Compute current estimate of regression coefficients and A_inv=A**-1
      We save both coefficients and A_inv in case they are needed again to avoid recomputing the inverse.
      The coefficients are computed only when needed because their computation can be expensive
          (involves matrix inversion)
  
      Note the inverse of matrix A is first tried by inv, then pinv if inv fails.
      - Though l2_reg_lambda makes matrix A full rank, when arm energey is huge A may still is close to rank deficient.
      - torch.linalg.pinv is SVD based and allows stable inverse of rank deficient matrix.
      - torch.linalg.inv is calculation more efficent than pinv but may suffer stableness issue.
      """
      # reduce the values of `avg_A` and `avg_b` across all trainer processes and reduce them with previous-epoch values.
      # The coefficients can't be averaged across trainers because they are a non-linear
      #   function of `A` and `b`
      self.avg_A = reduce_avg(
          self.avg_A,
          self.sum_weight,
          self.cur_avg_A,
          self.cur_sum_weight,
      )
      self.avg_b = reduce_avg(
          self.avg_b,
          self.sum_weight,
          self.cur_avg_b,
          self.cur_sum_weight,
      )
      # pyre-fixme[6]: For 2nd argument expected `Union[None, str, ReduceOp]` but
      #  got `RedOpType`.
      self.num_obs += sync_ddp_if_available(
          self.cur_num_obs, reduce_op=ReduceOp.SUM
      )
      self.sum_weight += sync_ddp_if_available(
          self.cur_sum_weight,
          # pyre-fixme[6]: For 2nd argument expected `Union[None, str, ReduceOp]`
          #  but got `RedOpType`.
          reduce_op=ReduceOp.SUM,
      )
  
      A_extended = (
          self.avg_A
          + self.l2_reg_lambda
          * torch.eye(self.input_dim, device=self.avg_A.device)
          / self.sum_weight
      )
      self.inv_avg_A = matrix_inv_fallback_pinv(matrix=A_extended)
  
      self._coefs = torch.matmul(self.inv_avg_A, self.avg_b)
      self.coefs_valid_for_avg_A = self.avg_A.clone()
  
      # reset buffers to zero
      self.cur_avg_A.zero_()
      self.cur_avg_b.zero_()
      self.cur_num_obs.zero_()
      self.cur_sum_weight.zero_()
  
file_path: ReAgent/reagent/models/linear_regression.py
imports: import logging
  from typing import Dict, Optional
  import torch
  from pytorch_lightning.utilities.distributed import ReduceOp, sync_ddp_if_available
  from reagent.models.cb_base_model import UCBBaseModel
label_desc: Use image node_id 2 for calling the LinearRegressionUCB obj's underlying member method code with example usage: obj._calculate_coefs() without return types