code: def __init__(
      self,
      denoise_fn,
      input_size,
      beta_end=0.1,
      diff_steps=100,
      loss_type="l2",
      betas=None,
      beta_schedule="linear",
  ):
      super().__init__()
      self.denoise_fn = denoise_fn
      self.input_size = input_size
      self.__scale = None
  
      if betas is not None:
          betas = (
              betas.detach().cpu().numpy()
              if isinstance(betas, torch.Tensor)
              else betas
          )
      else:
          if beta_schedule == "linear":
              betas = np.linspace(1e-4, beta_end, diff_steps)
          elif beta_schedule == "quad":
              betas = (
                  np.linspace(1e-4**0.5, beta_end**0.5, diff_steps)
                  ** 2
              )
          elif beta_schedule == "const":
              betas = beta_end * np.ones(diff_steps)
          elif beta_schedule == "jsd":  # 1/T, 1/(T-1), 1/(T-2), ..., 1
              betas = 1.0 / np.linspace(diff_steps, 1, diff_steps)
          elif beta_schedule == "sigmoid":
              betas = np.linspace(-6, 6, diff_steps)
              betas = (beta_end - 1e-4) / (np.exp(-betas) + 1) + 1e-4
          elif beta_schedule == "cosine":
              betas = cosine_beta_schedule(diff_steps)
          else:
              raise NotImplementedError(beta_schedule)
  
      alphas = 1.0 - betas
      alphas_cumprod = np.cumprod(alphas, axis=0)
      alphas_cumprod_prev = np.append(1.0, alphas_cumprod[:-1])
  
      (timesteps,) = betas.shape
      self.num_timesteps = int(timesteps)
      self.loss_type = loss_type
  
      to_torch = partial(torch.tensor, dtype=torch.float32)
  
      self.register_buffer("betas", to_torch(betas))
      self.register_buffer("alphas_cumprod", to_torch(alphas_cumprod))
      self.register_buffer(
          "alphas_cumprod_prev", to_torch(alphas_cumprod_prev)
      )
  
      # calculations for diffusion q(x_t | x_{t-1}) and others
      self.register_buffer(
          "sqrt_alphas_cumprod", to_torch(np.sqrt(alphas_cumprod))
      )
      self.register_buffer(
          "sqrt_one_minus_alphas_cumprod",
          to_torch(np.sqrt(1.0 - alphas_cumprod)),
      )
      self.register_buffer(
          "log_one_minus_alphas_cumprod",
          to_torch(np.log(1.0 - alphas_cumprod)),
      )
      self.register_buffer(
          "sqrt_recip_alphas_cumprod",
          to_torch(np.sqrt(1.0 / alphas_cumprod)),
      )
      self.register_buffer(
          "sqrt_recipm1_alphas_cumprod",
          to_torch(np.sqrt(1.0 / alphas_cumprod - 1)),
      )
  
      # calculations for posterior q(x_{t-1} | x_t, x_0)
      posterior_variance = (
          betas * (1.0 - alphas_cumprod_prev) / (1.0 - alphas_cumprod)
      )
      # above: equal to 1. / (1. / (1. - alpha_cumprod_tm1) + alpha_t / beta_t)
      self.register_buffer(
          "posterior_variance", to_torch(posterior_variance)
      )
      # below: log calculation clipped because the posterior variance is 0 at the beginning of the diffusion chain
      self.register_buffer(
          "posterior_log_variance_clipped",
          to_torch(np.log(np.maximum(posterior_variance, 1e-20))),
      )
      self.register_buffer(
          "posterior_mean_coef1",
          to_torch(
              betas
              * np.sqrt(alphas_cumprod_prev)
              / (1.0 - alphas_cumprod)
          ),
      )
      self.register_buffer(
          "posterior_mean_coef2",
          to_torch(
              (1.0 - alphas_cumprod_prev)
              * np.sqrt(alphas)
              / (1.0 - alphas_cumprod)
          ),
      )
  
imports: from functools import partial
  from inspect import isfunction
  import numpy
  import torch
  from torch import nn, einsum
  import torch.nn.functional
label_desc: Use image node_id 1 to create a new GaussianDiffusion object from inherited base classes: nn with example: obj = GaussianDiffusion(denoise_fn, input_size, beta_end, diff_steps, loss_type, betas, beta_schedule)