| import numpy as np
|
| import torch
|
| import math
|
| import gpytorch
|
| from gpytorch.constraints import Positive
|
| from gpytorch.priors import NormalPrior
|
| from gpytorch.distributions import MultivariateNormal
|
| from onescience.utils.GP_TO.plot_latenth import plot_sep
|
| from .gpregression import GPR
|
| import gpytorch.kernels as kernels
|
| from .mollified_uniform import MollifiedUniformPrior
|
| from pandas import DataFrame
|
| import matplotlib.pyplot as plt
|
| from torch.nn.parameter import Parameter
|
| import torch.nn.functional as F
|
|
|
| def setlevels(X, qual_index = None, return_label = False):
|
| labels = []
|
| if qual_index == []:
|
| return X
|
| if qual_index is None:
|
| qual_index = list(range(X.shape[-1]))
|
|
|
|
|
| temp = np.copy(X)
|
| if type(X) == torch.Tensor:
|
| temp = X.clone()
|
| if temp.ndim > 1:
|
| for j in qual_index:
|
| l = np.sort(np.unique(temp[..., j])).tolist()
|
| labels.append(l)
|
|
|
| temp[..., j] = torch.tensor([*map(lambda m: l.index(m),temp[..., j])])
|
| else:
|
| l = torch.unique(temp, sorted = True)
|
| temp = torch.tensor([*map(lambda m: l.tolist().index(m), temp)])
|
|
|
|
|
| if temp.dtype == object:
|
| temp = temp.astype(float)
|
| if type(X) == np.ndarray:
|
| temp = torch.from_numpy(temp)
|
|
|
| if return_label:
|
| return temp, labels
|
| else:
|
| return temp
|
| else:
|
| if type(X) == np.ndarray:
|
| temp = torch.from_numpy(temp)
|
| if return_label:
|
| return temp, labels
|
| else:
|
| return temp
|
|
|
| class GPPLUS(GPR):
|
| """The latent Map GP regression model (LMGP) which extends GPs to handle categorical inputs.
|
|
|
| :note: Binary categorical variables should not be treated as qualitative inputs. There is no
|
| benefit from applying a latent variable treatment for such variables. Instead, treat them
|
| as numerical inputs.
|
|
|
| :param train_x: The training inputs (size N x d). Qualitative inputs needed to be encoded as
|
| integers 0,...,L-1 where L is the number of levels. For best performance, scale the
|
| numerical variables to the unit hypercube.
|
| """
|
| def __init__(
|
| self,
|
|
|
| train_x:torch.Tensor,
|
| train_y:torch.Tensor,
|
| collocation_x:torch.Tensor,
|
| qual_ind_lev = {},
|
| multiple_noise = False,
|
| lv_dim:int=2,
|
| quant_correlation_class:str='Rough_RBF',
|
| noise:float=5e-8,
|
| fix_noise:bool=True,
|
| lb_noise:float=1e-8,
|
| NN_layers:list = [],
|
| name_output:str='u',
|
| encoding_type = 'one-hot',
|
| uniform_encoding_columns = 2,
|
| lv_columns = [] ,
|
| basis='neural_network',
|
| NN_layers_base=[4,4],
|
| basis_function_size=None,
|
| device="cpu",
|
| dtype= torch.float32
|
| ) -> None:
|
|
|
| tkwargs = {}
|
| tkwargs['dtype'] = dtype
|
| tkwargs['device'] =device
|
|
|
| qual_index = list(qual_ind_lev.keys())
|
| all_index = set(range(train_x.shape[-1]))
|
| quant_index = list(all_index.difference(qual_index))
|
| num_levels_per_var = list(qual_ind_lev.values())
|
|
|
| lm_columns = list(set(qual_index).difference(lv_columns))
|
| if len(lm_columns) > 0:
|
| qual_kernel_columns = [*lv_columns, lm_columns]
|
| else:
|
| qual_kernel_columns = lv_columns
|
|
|
|
|
| if len(qual_index) > 0:
|
| train_x = setlevels(train_x, qual_index=qual_index)
|
|
|
| if multiple_noise:
|
| noise_indices = list(range(0,num_levels_per_var[0]))
|
| else:
|
| noise_indices = []
|
|
|
| if len(qual_index) == 1 and num_levels_per_var[0] < 2:
|
| temp = quant_index.copy()
|
| temp.append(qual_index[0])
|
| quant_index = temp.copy()
|
| qual_index = []
|
| lv_dim = 0
|
| elif len(qual_index) == 0:
|
| lv_dim = 0
|
|
|
| quant_correlation_class_name = quant_correlation_class
|
|
|
| if len(qual_index) == 0:
|
| lv_dim = 0
|
|
|
| if quant_correlation_class_name == 'Rough_RBF':
|
| quant_correlation_class = 'RBFKernel'
|
|
|
| if quant_correlation_class_name == 'Matern32Kernel':
|
| quant_correlation_class = 'Matern32Kernel'
|
|
|
| if quant_correlation_class_name == 'Matern52Kernel':
|
| quant_correlation_class = 'Matern52Kernel'
|
|
|
| if quant_correlation_class_name == 'Matern12Kernel':
|
| quant_correlation_class = 'Matern12Kernel'
|
|
|
| if len(qual_index) > 0:
|
|
|
| qual_kernels = []
|
| for i in range(len(qual_kernel_columns)):
|
| qual_kernels.append(kernels.RBFKernel(
|
| active_dims=torch.arange(lv_dim) + lv_dim * i) )
|
| qual_kernels[i].initialize(**{'lengthscale':1.0})
|
| qual_kernels[i].raw_lengthscale.requires_grad_(False)
|
|
|
| if len(quant_index) == 0:
|
| correlation_kernel = qual_kernels[0]
|
| for i in range(1, len(qual_kernels)):
|
| correlation_kernel *= qual_kernels[i]
|
| else:
|
| try:
|
| quant_correlation_class = getattr(kernels,quant_correlation_class)
|
| except:
|
| raise RuntimeError(
|
| "%s not an allowed kernel" % quant_correlation_class
|
| )
|
|
|
| if quant_correlation_class_name == 'RBFKernel':
|
| quant_kernel = quant_correlation_class(
|
| ard_num_dims=len(quant_index),
|
| active_dims=len(qual_kernel_columns) * lv_dim+torch.arange(len(quant_index)),
|
| lengthscale_constraint= Positive(transform= torch.exp,inv_transform= torch.log)
|
| )
|
| elif quant_correlation_class_name == 'Rough_RBF':
|
| quant_kernel = quant_correlation_class(
|
| ard_num_dims=len(quant_index),
|
| active_dims=len(qual_kernel_columns)*lv_dim+torch.arange(len(quant_index)),
|
| lengthscale_constraint= Positive(transform = lambda x: 2.0**(-0.5) * torch.pow(10,-x/2),inv_transform= lambda x: -2.0*torch.log10(x/2.0))
|
| )
|
|
|
|
|
| elif quant_correlation_class_name == 'Matern12Kernel':
|
| quant_kernel = quant_correlation_class(
|
| ard_num_dims=len(quant_index),
|
| active_dims=len(qual_kernel_columns)*lv_dim+torch.arange(len(quant_index)),
|
| lengthscale_constraint= Positive(transform= lambda x: 2.0**(-0.5) * torch.pow(10,-x/2),inv_transform= lambda x: -2.0*torch.log10(x/2.0))
|
| )
|
|
|
| elif quant_correlation_class_name == 'Matern32Kernel':
|
| quant_kernel = quant_correlation_class(
|
| ard_num_dims=len(quant_index),
|
| active_dims=len(qual_kernel_columns)*lv_dim+torch.arange(len(quant_index)),
|
|
|
| lengthscale_constraint= Positive(transform= lambda x: 2.0**(-0.5) * torch.pow(10,-x/2),inv_transform= lambda x: -2.0*torch.log10(x/2.0))
|
| )
|
|
|
| elif quant_correlation_class_name == 'Matern52Kernel':
|
| quant_kernel = quant_correlation_class(
|
| ard_num_dims=len(quant_index),
|
| active_dims=len(qual_kernel_columns)*lv_dim+torch.arange(len(quant_index)),
|
|
|
| lengthscale_constraint= Positive(transform= lambda x: 2.0**(-0.5) * torch.pow(10,-x/2),inv_transform= lambda x: -2.0*torch.log10(x/2.0))
|
| )
|
|
|
| if quant_correlation_class_name == 'RBFKernel':
|
|
|
| quant_kernel.register_prior(
|
| 'lengthscale_prior', MollifiedUniformPrior(math.log(0.1),math.log(10)),'raw_lengthscale'
|
| )
|
|
|
| elif quant_correlation_class_name == 'Rough_RBF':
|
| quant_kernel.register_prior(
|
| 'lengthscale_prior',NormalPrior(-3.0,3.0),'raw_lengthscale'
|
| )
|
|
|
| elif quant_correlation_class_name == 'Matern12Kernel':
|
| quant_kernel.register_prior(
|
|
|
| 'lengthscale_prior',NormalPrior(-3.0,3.0),'raw_lengthscale'
|
| )
|
|
|
| elif quant_correlation_class_name == 'Matern32Kernel':
|
| quant_kernel.register_prior(
|
|
|
| 'lengthscale_prior',NormalPrior(-3.0,3.0),'raw_lengthscale'
|
| )
|
|
|
| elif quant_correlation_class_name == 'Matern52Kernel':
|
| quant_kernel.register_prior(
|
|
|
| 'lengthscale_prior',NormalPrior(-3.0,3.0),'raw_lengthscale'
|
| )
|
|
|
| if len(qual_index) > 0:
|
| temp = qual_kernels[0]
|
| for i in range(1, len(qual_kernels)):
|
| temp *= qual_kernels[i]
|
| correlation_kernel = temp*quant_kernel
|
| else:
|
| correlation_kernel = quant_kernel
|
|
|
| super(GPPLUS,self).__init__(
|
| train_x=train_x,train_y=train_y,noise_indices=noise_indices,
|
| correlation_kernel=correlation_kernel,
|
| noise=noise,fix_noise=fix_noise,lb_noise=lb_noise
|
| )
|
|
|
|
|
| self.register_buffer('quant_index',torch.tensor(quant_index))
|
| self.register_buffer('qual_index',torch.tensor(qual_index))
|
|
|
|
|
| self.num_levels_per_var = num_levels_per_var
|
| self.lv_dim = lv_dim
|
| self.uniform_encoding_columns = uniform_encoding_columns
|
| self.encoding_type = encoding_type
|
| self.perm =[]
|
| self.zeta = []
|
| self.perm_dict = []
|
| self.A_matrix = []
|
| self.collocation_x = collocation_x
|
| self.alpha = 1.0
|
| self.beta = 20.0
|
| self.covar_inv = None
|
| self.omega = 3
|
| self.name_output = name_output
|
| self.chol_decomp = None
|
| self.g_uvp = None
|
| self.k_xX = None
|
|
|
| if len(qual_kernel_columns) > 0:
|
| for i in range(len(qual_kernel_columns)):
|
| if type(qual_kernel_columns[i]) == int:
|
| num = self.num_levels_per_var[qual_index.index(qual_kernel_columns[i])]
|
| cat = [num]
|
| else:
|
| cat = [self.num_levels_per_var[qual_index.index(k)] for k in qual_kernel_columns[i]]
|
| num = sum(cat)
|
|
|
| zeta, perm, perm_dict = self.zeta_matrix(num_levels=cat, lv_dim = self.lv_dim)
|
| self.zeta.append(zeta.to(**tkwargs))
|
| self.perm.append(perm.to(**tkwargs))
|
| self.perm_dict.append(perm_dict)
|
|
|
| model_temp = FFNN(self, input_size= num, num_classes=lv_dim,
|
| layers = NN_layers, name = str(qual_kernel_columns[i])).to(**tkwargs)
|
| self.A_matrix.append(model_temp.to(**tkwargs))
|
|
|
| self.basis=basis
|
| i=0
|
| if self.basis=='single':
|
| self.mean_module = gpytorch.means.ConstantMean(prior=NormalPrior(0.,1.))
|
| self.mean_module.constant.data = torch.tensor([0.0])
|
| self.mean_module.constant.requires_grad = False
|
| elif self.basis=='multiple_constant':
|
| if basis_function_size is None:
|
| basis_function_size=train_x.shape[1]-1
|
| self.num_sources=int(torch.max(train_x[:,-1]))
|
| for i in range(self.num_sources +1):
|
| if i==0:
|
| setattr(self,'mean_module_'+str(i), gpytorch.means.ZeroMean())
|
|
|
| else:
|
|
|
| setattr(self,'mean_module_'+str(i), gpytorch.means.ConstantMean(prior=NormalPrior(0.,.3)))
|
|
|
| elif self.basis=='multiple_polynomial':
|
| if basis_function_size is None:
|
| basis_function_size=train_x.shape[1]-1
|
| self.num_sources=int(torch.max(train_x[:,-1]))
|
| for i in range(self.num_sources +1):
|
| if i==0:
|
| setattr(self,'mean_module_'+str(i), gpytorch.means.ZeroMean())
|
| else:
|
| setattr(self,'mean_module_'+str(i), LinearMean_with_prior(input_size=basis_function_size, batch_shape=torch.Size([]), bias=True))
|
| elif self.basis=='neural_network':
|
|
|
| if len(qual_index) == 0:
|
| setattr(self,'mean_module_NN_All', FFNN_for_Mean(self, input_size= train_x.shape[1], num_classes=4,layers =NN_layers_base, name = str('mean_module_'+str(i)+'_')))
|
| else:
|
| setattr(self,'mean_module_NN_All', FFNN_for_Mean(self, input_size= train_x.shape[1]-len(qual_index)+2, num_classes=1, layers =NN_layers_base, name = str('mean_module_'+str(i)+'_')))
|
| elif self.basis=='M3':
|
| setattr(self,'mean_module_NN_All', NetworkM4(input_dim = train_x.shape[1], output_dim=3, layers = NN_layers_base))
|
|
|
|
|
|
|
| self.covar_module.base_kernel.raw_lengthscale.data = torch.tensor([self.omega, self.omega], dtype=torch.float32)
|
| self.covar_module.base_kernel.raw_lengthscale.requires_grad = False
|
|
|
| self.covar_module.raw_outputscale.data = torch.tensor(0.541)
|
| self.covar_module.raw_outputscale.requires_grad = False
|
|
|
| def forward(self,x:torch.Tensor) -> MultivariateNormal:
|
| x_forward_raw=x.clone()
|
| nd_flag = 0
|
| if x.dim() > 2:
|
| xsize = x.shape
|
| x = x.reshape(-1, x.shape[-1])
|
| nd_flag = 1
|
|
|
| if len(self.qual_kernel_columns) > 0:
|
| embeddings = []
|
| for i in range(len(self.qual_kernel_columns)):
|
| temp= self.transform_categorical(x=x[:,self.qual_kernel_columns[i]].clone().type(torch.int64),
|
| perm_dict = self.perm_dict[i], zeta = self.zeta[i])
|
| embeddings.append(self.A_matrix[i](temp))
|
|
|
| x= torch.cat([embeddings[0],x[...,self.quant_index]],dim=-1)
|
|
|
| if nd_flag == 1:
|
| x = x.reshape(*xsize[:-1], -1)
|
|
|
|
|
| def multi_mean(x,x_forward_raw):
|
| mean_x=torch.zeros_like(x[:,-1])
|
| if self.basis=='single':
|
| mean_x=self.mean_module(x)
|
| elif self.basis=='multiple_constant':
|
| for i in range(len(mean_x)):
|
| qq=int(x_forward_raw[i,-1])
|
| mean_x[i]=getattr(self,'mean_module_'+str(qq))(torch.tensor(x[i,-1].clone()).reshape(-1,1))
|
| elif self.basis=='multiple_polynomial':
|
| for i in range(len(mean_x)):
|
| qq=int(x_forward_raw[i,-1])
|
| mean_x[i]=getattr(self,'mean_module_'+str(qq))(torch.cat((torch.tensor((x[i,-1].clone().double().reshape(-1,1))**2),torch.tensor(x[i,-1].clone().double()).reshape(-1,1)),1))
|
|
|
| elif self.basis=='neural_network':
|
| mean_x = getattr(self,'mean_module_NN_All')(x.clone())
|
|
|
| elif self.basis=='M3':
|
| if hasattr(self, 'name_output'):
|
| mean_x = getattr(self,'mean_module_NN_All')(x.clone())
|
| else:
|
| mean_x = getattr(self,'mean_module_NN_All')(x.clone()).reshape(-1)
|
|
|
| return mean_x
|
|
|
| if self.name_output == 'u':
|
| mean_x = multi_mean(x,x_forward_raw)[:,0].reshape(-1)
|
| if self.name_output == 'v':
|
| mean_x = multi_mean(x,x_forward_raw)[:,1].reshape(-1)
|
| if self.name_output == 'p':
|
| mean_x = multi_mean(x,x_forward_raw)[:,2].reshape(-1)
|
| if self.name_output == 'ro':
|
| mean_x = multi_mean(x,x_forward_raw)[:,3].reshape(-1)
|
| covar_x = self.covar_module(x)
|
|
|
| return MultivariateNormal(mean_x,covar_x)
|
|
|
| def predict(self, Xtest,return_std=True, include_noise = True):
|
| with torch.no_grad():
|
| return super().predict(Xtest, return_std = return_std, include_noise= include_noise)
|
|
|
| def predict_with_grad(self, Xtest,return_std=True, include_noise = True):
|
| return super().predict(Xtest, return_std = return_std, include_noise= include_noise)
|
|
|
| def noise_value(self):
|
| noise = self.likelihood.noise_covar.noise.detach() * self.y_std**2
|
| return noise
|
|
|
| def visualize_latent(self, suptitle = None):
|
| if len(self.qual_kernel_columns) > 0:
|
| for i in range(len(self.qual_kernel_columns)):
|
| zeta = self.zeta[i]
|
| A = self.A_matrix[i]
|
|
|
| positions = A(zeta)
|
| level = torch.max(self.perm[i], axis = 0)[0].tolist()
|
| perm = self.perm[i]
|
| plot_sep(positions = positions, levels = level, perm = perm, constraints_flag=True, )
|
|
|
|
|
| def visualize_latent_position(self,lv_columns=None):
|
| if len(self.qual_kernel_columns) > 0:
|
| for i in range(len(self.qual_kernel_columns)):
|
| zeta = self.zeta[i]
|
| A = self.A_matrix[i]
|
| positions = A(zeta)
|
| if self.qual_kernel_columns[i]==lv_columns[0]:
|
| return positions
|
|
|
|
|
| def visualize_latent_position_simple(self, suptitle = None):
|
| if len(self.qual_kernel_columns) > 0:
|
| for i in range(len(self.qual_kernel_columns)):
|
| zeta = self.zeta[i]
|
| A = self.A_matrix[i]
|
| positions = A(zeta)
|
| return positions
|
|
|
|
|
| @classmethod
|
| def show(cls):
|
| plt.show()
|
|
|
| def get_params(self, name = None):
|
| params = {}
|
| print('###################Parameters###########################')
|
| for n, value in self.named_parameters():
|
| params[n] = value
|
| if name is None:
|
| print(params)
|
| return params
|
| else:
|
| if name == 'Mean':
|
| key = 'mean_module.constant'
|
| elif name == 'Sigma':
|
| key = 'covar_module.raw_outputscale'
|
| elif name == 'Noise':
|
| key = 'likelihood.noise_covar.raw_noise'
|
| elif name == 'Omega':
|
| for n in params.keys():
|
| if 'raw_lengthscale' in n and params[n].numel() > 1:
|
| key = n
|
| print(params[key])
|
| return params[key]
|
|
|
| def get_latent_space(self):
|
| if len(self.qual_index) > 0:
|
| zeta = torch.tensor(self.zeta)
|
| positions = self.nn_model(zeta)
|
| return positions.detach()
|
| else:
|
| print('No categorical Variable, No latent positions')
|
| return None
|
|
|
| def zeta_matrix(self,
|
| num_levels:int,
|
| lv_dim:int,
|
| batch_shape=torch.Size()
|
| ) -> None:
|
|
|
| if any([i == 1 for i in num_levels]):
|
| raise ValueError('Categorical variable has only one level!')
|
|
|
| if lv_dim == 1:
|
| raise RuntimeWarning('1D latent variables are difficult to optimize!')
|
|
|
| for level in num_levels:
|
| if lv_dim > level - 0:
|
| lv_dim = min(lv_dim, level-1)
|
| raise RuntimeWarning(
|
| 'The LV dimension can atmost be num_levels-1. '
|
| 'Setting it to %s in place of %s' %(level-1,lv_dim)
|
| )
|
|
|
| from itertools import product
|
| levels = []
|
| for l in num_levels:
|
| levels.append(torch.arange(l))
|
|
|
| perm = list(product(*levels))
|
| perm = torch.tensor(perm, dtype=torch.int64)
|
|
|
|
|
| perm_dic = {}
|
| for i, row in enumerate(perm):
|
| temp = str(row.tolist())
|
| if temp not in perm_dic.keys():
|
| perm_dic[temp] = i
|
|
|
|
|
| for ii in range(perm.shape[-1]):
|
| if perm[...,ii].min() != 0:
|
| perm[...,ii] -= perm[...,ii].min()
|
|
|
| perm_one_hot = []
|
| for i in range(perm.size()[1]):
|
| perm_one_hot.append( torch.nn.functional.one_hot(perm[:,i]) )
|
|
|
| perm_one_hot = torch.concat(perm_one_hot, axis=1)
|
|
|
| return perm_one_hot, perm, perm_dic
|
|
|
|
|
| def transform_categorical(self, x:torch.Tensor,perm_dict = [], zeta = []) -> None:
|
| if x.dim() == 1:
|
| x = x.reshape(-1,1)
|
|
|
| if self.training == False:
|
| x = setlevels(x.cpu())
|
| if self.encoding_type == 'one-hot':
|
| index = [perm_dict[str(row.tolist())] for row in x]
|
|
|
| if x.dim() == 1:
|
| x = x.reshape(len(x),)
|
|
|
| return zeta[index,:]
|
|
|
| elif self.encoding_type == 'uniform':
|
|
|
| temp2=np.random.uniform(0,1,(len(self.perm), self.uniform_encoding_columns))
|
| dict={}
|
| dict2={}
|
|
|
| for i in range(0,self.perm.shape[0]):
|
| dict[tuple((self.perm[i,:]).numpy())]=temp2[i,:]
|
|
|
| for i in range(0,x.shape[0]):
|
| dict2[i]=dict[tuple((x[i]).numpy())]
|
|
|
| x_one_hot= torch.from_numpy(np.array(list(dict2.values())))
|
| else:
|
| raise ValueError ('Invalid type')
|
|
|
|
|
| return x_one_hot
|
|
|
|
|
|
|
|
|
| class LinearMean_with_prior(gpytorch.means.Mean):
|
| def __init__(self, input_size, batch_shape=torch.Size(), bias=True):
|
| super().__init__()
|
| self.register_parameter(name="weights", parameter=torch.nn.Parameter(torch.randn(*batch_shape, input_size, 1)))
|
| self.register_prior(name = 'weights_prior', prior=gpytorch.priors.NormalPrior(0.,1.), param_or_closure='weights')
|
|
|
| if bias:
|
| self.register_parameter(name="bias", parameter=torch.nn.Parameter(torch.randn(*batch_shape, 1)))
|
| self.register_prior(name = 'bias_prior', prior=gpytorch.priors.NormalPrior(0.,1.), param_or_closure='bias')
|
|
|
| else:
|
| self.bias = None
|
|
|
| def forward(self, x):
|
| res = x.matmul(self.weights).squeeze(-1)
|
| if self.bias is not None:
|
| res = res + self.bias
|
| return res
|
|
|
|
|
|
|
| class FFNN(torch.nn.Module):
|
| def __init__(self, lmgp, input_size, num_classes, layers,name):
|
| super(FFNN, self).__init__()
|
|
|
|
|
|
|
| self.hidden_num = len(layers)
|
| if self.hidden_num > 0:
|
| self.fci = torch.nn.Linear(input_size, layers[0], bias=False)
|
| lmgp.register_parameter('fci', self.fci.weight)
|
| lmgp.register_prior(name = 'latent_prior_fci', prior=gpytorch.priors.NormalPrior(0.,3.), param_or_closure='fci')
|
|
|
| for i in range(1,self.hidden_num):
|
|
|
| setattr(self, 'h' + str(i), torch.nn.Linear(layers[i-1], layers[i], bias=False))
|
| lmgp.register_parameter('h'+str(i), getattr(self, 'h' + str(i)).weight )
|
| lmgp.register_prior(name = 'latent_prior'+str(i), prior=gpytorch.priors.NormalPrior(0.,3.), param_or_closure='h'+str(i))
|
|
|
| self.fce = torch.nn.Linear(layers[-1], num_classes, bias= False)
|
| lmgp.register_parameter('fce', self.fce.weight)
|
| lmgp.register_prior(name = 'latent_prior_fce', prior=gpytorch.priors.NormalPrior(0.,3.), param_or_closure='fce')
|
| else:
|
| self.fci = Linear_MAP(input_size, num_classes, bias = False)
|
| lmgp.register_parameter(name, self.fci.weight)
|
| lmgp.register_prior(name = 'latent_prior_'+name, prior=gpytorch.priors.NormalPrior(0,3) , param_or_closure=name)
|
|
|
|
|
|
|
| def forward(self, x, transform = lambda x: x):
|
| """
|
| x here is the mnist images and we run it through fc1, fc2 that we created above.
|
| we also add a ReLU activation function in between and for that (since it has no parameters)
|
| I recommend using nn.functional (F)
|
| """
|
| if self.hidden_num > 0:
|
| x = torch.tanh(self.fci(x))
|
| for i in range(1,self.hidden_num):
|
| x = torch.tanh( getattr(self, 'h' + str(i))(x) )
|
|
|
| x = self.fce(x)
|
| else:
|
| x = self.fci(x, transform)
|
| return x
|
|
|
| class FFNN_for_Mean(gpytorch.Module):
|
| def __init__(self, lmgp, input_size, num_classes, layers, name):
|
| super(FFNN_for_Mean, self).__init__()
|
| self.dropout = torch.nn.Dropout(0.0)
|
|
|
|
|
|
|
| self.hidden_num = len(layers)
|
| if self.hidden_num > 0:
|
| self.fci = Linear_new(input_size, layers[0], bias=True, name='fci')
|
| for i in range(1,self.hidden_num):
|
| setattr(self, 'h' + str(i), Linear_new(layers[i-1], layers[i], bias=True,name='h' + str(i)))
|
|
|
| self.fce = Linear_new(layers[-1], num_classes, bias=True,name='fce')
|
| else:
|
| self.fci = Linear_new(input_size, num_classes, bias=True,name='fci')
|
|
|
| def forward(self, x, transform = lambda x: x):
|
| """
|
| x here is the mnist images and we run it through fc1, fc2 that we created above.
|
| we also add a ReLU activation function in between and for that (since it has no parameters)
|
| I recommend using nn.functional (F)
|
| """
|
| if self.hidden_num > 0:
|
|
|
| x = torch.tanh(self.fci(x))
|
|
|
|
|
| for i in range(1,self.hidden_num):
|
| x = torch.tanh( getattr(self, 'h' + str(i))(x) )
|
|
|
| x = self.fce(x)
|
|
|
| else:
|
| x = self.fci(x)
|
|
|
|
|
| return x
|
|
|
|
|
|
|
| class NetworkM4(torch.nn.Module):
|
| def __init__(self, input_dim = 2, output_dim = 1, layers = [40, 40, 40, 40], activation = 'tanh', collocation_x = []) -> None:
|
| super(NetworkM4, self).__init__()
|
| activation_list = {'tanh':torch.nn.Tanh(), 'Silu':torch.nn.SiLU(), 'Sigmoid':torch.nn.Sigmoid()}
|
| activation = activation_list[activation]
|
| self.dim = layers[0]
|
|
|
| self.U = torch.nn.Linear(input_dim, self.dim).to('cuda')
|
| self.V = torch.nn.Linear(input_dim, self.dim).to('cuda')
|
| self.H1 = torch.nn.Linear(input_dim, self.dim).to('cuda')
|
| self.last= torch.nn.Linear(self.dim, output_dim).to('cuda')
|
|
|
| self.collocation_x = collocation_x
|
| self.alpha = 1.0
|
| self.beta = 1.0
|
|
|
| l = torch.nn.ModuleList()
|
| for _ in range(len(layers)):
|
| l.append(torch.nn.Linear(self.dim, self.dim))
|
| l.append(activation)
|
| self.layers = torch.nn.Sequential(*l).to('cuda')
|
|
|
| def forward(self, input):
|
| U = torch.nn.Tanh()(self.U(input))
|
| V = torch.nn.Tanh()(self.V(input))
|
| H = torch.nn.Tanh()(self.H1(input))
|
|
|
| for layer in self.layers:
|
| Z = layer(H)
|
| H = (1-Z)*U + Z*V
|
|
|
| out = self.last(H)
|
| return out
|
|
|
| class Linear_new(gpytorch.means.Mean):
|
| r"""Applies a linear transformation to the incoming data: :math:`y = xA^T + b`
|
|
|
| This module supports :ref:`TensorFloat32<tf32_on_ampere>`.
|
|
|
| On certain ROCm devices, when using float16 inputs this module will use :ref:`different precision<fp16_on_mi200>` for backward.
|
|
|
| Args:
|
| in_features: size of each input sample
|
| out_features: size of each output sample
|
| bias: If set to ``False``, the layer will not learn an additive bias.
|
| Default: ``True``
|
|
|
| Shape:
|
| - Input: :math:`(*, H_{in})` where :math:`*` means any number of
|
| dimensions including none and :math:`H_{in} = \text{in\_features}`.
|
| - Output: :math:`(*, H_{out})` where all but the last dimension
|
| are the same shape as the input and :math:`H_{out} = \text{out\_features}`.
|
|
|
| Attributes:
|
| weight: the learnable weights of the module of shape
|
| :math:`(\text{out\_features}, \text{in\_features})`. The values are
|
| initialized from :math:`\mathcal{U}(-\sqrt{k}, \sqrt{k})`, where
|
| :math:`k = \frac{1}{\text{in\_features}}`
|
| bias: the learnable bias of the module of shape :math:`(\text{out\_features})`.
|
| If :attr:`bias` is ``True``, the values are initialized from
|
| :math:`\mathcal{U}(-\sqrt{k}, \sqrt{k})` where
|
| :math:`k = \frac{1}{\text{in\_features}}`
|
|
|
| Examples::
|
|
|
| >>> m = nn.Linear(20, 30)
|
| >>> input = torch.randn(128, 20)
|
| >>> output = m(input)
|
| >>> print(output.size())
|
| torch.Size([128, 30])
|
| """
|
| __constants__ = ['in_features', 'out_features']
|
| in_features: int
|
| out_features: int
|
| weight: torch.Tensor
|
|
|
| def __init__(self, in_features: int, out_features: int, bias: bool = True, name=None,
|
| device=None, dtype=None) -> None:
|
|
|
|
|
| super(Linear_new, self).__init__()
|
| self.in_features = in_features
|
| self.out_features = out_features
|
|
|
| self.name=str(name)
|
| self.register_parameter(name=str(self.name)+'weight', parameter= Parameter(torch.empty((out_features, in_features))))
|
| self.register_prior(name =str(self.name)+ 'prior_m_weight_fci', prior=gpytorch.priors.NormalPrior(0.,1.), param_or_closure=str(self.name)+'weight')
|
|
|
| if bias:
|
| self.register_parameter(name=str(self.name)+'bias', parameter=Parameter(torch.empty(out_features)))
|
| self.register_prior(name= str(self.name)+'prior_m_bias_fci', prior=gpytorch.priors.NormalPrior(0.,1.), param_or_closure=str(self.name)+'bias')
|
| else:
|
| self.register_parameter('bias', None)
|
| self.reset_parameters()
|
|
|
| def reset_parameters(self) -> None:
|
|
|
|
|
|
|
| torch.nn.init.kaiming_uniform_( getattr(self,str(self.name)+'weight'), a=math.sqrt(5))
|
| if getattr(self,str(self.name)+'bias') is not None:
|
| fan_in, _ = torch.nn.init._calculate_fan_in_and_fan_out(getattr(self,str(self.name)+'weight'))
|
| bound = 1 / math.sqrt(fan_in) if fan_in > 0 else 0
|
| torch.nn.init.uniform_(getattr(self,str(self.name)+'bias'), -bound, bound)
|
|
|
| def forward(self, input) -> torch.Tensor:
|
|
|
|
|
|
|
|
|
| return F.linear(input, getattr(self,str(self.name)+'weight'), getattr(self,str(self.name)+'bias'))
|
|
|
| def extra_repr(self) -> str:
|
| return 'in_features={}, out_features={}, bias={}'.format(
|
| self.in_features, self.out_features, self.bias is not None
|
| )
|
|
|
| class Linear_MAP(torch.nn.Linear):
|
| def __init__(self, in_features: int, out_features: int, bias: bool = True, device=None, dtype=None) -> None:
|
| super().__init__(in_features, out_features, bias, device, dtype)
|
|
|
| def forward(self, input, transform = lambda x: x):
|
| return F.linear(input,transform(self.weight), self.bias)
|
|
|
|
|
|
|
|
|