class_docstr: Binned univariate distribution designed as an nn.Module
  
  Arguments
  ----------
  bins_lower_bound: The lower bound of the bin edges
  bins_upper_bound: The upper bound of the bin edges
  nbins: The number of equidistance bins to allocate between `bins_lower_bound` and `bins_upper_bound`. Default value is 100.
  smoothing_indicator: The method of smoothing to perform on the bin probabilities
code: def __init__(
      self,
      bins_lower_bound: float,
      bins_upper_bound: float,
      nbins: int = 100,
      smoothing_indicator: Optional[str] = [None, "cheap", "kernel"][1],
      validate_args=None,
  ):
      super().__init__()
  
      assert (
          bins_lower_bound.shape.numel() == 1
      ), "bins_lower_bound needs to have shape torch.Size([1])"
      assert (
          bins_upper_bound.shape.numel() == 1
      ), "bins_upper_bound needs to have shape torch.Size([1])"
      assert bins_lower_bound < bins_upper_bound, (
          f"bins_lower_bound {bins_lower_bound} needs to less than"
          f" bins_upper_bound {bins_upper_bound}"
      )
  
      self.nbins = nbins
      self.epsilon = np.finfo(np.float32).eps
      self.smooth_indicator = smoothing_indicator
  
      # Creation the bin locations
      # Bins locations are placed uniformly between bins_lower_bound and bins_upper_bound, though more complex methods could be used
      self.bin_min = bins_lower_bound - self.epsilon * 6
      self.bin_max = bins_upper_bound + self.epsilon * 6
      self.bin_edges = torch.linspace(
          self.bin_min, self.bin_max, nbins + 1
      )
      self.bin_widths = self.bin_edges[1:] - self.bin_edges[:-1]
      self.bin_centres = (
          self.bin_edges[1:] + self.bin_edges[:-1]
      ) * 0.5
  
      logits = torch.ones(nbins)
      logits = (
          logits
          / logits.sum()
          / (1 + self.epsilon)
          / self.bin_widths.mean()
      )
      self.logits = torch.log(logits)
  
      # Keeps track of mini-batches
      self.idx = None
  
      self.device = None
  
imports: from typing import Optional
  import numpy
  import torch
  import torch.nn
  import torch.nn.functional
  import torch.optim
  from .genpareto import GenPareto
label_desc: Use image node_id 1 to create a new Binned object from inherited base classes: torch.nn with example: obj = Binned(bins_lower_bound, bins_upper_bound, nbins, smoothing_indicator, validate_args)