class_docstr: A linear regression model for Disjoint LinUCB.
  Note that instead of being trained by a PyTorch optimizer, we explicitly
      update attributes A and b.
  
  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.
      gamma: The discount factor to avoid exploding numbers when doing incremental training
      using gamma as part of simplified D-LinUCB: https://arxiv.org/pdf/1909.09146.pdf
      In this simplified version of D-LinUCB, we calculate A = \sum \gamma^t xx^T
      to discount the old data. See N2441818 for why we do this.
      set gamma=1.0 to use traditional model
docstr: self.A: num_arms * dim * dim
  self.A_inv: num_arms * dim * dim
  self.b: num_arms * dim
  self.coefs: num_arms * dim
  dim is feature dimension
code: def __init__(
      self,
      num_arms: int,
      input_dim: int,
      l2_reg_lambda: float = 1.0,
      ucb_alpha: float = 1.0,
      gamma: float = 1.0,
  ):
      """
      self.A: num_arms * dim * dim
      self.A_inv: num_arms * dim * dim
      self.b: num_arms * dim
      self.coefs: num_arms * dim
      dim is feature dimension
      """
      super().__init__()
  
      self.num_arms = num_arms
      self.input_dim = input_dim
      self.ucb_alpha = ucb_alpha
      self.cur_num_obs = torch.zeros(self.num_arms, dtype=torch.int64)
      self.gamma = gamma
      assert self.gamma <= 1.0 and self.gamma > 0.0
      self.l2_reg_lambda = l2_reg_lambda
      # A is accumulated from all training epochs
      self.register_buffer(
          "A",
          torch.zeros((self.input_dim, self.input_dim)).repeat(
              self.num_arms, 1, 1
          ),
      )
      # cur_A is x x^T accumulated within this training epoch
      self.register_buffer(
          "cur_A",
          torch.zeros((self.input_dim, self.input_dim)).repeat(
              self.num_arms, 1, 1
          ),
      )
      # b is accumulated from all training epochs
      self.register_buffer(
          "b", torch.zeros(self.num_arms, self.input_dim)
      )
      # cur_b is x * y accumulated within this training epoch
      self.register_buffer(
          "cur_b", torch.zeros(self.num_arms, self.input_dim)
      )
      self.register_buffer(
          "coefs", torch.zeros(self.input_dim).repeat(self.num_arms, 1)
      )
      self.register_buffer(
          "inv_A",
          torch.eye(self.input_dim).repeat(self.num_arms, 1, 1),
      )
      self.register_buffer(
          "coefs_valid_for_A",
          -torch.ones((self.input_dim, self.input_dim)).repeat(
              self.num_arms, 1, 1
          ),
      )  # value of A matrix for which self.coefs were estimated
  
      # add a dummy parameter so that DDP doesn't compain about lack of parameters with gradient
      self.dummy_param = torch.nn.parameter.Parameter(torch.zeros(1))
  
file_path: ReAgent/reagent/models/disjoint_linucb_predictor.py
imports: import logging
  from typing import Optional
  import torch
  from pytorch_lightning.utilities.distributed import ReduceOp, sync_ddp_if_available
  from reagent.models.base import ModelBase
label_desc: Use image node_id 1 to create a new DisjointLinearRegressionUCB object from inherited base classes: ModelBase with example: obj = DisjointLinearRegressionUCB(num_arms, input_dim, l2_reg_lambda, ucb_alpha, gamma)