class_docstr: Implementation of the UCB-Tuned algorithm from Section 4 of  https://link.springer.com/content/pdf/10.1023/A:1013689704352.pdf
  Biggest difference from basic UCB is that per-arm reward variance is estimated.
  IMPORTANT: This algorithm should only be used if the rewards of each arm have Bernoulli distribution.
class_docstr_tok: ["Implementation","of","the","UCB-Tuned","algorithm","from","Section","4","of","https",":","\/\/link.springer.com\/content\/pdf\/10.1023\/A:1013689704352.pdf","Biggest","difference","from","basic","UCB","is","that","per-arm","reward","variance","is","estimated",".","IMPORTANT",":","This","algorithm","should","only","be","used","if","the","rewards","of","each","arm","have","Bernoulli","distribution","."]
docstr: Get per-arm UCB scores. The formula is
  UCB_i = AVG([rewards_i]) + SQRT(LN(T)/N_i * min(V_i, 0.25))
  where V_i is a conservative variance estimate of arm i:
      V_i = AVG([rewards_i**2]) - AVG([rewards_i])**2 + sqrt(2ln(t) / n_i)
  
  Returns:
      Tensor: An array of UCB scores (one per arm)
docstr_tok: ["Get","per-arm","UCB","scores",".","The","formula","is","UCB_i","=","AVG","(","[","rewards_i","]",")","+","SQRT","(","LN","(","T",")","\/N_i","*","min","(","V_i",",","0.25",")",")","where","V_i","is","a","conservative","variance","estimate","of","arm","i",":","V_i","=","AVG","(","[","rewards_i","*","*","2","]",")","-","AVG","(","[","rewards_i","]",")","*","*","2","+","sqrt","(","2ln","(","t",")","\/","n_i",")","Returns",":","Tensor",":","An","array","of","UCB","scores","(","one","per","arm",")"]
code: def get_scores(self) -> Tensor:
      """
      Get per-arm UCB scores. The formula is
      UCB_i = AVG([rewards_i]) + SQRT(LN(T)/N_i * min(V_i, 0.25))
      where V_i is a conservative variance estimate of arm i:
          V_i = AVG([rewards_i**2]) - AVG([rewards_i])**2 + sqrt(2ln(t) / n_i)
  
      Returns:
          Tensor: An array of UCB scores (one per arm)
      """
      avg_rewards = self.get_avg_reward_values()
      log_t_over_ni = (
          math.log(self.total_n_obs_all_arms + 1)
          / self.total_n_obs_per_arm
      )
      per_arm_var_est = (
          self.total_sum_reward_squared_per_arm
          / self.total_n_obs_per_arm
          # pyre-fixme[58]: `**` is not supported for operand types `Tensor` and
          #  `int`.
          - avg_rewards**2
          + torch.sqrt(
              # pyre-fixme[6]: For 1st param expected `Tensor` but got `float`.
              2
              * log_t_over_ni
          )  # additional term to make the estimate conservative (unlikely to underestimate)
      )
      return avg_rewards + self.alpha * torch.sqrt(
          log_t_over_ni
          * torch.fmin(per_arm_var_est, torch.tensor(0.25))
      )
  
imports: import math
  from abc import ABC, abstractmethod
  from typing import List, Optional
  import torch
  from reagent.mab.mab_algorithm import MABAlgo
  from torch import Tensor
label_desc: Use image node_id 1 for calling the UCBTuned obj's underlying member method code with example usage: obj.get_scores() and returns: unknown