def __init__(self, main_dir=None, CaseStudy=0, seq=3, ndraw=10000, thin=1, nCR=3, DEpairs=3, parallelUpdate=0.9, pCR=True, k=10, pJumpRate_one=0.2, steps=100, savemodout=False, saveout=True, save_tmp_out=True, Prior='LHS', DoParallel=True, eps=5e-2, BoundHandling='Reflect', lik_sigma_est=False, parallel_jobs=4, jr_scale=1.0, rng_seed=123): self.CaseStudy = CaseStudy MCMCPar.seq = seq MCMCPar.ndraw = ndraw MCMCPar.thin = thin MCMCPar.nCR = nCR MCMCPar.DEpairs = DEpairs MCMCPar.parallelUpdate = parallelUpdate MCMCPar.Do_pCR = pCR MCMCPar.k = k MCMCPar.pJumpRate_one = pJumpRate_one MCMCPar.steps = steps MCMCPar.savemodout = savemodout MCMCPar.saveout = saveout MCMCPar.save_tmp_out = save_tmp_out MCMCPar.Prior = Prior MCMCPar.DoParallel = DoParallel MCMCPar.eps = eps MCMCPar.BoundHandling = BoundHandling MCMCPar.jr_scale = jr_scale MCMCPar.lik_sigma_est = lik_sigma_est Extra.n_jobs = parallel_jobs Extra.main_dir = main_dir np.random.seed(rng_seed) MCMCPar.rng_seed = rng_seed if self.CaseStudy == 2: ModelName = 'linear_gpr_tomo' MCMCPar.lik = 2 MCMCPar.savemodout = False MCMCPar.lik_sigma_est = False MCMCPar.lb = np.ones((1, 15)) * -1 MCMCPar.ub = np.ones((1, 15)) MCMCPar.n = MCMCPar.ub.shape[1] # Set forward model stuff: from tomokernel_straight import tomokernel_straight_2D nx = 60 # Here x is the horizontal axis (number of columns) and not the number of rows ny = 125 # Here y is the vertical axis (number of rows) and not the number of columns # The x-axis is varying the fastest x = np.arange(0, (nx / 10) + 0.1, 0.1) y = np.arange(0, (ny / 10) + 0.1, 0.1) sourcex = 0.01 sourcez = np.arange(0.5, ny / 10, 0.5) receiverx = nx / 10 - 0.01 receiverz = np.arange(0.5, ny / 10, 0.5) nsource = len(sourcez) nreceiver = len(receiverz) ndata = nsource * nreceiver data = np.zeros((ndata, 4)) # Calculate acquisition geometry (multiple-offset gather) for jj in range(0, nsource): for ii in range(0, nreceiver): data[(jj) * nreceiver + ii, :] = np.array( [sourcex, sourcez[jj], receiverx, receiverz[ii]]) # Calculate forward modeling kernel (from Matlab code by Dr. James Irving, UNIL) G = tomokernel_straight_2D( data, x, y) # Distance of ray-segment in each cell for each ray Extra.G = np.array(G.todense()) # DNN stuff DNN = AttrDict() DNN.nx = nx DNN.ny = ny DNN.zx = 5 DNN.zy = 3 DNN.nc = 1 DNN.nz = 1 DNN.depth = 5 DNN.threshold = True DNN.filtering = False DNN.cuda = True DNN.gpath = Extra.main_dir + '/generation/netG.pth' from generator import Generator as Generator DNN.npx = (DNN.zx - 1) * 2**DNN.depth + 1 DNN.npy = (DNN.zy - 1) * 2**DNN.depth + 1 DNN.netG = Generator(cuda=DNN.cuda, gpath=DNN.gpath) for param in DNN.netG.parameters(): param.requires_grad = False DNN.netG.eval() if DNN.cuda: DNN.netG.cuda() self.DNN = DNN # Load measurements file_name = 'measurements.pkl' Measurement.Sigma = 1 # Measurement error is 1 ns with open(file_name, 'rb') as fin: tmp = pickle.load(fin) Extra.z_true = tmp['z_true'] if DNN.threshold: Extra.m_true = tmp['m_true'] Measurement.MeasData = tmp['d'] else: Extra.m_true = tmp['m_true_cont'] Measurement.MeasData = tmp['d_cont'] del tmp Measurement.N = len(Measurement.MeasData) elif self.CaseStudy == 1: # A theoretical 10-dimensional bimodal distribution made of 2 Gaussians # (example 3 in Matlab DREAMzs code) self.ndim = 10 MCMCPar.n = self.ndim MCMCPar.Prior = 'COV' MCMCPar.lb = np.zeros((1, MCMCPar.n)) - 100 MCMCPar.ub = np.zeros((1, MCMCPar.n)) + 100 MCMCPar.BoundHandling = None Measurement.N = 1 ModelName = 'theoretical_case_bimodal_mvn' MCMCPar.lik = 1 Extra.cov1 = np.eye(MCMCPar.n) Extra.cov2 = np.eye(MCMCPar.n) Extra.mu1 = np.zeros((MCMCPar.n)) - 5 Extra.mu2 = np.zeros((MCMCPar.n)) + 5 elif self.CaseStudy == 0: # A theoretical multivariate normal distribution with 100 correlated dimensions # (example 2 in Matlab DREAM code) self.ndim = 100 MCMCPar.n = self.ndim MCMCPar.Prior = 'LHS' MCMCPar.lb = np.zeros((1, MCMCPar.n)) - 5 MCMCPar.ub = np.zeros((1, MCMCPar.n)) + 15 MCMCPar.BoundHandling = 'Reflect' Measurement.N = 1 ModelName = 'theoretical_case_mvn' MCMCPar.lik = 0 A = 0.5 * np.eye(MCMCPar.n) + 0.5 * np.ones(MCMCPar.n) cov = np.zeros((MCMCPar.n, MCMCPar.n)) # Rescale to variance-covariance matrix of interest for i in range(0, MCMCPar.n): for j in range(0, MCMCPar.n): cov[i, j] = A[i, j] * np.sqrt((i + 1) * (j + 1)) Extra.C = cov Extra.invC = np.linalg.inv(cov) else: # This should not happen and is thus probably not needed self.ndim = 1 MCMCPar.n = self.ndim MCMCPar.lb = np.zeros((1, MCMCPar.n)) MCMCPar.ub = np.zeros((1, MCMCPar.n)) + 1 MCMCPar.BoundHandling = None Measurement.N = 1 ModelName = None MCMCPar.lik = 1 MCMCPar.m0 = 10 * MCMCPar.n self.MCMCPar = MCMCPar self.Measurement = Measurement self.Extra = Extra self.ModelName = ModelName
def run_inv_gn(niter, gpath, nc, nz, zx, zy, cuda, model_index, noise_index, threshold, filtering, FDCalcJ, invCe, maxit, it_stop, rmse_stop, Prior, D, delta_z, labda, labda_max, labda_min, labdaUpdate, VaryAlfa, AdaptJump, Regularization, mv, test_type, alfa_min, alfa_f): # Load true model and measurement data model_path = './true_model_' + str(model_index) + '_noise_' + str( noise_index) with open(model_path + '.pkl', 'rb') as fin: tmp = pickle.load(fin) if threshold: #z_true=tmp['z_true'] model_true = tmp['m_true'] d = tmp['d'] else: model_true = tmp['m_true_cont'] #125 x 60 in [0,1] d = tmp['d_cont'] # forward setup from tomokernel_straight import tomokernel_straight_2D nx = 60 # Here x is the horizontal axis (number of columns) and not the number of rows ny = 125 # Here y is the vertical axis (number of rows) and not the number of columns # The x-axis is varying the fastest x = np.arange(0, (nx / 10) + 0.1, 0.1) y = np.arange(0, (ny / 10) + 0.1, 0.1) sourcex = 0.01 sourcez = np.arange(0.5, ny / 10, 0.5) receiverx = nx / 10 - 0.01 receiverz = np.arange(0.5, ny / 10, 0.5) nsource = len(sourcez) nreceiver = len(receiverz) ndata = nsource * nreceiver data = np.zeros((ndata, 4)) # Calculate acquisition geometry (multiple-offset gather) for jj in range(0, nsource): for ii in range(0, nreceiver): data[(jj) * nreceiver + ii, :] = np.array( [sourcex, sourcez[jj], receiverx, receiverz[ii]]) # Calculate forward modeling kernel (from Matlab code by Dr. James Irving, UNIL) G = tomokernel_straight_2D( data, x, y) # Distance of ray-segment in each cell for each ray G = np.array(G.todense()) del data netG = Generator(cuda=cuda, gpath=gpath) for param in netG.parameters(): param.requires_grad = False netG.eval() if cuda: netG.cuda() z_hist = np.zeros((maxit, zx * zy)) + np.nan labda_hist = np.zeros((maxit)) + np.nan rmse_hist = np.zeros((maxit)) + np.nan e_hist = np.zeros((maxit, ndata)) + np.nan improv_hist = np.zeros((maxit)) + np.nan alfa_hist = np.zeros((maxit)) + np.nan improv_hist[0] = 1 best_rmse = 1000 alfa = np.copy(alfa_min) z0 = np.random.randn(zx * zy) z = np.copy(z0) iter_hist = np.nan istart = 0 iend = maxit for i in range(istart, iend): z_old = z e, J, m_current = comp_res_J(z, d, G, zx, zy, nz, netG, Prior, 1 / alfa, mv=None, CalcJ=FDCalcJ, cuda=cuda, Regularization=Regularization, threshold=threshold, filtering=filtering) rmse = np.sqrt(np.sum(e**2) / len(e)) # Different ways of updating labda if tried if i > 0 and labdaUpdate == 'alternate': if np.mod(i, 2) == 0: labda = 100 else: labda = 1 if i > 0 and labdaUpdate == 'constant_SteepDesc': labda = np.minimum(labda * 1.1, labda_max) if i > 0 and labdaUpdate == 'constant_GN': labda = np.maximum(labda * 0.9, labda_min) if i > 9 and labdaUpdate == 'dynamic': if rmse < rmse_hist[i - 1]: # Decrease labda to get a more GN update labda = labda = np.maximum(labda * 0.5, labda_min) elif rmse > rmse_hist[ i - 1]: # Increase labda to get a more steepest descent update labda = np.minimum(labda * 2, labda_max) print('Current RMSE is ', rmse) if rmse < best_rmse: best_rmse = rmse # Store z, rmse and labda z_hist[i, :] = z.flatten() rmse_hist[i] = rmse alfa_hist[i] = alfa labda_hist[i] = labda e_hist[i] = e if i > 0 and (rmse > best_rmse): improv_hist[i] = 0 else: improv_hist[i] = 1 # Update z dhat = e + J @ z A = J.T @ invCe @ J + labda * D @ D.T z_new = np.linalg.inv(A) @ J.T @ invCe @ dhat # Update alfa if regularization by vanishing smearing or gradual contrasting of the models is tried if VaryAlfa == True: if np.mod(i, 1) == 0: alfa = np.minimum(np.maximum(alfa_min, alfa) * alfa_f, np.inf) print(alfa) alfa_hist[i] = alfa if i >= it_stop and best_rmse > rmse_stop: iter_hist = i print('Stop non-productive run') break # Try to reduce the jump if the fit is not improving after some given iterations if i >= 20 and AdaptJump == True and np.sum(improv_hist[i - 5:i]) == 0: beta = 0.5 print('reduce jump') else: beta = 1 z = z_old + beta * (z_new - z_old) print('iteration ', str(i), ' done - best RMSE = ', str(best_rmse)) return best_rmse, rmse, z_hist, rmse_hist, labda_hist, e_hist, improv_hist, z0, iter_hist
def run_gan_qn(lr, maxiter, gpath, init_z_file, nc, nz, zx, zy, cuda, adam, model_index, noise_index, clip): # Load initial z (z) if provided if init_z_file is None: z = torch.rand([1, nz, zx, zy]).to(device) * 2 - 1 else: z = torch.Tensor(init_z_file.reshape(1, nz, zx, zy)).to(device) z.requires_grad = True # Load true model and measurement data model_path = './true_data_model_' + str(model_index) + '_noise_' + str( noise_index) with open(model_path + '.pkl', 'rb') as fin: tmp = pickle.load(fin) #z_true=tmp['z_true'] model_true = tmp['m_true'] #d_true=tmp['d_true'] d = tmp['d'] # forward setup from tomokernel_straight import tomokernel_straight_2D nx = 60 # Here x is the horizontal axis (number of columns) and not the number of rows ny = 125 # Here y is the vertical axis (number of rows) and not the number of columns # The x-axis is varying the fastest x = np.arange(0, (nx / 10) + 0.1, 0.1) y = np.arange(0, (ny / 10) + 0.1, 0.1) sourcex = 0.01 sourcez = np.arange(0.5, ny / 10, 0.5) receiverx = nx / 10 - 0.01 receiverz = np.arange(0.5, ny / 10, 0.5) nsource = len(sourcez) nreceiver = len(receiverz) ndata = nsource * nreceiver data = np.zeros((ndata, 4)) # Calculate acquisition geometry (multiple-offset gather) for jj in range(0, nsource): for ii in range(0, nreceiver): data[(jj) * nreceiver + ii, :] = np.array( [sourcex, sourcez[jj], receiverx, receiverz[ii]]) # Calculate forward modeling kernel (from Matlab code by Dr. James Irving, UNIL) A = tomokernel_straight_2D( data, x, y) # Distance of ray-segment in each cell for each ray A = np.array(A.todense()) del data netG = Generator(cuda=True, gpath=gpath).to(device) for param in netG.parameters(): param.requires_grad = False netG.eval() if adam: optimizer = optim.Adam([z], lr=lr) else: optimizer = optim.LBFGS([z], lr=lr) data_cost = [] model_cost = [] zs = [] models = [] filtering = False threshold = True def closure(): # Produce model from z # clipping if clip == 'standard': z.data[z.data > 1] = 1 z.data[z.data < -1] = -1 if clip == 'stochastic': z.data[z.data > 1] = random.uniform(-1, 1) z.data[z.data < -1] = random.uniform(-1, 1) x0 = netG(z) # --- Here we quit pytorch --- x = x0.data.cpu().numpy( ) # copy x into cpu and numpy for further calculations zs.append(z.data.cpu().numpy().copy()) # Compute cost and gradient on model s_model = x[0, 0, 2:127, 3:63] s_model = (s_model + 1) * 0.5 # Convert from [-1,1] to [0,1] if filtering: s_model = medfilt(s_model, kernel_size=(3, 3)) s_model[s_model < 0.5] = 0 s_model[s_model >= 0.5] = 1 s_model[s_model == 0] = 0.08 # m/ns s_model[s_model == 1] = 0.06 # m/ns s_model = 1 / s_model sim = A @ s_model.flatten(order='F') e = d - sim cost = np.sum(np.power(e, 2)) grad = -2 * A.T @ e.T # change from Fortran ordering used by forward solver to C ordering used by numpy grad = grad.reshape((125, 60), order='F').reshape((7500)) # embed grad within array of the size used by the GAN grad_fs = np.zeros((129, 65)) grad_fs[2:127, 3:63] = grad.reshape((125, 60)) data_cost.append(cost) model_cost.append(np.linalg.norm(model_true - x[0, 0, 2:127, 3:63])) # Update z (z) using gradient information #--- Here we go back to pytorch --- optimizer.zero_grad() x0.backward(torch.Tensor(grad_fs.reshape(x0.shape)).to(device)) return cost for it in range(maxiter): optimizer.step(closure) print(it, data_cost[-1], model_cost[-1]) # Stop non-productive runs if it >= 100 and data_cost[-1] > 1e3: break x = netG(z) return z.data.cpu().numpy(), x.data.cpu().numpy( ), data_cost, model_cost, zs, models
def run_gan_qn(lr, maxiter, gpath, init_z_file,nc,nz,zx,zy,cuda,adam,model_index,noise_index,clip): def ssr_loss(true,sim): return torch.sum((true-sim)**2) # Load initial z (z) if provided if init_z_file is None: z = torch.rand([1, nz, zx, zy]).to(device)*2-1 else: z = torch.Tensor(init_z_file.reshape(1, nz, zx, zy)).to(device) z.requires_grad = True # Load true model and measurement data model_path = './true_model_'+str(model_index)+'_noise_'+str(noise_index) with open(model_path+'.pkl', 'rb') as fin: tmp=pickle.load(fin) z_true=tmp['z_true'] m_true=torch.Tensor(tmp['m_true_cont'] ).to(device)#125 x 60 in [0,1] d=torch.Tensor(tmp['d_cont'] ).to(device) # forward setup from tomokernel_straight import tomokernel_straight_2D nx=60 # Here x is the horizontal axis (number of columns) and not the number of rows ny = 125 # Here y is the vertical axis (number of rows) and not the number of columns # The x-axis is varying the fastest x = np.arange(0,(nx/10)+0.1,0.1) y = np.arange(0,(ny/10)+0.1,0.1) sourcex = 0.01 sourcez = np.arange(0.5,ny/10,0.5) receiverx = nx/10-0.01 receiverz = np.arange(0.5,ny/10,0.5) nsource = len(sourcez); nreceiver = len(receiverz) ndata=nsource*nreceiver data=np.zeros((ndata,4)) # Calculate acquisition geometry (multiple-offset gather) for jj in range(0,nsource): for ii in range(0,nreceiver): data[ ( jj ) * nreceiver + ii , :] = np.array([sourcex, sourcez[jj], receiverx, receiverz[ii]]) # Calculate forward modeling kernel (from Matlab code by Dr. James Irving, UNIL) A = tomokernel_straight_2D(data,x,y) # Distance of ray-segment in each cell for each ray A=A.todense() A=torch.Tensor(A).to(device) del data netG = Generator(cuda=True, gpath=gpath).to(device) for param in netG.parameters(): param.requires_grad = False netG.eval() if adam: optimizer = optim.Adam([z], lr=lr) else: optimizer = optim.LBFGS([z], lr=lr) data_cost = [] model_cost = [] zs = [] models = [] # train for i in range(maxiter): # clipping if clip == 'standard': z.data[z.data> 1] = 1 z.data[z.data < -1] = -1 if clip == 'stochastic': z.data[z.data > 1] = random.uniform(-1, 1) z.data[z.data < -1] = random.uniform(-1, 1) x0 = netG(z)[0,0,2:127,3:63] x0 = (x0 + 1) * 0.5 # Convert from [-1,1] to [0,1] s = 1 - x0 s= 0.06 + s*0.02 s=1/s #ns/m # change from C ordering to Fortran ordering and reshape s=s.permute(1,0).flatten().view(7500,1) sim = torch.mm(A,s).flatten() ssr = ssr_loss(d,sim) ssr_model = ssr_loss(x0,m_true) # if i % 10 == 0: # print("[Iter {}] ssr_g_z: {}, ssr_g_z: {}, ssr_model: {}" # .format(i, ssr.data[0], ssr, ssr_model.data[0])) # backprop optimizer.zero_grad() ssr.backward() optimizer.step() data_cost.append(ssr.detach().cpu().numpy()) model_cost.append(ssr_model.detach().cpu().numpy()) zs.append(z.detach().cpu().numpy()) # models.append(x0.detach().cpu.numpy()) print(i, data_cost[-1], model_cost[-1]) return z, x0, data_cost, model_cost, zs, models