├── .gitignore ├── README.md ├── dvi ├── __init__.py ├── bayes_layers.py ├── bayes_models.py ├── bayes_utils.py ├── dataset.py ├── invgamma.py ├── kl.py ├── loss.py ├── plot.py └── variables.py ├── main.ipynb ├── main.py └── test ├── InvGamma_validation.ipynb └── check.ipynb /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # deterministic-variational-inference-pytorch 2 | 3 | Re-implementation of [Deterministic-Variational-Inference](https://github.com/Microsoft/deterministic-variational-inference) 4 | -------------------------------------------------------------------------------- /dvi/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/makora9143/deterministic-variational-inference-pytorch/6a467593382acad4ee241fb58ddfb6775f3a8efd/dvi/__init__.py -------------------------------------------------------------------------------- /dvi/bayes_layers.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | 4 | import dvi.bayes_utils as bu 5 | from .variables import make_weight_matrix, make_bias_vector, GaussianVar 6 | 7 | 8 | class VariationalLinear(nn.Module): 9 | def __init__(self, input_features, output_features, 10 | prior_type='empirical', 11 | variance='wider_he', bias=True): 12 | super(VariationalLinear, self).__init__() 13 | self.input_features = input_features 14 | self.output_features = output_features 15 | 16 | self.weight = make_weight_matrix((output_features, input_features), prior_type, variance) 17 | if bias: 18 | self.bias = make_bias_vector((output_features, input_features), prior_type, variance) 19 | else: 20 | self.register_parameter("bias", None) 21 | 22 | def forward(self, input): 23 | x_mean = input.mean 24 | y_mean = x_mean.mm(self.weight.q_loc.t()) 25 | if self.bias: 26 | y_mean += self.bias.q_loc.unsqueeze(0).expand_as(y_mean) 27 | x_cov = input.var 28 | y_cov = self.forward_covariance(x_mean, x_cov) 29 | return GaussianVar(y_mean, y_cov) 30 | 31 | def surprise(self): 32 | kl = torch.sum(self.weight.surprise()) 33 | if self.bias: 34 | kl += torch.sum(self.bias.surprise()) 35 | return kl 36 | 37 | def forward_covariance(self, x_mean, x_cov): 38 | output_dim, input_dim = self.weight.q_loc.shape 39 | 40 | x_var_diag = torch.diagonal(x_cov, dim1=-2, dim2=-1) 41 | xx_mean = x_var_diag + x_mean * x_mean 42 | 43 | term1_diag = xx_mean.mm(torch.pow(torch.exp(self.weight.log_q_scale), 2).t()) 44 | 45 | flat_xCov = x_cov.reshape(-1, input_dim) 46 | xCov_W = flat_xCov.mm(self.weight.q_loc.t()) 47 | xCov_W = xCov_W.reshape(-1, input_dim, output_dim) 48 | xCov_W = xCov_W.transpose(1, 2) 49 | xCov_W = xCov_W.reshape(-1, input_dim) 50 | W_xCov_W = xCov_W.mm(self.weight.q_loc.t()) 51 | W_xCov_W = W_xCov_W.reshape(-1, output_dim, output_dim) 52 | 53 | term2 = W_xCov_W 54 | term2_diag = torch.diagonal(term2, dim1=-2, dim2=-1) 55 | 56 | term3_diag = torch.pow(torch.exp(self.bias.log_q_scale), 2).unsqueeze(0).expand_as(term2_diag) 57 | 58 | result_diag = term1_diag + term2_diag + term3_diag 59 | return bu.matrix_set_diag(term2, result_diag, dim1=-2, dim2=-1) 60 | 61 | def forward_mcmc(self, input, n_samples=None, average=False): 62 | if n_samples is None: 63 | n_samples = 1 64 | 65 | repeated_x = input.unsqueeze(0).repeat(n_samples, 1, 1) 66 | 67 | sampled_w = self.weight.sample(n_samples, average) 68 | 69 | h = torch.matmul(repeated_x, sampled_w.transpose(1, 2)) 70 | 71 | if self.bias: 72 | sampled_b = self.bias.sample(n_samples, average) 73 | h += sampled_b.unsqueeze(1).expand_as(h) 74 | return h 75 | 76 | 77 | class VariationalLinearCertainActivations(VariationalLinear): 78 | def forward(self, input): 79 | x_mean = input 80 | xx = x_mean * x_mean 81 | y_mean = x_mean.mm(self.weight.q_loc.t()) 82 | if self.bias: 83 | y_mean += self.bias.q_loc.unsqueeze(0).expand_as(y_mean) 84 | 85 | y_cov = xx.mm(torch.pow(torch.exp(self.weight.log_q_scale), 2).t()) 86 | if self.bias: 87 | y_cov += torch.pow(torch.exp(self.bias.log_q_scale), 2).unsqueeze(0).expand_as(y_cov) 88 | y_cov = torch.diag_embed(y_cov) 89 | return GaussianVar(y_mean, y_cov) 90 | 91 | 92 | class VariationalLinearReLU(VariationalLinear): 93 | def forward(self, input): 94 | x_var_diag = torch.diagonal(input.var, dim1=-2, dim2=-1) 95 | sqrt_x_var_diag = torch.sqrt(x_var_diag) 96 | mu = input.mean / (sqrt_x_var_diag + bu.EPSILON) 97 | 98 | def relu_covariance(x): 99 | mu1 = mu.unsqueeze(2) 100 | mu2 = mu1.transpose(1, 2) 101 | 102 | s11s22 = x_var_diag.unsqueeze(2) * x_var_diag.unsqueeze(1) 103 | rho = x.var / torch.sqrt(s11s22) 104 | rho = rho.clamp(-1 / (1 + bu.EPSILON), 1 / (1 + bu.EPSILON)) 105 | 106 | return x.var * bu.delta(rho, mu1, mu2) 107 | 108 | z_mean = sqrt_x_var_diag * bu.softrelu(mu) 109 | y_mean = z_mean.mm(self.weight.q_loc.t()) 110 | if self.bias: 111 | y_mean += self.bias.q_loc.unsqueeze(0).expand_as(y_mean) 112 | z_cov = relu_covariance(input) 113 | y_cov = self.forward_covariance(z_mean, z_cov) 114 | return GaussianVar(y_mean, y_cov) 115 | 116 | def forward_mcmc(self, input, n_samples=None, average=False): 117 | if n_samples is None: 118 | n_samples = 1 119 | 120 | sampled_w = self.weight.sample(n_samples, average) 121 | 122 | h = torch.matmul(input, sampled_w.transpose(1, 2)) 123 | 124 | if self.bias: 125 | sampled_b = self.bias.sample(n_samples, average) 126 | h += sampled_b.unsqueeze(1).expand_as(h) 127 | return h 128 | -------------------------------------------------------------------------------- /dvi/bayes_models.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | 5 | from .bayes_layers import VariationalLinearCertainActivations, VariationalLinearReLU 6 | from .variables import GaussianVar 7 | 8 | class MLP(nn.Module): 9 | def __init__(self, x_dim, y_dim, hidden_size=None): 10 | super(MLP, self).__init__() 11 | 12 | self.sizes = [x_dim] 13 | if hidden_size is not None: 14 | self.sizes += hidden_size 15 | self.sizes += [y_dim] 16 | self.make_layers() 17 | 18 | 19 | def make_layers(self): 20 | # layers = [VariationalLinearCertainActivations(self.sizes[0], self.sizes[1])] 21 | # for in_dim, out_dim in zip(self.sizes[1:-1], self.sizes[2:]): 22 | # print('in_dim:{}, out_dim:{}'.format(in_dim, out_dim)) 23 | # layers.append(VariationalLinearReLU(in_dim, out_dim)) 24 | # self.layers = nn.Sequential(*layers) 25 | 26 | self.layers = nn.Sequential( 27 | VariationalLinearCertainActivations(1, 128), 28 | VariationalLinearReLU(128, 128), 29 | VariationalLinearReLU(128, 2) 30 | ) 31 | # 32 | # self.layers = nn.Sequential(VariationalLinearCertainActivations(self.sizes[0], self.sizes[1])) 33 | # for in_dim, out_dim in zip(self.sizes[1:-1], self.sizes[2:]): 34 | # print('in_dim:{}, out_dim:{}'.format(in_dim, out_dim)) 35 | # self.layers.add_module('{}-{}'.format(in_dim, out_dim), VariationalLinearReLU(in_dim, out_dim)) 36 | 37 | def forward(self, input): 38 | return self.layers(input) 39 | 40 | def surprise(self): 41 | all_surprise = 0 42 | for layer in self.layers: 43 | all_surprise += layer.surprise() 44 | return all_surprise 45 | 46 | def forward_mcmc(self, input, n_samples=None, average=False): 47 | h = self.layers[0].forward_mcmc(input) 48 | for layer in self.layers[1:]: 49 | h = layer.forward_mcmc(F.relu(h), n_samples) 50 | return h 51 | 52 | 53 | 54 | class AdaptedMLP(object): 55 | def __init__(self, mlp, adapter, device=torch.device('cpu')): 56 | self.mlp = mlp.to(device) 57 | self.__dict__.update(mlp.__dict__) 58 | self.device = device 59 | self.make_adapters(adapter) 60 | 61 | 62 | def make_adapters(self, adapter): 63 | self.adapter = {} 64 | for ad in ['in', 'out']: 65 | self.adapter[ad] = { 66 | 'scale': torch.tensor(adapter[ad]['scale']).to(self.device), 67 | 'shift': torch.tensor(adapter[ad]['shift']).to(self.device) 68 | } 69 | 70 | def __call__(self, input): 71 | x_ad = self.adapter['in']['scale'] * input + self.adapter['in']['shift'] 72 | self.pre_adapt = self.mlp(x_ad) 73 | mean = self.adapter['out']['scale'] * self.pre_adapt.mean + self.adapter['out']['shift'] 74 | cov = self.adapter['out']['scale'].reshape(-1, 1) * self.adapter['out']['scale'].reshape(1, -1) * self.pre_adapt.var 75 | return GaussianVar(mean, cov) 76 | 77 | def __repr__(self): 78 | return "AdaptedMLP(\n" + self.mlp.__repr__() + ")" 79 | 80 | def surprise(self): 81 | return self.mlp.surprise() 82 | 83 | def parameters(self): 84 | return self.mlp.parameters() 85 | 86 | def mcmc(self, input, n_samples=None): 87 | x_ad = self.adapter['in']['scale'] * input + self.adapter['in']['shift'] 88 | self.pre_adapt = self.mlp.forward_mcmc(x_ad, n_samples) 89 | mean = self.adapter['out']['scale'] * self.pre_adapt + self.adapter['out']['shift'] 90 | return mean 91 | -------------------------------------------------------------------------------- /dvi/bayes_utils.py: -------------------------------------------------------------------------------- 1 | import math 2 | import torch 3 | 4 | EPSILON = 1e-6 5 | HALF_EPSILON = EPSILON / 2.0 6 | 7 | def matrix_set_diag(input, diagonal, dim1=0, dim2=1): 8 | org_diag = torch.diag_embed(torch.diagonal(input, dim1=dim1, dim2=dim2), 9 | dim1=dim1, dim2=dim2) 10 | new_diag = torch.diag_embed(diagonal, dim1=dim1, dim2=dim2) 11 | return input - org_diag + new_diag 12 | 13 | def gaussian_cdf(x): 14 | return 0.5 * (1.0 + torch.erf(x * 1 / math.sqrt(2.0))) 15 | 16 | def g(rho, mu1, mu2): 17 | one_plus_sqrt_one_minus_rho_sqr = 1.0 + torch.sqrt(1.0 - rho * rho) 18 | a = torch.asin(rho) - rho / one_plus_sqrt_one_minus_rho_sqr 19 | safe_a = torch.abs(a) + HALF_EPSILON 20 | safe_rho = torch.abs(rho) + EPSILON 21 | 22 | A = a / (2.0 * math.pi) 23 | sxx = safe_a * one_plus_sqrt_one_minus_rho_sqr / safe_rho 24 | one_ovr_sxy = (torch.asin(rho) - rho) / (safe_a * safe_rho) 25 | 26 | return A * torch.exp(-(mu1 * mu1 + mu2 * mu2) / (2.0 * sxx) + one_ovr_sxy * mu1 * mu2) 27 | 28 | 29 | def delta(rho, mu1, mu2): 30 | return gaussian_cdf(mu1) * gaussian_cdf(mu2) + g(rho, mu1, mu2) 31 | 32 | 33 | def standard_gaussian(x): 34 | return 1.0 / math.sqrt(2.0 * math.pi) * torch.exp(- x * x / 2.0) 35 | 36 | def softrelu(x): 37 | return standard_gaussian(x) + x * gaussian_cdf(x) 38 | 39 | def anneal(epoch, warmup=14000, anneal=1000): 40 | return 1.0 * max(min((epoch - warmup) / anneal, 1.0), 0.0) 41 | 42 | -------------------------------------------------------------------------------- /dvi/dataset.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | import torch 4 | from torch.utils.data import Dataset 5 | 6 | 7 | class ToyDataset(Dataset): 8 | # data_size = {'train': 500, 'valid': 100, 'test': 100} 9 | def __init__(self, model=None, noise=None, 10 | data_size=500, sampling=True, transform=None): 11 | if model is None: 12 | model = self.base_model 13 | self.model = model 14 | 15 | if noise is None: 16 | noise = self.noise_model 17 | self.noise = noise 18 | 19 | self.data_size = data_size 20 | 21 | self.sampling = sampling 22 | 23 | self.transform = transform 24 | 25 | self.create_data() 26 | 27 | def __len__(self): 28 | return self.data_size 29 | 30 | def __getitem__(self, idx): 31 | x, y = self.data[idx] 32 | 33 | if self.transform: 34 | x = self.transform(x) 35 | 36 | return x, y 37 | 38 | def __repr__(self): 39 | return "Toy Dataset" 40 | 41 | def base_model(self, x): 42 | return - (x + 0.5) * np.sin(3 * np.pi * x) 43 | 44 | def noise_model(self, x): 45 | return 0.45 * (x + 0.5) ** 2 46 | 47 | def sample_data(self, x): 48 | return self.model(x) + np.random.normal(0, self.noise(x)) 49 | 50 | def create_data(self): 51 | if self.sampling: 52 | xs = np.random.rand(self.data_size, 1) - 0.5 53 | else: 54 | xs = np.arange(-1, 1, 1 / 100) 55 | ys = self.sample_data(xs) 56 | 57 | self.data = [(torch.from_numpy(x).float(), torch.tensor(torch.from_numpy(y).item()).float()) 58 | for x, y in zip(xs, ys)] 59 | 60 | -------------------------------------------------------------------------------- /dvi/invgamma.py: -------------------------------------------------------------------------------- 1 | from numbers import Number 2 | 3 | import torch 4 | from torch.distributions import constraints 5 | from torch.distributions.exp_family import ExponentialFamily 6 | from torch.distributions import MultivariateNormal, Laplace 7 | from torch.distributions.utils import broadcast_all 8 | 9 | 10 | def _standard_gamma(concentration): 11 | return torch._standard_gamma(concentration) 12 | 13 | 14 | class InverseGamma(ExponentialFamily): 15 | arg_constraints = {'concentration': constraints.positive, 16 | 'scale': constraints.positive, 17 | 'rate': constraints.positive} 18 | support = constraints.positive 19 | has_rsample = True 20 | _mean_carrier_measure = 0 21 | 22 | @property 23 | def mean(self): 24 | return self.scale / (self.concentration - 1) 25 | 26 | @property 27 | def variance(self): 28 | return torch.pow(self.scale, 2) / torch.pow(self.concentration - 1, 2) / (self.constraints - 2) 29 | 30 | def __init__(self, concentration, scale=None, rate=None, validate_args=None): 31 | if rate is not None: 32 | scale = rate 33 | 34 | self.concentration, self.scale = broadcast_all(concentration, scale) 35 | if isinstance(concentration, Number) and isinstance(scale, Number): 36 | batch_shape = torch.Size() 37 | else: 38 | batch_shape = self.concentration.size() 39 | super(InverseGamma, self).__init__(batch_shape, validate_args=validate_args) 40 | 41 | def expand(self, batch_shape, _instance=None): 42 | new = self._get_checked_instance(InverseGamma, _instance) 43 | batch_shape = torch.Size(batch_shape) 44 | new.concentration = self.concentration.expand(batch_shape) 45 | new.scale = self.scale.expand(batch_shape) 46 | super(InverseGamma, new).__init__(batch_shape, validate_args=False) 47 | new._validate_args = self._validate_args 48 | return new 49 | 50 | def rsample(self, sample_shape=torch.Size()): 51 | shape = self._extended_shape(sample_shape) 52 | value = 1 / _standard_gamma(self.concentration.expand(shape)) * self.scale.expand(shape) 53 | value.detach().clamp_(min=torch.finfo(value.dtype).tiny) 54 | return value 55 | 56 | def log_prob(self, value): 57 | if self._validate_args: 58 | self._validate_sample(value) 59 | return (self.concentration * torch.log(self.scale) - 60 | (self.concentration + 1) * torch.log(value) - 61 | self.scale / value - torch.lgamma(self.concentration)) 62 | 63 | def entropy(self): 64 | return (self.concentration + torch.log(self.scale) + torch.lgamma(self.concentration) - 65 | (1 + self.concentration) * torch.digamma(self.concentration)) 66 | 67 | @property 68 | def _natural_params(self): 69 | return (-self.concentration - 1, -self.scale) 70 | 71 | def _log_normalizer(self, x, y): 72 | return torch.lgamma(- x - 1) + (- x - 1) * torch.log(-y.reciprocal()) 73 | -------------------------------------------------------------------------------- /dvi/kl.py: -------------------------------------------------------------------------------- 1 | import math 2 | import torch 3 | import torch.distributions as tdist 4 | from torch.distributions.kl import register_kl 5 | 6 | from .invgamma import InverseGamma 7 | 8 | one_ovr_sqrt2pi = 1.0 / math.sqrt(2.0 * math.pi) 9 | one_ovr_sqrt2 = 1.0 / math.sqrt(2.) 10 | 11 | 12 | def _standard_gaussian(x): 13 | return one_ovr_sqrt2pi * torch.exp(- x * x / 2.0) 14 | 15 | 16 | @register_kl(tdist.Normal, InverseGamma) 17 | def kl_normal_invgamma(p, q): 18 | # p: loc/scale, q: concentration, scale 19 | m = torch.numel(p.loc) 20 | S = p.scale.pow(2) + p.loc.pow(2) 21 | m_plus_2alpha_plus_2 = m + 2.0 * q.concentration + 2.0 22 | S_plus_2beta = S + 2.0 * q.scale / m 23 | 24 | term1 = torch.log(torch.sum(S_plus_2beta) / m_plus_2alpha_plus_2) 25 | term2 = S * (m_plus_2alpha_plus_2 / torch.sum(S_plus_2beta)) 26 | term3 = -(1 + torch.log(p.scale.pow(2))) 27 | return 0.5 * (term1 + term2 + term3) 28 | 29 | 30 | @register_kl(tdist.Normal, tdist.Laplace) 31 | def kl_normal_laplace(p, q): 32 | sigma = p.scale 33 | mu_ovr_sigma = p.loc / sigma 34 | tmp = 2 * _standard_gaussian(mu_ovr_sigma) + mu_ovr_sigma * torch.erf(mu_ovr_sigma * one_ovr_sqrt2) 35 | tmp *= sigma / q.scale 36 | tmp += 0.5 * torch.log(2 * q.scale * q.scale / (math.pi * p.scale)) - 0.5 37 | return tmp 38 | -------------------------------------------------------------------------------- /dvi/loss.py: -------------------------------------------------------------------------------- 1 | import math 2 | import torch 3 | import torch.nn as nn 4 | 5 | 6 | 7 | class GLLLoss(nn.Module): 8 | """Gaussian Log-Likelihood Loss 9 | """ 10 | def __init__(self, style='heteroschedastic', method='bayes', homo_logvar_scale=0.4): 11 | super(GLLLoss, self).__init__() 12 | 13 | self.style = style 14 | self.method = method 15 | self.homo_logvar_scale = homo_logvar_scale 16 | self.gaussian_loglikelihood = (self.heteroschedastic_gaussian_loglikelihood 17 | if self.style == 'heteroschedastic' 18 | else self.homoschedastic_gaussian_loglikelihood) 19 | 20 | def forward(self, pred, target): 21 | log_likelihood = self.gaussian_loglikelihood(pred, target) 22 | return log_likelihood 23 | 24 | def extra_repr(self): 25 | return 'style={}, method={}{}'.format(self.style, self.method, 26 | ', scale={}'.format(self.homo_logvar_scale) 27 | if self.style != 'heteroschedastic' else '') 28 | 29 | def heteroschedastic_gaussian_loglikelihood(self, pred, target): 30 | log_variance = pred.mean[:, 1].reshape(-1) 31 | mean = pred.mean[:, 0].reshape(-1) 32 | 33 | if self.method.lower().strip() == 'bayes': 34 | sll = pred.var[:, 1, 1].reshape(-1) 35 | smm = pred.var[:, 0, 0].reshape(-1) 36 | sml = pred.var[:, 0, 1].reshape(-1) 37 | else: 38 | sll = torch.tensor(0.0).to(target.device) 39 | smm = torch.tensor(0.0).to(target.device) 40 | sml = torch.tensor(0.0).to(target.device) 41 | return self.gaussian_loglikelihood_core(target, mean, log_variance, smm, sml, sll) 42 | 43 | def homoschedastic_gaussian_loglikelihood(self, pred, target): 44 | log_variance = torch.tensor(self.homo_logvar_scale).to(target.device) 45 | mean = pred.mean[:, 0].reshape(-1) 46 | sll = torch.tensor(0.0).to(target.device) 47 | sml = torch.tensor(0.0).to(target.device) 48 | if self.method.lower().strip() == 'bayes': 49 | smm = pred.var[:, 0, 0].reshape(-1) 50 | else: 51 | smm = torch.tensor(0.0).to(target.device) 52 | return self.gaussian_loglikelihood_core(target, mean, log_variance, smm, sml, sll) 53 | 54 | def gaussian_loglikelihood_core(self, target, mean, log_variance, smm, sml, sll): 55 | return (-0.5 * (torch.tensor(math.log(2.0 * math.pi)) + log_variance 56 | + torch.exp(-log_variance + 0.5 * sll) * (smm + (mean - sml - target) ** 2))) 57 | -------------------------------------------------------------------------------- /dvi/plot.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import matplotlib.pyplot as plt 3 | 4 | def toydata_result_plot(trainloader, model=None): 5 | mean_model = trainloader.dataset.base_model 6 | std_model = trainloader.dataset.noise_model 7 | 8 | xs, ys = iter(trainloader).next() 9 | 10 | train_x = torch.arange(torch.min(xs.reshape(-1)), torch.max(xs.reshape(-1)), 1/100).cpu() 11 | 12 | plt.plot(train_x.numpy(), mean_model(train_x).numpy(), 'red', label='data mean') 13 | plt.fill_between(train_x.cpu().numpy(), 14 | (mean_model(train_x) - std_model(train_x)).numpy(), 15 | (mean_model(train_x) + std_model(train_x)).numpy(), 16 | color='orange', alpha=1, label='data 1-std') 17 | plt.plot(xs.cpu().numpy(), ys.cpu().numpy(), 'r.', alpha=0.2, label='train sample') 18 | 19 | 20 | if model is not None: 21 | with torch.no_grad(): 22 | test_x = torch.arange(-1, 1, 1/100).reshape(-1, 1) 23 | pred = model(test_x) 24 | y_mean = pred.mean[:,0].cpu() 25 | ell_mean = pred.mean[:,1].cpu() 26 | y_var = pred.var[:,0,0].cpu() 27 | ell_var = pred.var[:,1,1].cpu() 28 | 29 | heteroskedastic_part = torch.exp(0.5 * ell_mean) 30 | full_std = torch.sqrt(y_var + torch.exp(ell_mean + 0.5 * ell_var)) 31 | 32 | plt.plot(test_x.cpu().numpy(), y_mean.numpy(), label='model mean') 33 | plt.fill_between(test_x.cpu().reshape(-1).numpy(), 34 | (y_mean - heteroskedastic_part).numpy(), 35 | (y_mean + heteroskedastic_part).numpy(), 36 | color='g', alpha = 0.2, label='$\ell$ contrib') 37 | plt.fill_between(test_x.cpu().reshape(-1).numpy(), 38 | (y_mean - full_std).numpy(), 39 | (y_mean + full_std).numpy(), 40 | color='b', alpha = 0.2, label='model 1-std') 41 | 42 | plt.xlabel('x') 43 | plt.ylabel('y') 44 | plt.ylim([-3,2]) 45 | plt.legend() -------------------------------------------------------------------------------- /dvi/variables.py: -------------------------------------------------------------------------------- 1 | import math 2 | import numpy as np 3 | 4 | import torch 5 | import torch.nn as nn 6 | import torch.distributions as tdist 7 | 8 | from .invgamma import InverseGamma 9 | from .kl import kl_normal_invgamma, kl_normal_laplace 10 | 11 | class GaussianVar(object): 12 | def __init__(self, mean, var): 13 | self.mean = mean 14 | self.var = var 15 | self.shape = mean.shape 16 | 17 | 18 | class Parameter(nn.Module): 19 | def __init__(self, prior, approximation, q_loc, log_q_scale): 20 | super(Parameter, self).__init__() 21 | 22 | self.prior = prior 23 | self.approximation = approximation 24 | 25 | self.q_loc = q_loc 26 | self.log_q_scale = log_q_scale 27 | 28 | def q(self): 29 | return self.approximation(loc=self.q_loc, scale=torch.exp(self.log_q_scale)) 30 | 31 | def __repr__(self): 32 | args_string = 'Prior: {}\n Variational: {}'.format( 33 | self.prior, 34 | self.q() 35 | ) 36 | return self.__class__.__name__ + '(\n ' + args_string + '\n)' 37 | 38 | def surprise(self): 39 | q = self.q() 40 | p = self.prior 41 | return tdist.kl_divergence(q, p) 42 | 43 | def sample(self, n_sample=None, average=False): 44 | if n_sample is None: 45 | n_sample = 1 46 | samples = self.q().rsample((n_sample,)) 47 | return samples 48 | 49 | 50 | def get_variance_scale(initialization_type, shape): 51 | if initialization_type == "standard": 52 | prior_var = 1.0 53 | elif initialization_type == "wide": 54 | prior_var = 100.0 55 | elif initialization_type == "narrow": 56 | prior_var = 0.01 57 | elif initialization_type == "glorot": 58 | prior_var = (2.0 / (shape[-1] + shape[-2])) 59 | elif initialization_type == "xavier": 60 | prior_var = 1.0/shape[-1] 61 | elif initialization_type == "he": 62 | prior_var = 2.0/shape[-1] 63 | elif initialization_type == "wider_he": 64 | prior_var = 5.0/shape[-1] 65 | else: 66 | raise NotImplementedError('prior type "%s" not recognized' % initialization_type) 67 | return prior_var 68 | 69 | 70 | def gaussian_init(loc, scale, shape): 71 | return loc + scale * torch.randn(*shape) 72 | 73 | 74 | def laplace_init(loc, scale, shape): 75 | return torch.from_numpy(np.random.laplace(loc, scale/np.sqrt(2.0), size=shape).astype(np.float32)) 76 | 77 | 78 | def make_weight_matrix(shape, prior_type, variance): 79 | """ 80 | Args: 81 | shape (list, required): The shape of weight matrix. It should be `(out_features, in_features)`. 82 | prior_type (list, required): Prior Type. It should be `[prior, weight_scale, bias_scale]` 83 | `["gaussian", "wider_he", "wider_he"]`. 84 | """ 85 | variance = get_variance_scale(variance.strip().lower(), shape) 86 | stddev = torch.sqrt(torch.ones(shape) * variance).float() 87 | log_stddev = nn.Parameter(torch.log(stddev)) 88 | stddev = torch.exp(log_stddev) 89 | 90 | prior = prior_type.strip().lower() 91 | 92 | if prior == 'empirical': 93 | a = 4.4798 94 | alpha = a 95 | beta = (1 + a) * variance 96 | 97 | prior = InverseGamma(alpha, beta) 98 | 99 | mean = nn.Parameter(torch.Tensor(*shape)) 100 | nn.init.normal_(mean, 0.0, math.sqrt(variance)) 101 | return Parameter(prior, tdist.Normal, mean, log_stddev) 102 | 103 | elif prior == 'gaussian' or prior == 'normal': 104 | init_function = gaussian_init 105 | prior_generator = tdist.Normal 106 | elif prior == 'laplace': 107 | init_function = laplace_init 108 | prior_generator = tdist.Laplace 109 | else: 110 | raise NotImplementedError('prior type "{}" not recognized'.format(prior)) 111 | 112 | mean = nn.Parameter(init_function(0.0, math.sqrt(variance), shape)) 113 | 114 | prior_loc = torch.zeros(*shape) 115 | prior_scale = torch.ones(*shape) * math.sqrt(variance) 116 | prior = prior_generator(prior_loc, prior_scale) 117 | 118 | return Parameter(prior, tdist.Normal, mean, log_stddev) 119 | 120 | 121 | def make_bias_vector(shape, prior_type, variance): 122 | fudge_factor = 10.0 123 | variance = get_variance_scale(variance.strip().lower(), shape) 124 | stddev = torch.sqrt(torch.ones(shape[-2],) * variance / fudge_factor) 125 | log_stddev = nn.Parameter(torch.log(stddev)) 126 | stddev = torch.exp(log_stddev) 127 | 128 | prior = prior_type.strip().lower() 129 | 130 | if prior == 'empirical': 131 | a = 4.4798 132 | alpha = a 133 | beta = (1 + a) * variance 134 | 135 | prior = InverseGamma(alpha, beta) 136 | 137 | mean = nn.Parameter(torch.zeros(shape[-2],)) 138 | return Parameter(prior, tdist.Normal, mean, log_stddev) 139 | else: 140 | raise NotImplementedError('prior type "{}" not recognized'.format(prior)) 141 | -------------------------------------------------------------------------------- /main.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "data": { 10 | "text/plain": [ 11 | "" 12 | ] 13 | }, 14 | "execution_count": 1, 15 | "metadata": {}, 16 | "output_type": "execute_result" 17 | } 18 | ], 19 | "source": [ 20 | "%matplotlib inline\n", 21 | "import matplotlib.pyplot as plt\n", 22 | "\n", 23 | "from IPython.display import clear_output\n", 24 | "\n", 25 | "import math\n", 26 | "import numpy as np\n", 27 | "import torch\n", 28 | "import torch.optim as optim\n", 29 | "from torch.utils.data import DataLoader\n", 30 | "\n", 31 | "import dvi.bayes_utils as bu\n", 32 | "from dvi.dataset import ToyDataset\n", 33 | "from dvi.bayes_models import MLP, AdaptedMLP\n", 34 | "from dvi.loss import GLLLoss\n", 35 | "from dvi.plot import toydata_result_plot\n", 36 | "\n", 37 | "np.random.seed(1234)\n", 38 | "torch.manual_seed(1234)" 39 | ] 40 | }, 41 | { 42 | "cell_type": "code", 43 | "execution_count": 2, 44 | "metadata": {}, 45 | "outputs": [], 46 | "source": [ 47 | "TRAIN_SIZE = 500\n", 48 | "X_DIM = 1\n", 49 | "Y_DIM = 2\n", 50 | "LEARNING_RATE = 1e-3\n", 51 | "EPOCHS = 20000\n", 52 | "ADAPTER = {\n", 53 | " 'in': {\"scale\": [[1.0]], \"shift\": [[0.0]]},\n", 54 | " 'out': {\"scale\": [[1.0, 0.83]], \"shift\": [[0.0, -3.5]]}\n", 55 | " }\n", 56 | "WARMUP = 14000\n", 57 | "ANNEAL = 1000\n", 58 | "\n", 59 | "if torch.cuda.is_available():\n", 60 | " DEVICE = torch.device('cuda')\n", 61 | " torch.set_default_tensor_type(torch.cuda.FloatTensor)\n", 62 | "else:\n", 63 | " DEVICE = torch.device('cpu')" 64 | ] 65 | }, 66 | { 67 | "cell_type": "markdown", 68 | "metadata": {}, 69 | "source": [ 70 | "## Dataset\n", 71 | "\n", 72 | "First we generate a toy dataset according to:\n", 73 | "\\begin{equation} \n", 74 | "y = -(x+0.5)\\sin(3\\pi x) + \\eta\n", 75 | "\\end{equation}\n", 76 | "\n", 77 | "Where the noise is generated according to:\n", 78 | "\n", 79 | "\\begin{equation}\n", 80 | " \\eta = 0.45(x + 0.5)^2\n", 81 | "\\end{equation}" 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "execution_count": 3, 87 | "metadata": {}, 88 | "outputs": [], 89 | "source": [ 90 | "trainset = ToyDataset(data_size=TRAIN_SIZE, sampling=True)\n", 91 | "trainloader = DataLoader(trainset, batch_size=TRAIN_SIZE, shuffle=True)" 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "execution_count": 4, 97 | "metadata": {}, 98 | "outputs": [ 99 | { 100 | "data": { 101 | "image/png": "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\n", 102 | "text/plain": [ 103 | "
" 104 | ] 105 | }, 106 | "metadata": { 107 | "needs_background": "light" 108 | }, 109 | "output_type": "display_data" 110 | } 111 | ], 112 | "source": [ 113 | "toydata_result_plot(trainloader)" 114 | ] 115 | }, 116 | { 117 | "cell_type": "markdown", 118 | "metadata": {}, 119 | "source": [ 120 | "## Model" 121 | ] 122 | }, 123 | { 124 | "cell_type": "code", 125 | "execution_count": 5, 126 | "metadata": {}, 127 | "outputs": [ 128 | { 129 | "data": { 130 | "text/plain": [ 131 | "AdaptedMLP(\n", 132 | "MLP(\n", 133 | " (layers): Sequential(\n", 134 | " (0): VariationalLinearCertainActivations(\n", 135 | " (weight): Parameter(\n", 136 | " Prior: InverseGamma(concentration: 4.479800224304199, scale: 27.39900016784668)\n", 137 | " Variational: Normal(loc: torch.Size([128, 1]), scale: torch.Size([128, 1]))\n", 138 | " )\n", 139 | " (bias): Parameter(\n", 140 | " Prior: InverseGamma(concentration: 4.479800224304199, scale: 27.39900016784668)\n", 141 | " Variational: Normal(loc: torch.Size([128]), scale: torch.Size([128]))\n", 142 | " )\n", 143 | " )\n", 144 | " (1): VariationalLinearReLU(\n", 145 | " (weight): Parameter(\n", 146 | " Prior: InverseGamma(concentration: 4.479800224304199, scale: 0.21405468881130219)\n", 147 | " Variational: Normal(loc: torch.Size([128, 128]), scale: torch.Size([128, 128]))\n", 148 | " )\n", 149 | " (bias): Parameter(\n", 150 | " Prior: InverseGamma(concentration: 4.479800224304199, scale: 0.21405468881130219)\n", 151 | " Variational: Normal(loc: torch.Size([128]), scale: torch.Size([128]))\n", 152 | " )\n", 153 | " )\n", 154 | " (2): VariationalLinearReLU(\n", 155 | " (weight): Parameter(\n", 156 | " Prior: InverseGamma(concentration: 4.479800224304199, scale: 0.21405468881130219)\n", 157 | " Variational: Normal(loc: torch.Size([2, 128]), scale: torch.Size([2, 128]))\n", 158 | " )\n", 159 | " (bias): Parameter(\n", 160 | " Prior: InverseGamma(concentration: 4.479800224304199, scale: 0.21405468881130219)\n", 161 | " Variational: Normal(loc: torch.Size([2]), scale: torch.Size([2]))\n", 162 | " )\n", 163 | " )\n", 164 | " )\n", 165 | "))" 166 | ] 167 | }, 168 | "execution_count": 5, 169 | "metadata": {}, 170 | "output_type": "execute_result" 171 | } 172 | ], 173 | "source": [ 174 | "mlp = MLP(X_DIM, Y_DIM)\n", 175 | "model = AdaptedMLP(mlp, ADAPTER, device=DEVICE)\n", 176 | "model" 177 | ] 178 | }, 179 | { 180 | "cell_type": "markdown", 181 | "metadata": {}, 182 | "source": [ 183 | "## Training " 184 | ] 185 | }, 186 | { 187 | "cell_type": "code", 188 | "execution_count": 6, 189 | "metadata": {}, 190 | "outputs": [], 191 | "source": [ 192 | "criterion = GLLLoss()\n", 193 | "\n", 194 | "optimizer = optim.Adam(model.parameters(),\n", 195 | " lr=LEARNING_RATE)\n" 196 | ] 197 | }, 198 | { 199 | "cell_type": "code", 200 | "execution_count": 7, 201 | "metadata": {}, 202 | "outputs": [], 203 | "source": [ 204 | "def train(epoch, model, criterion, dataloader, optimizer):\n", 205 | " model.mlp.train()\n", 206 | "\n", 207 | " for xs, ys in dataloader:\n", 208 | " xs, ys = xs.to(DEVICE), ys.to(DEVICE)\n", 209 | "\n", 210 | " optimizer.zero_grad()\n", 211 | "\n", 212 | " pred = model(xs)\n", 213 | "\n", 214 | " kl = model.surprise()\n", 215 | "\n", 216 | " log_likelihood = criterion(pred, ys)\n", 217 | " batch_log_likelihood = torch.mean(log_likelihood)\n", 218 | "\n", 219 | " lmbd = bu.anneal(epoch, WARMUP, ANNEAL)\n", 220 | "\n", 221 | " loss = lmbd * kl / TRAIN_SIZE - batch_log_likelihood\n", 222 | "\n", 223 | " loss.backward()\n", 224 | " torch.nn.utils.clip_grad_norm_(model.parameters(), 0.1)\n", 225 | "\n", 226 | " optimizer.step()\n", 227 | "\n", 228 | " accuracy = torch.mean(torch.abs(pred.mean[:, 0].reshape(-1) - ys))\n", 229 | " if epoch % 20 == 0:\n", 230 | " print(\"Epoch {}: GLL={:.4f}, KL={:.4f}(anneal:{}) | MAE={:.4f}\".format(\n", 231 | " epoch, batch_log_likelihood.item(), kl.item()/500, lmbd, accuracy))" 232 | ] 233 | }, 234 | { 235 | "cell_type": "code", 236 | "execution_count": 8, 237 | "metadata": {}, 238 | "outputs": [ 239 | { 240 | "data": { 241 | "image/png": "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\n", 242 | "text/plain": [ 243 | "
" 244 | ] 245 | }, 246 | "metadata": { 247 | "needs_background": "light" 248 | }, 249 | "output_type": "display_data" 250 | } 251 | ], 252 | "source": [ 253 | "toydata_result_plot(trainloader, model)\n", 254 | "plt.show()\n", 255 | "\n", 256 | "for epoch in range(1, EPOCHS+1):\n", 257 | " train(epoch, model, criterion, trainloader, optimizer)\n", 258 | " if epoch % 100 == 0:\n", 259 | " clear_output()\n", 260 | " toydata_result_plot(trainloader, model)\n", 261 | " plt.show()\n" 262 | ] 263 | }, 264 | { 265 | "cell_type": "markdown", 266 | "metadata": {}, 267 | "source": [ 268 | "## Comparison with MC\n", 269 | "\n", 270 | "We compare the output activations of the BNN as predicted using our deterministic approximation with the activations predicted by Monte Carlo approximation (see Figure 3 of the paper)" 271 | ] 272 | }, 273 | { 274 | "cell_type": "code", 275 | "execution_count": 9, 276 | "metadata": {}, 277 | "outputs": [ 278 | { 279 | "name": "stderr", 280 | "output_type": "stream", 281 | "text": [ 282 | "/home/makotok/projects/deterministic-variational-inference-pytorch/dvi/bayes_models.py:66: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).\n", 283 | " 'scale': torch.tensor(adapter[ad]['scale']).to(self.device),\n", 284 | "/home/makotok/projects/deterministic-variational-inference-pytorch/dvi/bayes_models.py:67: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).\n", 285 | " 'shift': torch.tensor(adapter[ad]['shift']).to(self.device)\n" 286 | ] 287 | } 288 | ], 289 | "source": [ 290 | "# from matplotlib import rc\n", 291 | "# rc('text', usetex=True)\n", 292 | "torch.set_default_tensor_type(torch.FloatTensor)\n", 293 | "model.device = torch.device('cpu')\n", 294 | "model.make_adapters(model.adapter)\n", 295 | "import numpy as np\n", 296 | "n_sample = 10000\n", 297 | "x = 0.25\n", 298 | "with torch.no_grad():\n", 299 | " model.mlp.cpu()\n", 300 | " test_x = torch.ones(n_sample, 1) * x\n", 301 | "\n", 302 | " samples = model.mcmc(test_x, n_sample)\n", 303 | " tmp = model(test_x)\n", 304 | " approx = [tmp.mean, tmp.var]\n", 305 | " \n", 306 | "def gaussian1d(mean, var):\n", 307 | " x_axis = torch.linspace(-5,5,1000)\n", 308 | " return x_axis.cpu().numpy(), (1.0 / torch.sqrt(2.0 * math.pi * var) * torch.exp(-1.0 / (2.0 * var) * (x_axis - mean)**2)).cpu().numpy()" 309 | ] 310 | }, 311 | { 312 | "cell_type": "code", 313 | "execution_count": 23, 314 | "metadata": {}, 315 | "outputs": [ 316 | { 317 | "data": { 318 | "image/png": "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\n", 319 | "text/plain": [ 320 | "
" 321 | ] 322 | }, 323 | "metadata": { 324 | "needs_background": "light" 325 | }, 326 | "output_type": "display_data" 327 | }, 328 | { 329 | "data": { 330 | "image/png": "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\n", 331 | "text/plain": [ 332 | "
" 333 | ] 334 | }, 335 | "metadata": { 336 | "needs_background": "light" 337 | }, 338 | "output_type": "display_data" 339 | } 340 | ], 341 | "source": [ 342 | "plt.figure(figsize=(3,2))\n", 343 | "# plt.hist(samples[:,0,0].cpu().numpy(), int(np.round(200/(1))), density=True, edgecolor='k', facecolor='#b4c7e7')\n", 344 | "plt.hist(samples[:,0,0].cpu().numpy(), 30, density=True, edgecolor='k', facecolor='#b4c7e7')\n", 345 | "\n", 346 | "plt.plot(*gaussian1d(approx[0][0,0], approx[1][0,0,0]), 'b')\n", 347 | "plt.xlim([-1,-0.0])\n", 348 | "plt.yticks([])\n", 349 | "plt.xlabel('$m$')\n", 350 | "plt.ylabel('$q(m)$')\n", 351 | "plt.show()\n", 352 | "\n", 353 | "plt.figure(figsize=(3,2))\n", 354 | "# plt.hist(samples[:,0,1].cpu().numpy(), int(np.round(200/(3.8-1.9))), density=True, edgecolor='k', facecolor='#b4c7e7', label=\"MC\")\n", 355 | "plt.hist(samples[:,0,1].cpu().numpy(), 30, density=True, edgecolor='k', facecolor='#b4c7e7', label=\"MC\")\n", 356 | "plt.plot(*gaussian1d(approx[0][0,1], approx[1][0,1,1]), 'b', label=\"ours\")\n", 357 | "plt.xlim([-3.8,-1.9])\n", 358 | "plt.yticks([])\n", 359 | "plt.xlabel('$\\ell$')\n", 360 | "plt.ylabel('$q(\\ell)$')\n", 361 | "plt.legend()\n", 362 | "plt.show()" 363 | ] 364 | }, 365 | { 366 | "cell_type": "code", 367 | "execution_count": null, 368 | "metadata": {}, 369 | "outputs": [], 370 | "source": [] 371 | } 372 | ], 373 | "metadata": { 374 | "kernelspec": { 375 | "display_name": "Python 3", 376 | "language": "python", 377 | "name": "python3" 378 | }, 379 | "language_info": { 380 | "codemirror_mode": { 381 | "name": "ipython", 382 | "version": 3 383 | }, 384 | "file_extension": ".py", 385 | "mimetype": "text/x-python", 386 | "name": "python", 387 | "nbconvert_exporter": "python", 388 | "pygments_lexer": "ipython3", 389 | "version": "3.7.1" 390 | } 391 | }, 392 | "nbformat": 4, 393 | "nbformat_minor": 2 394 | } 395 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | 3 | import numpy as np 4 | 5 | import torch 6 | import torch.optim as optim 7 | from torch.utils.data import DataLoader 8 | 9 | 10 | import dvi.bayes_utils as bu 11 | from dvi.dataset import ToyDataset 12 | from dvi.bayes_models import MLP, AdaptedMLP 13 | from dvi.loss import GLLLoss 14 | 15 | 16 | def train(epoch, model, criterion, dataloader, optimizer): 17 | model.mlp.train() 18 | 19 | for xs, ys in dataloader: 20 | xs, ys = xs.to(args.device), ys.to(args.device) 21 | 22 | optimizer.zero_grad() 23 | 24 | pred = model(xs) 25 | 26 | kl = model.surprise() 27 | 28 | log_likelihood = criterion(pred, ys) 29 | batch_log_likelihood = torch.mean(log_likelihood) 30 | 31 | lmbd = bu.anneal(epoch) 32 | 33 | loss = lmbd * kl / args.train_size - batch_log_likelihood 34 | 35 | loss.backward() 36 | torch.nn.utils.clip_grad_norm_(model.parameters(), 0.1) 37 | 38 | optimizer.step() 39 | 40 | accuracy = torch.mean(torch.abs(pred.mean[:, 0].reshape(-1) - ys)) 41 | if epoch % 20 == 0: 42 | print("Epoch {}: GLL={:.4f}, KL={:.4f}(anneal:{}) | MAE={:.4f}".format(epoch, batch_log_likelihood.item(), kl.item()/500, lmbd, accuracy)) 43 | 44 | 45 | def main(): 46 | trainset = ToyDataset(data_size=args.train_size, sampling=True) 47 | trainloader = DataLoader(trainset, batch_size=args.train_size, shuffle=True) 48 | 49 | 50 | mlp = MLP(args.x_dim, args.y_dim, args.hidden_dims) 51 | model = AdaptedMLP(mlp, args.adapter, device=args.device) 52 | 53 | criterion = GLLLoss() 54 | 55 | optimizer = optim.Adam(model.parameters(), 56 | lr=args.lr) 57 | 58 | for epoch in range(1, args.epochs+1): 59 | train(epoch, model, criterion, trainloader, optimizer) 60 | torch.save(model, 'temp.pth.tar') 61 | 62 | 63 | if __name__ == '__main__': 64 | parser = argparse.ArgumentParser(description="Deterministic Variational Inference") 65 | parser.add_argument('--method', type=str, default='bayes', 66 | help="Method: bayes|point") 67 | parser.add_argument('--x-dim', type=int, default=1, 68 | help="input dimension") 69 | parser.add_argument('--y-dim', type=int, default=1, 70 | help="output dimension") 71 | parser.add_argument('--nonlinear', type=str, default='relu', 72 | help="Non-Linearity") 73 | 74 | parser.add_argument('--epochs', type=int, default=3000, 75 | help="Epochs") 76 | parser.add_argument('--lr', type=float, default=1e-3, 77 | help='learning rate') 78 | parser.add_argument('--train-size', type=int, default=500, 79 | help='Train size (Also Training batch data size)') 80 | parser.add_argument('--test-size', type=int, default=100, 81 | help='Test size (Also Testing batch data size)') 82 | 83 | parser.add_argument('--seed', type=int, default=3, 84 | help="Random Seed") 85 | 86 | args = parser.parse_args() 87 | args.prior_type = ["empirical", "wider_he", "wider_he"] 88 | args.hidden_dims = [128, 128] 89 | args.adapter = { 90 | 'in': {"scale": [[1.0]], "shift": [[0.0]]}, 91 | 'out': {"scale": [[1.0, 0.83]], "shift": [[0.0, -3.5]]} 92 | } 93 | 94 | if torch.cuda.is_available(): 95 | args.device = torch.device('cuda') 96 | torch.set_default_tensor_type(torch.cuda.FloatTensor) 97 | else: 98 | args.device = torch.device('cpu') 99 | # args.device = torch.device('cpu') 100 | 101 | np.random.seed(args.seed) 102 | torch.manual_seed(args.seed) 103 | print(args) 104 | 105 | main() 106 | 107 | -------------------------------------------------------------------------------- /test/InvGamma_validation.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 16, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "%matplotlib inline\n", 10 | "import matplotlib.pyplot as plt\n", 11 | "import seaborn as sns" 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": 17, 17 | "metadata": {}, 18 | "outputs": [], 19 | "source": [ 20 | "import torch\n", 21 | "from distributions import InverseGamma\n", 22 | "import numpy as np" 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": 25, 28 | "metadata": {}, 29 | "outputs": [], 30 | "source": [ 31 | "alpha = torch.tensor(3.)\n", 32 | "beta = torch.tensor(0.5)\n", 33 | "p = InverseGamma(alpha, scale=beta)\n", 34 | "alpha = torch.tensor(3.)\n", 35 | "beta = torch.tensor(1.)\n", 36 | "p2 = InverseGamma(alpha, scale=beta)\n", 37 | "alpha = torch.tensor(2.)\n", 38 | "beta = torch.tensor(1.)\n", 39 | "p3 = InverseGamma(alpha, scale=beta)\n", 40 | "alpha = torch.tensor(4.47)\n", 41 | "beta = torch.tensor(5.47)\n", 42 | "p4 = InverseGamma(alpha, scale=beta)" 43 | ] 44 | }, 45 | { 46 | "cell_type": "code", 47 | "execution_count": 26, 48 | "metadata": {}, 49 | "outputs": [], 50 | "source": [ 51 | "result1 = []\n", 52 | "result2 = []\n", 53 | "result3 = []\n", 54 | "result4 = []\n", 55 | "for i in range(10000):\n", 56 | " result1.append(p.rsample().item())\n", 57 | " result2.append(p2.rsample().item())\n", 58 | " result3.append(p3.rsample().item())\n", 59 | " result4.append(p4.rsample().item())" 60 | ] 61 | }, 62 | { 63 | "cell_type": "code", 64 | "execution_count": 27, 65 | "metadata": {}, 66 | "outputs": [ 67 | { 68 | "data": { 69 | "text/plain": [ 70 | "" 71 | ] 72 | }, 73 | "execution_count": 27, 74 | "metadata": {}, 75 | "output_type": "execute_result" 76 | }, 77 | { 78 | "data": { 79 | "image/png": "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\n", 80 | "text/plain": [ 81 | "
" 82 | ] 83 | }, 84 | "metadata": { 85 | "needs_background": "light" 86 | }, 87 | "output_type": "display_data" 88 | } 89 | ], 90 | "source": [ 91 | "plt.xlim(0, 3)\n", 92 | "sns.distplot(np.array(result4), label=r\"$\\alpha=3, \\beta=4$\")\n", 93 | "# sns.distplot(np.array(result3), label=r\"$\\alpha=2, \\beta=1$\")\n", 94 | "sns.distplot(np.array(result2), label=r\"$\\alpha=3, \\beta=1$\")\n", 95 | "sns.distplot(np.array(result1), label=r\"$\\alpha=3, \\beta=0.5$\")\n", 96 | "plt.legend()" 97 | ] 98 | }, 99 | { 100 | "cell_type": "code", 101 | "execution_count": 51, 102 | "metadata": {}, 103 | "outputs": [], 104 | "source": [ 105 | "from torch.distributions import Gamma" 106 | ] 107 | }, 108 | { 109 | "cell_type": "code", 110 | "execution_count": 9, 111 | "metadata": {}, 112 | "outputs": [], 113 | "source": [ 114 | "alpha = torch.tensor(4.4798)\n", 115 | "beta = torch.tensor(1/5.4798)\n", 116 | "q = InverseGamma(alpha, beta)" 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "execution_count": 10, 122 | "metadata": {}, 123 | "outputs": [], 124 | "source": [ 125 | "result = []\n", 126 | "for i in range(10000):\n", 127 | " result.append(q.rsample().item())" 128 | ] 129 | }, 130 | { 131 | "cell_type": "code", 132 | "execution_count": 11, 133 | "metadata": {}, 134 | "outputs": [ 135 | { 136 | "data": { 137 | "text/plain": [ 138 | "" 139 | ] 140 | }, 141 | "execution_count": 11, 142 | "metadata": {}, 143 | "output_type": "execute_result" 144 | }, 145 | { 146 | "data": { 147 | "image/png": "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\n", 148 | "text/plain": [ 149 | "
" 150 | ] 151 | }, 152 | "metadata": { 153 | "needs_background": "light" 154 | }, 155 | "output_type": "display_data" 156 | } 157 | ], 158 | "source": [ 159 | "sns.distplot(np.array(result))" 160 | ] 161 | }, 162 | { 163 | "cell_type": "code", 164 | "execution_count": null, 165 | "metadata": {}, 166 | "outputs": [], 167 | "source": [] 168 | }, 169 | { 170 | "cell_type": "code", 171 | "execution_count": null, 172 | "metadata": {}, 173 | "outputs": [], 174 | "source": [] 175 | } 176 | ], 177 | "metadata": { 178 | "kernelspec": { 179 | "display_name": "Python 3", 180 | "language": "python", 181 | "name": "python3" 182 | }, 183 | "language_info": { 184 | "codemirror_mode": { 185 | "name": "ipython", 186 | "version": 3 187 | }, 188 | "file_extension": ".py", 189 | "mimetype": "text/x-python", 190 | "name": "python", 191 | "nbconvert_exporter": "python", 192 | "pygments_lexer": "ipython3", 193 | "version": "3.7.1" 194 | } 195 | }, 196 | "nbformat": 4, 197 | "nbformat_minor": 2 198 | } 199 | -------------------------------------------------------------------------------- /test/check.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "from dataset import ToyDataset\n", 10 | "from torch.utils.data import DataLoader\n", 11 | "from bayes_models import MLP, AdaptedMLP\n", 12 | "from loss import GLLLoss\n", 13 | "import torch" 14 | ] 15 | }, 16 | { 17 | "cell_type": "code", 18 | "execution_count": 2, 19 | "metadata": {}, 20 | "outputs": [], 21 | "source": [ 22 | "dataset = ToyDataset()\n", 23 | "dataloader = DataLoader(dataset, batch_size=500)" 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": 3, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "train_x, train_y = list(dataloader)[0]\n", 33 | "# train_x, train_y = train_x.cuda(), train_y.cuda()" 34 | ] 35 | }, 36 | { 37 | "cell_type": "code", 38 | "execution_count": 4, 39 | "metadata": {}, 40 | "outputs": [], 41 | "source": [ 42 | "prior_type = [\"empirical\", \"wider_he\", \"wider_he\"]\n", 43 | "hidden_dims = [128, 128]\n", 44 | "adapter = {\n", 45 | " 'in': {\"scale\": [[1.0]], \"shift\": [[0.0]]},\n", 46 | " 'out': {\"scale\": [[1.0, 0.83]], \"shift\": [[0.0, -3.5]]}\n", 47 | "}" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": 5, 53 | "metadata": {}, 54 | "outputs": [], 55 | "source": [ 56 | "mlp = MLP(1, 2, prior_type, hidden_dims)\n", 57 | "model = AdaptedMLP(mlp, adapter)" 58 | ] 59 | }, 60 | { 61 | "cell_type": "code", 62 | "execution_count": 6, 63 | "metadata": {}, 64 | "outputs": [ 65 | { 66 | "data": { 67 | "text/plain": [ 68 | "MLP(\n", 69 | " (layers): Sequential(\n", 70 | " (0): LinearCertainActivations(\n", 71 | " prior=empirical, in_features=1, out_features=128, bias=True\n", 72 | " (weight): Parameter=>\n", 73 | " \tVariational Distribution: Normal(loc=torch.Size([128, 1]), scale=torch.Size([128, 1]))\n", 74 | " \tPrior: InverseGamma(concentration: 4.479800224304199, scale: 27.39900016784668)\n", 75 | " (bias): Parameter=>\n", 76 | " \tVariational Distribution: Normal(loc=torch.Size([128]), scale=torch.Size([128]))\n", 77 | " \tPrior: InverseGamma(concentration: 4.479800224304199, scale: 27.39900016784668)\n", 78 | " )\n", 79 | " (1): LinearReLU(\n", 80 | " prior=empirical, in_features=128, out_features=128, bias=True\n", 81 | " (weight): Parameter=>\n", 82 | " \tVariational Distribution: Normal(loc=torch.Size([128, 128]), scale=torch.Size([128, 128]))\n", 83 | " \tPrior: InverseGamma(concentration: 4.479800224304199, scale: 0.21405468881130219)\n", 84 | " (bias): Parameter=>\n", 85 | " \tVariational Distribution: Normal(loc=torch.Size([128]), scale=torch.Size([128]))\n", 86 | " \tPrior: InverseGamma(concentration: 4.479800224304199, scale: 0.21405468881130219)\n", 87 | " )\n", 88 | " (2): LinearReLU(\n", 89 | " prior=empirical, in_features=128, out_features=2, bias=True\n", 90 | " (weight): Parameter=>\n", 91 | " \tVariational Distribution: Normal(loc=torch.Size([2, 128]), scale=torch.Size([2, 128]))\n", 92 | " \tPrior: InverseGamma(concentration: 4.479800224304199, scale: 0.21405468881130219)\n", 93 | " (bias): Parameter=>\n", 94 | " \tVariational Distribution: Normal(loc=torch.Size([2]), scale=torch.Size([2]))\n", 95 | " \tPrior: InverseGamma(concentration: 4.479800224304199, scale: 0.21405468881130219)\n", 96 | " )\n", 97 | " )\n", 98 | ")" 99 | ] 100 | }, 101 | "execution_count": 6, 102 | "metadata": {}, 103 | "output_type": "execute_result" 104 | } 105 | ], 106 | "source": [ 107 | "model" 108 | ] 109 | }, 110 | { 111 | "cell_type": "code", 112 | "execution_count": 7, 113 | "metadata": {}, 114 | "outputs": [], 115 | "source": [ 116 | "pred = model(train_x)" 117 | ] 118 | }, 119 | { 120 | "cell_type": "code", 121 | "execution_count": 8, 122 | "metadata": {}, 123 | "outputs": [], 124 | "source": [ 125 | "log_variance = pred.mean[:, 1].reshape(-1)\n", 126 | "mean = pred.mean[:, 0].reshape(-1)" 127 | ] 128 | }, 129 | { 130 | "cell_type": "code", 131 | "execution_count": 9, 132 | "metadata": {}, 133 | "outputs": [], 134 | "source": [ 135 | "sll = pred.var[:, 1, 1].reshape(-1)\n", 136 | "smm = pred.var[:, 0, 0].reshape(-1)\n", 137 | "sml = pred.var[:, 0, 1].reshape(-1)" 138 | ] 139 | }, 140 | { 141 | "cell_type": "code", 142 | "execution_count": 13, 143 | "metadata": {}, 144 | "outputs": [ 145 | { 146 | "data": { 147 | "text/plain": [ 148 | "tensor([[-inf, -inf, -inf, ..., -inf, -inf, -inf],\n", 149 | " [-inf, -inf, -inf, ..., -inf, -inf, -inf],\n", 150 | " [-inf, -inf, -inf, ..., -inf, -inf, -inf],\n", 151 | " ...,\n", 152 | " [-inf, -inf, -inf, ..., -inf, -inf, -inf],\n", 153 | " [-inf, -inf, -inf, ..., -inf, -inf, -inf],\n", 154 | " [-inf, -inf, -inf, ..., -inf, -inf, -inf]], grad_fn=)" 155 | ] 156 | }, 157 | "execution_count": 13, 158 | "metadata": {}, 159 | "output_type": "execute_result" 160 | } 161 | ], 162 | "source": [ 163 | "from loss import GLLLoss\n", 164 | "loss = GLLLoss()\n", 165 | "loss(pred, train_y)" 166 | ] 167 | }, 168 | { 169 | "cell_type": "code", 170 | "execution_count": 11, 171 | "metadata": {}, 172 | "outputs": [], 173 | "source": [ 174 | "%matplotlib inline\n", 175 | "import matplotlib.pyplot as plt" 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "execution_count": 12, 181 | "metadata": {}, 182 | "outputs": [], 183 | "source": [ 184 | "import bayes_utils as bu\n", 185 | "\n", 186 | "x = torch.arange(-10, 10, 1/100)" 187 | ] 188 | }, 189 | { 190 | "cell_type": "code", 191 | "execution_count": 42, 192 | "metadata": {}, 193 | "outputs": [ 194 | { 195 | "data": { 196 | "text/plain": [ 197 | "[]" 198 | ] 199 | }, 200 | "execution_count": 42, 201 | "metadata": {}, 202 | "output_type": "execute_result" 203 | }, 204 | { 205 | "data": { 206 | "image/png": "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\n", 207 | "text/plain": [ 208 | "
" 209 | ] 210 | }, 211 | "metadata": { 212 | "needs_background": "light" 213 | }, 214 | "output_type": "display_data" 215 | } 216 | ], 217 | "source": [ 218 | "plt.plot(x.numpy(), bu.softrelu(x).numpy())\n", 219 | "plt.plot(x.numpy(), bu.standard_gaussian(x).numpy())\n", 220 | "plt.plot(x.numpy(), bu.gaussian_cdf(x).numpy())\n", 221 | "plt.plot(x.numpy(), (x * bu.gaussian_cdf(x)).numpy())" 222 | ] 223 | }, 224 | { 225 | "cell_type": "code", 226 | "execution_count": 39, 227 | "metadata": {}, 228 | "outputs": [ 229 | { 230 | "data": { 231 | "text/plain": [ 232 | "[]" 233 | ] 234 | }, 235 | "execution_count": 39, 236 | "metadata": {}, 237 | "output_type": "execute_result" 238 | }, 239 | { 240 | "data": { 241 | "image/png": "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\n", 242 | "text/plain": [ 243 | "
" 244 | ] 245 | }, 246 | "metadata": { 247 | "needs_background": "light" 248 | }, 249 | "output_type": "display_data" 250 | } 251 | ], 252 | "source": [ 253 | "plt.plot(x.numpy(), bu.standard_gaussian(x).numpy())" 254 | ] 255 | }, 256 | { 257 | "cell_type": "code", 258 | "execution_count": null, 259 | "metadata": {}, 260 | "outputs": [], 261 | "source": [] 262 | } 263 | ], 264 | "metadata": { 265 | "kernelspec": { 266 | "display_name": "Python 3", 267 | "language": "python", 268 | "name": "python3" 269 | }, 270 | "language_info": { 271 | "codemirror_mode": { 272 | "name": "ipython", 273 | "version": 3 274 | }, 275 | "file_extension": ".py", 276 | "mimetype": "text/x-python", 277 | "name": "python", 278 | "nbconvert_exporter": "python", 279 | "pygments_lexer": "ipython3", 280 | "version": "3.7.1" 281 | } 282 | }, 283 | "nbformat": 4, 284 | "nbformat_minor": 2 285 | } 286 | --------------------------------------------------------------------------------