diffusion_baseline / upstreams /rdlm /scheduler_lib.py
jyliuAI's picture
Add files using upload-large-folder tool
93cd35a verified
Raw History Blame Contribute Delete
3.17 kB
import abc
import torch
import numpy as np
from utils.weight_utils import get_weight_fn
class Scheduler(abc.ABC):
"""
prior -> data
"""
def __init__(self, **kwargs):
super().__init__()
self.eps = kwargs.get("eps", 1e-6)
self.beta_0 = kwargs.get("beta_0")
self.beta_f = kwargs.get("beta_f")
self.rbeta = self.beta_0 / self.beta_f if self.beta_f>0 else self.beta_0 / self.beta(self.eps)
assert np.isfinite(self.rbeta)
self._beta = self.beta_f - self.beta_0
self.weight_type = kwargs.get("weight_type", "default")
self.weight_fn = get_weight_fn(self.weight_type)(**kwargs)
@property
def T(self):
return 1
@abc.abstractmethod
def beta(self, t):
pass
@abc.abstractmethod
def int_beta(self, t):
# integrate beta from time t to T
pass
@abc.abstractmethod
def drift_coeff(self, t):
# return self.beta(t) / self.int_beta(t)
pass
def importance_weight(self, t, train):
if train:
return self.weight_fn.norm_const / self.weight_fn(t)
else:
return 1.
def importance_weighted_time(self, shape, device, steps=100):
quantile = torch.rand(shape, device=device) * self.weight_fn.norm_const
lb = torch.zeros_like(quantile)
ub = torch.ones_like(quantile) * (1 - self.eps)
for _ in range(steps):
mid = (lb + ub) / 2.
value = self.weight_fn.cum_weight_fn(mid)
lb = torch.where(value <= quantile, mid, lb)
ub = torch.where(value <= quantile, ub, mid)
return (lb + ub) / 2.
class Linear(Scheduler):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def beta(self, t):
return self.beta_0 + t * self._beta
def int_beta(self, t):
return (1-t) * (self.beta_0 + 0.5 * (1+t) * self._beta)
def drift_coeff(self, t):
numer = (1-t) * self.rbeta + t
denom = (1-t) * (self.rbeta + 0.5 * (1+t) * (1-self.rbeta))
return numer / denom
class Geometric(Scheduler):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def beta(self, t):
return self.beta_0**(1-t) * self.beta_f**t
def int_beta(self, t):
if self.beta_0 == self.beta_f:
return self.beta_0 * (1-t)
else:
r = self.beta_f / self.beta_0
return self.beta_0 * (r - r**t) / np.log(r)
def drift_coeff(self, t):
if self.beta_0 == self.beta_f:
return 1 / (1-t)
else:
r = self.beta_f / self.beta_0
return np.log(r) / (r**(1-t) - 1)
class Cosine(Scheduler):
def __init__(self, **kwargs):
super().__init__(**kwargs)
def beta(self, t):
cos_t = (np.pi/2 * (1-t)).cos()
return self.beta_0 * (1 - cos_t) + self.beta_f * cos_t
def int_beta(self, t):
return self.beta_0 * (1-t) + 2 / np.pi * self._beta * (np.pi/2 * (1-t)).sin()
def drift_coeff(self, t):
return self.beta(t) / self.int_beta(t)