def run_inversion_cg( self, maxIter=60, m0=0.0, mref=0.0, percentage=5, floor=0.1, chifact=1, beta0_ratio=1.0, coolingFactor=1, coolingRate=1, alpha_s=1.0, alpha_x=1.0, use_target=False, ): survey, prob = self.get_problem_survey() survey.eps = percentage survey.std = floor survey.dobs = self.data.copy() self.uncertainty = percentage * abs(survey.dobs) * 0.01 + floor m0 = np.ones(self.M) * m0 mref = np.ones(self.M) * mref reg = Regularization.Tikhonov( self.mesh, alpha_s=alpha_s, alpha_x=alpha_x, mref=mref ) dmis = DataMisfit.l2_DataMisfit(survey) dmis.W = 1.0 / self.uncertainty opt = Optimization.InexactGaussNewton(maxIter=maxIter, maxIterCG=20) opt.remember("xc") opt.tolG = 1e-10 opt.eps = 1e-10 invProb = InvProblem.BaseInvProblem(dmis, reg, opt) save = Directives.SaveOutputEveryIteration() beta_schedule = Directives.BetaSchedule( coolingFactor=coolingFactor, coolingRate=coolingRate ) target = Directives.TargetMisfit(chifact=chifact) if use_target: directives = [ Directives.BetaEstimate_ByEig(beta0_ratio=beta0_ratio), beta_schedule, target, save, ] else: directives = [ Directives.BetaEstimate_ByEig(beta0_ratio=beta0_ratio), beta_schedule, save, ] inv = Inversion.BaseInversion(invProb, directiveList=directives) mopt = inv.run(m0) model = opt.recall("xc") model.append(mopt) pred = [] for m in model: pred.append(survey.dpred(m)) return model, pred, save
# Specify how the initial beta is found # if input_dict["inversion_type"].lower() in ['mvi', 'mvis']: betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e+1) # Pre-conditioner update_Jacobi = Directives.UpdatePreconditioner() IRLS = Directives.Update_IRLS(f_min_change=1e-3, minGNiter=1, beta_tol=0.25, maxIRLSiter=max_IRLS_iter, chifact_target=target_chi, betaSearch=False) # Save model saveDict = Directives.SaveOutputEveryIteration(save_txt=False) saveIt = Directives.SaveUBCModelEveryIteration( mapping=activeCellsMap, fileName=outDir + input_dict["inversion_type"].lower() + "_C", vector=input_dict["inversion_type"].lower()[0:3] == 'mvi') # Put all the parts together inv = Inversion.BaseInversion( invProb, directiveList=[saveIt, saveDict, betaest, IRLS, update_Jacobi]) # SimPEG reports half phi_d, so we scale to matrch print("Start Inversion\nTarget Misfit: %.2e (%.0f data with chifact = %g)" % (0.5 * target_chi * len(survey.std), len(survey.std), target_chi)) # Run the inversion mrec = inv.run(mstart)
problem.pair(survey) problem.Solver = Solver regmap = Maps.IdentityMap(nP=m0.size) survey.std = perc survey.eps = floor survey.dobs = dobs dmisfit = DataMisfit.l2_DataMisfit(survey) reg = Regularization.Simple(mesh, mapping=regmap, indActive=~airind) opt = Optimization.InexactGaussNewton(maxIter=20) invProb = InvProblem.BaseInvProblem(dmisfit, reg, opt) # Create an inversion object beta = Directives.BetaSchedule(coolingFactor=5, coolingRate=2) betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e0) save = Directives.SaveOutputEveryIteration() save_model = Directives.SaveModelEveryIteration() target = Directives.TargetMisfit() inv = Inversion.BaseInversion( invProb, directiveList=[beta, betaest, save, save_model, target]) reg.alpha_s = 1e-2 reg.alpha_x = 1. reg.alpha_y = 1. reg.alpha_z = 1. problem.counter = opt.counter = Utils.Counter() opt.LSshorten = 0.5 mopt = inv.run(m0) sigopt = mapping * mopt np.save("sigest", sigopt)
def run(plotIt=True): # Define the inducing field parameter H0 = (50000, 90, 0) # Create a mesh dx = 5. hxind = [(dx, 5, -1.3), (dx, 10), (dx, 5, 1.3)] hyind = [(dx, 5, -1.3), (dx, 10), (dx, 5, 1.3)] hzind = [(dx, 5, -1.3), (dx, 10)] mesh = Mesh.TensorMesh([hxind, hyind, hzind], 'CCC') # Get index of the center midx = int(mesh.nCx / 2) midy = int(mesh.nCy / 2) # Lets create a simple Gaussian topo and set the active cells [xx, yy] = np.meshgrid(mesh.vectorNx, mesh.vectorNy) zz = -np.exp((xx**2 + yy**2) / 75**2) + mesh.vectorNz[-1] # We would usually load a topofile topo = np.c_[Utils.mkvc(xx), Utils.mkvc(yy), Utils.mkvc(zz)] # Go from topo to array of indices of active cells actv = Utils.surface2ind_topo(mesh, topo, 'N') actv = np.where(actv)[0] nC = len(actv) # Create and array of observation points xr = np.linspace(-20., 20., 20) yr = np.linspace(-20., 20., 20) X, Y = np.meshgrid(xr, yr) # Move the observation points 5m above the topo Z = -np.exp((X**2 + Y**2) / 75**2) + mesh.vectorNz[-1] + 5. # Create a MAGsurvey rxLoc = np.c_[Utils.mkvc(X.T), Utils.mkvc(Y.T), Utils.mkvc(Z.T)] rxLoc = PF.BaseMag.RxObs(rxLoc) srcField = PF.BaseMag.SrcField([rxLoc], param=H0) survey = PF.BaseMag.LinearSurvey(srcField) # We can now create a susceptibility model and generate data # Here a simple block in half-space model = np.zeros((mesh.nCx, mesh.nCy, mesh.nCz)) model[(midx - 2):(midx + 2), (midy - 2):(midy + 2), -6:-2] = 0.02 model = Utils.mkvc(model) model = model[actv] # Create active map to go from reduce set to full actvMap = Maps.InjectActiveCells(mesh, actv, -100) # Create reduced identity map idenMap = Maps.IdentityMap(nP=nC) # Create the forward model operator prob = PF.Magnetics.MagneticIntegral(mesh, chiMap=idenMap, actInd=actv) # Pair the survey and problem survey.pair(prob) # Compute linear forward operator and compute some data d = prob.fields(model) # Add noise and uncertainties # We add some random Gaussian noise (1nT) data = d + np.random.randn(len(d)) wd = np.ones(len(data)) * 1. # Assign flat uncertainties survey.dobs = data survey.std = wd survey.mtrue = model # Create sensitivity weights from our linear forward operator rxLoc = survey.srcField.rxList[0].locs wr = np.sum(prob.G**2., axis=0)**0.5 wr = (wr / np.max(wr)) # Create a regularization reg = Regularization.Sparse(mesh, indActive=actv, mapping=idenMap) reg.cell_weights = wr reg.mref = np.zeros(nC) reg.norms = np.c_[0, 0, 0, 0] # reg.eps_p, reg.eps_q = 1e-0, 1e-0 # Data misfit function dmis = DataMisfit.l2_DataMisfit(survey) dmis.W = 1 / wd # Add directives to the inversion opt = Optimization.ProjectedGNCG(maxIter=100, lower=0., upper=1., maxIterLS=20, maxIterCG=20, tolCG=1e-3) invProb = InvProblem.BaseInvProblem(dmis, reg, opt) betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e-1) # Here is where the norms are applied # Use pick a threshold parameter empirically based on the distribution of # model parameters IRLS = Directives.Update_IRLS(f_min_change=1e-4, maxIRLSiter=40) saveDict = Directives.SaveOutputEveryIteration(save_txt=False) update_Jacobi = Directives.UpdatePreconditioner() inv = Inversion.BaseInversion( invProb, directiveList=[IRLS, betaest, update_Jacobi, saveDict]) # Run the inversion m0 = np.ones(nC) * 1e-4 # Starting model mrec = inv.run(m0) if plotIt: # Here is the recovered susceptibility model ypanel = midx zpanel = -5 m_l2 = actvMap * invProb.l2model m_l2[m_l2 == -100] = np.nan m_lp = actvMap * mrec m_lp[m_lp == -100] = np.nan m_true = actvMap * model m_true[m_true == -100] = np.nan # Plot the data Utils.PlotUtils.plot2Ddata(rxLoc, d) plt.figure() # Plot L2 model ax = plt.subplot(321) mesh.plotSlice(m_l2, ax=ax, normal='Z', ind=zpanel, grid=True, clim=(model.min(), model.max())) plt.plot(([mesh.vectorCCx[0], mesh.vectorCCx[-1]]), ([mesh.vectorCCy[ypanel], mesh.vectorCCy[ypanel]]), color='w') plt.title('Plan l2-model.') plt.gca().set_aspect('equal') plt.ylabel('y') ax.xaxis.set_visible(False) plt.gca().set_aspect('equal', adjustable='box') # Vertica section ax = plt.subplot(322) mesh.plotSlice(m_l2, ax=ax, normal='Y', ind=midx, grid=True, clim=(model.min(), model.max())) plt.plot(([mesh.vectorCCx[0], mesh.vectorCCx[-1]]), ([mesh.vectorCCz[zpanel], mesh.vectorCCz[zpanel]]), color='w') plt.title('E-W l2-model.') plt.gca().set_aspect('equal') ax.xaxis.set_visible(False) plt.ylabel('z') plt.gca().set_aspect('equal', adjustable='box') # Plot Lp model ax = plt.subplot(323) mesh.plotSlice(m_lp, ax=ax, normal='Z', ind=zpanel, grid=True, clim=(model.min(), model.max())) plt.plot(([mesh.vectorCCx[0], mesh.vectorCCx[-1]]), ([mesh.vectorCCy[ypanel], mesh.vectorCCy[ypanel]]), color='w') plt.title('Plan lp-model.') plt.gca().set_aspect('equal') ax.xaxis.set_visible(False) plt.ylabel('y') plt.gca().set_aspect('equal', adjustable='box') # Vertical section ax = plt.subplot(324) mesh.plotSlice(m_lp, ax=ax, normal='Y', ind=midx, grid=True, clim=(model.min(), model.max())) plt.plot(([mesh.vectorCCx[0], mesh.vectorCCx[-1]]), ([mesh.vectorCCz[zpanel], mesh.vectorCCz[zpanel]]), color='w') plt.title('E-W lp-model.') plt.gca().set_aspect('equal') ax.xaxis.set_visible(False) plt.ylabel('z') plt.gca().set_aspect('equal', adjustable='box') # Plot True model ax = plt.subplot(325) mesh.plotSlice(m_true, ax=ax, normal='Z', ind=zpanel, grid=True, clim=(model.min(), model.max())) plt.plot(([mesh.vectorCCx[0], mesh.vectorCCx[-1]]), ([mesh.vectorCCy[ypanel], mesh.vectorCCy[ypanel]]), color='w') plt.title('Plan true model.') plt.gca().set_aspect('equal') plt.xlabel('x') plt.ylabel('y') plt.gca().set_aspect('equal', adjustable='box') # Vertical section ax = plt.subplot(326) mesh.plotSlice(m_true, ax=ax, normal='Y', ind=midx, grid=True, clim=(model.min(), model.max())) plt.plot(([mesh.vectorCCx[0], mesh.vectorCCx[-1]]), ([mesh.vectorCCz[zpanel], mesh.vectorCCz[zpanel]]), color='w') plt.title('E-W true model.') plt.gca().set_aspect('equal') plt.xlabel('x') plt.ylabel('z') plt.gca().set_aspect('equal', adjustable='box') # Plot convergence curves fig, axs = plt.figure(), plt.subplot() axs.plot(saveDict.phi_d, 'k', lw=2) axs.plot(np.r_[IRLS.iterStart, IRLS.iterStart], np.r_[0, np.max(saveDict.phi_d)], 'k:') twin = axs.twinx() twin.plot(saveDict.phi_m, 'k--', lw=2) axs.text(IRLS.iterStart, 0, 'IRLS Steps', va='bottom', ha='center', rotation='vertical', size=12, bbox={'facecolor': 'white'}) axs.set_ylabel('$\phi_d$', size=16, rotation=0) axs.set_xlabel('Iterations', size=14) twin.set_ylabel('$\phi_m$', size=16, rotation=0)
def run_inversion( self, maxIter=60, m0=0.0, mref=0.0, percentage=5, floor=0.1, chifact=1, beta0_ratio=1.0, coolingFactor=1, n_iter_per_beta=1, alpha_s=1.0, alpha_x=1.0, alpha_z=1.0, use_target=False, use_tikhonov=True, use_irls=False, p_s=2, p_x=2, p_y=2, p_z=2, beta_start=None, ): self.uncertainty = percentage * abs(self.survey.dobs) * 0.01 + floor m0 = np.ones(self.mesh.nC) * m0 mref = np.ones(self.mesh.nC) * mref if ~use_tikhonov: reg = Regularization.Sparse( self.mesh, alpha_s=alpha_s, alpha_x=alpha_x, alpha_y=alpha_z, mref=mref, mapping=Maps.IdentityMap(self.mesh), cell_weights=self.mesh.vol, ) else: reg = Regularization.Tikhonov( self.mesh, alpha_s=alpha_s, alpha_x=alpha_x, alpha_y=alpha_z, mref=mref, mapping=Maps.IdentityMap(self.mesh), ) dmis = DataMisfit.l2_DataMisfit(self.survey) dmis.W = 1.0 / self.uncertainty opt = Optimization.ProjectedGNCG(maxIter=maxIter, maxIterCG=20) opt.lower = 0.0 opt.remember("xc") opt.tolG = 1e-10 opt.eps = 1e-10 invProb = InvProblem.BaseInvProblem(dmis, reg, opt) save = Directives.SaveOutputEveryIteration() beta_schedule = Directives.BetaSchedule(coolingFactor=coolingFactor, coolingRate=n_iter_per_beta) if use_irls: IRLS = Directives.Update_IRLS( f_min_change=1e-4, minGNiter=1, silent=False, maxIRLSiter=40, beta_tol=5e-1, coolEpsFact=1.3, chifact_start=chifact, ) if beta_start is None: directives = [ Directives.BetaEstimate_ByEig(beta0_ratio=beta0_ratio), IRLS, save, ] else: directives = [IRLS, save] invProb.beta = beta_start reg.norms = np.c_[p_s, p_x, p_z, 2] else: target = Directives.TargetMisfit(chifact=chifact) directives = [ Directives.BetaEstimate_ByEig(beta0_ratio=beta0_ratio), beta_schedule, save, ] if use_target: directives.append(target) inv = Inversion.BaseInversion(invProb, directiveList=directives) mopt = inv.run(m0) model = opt.recall("xc") model.append(mopt) pred = [] for m in model: pred.append(self.survey.dpred(m)) return model, pred, save
def run(N=100, plotIt=True): np.random.seed(1) std_noise = 1e-2 mesh = Mesh.TensorMesh([N]) m0 = np.ones(mesh.nC) * 1e-4 mref = np.zeros(mesh.nC) nk = 20 jk = np.linspace(1., 60., nk) p = -0.25 q = 0.25 def g(k): return ( np.exp(p*jk[k]*mesh.vectorCCx) * np.cos(np.pi*q*jk[k]*mesh.vectorCCx) ) G = np.empty((nk, mesh.nC)) for i in range(nk): G[i, :] = g(i) mtrue = np.zeros(mesh.nC) mtrue[mesh.vectorCCx > 0.3] = 1. mtrue[mesh.vectorCCx > 0.45] = -0.5 mtrue[mesh.vectorCCx > 0.6] = 0 prob = Problem.LinearProblem(mesh, G=G) survey = Survey.LinearSurvey() survey.pair(prob) survey.dobs = prob.fields(mtrue) + std_noise * np.random.randn(nk) wd = np.ones(nk) * std_noise # Distance weighting wr = np.sum(prob.getJ(m0)**2., axis=0)**0.5 wr = wr/np.max(wr) dmis = DataMisfit.l2_DataMisfit(survey) dmis.W = 1./wd betaest = Directives.BetaEstimate_ByEig(beta0_ratio=1e0) # Creat reduced identity map idenMap = Maps.IdentityMap(nP=mesh.nC) reg = Regularization.Sparse(mesh, mapping=idenMap) reg.mref = mref reg.cell_weights = wr reg.norms = np.c_[0., 0., 2., 2.] reg.mref = np.zeros(mesh.nC) opt = Optimization.ProjectedGNCG( maxIter=100, lower=-2., upper=2., maxIterLS=20, maxIterCG=10, tolCG=1e-3 ) invProb = InvProblem.BaseInvProblem(dmis, reg, opt) update_Jacobi = Directives.UpdatePreconditioner() # Set the IRLS directive, penalize the lowest 25 percentile of model values # Start with an l2-l2, then switch to lp-norms IRLS = Directives.Update_IRLS( maxIRLSiter=40, minGNiter=1, f_min_change=1e-4) saveDict = Directives.SaveOutputEveryIteration(save_txt=False) inv = Inversion.BaseInversion( invProb, directiveList=[IRLS, betaest, update_Jacobi, saveDict] ) # Run inversion mrec = inv.run(m0) print("Final misfit:" + str(invProb.dmisfit(mrec))) if plotIt: fig, axes = plt.subplots(2, 2, figsize=(12*1.2, 8*1.2)) for i in range(prob.G.shape[0]): axes[0, 0].plot(prob.G[i, :]) axes[0, 0].set_title('Columns of matrix G') axes[0, 1].plot(mesh.vectorCCx, mtrue, 'b-') axes[0, 1].plot(mesh.vectorCCx, invProb.l2model, 'r-') # axes[0, 1].legend(('True Model', 'Recovered Model')) axes[0, 1].set_ylim(-1.0, 1.25) axes[0, 1].plot(mesh.vectorCCx, mrec, 'k-', lw=2) axes[0, 1].legend( ( 'True Model', 'Smooth l2-l2', 'Sparse norms: {0}'.format(*reg.norms) ), fontsize=12 ) axes[1, 1].plot(saveDict.phi_d, 'k', lw=2) twin = axes[1, 1].twinx() twin.plot(saveDict.phi_m, 'k--', lw=2) axes[1, 1].plot( np.r_[IRLS.iterStart, IRLS.iterStart], np.r_[0, np.max(saveDict.phi_d)], 'k:' ) axes[1, 1].text( IRLS.iterStart, 0., 'IRLS Start', va='bottom', ha='center', rotation='vertical', size=12, bbox={'facecolor': 'white'} ) axes[1, 1].set_ylabel('$\phi_d$', size=16, rotation=0) axes[1, 1].set_xlabel('Iterations', size=14) axes[1, 0].axis('off') twin.set_ylabel('$\phi_m$', size=16, rotation=0) return prob, survey, mesh, mrec