class inference(object): def __init__(self,step,burn_in,dim,obs,sigma,true_permeability,true_pressure,obs_position,scale,device): self.dim = dim self.burn_in = burn_in self.step = step self.obs = obs self.sigma = sigma self.true_permeability = true_permeability self.true_pressure = true_pressure self.pos = obs_position self.plot_interval = 1000 self.num_obs = 64 self.prediction = Prediction(scale,device) def pCN(self,old_params,beta,dim): ''' Here the prior distribution is standart Normal ''' new_params = np.sqrt(1-beta*beta)*old_params+beta*np.random.randn(dim,) return new_params def fx(self,model,exp,zc,zf): ''' compute the permeability field X using MDGM, and compute f(X) using forward model ''' input = self.prediction.permeability(exp,model,zc,zf=zf) like , pre = self.prediction.forward(input) f_x = np.reshape(like,(1,-1)) return f_x,input,pre def Comp_log_likelihood(self,obs,sigma,exp,model,zc,zf=None): ''' compute likelihood function for inference ''' f_x,input,pre = self.fx(model,exp,zc,zf) e=obs-f_x log_likelihood = -0.5 * np.sum( np.power(e/sigma,2.0)) print('log_like:',log_likelihood) return f_x,input,pre, log_likelihood def pCN_MH(self,init_c,init_state_f,beta,exp,noise,output_dir): ''' MH algorithm with MDGM, two proposal distributions for latent zc and zf respectively, where zc can capture global feature, zf is latent variable for parameter local adaption. proposal for zc with small step size(0.01) proposal for zf with big step size(first 50% state using 0.08, rest with 0.04) ''' coarse_beta = 0.01 model = self.prediction.model(exp) old_params_c = init_c dim_c=old_params_c.shape[0] accept_num = 0 dim = dim_c+self.dim samples = np.zeros([dim,self.step]) fx_obs = np.zeros([self.num_obs,self.step]) log_likelihood = np.zeros([1,self.step]) old_params_f = init_state_f old_fx,old_input,old_pre,old_log_l= self.Comp_log_likelihood(self.obs,self.sigma,exp,model,old_params_c,zf = old_params_f) old_params = np.concatenate((old_params_c,old_params_f),axis=0) samples[:,0] = old_params.reshape([dim,]) fx_obs[:,0] = old_fx log_likelihood[:,0] = old_log_l self.plot_para_field(0,old_input,old_pre,self.true_permeability, self.true_pressure,beta,'pCN',exp,noise,output_dir) for i in tqdm(range(1,self.step)): if i > 0.5*self.step: beta = 0.04 new_params_c = self.pCN(old_params_c,coarse_beta,dim_c) new_params_f = self.pCN(old_params_f,beta,self.dim) new_fx,new_input,new_pre,new_log_l= self.Comp_log_likelihood(self.obs,self.sigma,exp,model,new_params_c,zf = new_params_f) new_params = np.concatenate((new_params_c,new_params_f),axis=0) ratio = np.exp(new_log_l - old_log_l) alpha = min(1,ratio) np.random.seed(i) z = np.random.rand() if z<= alpha: print('-----------------------------------------------------------------') log_likelihood[:,i] = new_log_l fx_obs[:,i] = new_fx old_fx= new_fx samples[:,i] = new_params old_input = new_input old_pre = new_pre old_params = new_params old_params_c = new_params_c old_params_f = new_params_f old_log_l = new_log_l accept_num = accept_num +1 elif z>alpha: samples[:,i] = old_params fx_obs[:,i] = old_fx log_likelihood[:,i] = old_log_l if (i+1)%self.plot_interval == 0: self.plot_para_field(i,old_input,old_pre,self.true_permeability, self.true_pressure,beta,'pCN',exp,noise,output_dir) post_samples = samples[:,self.burn_in:] accept_ratio = (accept_num/self.step) print('accept_ratio:',accept_ratio) accept = [accept_ratio,accept_num] return samples, post_samples,fx_obs,accept,log_likelihood def plot_para_field(self,i,input,pre_pressure, true_permeability, true_pressure,beta,type,exp,noise,output_dir): ''' Plot Markov chain state(log permeability) ''' samples = [np.log(true_permeability),input.data.cpu().numpy(), true_pressure.reshape(64,64),pre_pressure] fig, _ = plt.subplots(2,2, figsize=(6,6)) vmin1 = [np.amin(samples[0]), np.amin(samples[0]),np.amin(samples[2]), np.amin(samples[2])] vmax1 = [np.amax(samples[0]), np.amax(samples[0]),np.amax(samples[2]), np.amax(samples[2])] for j, ax in enumerate(fig.axes): ax.set_aspect('equal') ax.set_axis_off() cax = ax.imshow(samples[j], cmap='jet',vmin=vmin1[j],vmax=vmax1[j]) cbar = plt.colorbar(cax, ax=ax, fraction=0.046, pad=0.04, format=ticker.ScalarFormatter(useMathText=True)) plt.savefig(output_dir+f'/{type}_step_size{beta}_state_{i+1}.pdf') plt.close()
class inference(object): def __init__(self,step,burn_in,dim,obs,sigma,true_permeability,true_pressure,obs_position,scale,device): self.dim = dim self.burn_in = burn_in self.step = step self.obs = obs self.sigma = sigma self.true_permeability = true_permeability self.true_pressure = true_pressure self.pos = obs_position self.Prior_type = 'Standard Normal' self.plot_interval = 1000 self.num_obs = 64 self.prediction = Prediction(scale,device) def pCN(self,old_params,beta): ''' Here the prior distribution is standart Normal ''' new_params = np.sqrt(1-beta*beta)*old_params+beta*np.random.randn(self.dim,) return new_params def fx(self,model,exp,z): ''' compute the permeability field X using MDGM, and compute f(X) using forward model ''' input = self.prediction.permeability(exp,model,z) like , pre = self.prediction.forward(input) fx = np.reshape(like,(1,-1)) return fx def Comp_log_likelihood(self,z,obs,sigma,exp,model): ''' compute likelihood function for inference ''' fx = self.fx(model,exp,z) e=obs-fx log_likelihood = -0.5 * np.sum( np.power(e/sigma,2.0)) print('log_like:',log_likelihood) return fx, log_likelihood def pCN_MH(self,init_state,beta,exp,noise,output_dir): ''' MH algorithm with DGM on the first scale(the coarsest scale) proposal for latent variable z1 with big step size to explore the whole space (first 50% state using 0.08, rest with 0.04) ''' model = self.prediction.model(exp) accept_num = 0 old_params = init_state samples = np.zeros([self.dim,self.step]) log_likelihood = np.zeros([1,self.step]) fx_obs = np.zeros([self.num_obs,self.step]) old_fx ,old_log_l= self.Comp_log_likelihood(old_params,self.obs,self.sigma,exp,model) fx_obs[:,0] = old_fx log_likelihood[:,0] = old_log_l samples [:,0] = old_params.reshape([self.dim,]) self.plot_para_field(0,old_params,self.true_permeability, self.true_pressure,beta,'pCN',exp,model,noise,output_dir) for i in tqdm(range(1,self.step)): if i > 0.5*self.step: beta = 0.04 new_params = self.pCN(old_params,beta) new_fx ,new_log_l = self.Comp_log_likelihood(new_params,self.obs,self.sigma,exp,model) ratio = np.exp(new_log_l - old_log_l) alpha = min(1,ratio) np.random.seed(i) z = np.random.rand() if z<= alpha: print('-----------------------------------------------------------------') old_params = new_params.reshape([self.dim,]) fx_obs[:,i] = new_fx log_likelihood[:,i] = new_log_l samples[:,i] = new_params.reshape([self.dim,]) old_log_l = new_log_l old_fx = new_fx accept_num = accept_num +1 elif z>alpha: old_params = old_params samples[:,i] = old_params.reshape([self.dim,]) fx_obs[:,i] = old_fx log_likelihood[:,i] = old_log_l if (i+1)%self.plot_interval == 0: self.plot_para_field(i,old_params,self.true_permeability, self.true_pressure,beta,'pCN',exp,model,noise,output_dir) post_samples = samples[:,self.burn_in:] accept_ratio = accept_num/self.step print('accept_ratio:',accept_ratio) accept = [accept_ratio,accept_num] return samples, post_samples,fx_obs,accept,log_likelihood def plot_para_field(self,i,params, true_permeability, true_pressure,beta,type,exp,model,noise,output_dir): ''' Plot Markov chain state(log permeability) ''' pre_permeability = self.prediction.permeability(exp,model,params) _, pre_pressure = self.prediction.forward(pre_permeability) if exp=='inversion_16': pre_permeability = pre_permeability.data.cpu().numpy().reshape(16,16) if exp=='inversion_64': pre_permeability = pre_permeability.data.cpu().numpy().reshape(64,64) samples = [np.log(true_permeability),pre_permeability, true_pressure,pre_pressure] fig, _ = plt.subplots(2,2, figsize=(6,6)) vmin1 = [np.amin(samples[0]), np.amin(samples[0]),np.amin(samples[2]),np.amin(samples[2])] vmax1 = [np.amax(samples[0]), np.amax(samples[0]),np.amax(samples[2]),np.amax(samples[2])] for j, ax in enumerate(fig.axes): ax.set_aspect('equal') ax.set_axis_off() cax = ax.imshow(samples[j], cmap='jet',vmin=vmin1[j],vmax=vmax1[j]) cbar = plt.colorbar(cax, ax=ax, fraction=0.046, pad=0.04, format=ticker.ScalarFormatter(useMathText=True)) plt.savefig(output_dir+f'/{type}_step_size{beta}_state_{i+1}.pdf') plt.close()